文章目录
- 前言
- 游戏选择与环境搭建
- 查找人物血量
- 查找血量基址
- 总结
前言 本系列文章旨在从零开始学习游戏辅助的工作流程和开发方法,了解游戏背后的攻防对抗手段,重点侧重数据和call的追踪查找。
侧重方向在于学习整个分析过程以及思路方法,最终实现的效果和游戏不是关心的重点。
涉及到的技术有:
- windows API Hook
- dll注入
- 汇编语言
- 软件逆向
- Windows编程
- C/C++基础
没有上述的前置知识建议劝退
游戏选择与环境搭建 这里用来进行分析的游戏是口袋西游,链接如下:
链接:https://pan.baidu.com/s/1nXUoK8UUEI3t3-hgAQ5pBg
提取码:e57t
复制这段内容后打开百度网盘手机App,操作更方便哦
下载以后直接解压缩,element文件夹中的ELEMENTCLIENT.EXE就是口袋西游主程序
选择这个游戏的好处在于,这个游戏是老版本的口袋西游,不会一直更新,难度也非常适合新手,方便进行调试学习。
在正式开始逆向之前建议先玩一段时间,熟悉一下游戏规则,后续操作起来会比较方便
查找人物血量 首先用CE附加游戏
001 从人物血量学习数据查找
直接搜索当前的人物血量值810
001 从人物血量学习数据查找
然后通过换装备的方式改变一下当前的人物血量,再次搜索,会得到两个值,一个是当前血量,一个是最大血量
001 从人物血量学习数据查找
区分的方式是通过再次换装然后观察数据变化进行分辨,或者直接在CE中修改数据
查找血量基址 接下来我们要通过这个地址把血量的基址追出来。
血量为零时角色会被判断死亡,血量不足最大值时会有一个回血的效果,而这些都会导致血量无时无刻被访问。
001 从人物血量学习数据查找
接着在当前地址右键,找出是什么访问了这个地址,可以看到这里有四条汇编语句在访问当前这个血量地址
008199FA - DB 87 88020000 - fild dword ptr [edi+00000288]
0055C062 - 8B 9E 88020000 - mov ebx,[esi+00000288]
00482A36 - 8B 8E 88020000 - mov ecx,[esi+00000288]
00482AA9 - 89 96 88020000 - mov [esi+00000288],edx
无论我们从哪条汇编开始追都能得到我们想要的基址,区别在于难度不一样。在学习阶段尽可能尝试所有的难度以应付后期的实战,这里先从第一条线开始追
第一条线(简单)008199FA - DB 87 88020000 - fild dword ptr [edi+00000288]
在这个地址下断
001 从人物血量学习数据查找
这里很快就能追到基址
- edi+0x288是血量
- edi来自于eax+0x28
- eax来自eax+0x1C
- eax=[0xD0DF1C]
最后得出血量基址公式为
血量=[[[0xD0DF1C+1C]+0x28]+0x288]
在CE里添加这个地址
001 从人物血量学习数据查找
数值显示和当前血量一致,说明基址正确
第二条线(一般)0055C062 - 8B 9E 88020000 - mov ebx,[esi+00000288]
在这个地址下断,让程序断下
001 从人物血量学习数据查找
用OD载入,直接在第一条汇编语句上面下断,这个时候esi+0x288的值是0x32A(810),也就是人物的当前血量。那么接着我们就要往上找这个esi来自于哪里。
001 从人物血量学习数据查找
借助OD的寄存器高亮插件一直往上翻,可以找到一条给esi赋值的语句,也就是说
而eax前面有一个call,所以可能是上面这个call的返回值,进入这个call
001 从人物血量学习数据查找
可以看到这个call内部进行了一些运算,从下往上进行逆推,我们很容易就能得出血量的基址为下面的值: 血量=[[[[0xD0DF1C]+0x1C]+0x28]+0x288]
这里的基址和第一条线是一致的,也没有问题。
第三条线(困难) 仔细观察,其实第三条线和第四条线其实是一个东西
00482A36 - 8B 8E 88020000 - mov ecx,[esi+00000288]
00482AA9 - 89 96 88020000 - mov [esi+00000288],edx
两个地址很近, [esi+00000288]来自edx,而ecx来自[esi+00000288],那么我们就继续往上追esi
在这个地址下断,让程序断下
001 从人物血量学习数据查找
esi+288就是当前的血量值,接下来往上追esi的来源
001 从人物血量学习数据查找
esi来源于ecx,继续到上层函数追ecx的值
001 从人物血量学习数据查找
而这层函数里并没有找到对ecx赋值的语句,所以继续找到上上层函数
001 从人物血量学习数据查找
这里ecx来自于eax,所以我们要进到这个call里面继续找eax
001 从人物血量学习数据查找
这里有两个对eax进行赋值的语句,倒推出来可以得出
血量=[[[ecx+0x8]+0x28]+288]
返回刚刚的位置,继续追ecx
001 从人物血量学习数据查找
这里ecx已经到了函数头,需要再往上找一层
001 从人物血量学习数据查找
这里ecx来自于[ebp+eax*4+0x1C],我们在这个地方下个断点,这里eax=0,那么ecx就等于[ebp+0x1C],血量地址如下:
血量=[[[[ebp+0x1C]+0x8]+0x28]+288]
继续找ebp的来源
001 从人物血量学习数据查找
这里ebp来自eax+0x8,血量地址就等于
血量=[[[[[eax+0x8]+0x1C]+0x8]+0x28]+288]
eax则来自于[ebx+0x4]
血量=[[[[[[ebx+0x4]+0x8]+0x1C]+0x8]+0x28]+288]
001 从人物血量学习数据查找
而ebx来自ecx,所以
血量=[[[[[[ecx+0x4]+0x8]+0x1C]+0x8]+0x28]+288]
这里已经到了函数头,继续返回上一层追ecx
001 从人物血量学习数据查找
这里下断 找到上层返回地址
001 从人物血量学习数据查找
ecx来自[edi+0x68],所以
血量=[[[[[[[edi+0x68]+0x4]+0x8]+0x1C]+0x8]+0x28]+288]
继续追edi
001 从人物血量学习数据查找
这里edi来自ecx,那么血量就等于
血量=[[[[[[[ecx+0x68]+0x4]+0x8]+0x1C]+0x8]+0x28]+288]
这个地方又到了函数头部,所以继续找到返回地址向上跟
001 从人物血量学习数据查找
这里ecx来自ebp,所以
血量=[[[[[[ebp+0x68]+0x4]+0x8]+0x1C]+0x8]+0x28]+288
继续找ebp
001 从人物血量学习数据查找
往上翻的时候这里会看到ebp来自[ebp+0x28],实际上我们在这下个断点,会发现这个地方根本断不下来,说明这条语句不被访问。
那么这个[ebp+0x28]就是无效的,继续往上找ebp来源
001 从人物血量学习数据查找
这里ebp来自于ecx,那么
血量=[[[[[[ecx+0x68]+0x4]+0x8]+0x1C]+0x8]+0x28]+288
001 从人物血量学习数据查找
这里也到也函数头,继续往上找ecx
001 从人物血量学习数据查找
返回上层我们发现ecx=[ebp+0x1C],下个断点,发现ebp的值是个基址,那么ecx就等于[00D11A50+0x1C]
血量=[[[[[[[00D11A50+0x1C]+0x68]+0x4]+0x8]+0x1C]+0x8]+0x28]+288
到这里整个第三条线的基址数据就追完了
001 从人物血量学习数据查找
在CE里添加这个基址,结果为810,正好是我们的人物血量
总结 在逆向分析数据的过程中会有很多条线路,无论是哪条都能追到我们想要的结果。区别在于有的是康庄大道,有的是荆棘丛生。
最后我们得出了一条经验:在实际分析过程中如果感觉数据查找比较困难,赶紧劝退,换另外一种方式,曲线救国。
https://github.com/TonyChen56/GameReverseNote
|