这个游戏很火的,是单机、射击类游戏的经典,网上下载地址很多。。。
附个下载地址:
http://www.downza.cn/soft/21790.html
(我没试过,都差不多吧 )
运行游戏,CE附加进程
因为血量肯定是一定范围内的值,所以初始就搜索1-1000的值,每次收到攻击时,就搜索减少的值,未收到攻击时,就搜索未改变的值,最后定位到一个地址,然后搜索什么改写了这个地址:
00487769 - 8B 4D 0C - mov ecx,[ebp+0C]
0048776C - 57 - push edi
0048776D - 89 46 0C - mov [esi+0C],eax <<
00487770 - D8C9 - fmul st(0),st(1)
00487772 - 89 4E 10 - mov [esi+10],ecx
然后就分析一下eax这个地址怎么来的,需要静态分析了,上IDA:
可以看到eax来自函数的第一个参数,那就将这个函数命名为heart_blood,然后查看该函数的调用:
可以看到该函数的调用有6处之多,怎么定位是哪一处调用的函数heart_blood呢
比如在OD中可以在函数sub_455EF0处下条件记录断点,查看该处的函数第一个参数的值
依次使用上述方法,最后定位到hero_blood_1+105处是修改血量时调用,同时我们发现,因为游戏界面上最多只有8颗星,血量值是0x5 0x19 0x2d 0x41 0x55 0x69 0x7d 0x91这八个值之一
有意思的一点是,如果血量是满血就会发送0x5 0x19 0x2d 0x41 0x55 0x69 0x7d 0x91这八个参数,如果血量是四颗星,那么就会发送0x5 0x19 0x2d 0x41这四个参数,这不是很奇怪嘛
看一下hero_blood_1的部分伪代码:
可以看到英雄的血量就是*((_DWORD *)v1 + 5) + v2++ % 8 * (v12 + 5) ,其中有个%8就是灵感所在,可以猜想如下:如果满血的话 这里就会传入0x5 0x19 0x2d 0x41 0x55 0x69 0x7d 0x91 如果是7颗星就会传入0x5 0x19 0x2d 0x41 0x55 0x69 0x7d 如果是6颗星就会传入0x5 0x19 0x2d 0x41 0x55 0x69
而控制这一切的就是while循环的条件v2<v15,看上下文 每次进入函数 然后循环的时候v2从0开始递增,所以重点就是v15,猜测如下:如果是满血,那么v15应该就是8 如果7颗星那么v15就是7,以此类推
看一下v15怎么来的:
通过下断点测试,v15来自v9,并不是来自v10,而且v15确实像我们猜测的那样,当有6颗星时,v15就是6,依次类推
继续往上推倒 v9=v7,v7 = v6 / sub_4331A0((void *)v3) + 0.050000001; 通过调试发现sub_4331A0((void *)v3)=7 而且通过该函数操作 sp0=0.62500
伪代码可能不太准确,直接看汇编吧
通过这段代码可以看到,最终影响结果的是[ebp-0x18],如果满血的话[ebp-0x18]===5.0,这样fdivr后 sp0=8 当有七颗星时,[ebp-0x18]===4.375,这样fdivr(4.375/0.625)后 sp0=7,依次类推
重点是[ebp-0x18]怎么来的 通过
mov ecx, [esi+8]
mov eax, [ecx+18h]
mov edx, [eax+0F0h]
mov eax, [eax+0F4h]
mov [ebp+var_20], edx
mov [ebp+var_18], eax ; biggest is 5.000
可以看到[ebp-0x18]=[[[esi+8]+0x18]+0xf4] ,这样将改地址固定为5.000,就可以实现无敌效果了。