<-- Home

东方风神录逆向

简单逆向这个游戏要选一个入口点,不然没法断点调试,为了找到突破口,我先用了Cheat Engine来进行预分析。

首先是获取人物的坐标,我不断移动改变自机的坐标,在CE中寻找变动的值,最后锁定了44个结果。

这44个值无论我怎么移动都没法再少了,猜测部分值应该是上几帧计算后留下来的,有的数是浮点数,有的是4字节整数,那如何找到准确的那一个值呢?我有一个大胆的想法,自机重生的时候会更新坐标值,这个值应该有特殊之处。然后我送了一命(灵梦,对不起)。复活之后果然出现了特殊的数值。

40000应该就是自机重生后的Y坐标了,居然有两个,然后看看剩下的浮点数。

第二个浮点数是400!这个值大有研究价值。

来监视一下这个地址的改变

找到了一个入口,可以在0x004254C2处下断调试了。

游戏在断点处停了下来,根据汇编代码,其含义是把一个浮点数写入这个地址,而这个浮点数是通过ds:[edi+0x3D0]得到的,而这个ds:[edi+0x3D0]的地址值是01BAEE70也就是那两个存储40000的地址之一,也就是说它把40000转化成400.0f,那么这两个值都是自机的Y坐标,而edi可能就是存储玩家信息的地址。

为了偷懒,直接用CE搜索edi的值,发现了一个绿色的值0x00477834,该值就是玩家的基地址啦。分析附近的代码找到了ds:[edi+0x3C0]ds:[edi+0x3CC],分别是玩家X坐标的浮点数和4字节整数表示形式。那么玩家的X、Y坐标可以表示为(float)*(*((int *)0x00477834) + 3C0)(float)*(*((int *)0x00477834) + 3C4)啦。

为了找到敌人和子弹的坐标,我们需要知道游戏在什么地方调用了碰撞检测函数,游戏必定会将自机的数据和敌人数据作为参数传给碰撞检测函数。继续使用CE,看看是什么访问了存玩家Y坐标值的地址。这一监视发现有很多地方访问了该地址。

碰撞检测函数应该是在游戏开始后每一帧都要被调用的,暂停游戏就不会调用。第一条指令在我按了暂停之后仍被执行,说明与碰撞检查无关。第二条是fstp指令,只是改写玩家Y坐标的值,暂不考虑。在第三条指令0x00425F1A处下断点,分析其附近的代码。

我们可以知道,玩家Y坐标的值与一个数做了减法,最后写到了ds:[eax+0x4]中了,而eax是多少呢,前面一个lea指令可知,是ebp+0x404。这个地址十分可疑,碰撞检测的运算应该要考虑玩家的碰撞范围,猜测该值会参与碰撞检测的运算,于是使用CE监视该地址。

除了之前分析过的指令,还有两条指令访问了该地址,用OD一看,发现两条指令位于同一个函数里面。而且指令是fcomp浮点数比较指令,猜测该函数为碰撞检测函数。

为了测试该函数的功能,我把其代码改成直接return,看看游戏中出现什么效果。

之后游戏里面的表现如下

没错,老夫无敌了。

既然确定了碰撞检测函数,那么我们的工作就很轻松啦,碰撞检测函数里面会出现敌方单位的坐标和判定范围,我们只需要逆向找到传递给该函数的值即可。

调用来至0x0040649C0x0040E2DF,猜测分别是检测敌机和敌弹的,分析参数值来源,结合CE等工具,果然找到了敌机和敌弹的基址,分别为0x004777040x004776F00x0047781C

结合基址,分析汇编代码可以获得所有的位置信息。

然后用ReadProcessMemory函数将这些值读取出来,开一个画图线程,将读取的数据绘制出来