[原创]植物大战僵尸修改器开发--逆向与应用-软件逆向-看雪-安全社区|安全招聘|kanxue.com
2025-1-17 09:59:0 Author: bbs.kanxue.com(查看原文) 阅读量:1 收藏

     1.1 工具

        ①植物大战僵尸原版 (英文名PlantsVsZombies, 简称PVZ)

        CheatEngine (CE)

        IDA

        ④VS

     1.2 基础

        ①C丶C++丶Asm丶逆向基础

        ②Win32开发基础

        ③ImGui基础

     2.1 阳光查找

        对于作弊小子而言, CE一定不陌生, 网上的CE入门教学基本都是拿PlantsVsZombies开刀。

而入门的第一课通常是找阳光, CE的基操此处不过多赘述, 因为目标是逆向。先找到阳光地址178D1028:

\

     2.2 CE+IDA分析数据来源

右键阳光地址查找访问, 可以看到有两处不断访问阳光地址, 分别是00489825和0041BAB5

选择00489825显示反汇编程序来到PlantsVsZombies.exe+89825 , mov eax,[esi+5560]这行代码在不断访问阳光

esi很明显就是对象的首地址(this), 5560 为阳光的偏移, 下断点后得知esi == 178CBAC8

使用CE和IDA动静态结合分析:

①CE在函数头下断点, 取出栈顶(esp)的返回地址(CE右下角的调用堆栈不可靠, 需要手动取)

②IDA跳到返回地址处, 往上找函数头, 将函数头复制到CE再下断点。重复操作, 查找this来源

从访问阳光处开始:

复制代码地址PlantsVsZombies.exe+89825(00489825)到IDA中, 往上找到函数头489630

复制函数头到CE跳过去下断点, 从ESP取出返回地址, 重复操作

回溯调用堆栈:

0041A21A

004172EC

0041AE38

反复操作的过程中, 在函数sub_41ACF0中看到一行有意思的代码

push offset aBoardDraw, 压入的字符串"Board::Draw"值得注意

如果玩过C++, 不难看出Board是一个类名/命名空间, 而Draw则是函数名

在VS中, 使用__FUNCTION__即可得到验证, 因此在sub_41ACF0中使用的

字符串, 极大概率是调试输出的函数信息。此处可以给sub_41ACF0命名为Board::Draw

搜索字符串Board, 可以看到还有个Board::Update

交叉引用过去, 该字符串引用自sub_415D40, 与Board::Draw一样, 大概率也是调试输出信息, 同样给它命名

在Board::Update处下断点, 得知ecx == 178CBAC8, 即上边找阳光时的this。

而this在寄存器ecx, 这符合thiscall调用约定, 即第一个参数在ecx

综上所述, 基本确定Board是一个类, 在Board的翻译中有"棋盘"的意思, 游戏的关卡形容成棋盘很贴切

    2.3 Board虚表

对着Board::Update下断点, 在调用处可以看到多态的操作

ecx是this, 而this来源自于esi, 上边的mov edx,[esi]是非常经典的取虚表操作

虚表为656CA8, 在IDA中跳过去, 可以看到Board::Update和Board::Draw都记录在其中, 这里将其命名为BoardVTable

在C++中, 构造填充虚表, 析构还原虚表。即构造和析构都涉及到虚表的引用

找到虚表, 定位构造和析构函数只是一个交叉引用的事情

对着BoardVTable交叉引用, 有两个函数引用了虚表, 分别是sub_407B50和sub_408690

sub_408690中调用了一堆free释放资源, 毫无疑问是析构, 另一个就是构造, 分别命名为Board::Ctor和Board::Dtor

在返回主菜单/关掉游戏后, 地址会变动, 用CE玩家的话讲, 这不是基址, 接下来需要找到基址

经过前边的折腾, 定位到了与Board类相关的函数, 接下来的逆向分析要简单的多

这里选择Board::Ctor进行分析, 因为创建对象时肯定要调用Board::Ctor

交叉引用可以看到熟悉的new, new完后返回的指针给了[edi+768]

在mov [edi+768],eax处下断点, 进入游戏关卡后会断下, 从而拿到this指针(edi == 02C79E60)

查看this对应的内存, 可以看到首地址处的两张虚表, 即00667BA0和00667D50(怎么看出的? 因为和BoardVTable挨的太近)

掏出00667BA0这张虚表, 到IDA里交叉引用, 轻松定位到构造和析构

sub_44EAA0为构造, sub_44EDF0为析构

在构造中可以看到一些初始化信息, 这个类的名称大概率和PlantsVsZombies有关, 这里姑且将类命名为PVZ

sub_44EAA0命名为PVZ::Ctor, sub_44EDF0命名为PVZ::Dtor

同样对着PVZ::Ctor交叉引用, 熟悉的名称映入眼帘, 是老朋友WinMain

在WinMain中, new PVZ之后, 将返回的指针储存在6A9EC0, 

6A9EC0这个地址常量相当于二级指针, 姑且命名为GPVZ

手动添加地址, 将逆向出来的数据添加到其中并保存, 以便后续分析

GPVZ = [6A9EC0]

Board = [GPVZ+768]

阳光 = [Board+5560]

扯了这么多, 总不能一直纸上谈兵, 该上代码意思一下了

此处仅仅是测试, 简单写个Dll注入到PVZ中改一下阳光

使用CE将Dll注入后, 进入关卡中阳光不断自增, 溢出7FFFFFFF后, 游戏应该做了处理, 负数都显示为0

这里的代码仅仅是测试, 在后边会使用ImGui结合逆向的内容进行修改器开发, 也会开源该项目

棋盘中有植物丶僵尸丶小推车等, 找到这些数据储存的位置, 我们便可以随意拿捏这些对象

对象在哪? 对象相关的数据哪个更好找? 毫无疑问, 对象的个数无疑是最合适的切入点

使用CE搜索植物个数, 植物增加+1, 铲除植物-1, 找到了两个结果, 分别为20FB88E8和20FB88EC

 

选中20FB88EC右键查找访问, 种植植物时41DEE7处的代码访问了该地址, esi是this

同样在函数头下断点, 查找this来源

在调用处可以看到, esi源于ebp+AC, 而ebp正是我们熟悉的Board

通过lea esi,[ebp+AC]这行指令, 得知Board+AC位置储存着植物对象相关信息

此时前边逆向工作带来的优势已逐步体现, 与植物对象相关的信息在Board中

对象的初始化工作, 肯定在Board::Ctor中, IDA跳到Board::Ctor

找到给偏移AC赋值的地方, 附近有着丰富的信息提示

根据字符串plants的提示, 猜测Board+AC指向的是植物对象的数组

使用CE的结构分析, 将Board的地址填入, 在偏移AC处展开

发现58处一直在减少, 当改成0时, 后边的向日葵立刻产生阳光

右键添加到地址列表, 改成0锁定, 向日葵发泄般的喷阳光

此时可以确定了对象数组信息都在Board中, 根据Board::Ctor中的信息, 将各种数组信息的位置逆向出来:

Board+90: zombies(僵尸)

Board+AC: plants(植物)

Board+C8: projectiles(子弹)

Board+E4: coins(货币)

[注意]APP应用上架合规检测服务,协助应用顺利上架!


文章来源: https://bbs.kanxue.com/thread-284929.htm
如有侵权请联系:admin#unsafe.sh