001 从人物血量学习数据查找

前言

本系列文章旨在从零开始学习游戏辅助的工作流程和开发方法,了解游戏背后的攻防对抗手段,重点侧重数据和call的追踪查找。

侧重方向在于学习整个分析过程以及思路方法,最终实现的效果和游戏不是关心的重点。

涉及到的技术有:

  • windows API Hook
  • dll注入
  • 汇编语言
  • 软件逆向
  • Windows编程
  • C/C++基础

没有上述的前置知识建议劝退

游戏选择与环境搭建

这里用来进行分析的游戏是口袋西游,链接如下:

链接:https://pan.baidu.com/s/1nXUoK8UUEI3t3-hgAQ5pBg
提取码:e57t
复制这段内容后打开百度网盘手机App,操作更方便哦

下载以后直接解压缩,element文件夹中的ELEMENTCLIENT.EXE就是口袋西游主程序

选择这个游戏的好处在于,这个游戏是老版本的口袋西游,不会一直更新,难度也非常适合新手,方便进行调试学习。

在正式开始逆向之前建议先玩一段时间,熟悉一下游戏规则,后续操作起来会比较方便

查找人物血量

首先用CE附加游戏

在这里插入图片描述

直接搜索当前的人物血量值810
在这里插入图片描述

然后通过换装备的方式改变一下当前的人物血量,再次搜索,会得到两个值,一个是当前血量,一个是最大血量

在这里插入图片描述

区分的方式是通过再次换装然后观察数据变化进行分辨,或者直接在CE中修改数据

查找血量基址

接下来我们要通过这个地址把血量的基址追出来。

血量为零时角色会被判断死亡,血量不足最大值时会有一个回血的效果,而这些都会导致血量无时无刻被访问。
在这里插入图片描述

接着在当前地址右键,找出是什么访问了这个地址,可以看到这里有四条汇编语句在访问当前这个血量地址

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]

在这个地址下断

在这里插入图片描述

这里很快就能追到基址

  • edi+0x288是血量
  • edi来自于eax+0x28
  • eax来自eax+0x1C
  • eax=[0xD0DF1C]

最后得出血量基址公式为

血量=[[[0xD0DF1C+1C]+0x28]+0x288]

在CE里添加这个地址

在这里插入图片描述

数值显示和当前血量一致,说明基址正确

第二条线(一般)

0055C062 - 8B 9E 88020000  - mov ebx,[esi+00000288]

在这个地址下断,让程序断下

在这里插入图片描述

用OD载入,直接在第一条汇编语句上面下断,这个时候esi+0x288的值是0x32A(810),也就是人物的当前血量。那么接着我们就要往上找这个esi来自于哪里。

在这里插入图片描述

借助OD的寄存器高亮插件一直往上翻,可以找到一条给esi赋值的语句,也就是说

血量=[eax+0x288]

而eax前面有一个call,所以可能是上面这个call的返回值,进入这个call

在这里插入图片描述
可以看到这个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

在这个地址下断,让程序断下

在这里插入图片描述

esi+288就是当前的血量值,接下来往上追esi的来源

在这里插入图片描述

esi来源于ecx,继续到上层函数追ecx的值

在这里插入图片描述

而这层函数里并没有找到对ecx赋值的语句,所以继续找到上上层函数

在这里插入图片描述
这里ecx来自于eax,所以我们要进到这个call里面继续找eax

在这里插入图片描述

这里有两个对eax进行赋值的语句,倒推出来可以得出

血量=[[[ecx+0x8]+0x28]+288]

返回刚刚的位置,继续追ecx

在这里插入图片描述

这里ecx已经到了函数头,需要再往上找一层

在这里插入图片描述

这里ecx来自于[ebp+eax*4+0x1C],我们在这个地方下个断点,这里eax=0,那么ecx就等于[ebp+0x1C],血量地址如下:

血量=[[[[ebp+0x1C]+0x8]+0x28]+288]

继续找ebp的来源

在这里插入图片描述

这里ebp来自eax+0x8,血量地址就等于

血量=[[[[[eax+0x8]+0x1C]+0x8]+0x28]+288]

eax则来自于[ebx+0x4]

血量=[[[[[[ebx+0x4]+0x8]+0x1C]+0x8]+0x28]+288]

在这里插入图片描述

而ebx来自ecx,所以

血量=[[[[[[ecx+0x4]+0x8]+0x1C]+0x8]+0x28]+288]

这里已经到了函数头,继续返回上一层追ecx

在这里插入图片描述
这里下断 找到上层返回地址

在这里插入图片描述

ecx来自[edi+0x68],所以

血量=[[[[[[[edi+0x68]+0x4]+0x8]+0x1C]+0x8]+0x28]+288]

继续追edi

在这里插入图片描述

这里edi来自ecx,那么血量就等于

血量=[[[[[[[ecx+0x68]+0x4]+0x8]+0x1C]+0x8]+0x28]+288]

这个地方又到了函数头部,所以继续找到返回地址向上跟

在这里插入图片描述

这里ecx来自ebp,所以

血量=[[[[[[ebp+0x68]+0x4]+0x8]+0x1C]+0x8]+0x28]+288

继续找ebp

在这里插入图片描述

往上翻的时候这里会看到ebp来自[ebp+0x28],实际上我们在这下个断点,会发现这个地方根本断不下来,说明这条语句不被访问。

那么这个[ebp+0x28]就是无效的,继续往上找ebp来源

在这里插入图片描述

这里ebp来自于ecx,那么

血量=[[[[[[ecx+0x68]+0x4]+0x8]+0x1C]+0x8]+0x28]+288

在这里插入图片描述

这里也到也函数头,继续往上找ecx

在这里插入图片描述

返回上层我们发现ecx=[ebp+0x1C],下个断点,发现ebp的值是个基址,那么ecx就等于[00D11A50+0x1C]

血量=[[[[[[[00D11A50+0x1C]+0x68]+0x4]+0x8]+0x1C]+0x8]+0x28]+288

到这里整个第三条线的基址数据就追完了

在这里插入图片描述

在CE里添加这个基址,结果为810,正好是我们的人物血量

总结

在逆向分析数据的过程中会有很多条线路,无论是哪条都能追到我们想要的结果。区别在于有的是康庄大道,有的是荆棘丛生。

最后我们得出了一条经验:在实际分析过程中如果感觉数据查找比较困难,赶紧劝退,换另外一种方式,曲线救国。

https://github.com/TonyChen56/GameReverseNote

©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页