进入 RTMP 金矿¶
实时消息协议(RTMP)是 ActionScript 用来序列化并通过网络发送整个对象的基于文本的网络协议。RTMP 位于超文本传输协议(HTTP)之上,安全版本 RTMPS 位于 HTTP Secure(HTTPS)之上。RTMPS 允许游戏开发者轻松地通过安全连接发送和接收整个对象实例,几乎不用什么麻烦,使它成为任何运行在 AIR 上游戏的首选网络协议。
注 通过 RTMP/RTMPS 发送的数据通过 Action 消息格式(AMF)序列化,解析 AMF 数据包超出了本书的范围。在网上搜索「AMF3 Parser」,你会找到很多做这件事的代码。
通过 RTMP 和 RTMPS 发送的数据非常丰富。数据包包含关于对象类型、名称和值的信息。这是一座金矿。如果你能实时拦截这些数据,你就能瞬时响应游戏状态的变化,无需从内存读取就能看到大量关键信息,并找到你可能都不知道存在的有用数据。
不久前,我在开发一个需要大量了解游戏状态的工具。直接从内存获取这么多数据极其困难,甚至不可能。经过一番研究,我意识到游戏使用 RTMPS 与服务器通信,这促使我开始挖掘这座金矿。
由于 RTMPS 是加密的,我知道获得任何可用数据之前,必须以某种方式钩住 AIR 使用的加密函数。在网上搜索后,我找到了一个名为 airlog 的小工具源代码,它由另一位和我一样试图记录 RTMPS 发送数据包的游戏黑客创建。虽然这个工具钩住了我需要的精确函数,但代码过时、混乱,最糟的是,它在我试图钩住的 AIR 版本上不工作。
但这并不意味着它没用。airlog 不仅钩住了我需要的两个函数,还通过扫描 Adobe AIR 库中特定字节模式来定位它们。不过这些字节模式已经有三年历史,不再有效。新版本的 Adobe AIR 变化很大,汇编字节不再相同。
字节差异对 airlog 的代码是个问题,但对我不是。在内联汇编块中,你可以用以下函数调用指定原始字节:
如果你把 BYTE 替换为,比如说,0x03,代码会以把 0x03 当作汇编代码中的一个字节的方式来编译,无论这是否合理。利用这个技巧,我把字节数组重新编译成汇编代码。代码不做任何事情,也不是为了做任何事;使用这个技巧只是让我可以把 OllyDbg 附加到我的虚拟应用程序上并检查字节,它们被方便地呈现为干净的反汇编。
由于这些字节代表了我需要函数周围的代码,它们的反汇编也是如此。代码相当标准,似乎不太可能改变,所以我把注意力转向常量。代码中有些作为命令偏移量传递的立即值。知道这些值有多容易改变,我重新接线了 airlog 的模式匹配算法以支持通配符,更新模式把所有常量当作通配符,然后运行匹配。经过对模式的一些调整和对重复搜索结果的一些挖掘,我找到了想钩的函数。我恰地命名它们为 encode() 和 decode(),并开始开发一个类似 airlog 但更好的工具。