之前好几位朋友留言都提到通过追send找动作CALL但失败了问我怎么追,以前我其实也没研究过航海的数据包部分,今天简单研究了一下。
网游发包CALL有好几种设计思路。设计思路简单,实现也就简单,追踪也简单;设计思路复杂,实现就复杂,追踪也麻烦。
最简单直男的思路就是:动作CALL→构造数据包→加密数据包→发包。这种思路的游戏几乎已经没有了,代码复用性不高,效率也低。
改进的思路是:构造消息队列或者使用多线程,不管哪种,都需要有一个共享的变量容器用于存取数据包。
断点 bp ws2_32.send
断点时机很重要。最好的断点时机是随便输入账号密码,来到选择服务器界面,这个时候没有心跳包和游戏互动内容干扰。X64DBG开启断点,游戏点确认,会中断3次。包的大小分别是8、260、变动。包的数据不需要看最开头的40字节,那是用于数据包协议的,跟游戏无关。
登录了3次,每次固定3个发包,3个收包。前2个发包长度是固定的,后一个长度随账号密码的长度而变。
第一个发包只发送8,接受了一大堆字符,三次均如此。那么猜测第一个发包是请求本机解密数据包的通信密钥之类的证书,服务器发回了证书。
第二个发包也发送了证书,猜测是服务器用于解密数据包的。第二个收包直接就是加密的数据了,猜测是服务器回答“已成功加解密”之类的回复。
第三个发包长度随账号密码的长度而变。登录了3次,第2次我输入帐号1密码1,第三次我输入帐号111111111111密码111111111111,长度分别是24和48。可以猜测第三次发包是发送账号密码。收包是服务器回复账号密码是否正确。这里不正确,所以发了回复就不继续了,如果正确,应该是双方继续通信人物信息之类的。
所以应该从第3次发包中断的时候往回追溯。
v12020
第3次发包中断时的堆栈信息:
0019DB5C | 00BF14F7 返回到 gvo12020.00BF14F7 自 ??? | 游戏send发包函数 |
0019DB68 | 00000BAC | |
0019DB6C | 10A62110 | |
0019DB70 | 00000030 | |
0019DB74 | 00000000 | |
0019DB78 | 0019FDD8 | |
0019DB7C | 00000000 | |
0019DB80 | 011D10E8 gvo12020.011D10E8 | |
0019DBC0 | 00BF3F42 返回到 gvo12020.00BF3F42 自 gvo12020.00BF14C0 | 只发数据包 |
0019DBCC | 00000BAC | |
0019DBD0 | 10A62110 | |
0019DBD4 | 00000030 | |
0019DBD8 | 0019DCF0 | |
0019DBDC | 0019FE5C | |
0019DBE0 | 00000000 | |
0019DBE4 | 011D10E8 gvo12020.011D10E8 | |
0019FDD4 | 00BF5E38 返回到 gvo12020.00BF5E38 自 gvo12020.00BF3C30 | 发包总函数。不连接服务器时不调用,发包包括心跳包和数据包。 |
0019FDE0 | 015D3E48 | |
0019FDE4 | 00000000 | |
0019FDE8 | 00000001 | |
0019FDEC | 0019FEB0 | |
0019FDF0 | 00000000 | |
0019FDF4 | 011D10E8 gvo12020.011D10E8 | |
0019FE58 | 00BF89AF 返回到 gvo12020.00BF89AF 自 gvo12020.00BF5A80 | 直接调用下层函数,下断点立刻中断 |
0019FE64 | 011D5C58 gvo12020.011D5C58 | |
0019FE68 | 00000000 | |
0019FE6C | 011D10E8 gvo12020.011D10E8 | |
0019FEAC | 00BF070F 返回到 gvo12020.00BF070F 自 gvo12020.00BF8980 | 直接调用下层函数,下断点立刻中断 |
0019FEB8 | 011CF640 gvo12020.011CF640 | |
0019FEBC | 00000001 | |
0019FEC0 | 0019FEE0 | |
0019FEBC | 009E1E45 返回到 gvo12020.009E1E45 自 ??? | 直接调用下层函数,下断点立刻中断 |
0019FEC8 | 00000001 | |
0019FECC | 011CF640 gvo12020.011CF640 | |
0019FED0 | 00000002 | |
0019FED4 | 00000002 | |
0019FED8 | 00000001 | |
0019FEDC | 0DE7C898 | |
0019FEE0 | 0019FEF0 | |
0019FEE4 | 009E1D14 返回到 gvo12020.009E1D14 自 ??? | 直接调用下层函数,下断点立刻中断 |
0019FEE8 | 00000001 | |
0019FEEC | 011CF640 gvo12020.011CF640 | |
0019FEF0 | 0019FF10 | |
0019FEF4 | 00D546E9 返回到 gvo12020.00D546E9 自 ??? | PeekMessageA循环 |
0019FEF8 | 00000002 | |
0019FEFC | FFFFFFFF | |
0019FF00 | 011CF640 gvo12020.011CF640 | |
0019FF04 | 011CF640 gvo12020.011CF640 | |
0019FF08 | 01587FD0 | |
0019FF0C | 01588000 | |
0019FF10 | 0019FF24 |
回到游戏主界面,从最外层函数(最下面的)依次在CALL下层函数语句下断点测试,找出下断点后不中断的某层函数。找出后【00BF5E33 | call 0xBF3C30】,点开始游戏,游戏会问服务器要版本数据,此时理论上会中断,实际上也中断了。说明该语句所在的函数sub_BF5A80是发包函数的最外层逻辑函数。
但是在函数BF5A80的开头BF5A80地址处下中断,立刻又被中断了,说明是在函数内部判断是否需要发包。函数判断跳转较多,跟踪麻烦,不管他,直接在地址BF5E33下断点即可。
接下来需要过滤心跳包。进入游戏,找个不受干扰的环境避免杂包,比如码头就很棒。
Wireshark捕获数据包,发现心跳包长度是0。
这说明游戏是使用TCP协议本身来实现心跳包的,或者说保持TCP连接的。
0长度的心跳包是用来保持TCP连接的,游戏自己还有一个长度24字节的心跳包,每30秒发送一次。如果游戏内没操作,第10分钟的那次心跳包发完后游戏就显示闲置提示。
2023年8月14日14:28:43修改
还是在码头,在地址BF5E33下中断,立刻会被断下。说明函数【00BF5E33 | call 0xBF3C30】是发包总函数。不连接服务器时不调用,发包包括心跳包和数据包。最好找只发数据包的地方。
找到函数BF5E33中调用下层发包函数的语句【00BF3F3D | call 0xBF14C0】,在此下中断。程序没有被中断下来,然后点击进城按钮,程序立刻被中断。说明此处是只发送数据包的语句。这里下断点最舒服。
但跟踪后发现找不到动作CALL的信息。说明虽然航海没有把收发包设计为多线程,也不是用消息队列触发发包动作,那有可能是有一个deque容器之类的数据结构,动作CALL往里放包,发包CALL往出拿包。需要找出这个共享容器,找出后在容器下写入断点,就可以追到动作CALL。(用这种方法追动作CALL属实是高射炮打蚊子大材小用,本篇文章追踪回溯的路线最适合用来跟踪加密解密函数)
之后的内容就不适合公开了😁
参考:https://www.cnblogs.com/Sna1lGo/category/1988759.html
文章评论
多谢啊,真是学习了
CALL生成数据放入发送队列,不在一个线程,当然不好追
十多年前研究过,密钥交换使用DH算法,数据包加密使用Blowfish算法
@ok 原来如此,感谢大佬指点
博主,你好!感谢分享技术。我想请教一下这个游戏人物物品信息本地内存里有吗?还是每次打开物品栏才会与服务器通讯获取信息?我试了很多方式找不到物品信息来源。
@mashoo 当你打开持有物品栏时,物品列表和数量都是从服务器发过来的数据,游戏收到数据后才显示物品栏,这个时候本地内存有一份数据。当你关闭持有物品栏时,本地内存的数据被释放。但也可能没释放完全,可能有残存数据(涉及到可用内存的申请和释放),残存数据不能用来逆推。
@wking,感谢解答。
这是味精大神?
@maike 不是
请wking给讲解海上的坐标的搜索,用CE找到俩个基址城里是正确的,可是一出海就对不上了,海上的坐标数值也搜索不出来,请指导下,非常感谢,这个问题困惑了快10年了。求解答
@海航爱好者 海上测量坐标=内存坐标/10000+海域偏移值。每个海域的偏移值是固定的。所以有两种办法获得偏移值。第一种是反汇编程序,可获取基址和实时偏移值。这种方法我有空了写个文章。第二种方法是根据公式,在游戏里去每个海域手动记录计算海域偏移值。
我记得海上要加海域所在坐标的值,例如坐标你搜到的是1, 1 里斯本海值是22,22,那么海上坐标就是23,23,如果到达东亚,东亚值是33,33,那么坐标加东亚值,海上坐标就是34,34
好像有公式,但是不知道怎么算的。
请问测量技能显示的数据是什么类型的,CE扫描不到呢?
@海航爱好者 测量坐标是游戏算出来的,CE搜索不到。
wking大佬,能不能给写个简易的无限抽塔罗牌脚本
@海航爱好者 这个还没有研究