逆向分析Flash在线游戏时,如何确定代码中_root的含义?
嘿,针对你在逆向这款老Flash游戏时遇到的_root和RC4加密相关问题,我来给你拆解清楚:
一、代码里_root到底是什么?
在ActionScript 2.0(也就是这类老Flash游戏常用的语言)里,_root是整个SWF的顶级全局上下文——说白了就是主时间轴的引用,所有全局变量、影片剪辑、全局函数都挂在这个对象下面,相当于客户端运行时的“全局变量容器”。
看你给出的代码,utilites.Crypt.DecryptH(_loc2_[_loc5_].attributes.value,_root)把_root传给了解密函数,结合RC4的特性,这里的_root肯定是用来提供解密密钥的。大概率这个DecryptH函数内部会从_root上读取某个预设的全局变量(比如_root.rc4Key、_root.sessionToken这类和用户绑定的密钥值),因为RC4算法必须依赖一个对称密钥才能完成加解密。
为什么不直接传密钥?估计是这个解密函数被设计成通用工具函数,依赖全局根节点的预设参数,避免每个调用处都重复传密钥,减少代码冗余。
二、服务器怎么“获取”_root内容来加密?
先明确:服务器绝对不可能直接读取客户端SWF里的_root对象——Flash有沙箱安全限制,客户端内存里的数据没法被服务器直接访问。实际的流程应该是这样的:
- 游戏初始化阶段,客户端会从服务器请求一个对称密钥(或者会话标识),拿到之后会把这个值存在
_root的某个全局变量里(比如_root.userSecret); - 当客户端要给服务器发加密数据时,就从
_root里取出这个密钥,用RC4加密数据再发送; - 服务器这边会存储和这个客户端对应的密钥(比如通过会话ID绑定),收到加密数据后用相同密钥解密;反过来,服务器给客户端发加密数据时,也是用这个提前约定好的密钥加密,客户端再用
_root里的密钥解密(就是你代码里DecryptH做的事)。
简单说:_root只是客户端存密钥的“小仓库”,服务器和客户端是提前共享了这个密钥,不是服务器直接读取_root。
三、结合你的代码片段进一步分析
你的代码里的解密逻辑链是这样的:
var _loc3_ = new XML(utilites.UTF8.Decode(utilites.Crypt.DecryptH(_loc2_[_loc5_].attributes.value,_root))).firstChild;
一步步拆解:
- 从XML节点的
value属性取出加密后的字符串; - 调用
DecryptH解密,传入_root让函数内部读取密钥; - 把解密后的二进制数据用UTF-8解码成可读字符串;
- 把字符串解析成XML节点,最终存入
event.cdata。
因为你没法重编译SWF用trace()调试,给你几个替代方案来确认_root里的内容:
- 用Adobe Flash Debug Player配合调试工具加载SWF,运行时直接查看
_root的属性列表,能看到所有挂在上面的全局变量; - 用逆向工具(比如JPEXS Free Flash Decompiler)反编译SWF,全局搜索
_root的赋值语句,找到哪里给_root设置了密钥相关的变量; - 反编译后手动修改
DecryptH函数,把_root里用到的密钥值输出到舞台上的文本框里,再重新打包SWF(老游戏一般没有防篡改,这个方法大概率可行)。
内容的提问来源于stack exchange,提问作者Denis Pedofilov

