通过游戏外挂,学习逆向技术之快速寻找植物大战僵尸阳光基址.以及动态基址跟静态基址的区别
一丶静态基址. 动态基址. 基址的区别
通过上一讲超级马里奥的游戏外挂技术制作.我们学习到了静态基址.以及观看内存区域得出相关偏移出的静态基址.
那么什么是静态基址.什么是动态基址. 什么是基址.
1.静态基址
静态基址指的是.程序在启动后地址是不变的.游戏关闭后重新启动.那么地址也是不会变的.我们通过逆向技术直接对其修改那么则可以进行我们的外挂制作.
2.动态地址.
动态地址是指当前地址保存了我们想要的属性信息. 但是当游戏重新打开.的时候.其当前地址的信息已经不是我们的信息了.所以我们要寻找基址.
3.基址
基址指的就是最顶层的地址. 这个地址是不会改变的.除非游戏重新编译.或者增加减少成员.
二丶以植物大战僵尸为例.寻找当前动态地址.
植物大战僵尸这款游戏.相信我们大家都应该玩过.那么我们通过这款游戏.来学习 动态地址. + 基址的寻找方法.
文字简介: CE附加植物大战僵尸进程 -> 搜索阳光数量(精确数值 4字节搜索) -> 改变阳光数值 -> CE再次搜索改变之后的数值.
改变阳光数值.点击再次扫描.进行新的搜索.
通过在次扫描之后.我们得出一个地址.这个地址是一个动态地址. 怎么判断是否是动态地址.
1.我们首先修改这个地址里面的值. 看看是否能把阳光修改 (已经测试.可以修改.不截图说明了)
2.我们重新打开游戏.看看当前地址里面的值是否是我们阳光的值. (不是,已经测试)
经过上面两个步骤.我们可以得出.这个地址是一个动态地址.所以我们还要继续向上寻找.
三丶寻找基址.
通过上面的地址我们知道这一个是一个动态的地址.那么我们需要找到基址应该怎么寻找?
思路: 如果找到一个动态地址.那么修改阳光肯定会修改这个地址这个地址里面的值. 所以我们可以下一个写入断点
1.我们可以用CE 下写入断电. 找出什么修改了这个地址
2.我们可以用OD / x32Dbg 下写入断点
上面两种方式都是可以完成的.
我们双击打开反汇编
可以看到里面的值是 add[eax + 0x5560],ecx
那么我们寻找到了一级偏移. 5560
那么这里涉及到偏移. 我们讲下原理吧.
其实很简单.植物大战僵尸编写的时候都是对象或者结构体成员.
例如:
struct Plant { ...... int sunNumber; }
而在汇编指令中则是 结构体到地址 + 偏移 得出 阳光的个数.
所以我们要继续寻找结构体首地址. 也就是谁保存了结构体首地址.所以根据上图汇编得出.我们需要继续寻找eax
继续寻找eax
CE 以16进制搜索eax的值
根据上图可以得出. 一个地址里面保存了结构体的值. 那么猜想这个可能就是结构体的首地址了.我们使用CE的手动添加地址添加我们的偏移看一下.
我们也不知道上面的地址那个是保存了结构体的地址. 不过CE一般都是前五个.当前也不一定.可以尝试一下.
根据上图我们可以得出 0299a4a0地址的内容是结构体首地址. 根据CE的手动添加指针.我们加上我们的偏移.可以得出阳光的地址.(对地址取内容则是阳光的值)
现在我们找的这个地址还是一个动态地址. 所以我们要找一下什么访问了这个地址为什么是访问? 因为要操作阳光.肯定会访问这个地址. 如果修改阳光则会修改这个阳光的值.
因为这个地址保存了结构体首地址.那么他肯定不会改写了.所以肯定会访问.所以我们找一下访问的地址.
根据上图的值, 看汇编代码得出 mov esi[edi + 0x768] 访问了这个地址.
那么同理 [edi + 0x768]保存了结构体的地址. 那么edi 是一个新的结构体的地址. 而我们进行搜索的时候会发现其实这是一个结构体的嵌套.
例如:
struct aaa { ....... struct plant plant //0x768 { int SunNumber; //0x5560 } }
所以我们要继续寻找edi是谁保存了.
继续寻找edi的值我们发现有几个绿色的值.一般遇到这个很有可能是基址了.
那么我们尝试一下.使用CE自带的手动添加地址.
确实是我们的地址.那么我们继续看谁访问.
发现我们地址都是这样了.汇编指令 mov reg,[常量地址] 那么则确定我们找到了我们的基址了.
原理:
如果对基址不太熟悉.那么熟悉C++语法的大概能明白.
struct aaa { struct plant { int SunNumber; } } aaa *p= new aaa; new aaa 是我们的结构体首地址 new aaa + 768 = plant结构体的首地址 new aaa + 768 + 5560 = 阳光个数的地址 那么我们知道 new aaa是一个无名对象.所以肯定有一个变量保存着. 所以 *p 这个变量就是我们寻找的基址. p + 768 + 5560 = 阳光个数地址 *(p + 768 + 5560 ) = 阳光个数. 所以我们找的基址就是p的地址. 而p保存的就是 new aaa的地址 new aaa中保存了 plant结构体的地址.
如果不理解也可以滤过. 熟悉我们的寻找方法即可.
通过上面我们的汇编指令.
add [reg + 0x5560],ecx 注意reg代表是任何寄存器. add指令在汇编中是增加的意思. []的意思是对这个地址的内容进行操作
上面的汇编指令的意思是: 对 reg + 5560 的这个地址进行操作.因为带有中括号.[] 所以意思是对reg + 5560这个地址里面的值进行操作.
mov reg,[reg + 0x768]. 内容同上. mov 指令是传送指令. 也就是将这个地址里面的值辅赋值给左操作数.
[[[6A9EC0] + 0x768] + 0x5560] = 阳光的地址.
所以我们可以写程序来实现增加阳光跟减少阳光了
C++ : 学习OpenProcess WriteProcessMemory //注意: 在调用OpenProcess获得进程句柄前.需要获得进程PID. 可以通过FindWindow 查找窗口句柄.然后通过GetWindowsThreadProcessID() 通过窗口句柄获取进程pID. 当前也可以通过 进程快照.遍历进程.得出进程PID.都是可以的.具体不在累赘.
易语言: 因为使用了超级模块所以 熟悉 取进程ID 十六到十 写内存整数型即可.
因为易语言实现简单.所以直接使用易语言写一个了.
总结:
通过这一讲.我们学习了 add 汇编指令. mov 汇编指令. 以及结构体在汇编中表现的形式. 例如 [reg + 5560] 这样的其实是结构体偏移.
学会了如果通过动态地址寻找基址.
课堂资料下载: 链接:https://pan.baidu.com/s/1DDWfx68wi37Dc2OV2aTpqQ 密码:3w2x