若干个游戏辅助的分析手记(二)

----飞五棋牌平台五张牌找基址

  游戏进程名为ShowHand.exe。 该进程每次进入不同的桌进行游戏都会启动新的进程,离开桌子则结束进程. 玩家肯定是一个对象. 该对象里面肯定包含当前手里的牌.然而不知道该游戏各种牌在内存中的表现形式,所以用CE搜索相关的牌就显得无从下手.所以关键是要找到突破口.

  大胆推测,玩家对象有一个变量记录了当前自己桌上的牌的数量.以此作为突破口. 用CE搜索当前手里牌的数量,(查找方法略),得到两个地址,经过观察这两个地址记录的数量一个是对家的牌的数量,一个是自己的数量. 通过实验,发现瞄一眼牌则桌上的牌的数量会减1,以此就可以确定哪个地址是记录自己牌的数量了的地址了.

  接下来,进入OD,附加进游戏,在记录自己牌数量的内存地址,下一个内存写断点.游戏中瞄一眼底牌,游戏断下在下面的代码: 10001f02 - 89 73 10 - mov [ebx+10],esi 

  接着 OD 命令: dd ebx 查看ebx地址的内存数据,发现这一块内存非常像玩家对象,那么找到玩家对象,突破口就打开了.           

  接下来可以整理一下资料: 通过以上的代码可知, 对象基址 + 10 为自己牌的数量,在这一块内存并没有发现类似牌信息的数据.那么凭直觉该对象肯定有一个变量记录了牌信息的地址. 那么接下来找比较像内存地址的数据. 首先发现 [对象基址 + 4] 该数据很像一个地址,OD "数据跟随"此地址,在游戏里试玩一下,注意观察此片内存. 发现该片内存,每添加一张牌,则会修改一部分内存.凭经验直觉,这里就是我们要找的牌信息的地方了. 接下来的重点是解码牌信息.具体过程就是多看多观察了. 下面是最终破译出的信息:

[牌信息基址 + 0x2](字节) 底牌信息

[牌信息基址 + 0x7](字节) 第一张明牌信息

[牌信息基址 + 0x0D](字节) 第二张明牌信息

[牌信息基址 + 0x13](字节) 第三张明牌信息

[牌信息基址 + 0x19](字节) 第四张明牌信息

牌信息用一个字节表示,其中高4位代表花色,低4位为点数 花色(高4位): 方块:0 草花:1 红心:2 黑桃:3

点数(低4位) A~K:(0x1~0xD) 例如:0xD代表K,0x10代表10,0x0C代表Q等.

再举例: 若某牌信息字节内存数据为 3A,则代表该牌是黑桃10,若为1D,则为草花K.

  至此,各张明牌都已经找到,还差底牌.通过观察牌信息的这块内存并没有发现底牌信息.但是有了上面分析的牌信息就好办多了.再进游戏,用CE查找字节,看自己的底牌后,直接利用上面分析的牌信息搜索16进制的字节数据.比如底牌为红心9则搜索29,这样就可以定位到底牌了. 用CE调试游戏进程查找访问该内存的代码,得到一些代码。注意观察所有代码操作的地址都是[xxx+0000160a],所以随便选一条代码: 00404214 - 8a 8e 0a 16 00 00 - mov cl,[esi+0000160a] 那么在此代码处下断,断下来后OD命令 dd esi + 160a 来到该内存地址,查看数据,发现这里的牌数据比上面分析的牌数据爽多了,这里不仅有底牌信息而且有明牌信息. 最终用来读取牌信息的地址,就用这里了. 分析的结果如下:

[(esi+160a) + 0](字节)  底牌

[(esi+160a) + 2](字节)  第一张明牌

[(esi+160a) + 3](字节)  第二张明牌

[(esi+160a) + 4](字节)  第三张明牌

[(esi+160a) + 5](字节)  第四张明牌

各个字节的高4位及低4位跟上面分析的是一致的.

  剩下来的关键就是找到esi的基址就可以大功告成了. 再次回到下面这条代码 00404214 - 8a 8e 0a 16 00 00 - mov cl,[esi+0000160a] 发现esi为上层CALL的ecx,那么一路顺藤摸瓜,发现跟进了MFC的模块,这样找起来效率太低,也麻烦. 碰下运气看看 直接CE搜索 esi的值, 发现有个基址 41A1C8 里面保存了esi的值, 经过测试 41A1C8确实可用 那么牌信息的基址则为 [[41A1C8]+160a] 至此大功告成,完.

漓江里的大虾 2012.08.30 04:27

posted on 2013-05-16 21:14  漓江里的大虾  阅读(547)  评论(1编辑  收藏  举报