问道手游中anglescript脚本引擎学习与研究
该手游使用的脚本引擎为anglescript和lua。不同于lua,anglescript脚本引擎在google和baidu上基本找不到资料,抱着学习的目的,写下这篇文章。
关键的加密算法在anglescript的as脚本中,名称为data.cas,是一个编译后的字节码文件。关于anglescript的介绍请浏览官网。
1 学习与研究
拿到这款手游apk后,先看看是否加固,用了哪个脚本引擎。搜索一下字符串查找游戏发包位置,从so里面了解到,发包函数有可能在lua中或者anglescript中。具体在哪里还不好确定,我们可以dump出脚本。
先别急着动态调试,往往在收集信息的过程中有意想不到的惊喜。我们看下ios版本,用frida-ios-dump工具砸壳。解压出来发现了大量没有加密的lua脚本,从lua脚本分析结果来看发包函数在lua中,数据包的加密算法在anglescript中,加密函数为gfParseK
和gfParseK
。
通过简单的分析,基本上确定了加密算法的位置,还需要动态调试验证一下。
接下来我们从官网下载anglescript的sdk,随便下载一个版本,主要用来学习,找找有用的函数。因为我们还无法确定问道中是用了哪一个版本的anglescript。
- 学习anglescript
从官网下载sdk,导入到clion中。简单的浏览源码,发现了几个关键的函数
|
|
接下来我们继续分析anglescript汇编指令的执行细节,从as_restore.cpp中了解到,指令+参数的总长度4字节对齐,其中指令的长度为2字节。as_bytecode.cpp中的DebugOutput函数会打印执行的汇编指令。要打印data.cas中所有的函数签名则可以调用以下流程engine->GetModule()->GetFunctionByIndex()->GetDeclaration()
从打印的函数签名中,我们找到了gfParseK
和gfParseK
函数,证明了上面的分析没有错,接下来我们需要做一个测试验证我们的猜想:加载data.cas,调用gfParseK函数。
前面我们提到了,加载data.as脚本,调用脚本中的函数。需要注册大量的C++函数。重新实现这些函数,很麻烦。
2 漫漫长征路
我们用到了以下工具:
- frida
- ida
- android studio
从so里面dump出解密后的data.cas
- 从anglescript sdk中我们学习到一个函数
CScriptBuilder::LoadByteCode
,该函数从内存中加载字节码文件。所有我们用frida进行hook,成功导出了data.cas。
dump出config文件
- 同样我们用frida 调用函数
WriteConfigToFile
,实验中发现无法调用。 所以采用android inline hook的方式进行调用,先hookCScriptBuilder::StartNewModule
获取到engine,然后hookCScriptBuilder::LoadByteCode
,在这里调用WriteConfigToFile
函数成功输出config文件
到这里我们的准备工作算是做完了,剩下就差将字节码反汇编成汇编指令了。要完成转译工作,仍然是学习anglescript sdk源码。具体过程如下:
- 创建engine
asIScriptEngine *engine = asCreateScriptEngine()
- 配置config
ConfigureEngine(engine, "config.txt");
- 开启一个module
builder.StartNewModule(engine, "mymodule");
- 加载字节码
module->LoadByteCode()
- 通过module打印所有函数签名
module->GetFunctionCount()
,module->GetFunctionByIndex(i)->GetDeclaration
asIScriptFunction
保存了一个函数的所有信息。通过这个结构可以获取到该函数的所有汇编指令,指令同样用一个结构体保存asSBCInfo
。
从as_context.cpp
的execute
函数中我们找到了最终汇编指令执行的过程,并且DebugOutput
中也存在字节码转译汇编指令的过程。
编写代码翻译函数中的所有asSBCInfo
,我们很轻松的得到了gfParseK
和gfParseK
函数的汇编指令,然后参考官方的文档还原出了这两个函数的C语言版本。
3 讨论
在整个过程中,很清晰能体会到的问题是脚本引擎的代码保护强度非常薄弱,lua脚本在ios中直接就是明文了,虽然anglescript进行了加密,但是并不能很好的隐藏关键代码,反而是协议部分相对复杂,有种舍本逐末的感觉。
4 最后
附上两个函数的汇编指令:
|
|
本文仅供学习与交流,不得用于非法目的。如有侵权,请联系作者!