前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >学习逆向知识之用于游戏外挂的实现.第二讲,快速寻找植物大战僵尸阳光基址.以及动态基址跟静态基址的区别

学习逆向知识之用于游戏外挂的实现.第二讲,快速寻找植物大战僵尸阳光基址.以及动态基址跟静态基址的区别

作者头像
IBinary
发布2018-08-30 17:18:29
3K2
发布2018-08-30 17:18:29
举报
文章被收录于专栏:逆向技术逆向技术

一丶静态基址. 动态基址. 基址的区别

 通过上一讲超级马里奥的游戏外挂技术制作.我们学习到了静态基址.以及观看内存区域得出相关偏移出的静态基址.

那么什么是静态基址.什么是动态基址. 什么是基址.

1.静态基址

  静态基址指的是.程序在启动后地址是不变的.游戏关闭后重新启动.那么地址也是不会变的.我们通过逆向技术直接对其修改那么则可以进行我们的外挂制作.

2.动态地址.

  动态地址是指当前地址保存了我们想要的属性信息. 但是当游戏重新打开.的时候.其当前地址的信息已经不是我们的信息了.所以我们要寻找基址.

3.基址

  基址指的就是最顶层的地址. 这个地址是不会改变的.除非游戏重新编译.或者增加减少成员.

二丶以植物大战僵尸为例.寻找当前动态地址.

植物大战僵尸这款游戏.相信我们大家都应该玩过.那么我们通过这款游戏.来学习 动态地址. + 基址的寻找方法. 

文字简介:  CE附加植物大战僵尸进程 -> 搜索阳光数量(精确数值 4字节搜索) -> 改变阳光数值 -> CE再次搜索改变之后的数值.

改变阳光数值.点击再次扫描.进行新的搜索.

通过在次扫描之后.我们得出一个地址.这个地址是一个动态地址. 怎么判断是否是动态地址.

1.我们首先修改这个地址里面的值. 看看是否能把阳光修改 (已经测试.可以修改.不截图说明了)

2.我们重新打开游戏.看看当前地址里面的值是否是我们阳光的值. (不是,已经测试)

经过上面两个步骤.我们可以得出.这个地址是一个动态地址.所以我们还要继续向上寻找.

三丶寻找基址.

  通过上面的地址我们知道这一个是一个动态的地址.那么我们需要找到基址应该怎么寻找?

思路: 如果找到一个动态地址.那么修改阳光肯定会修改这个地址这个地址里面的值. 所以我们可以下一个写入断点

1.我们可以用CE 下写入断电. 找出什么修改了这个地址

2.我们可以用OD / x32Dbg 下写入断点

上面两种方式都是可以完成的.

我们双击打开反汇编

可以看到里面的值是 add[eax + 0x5560],ecx

那么我们寻找到了一级偏移. 5560

那么这里涉及到偏移. 我们讲下原理吧.

其实很简单.植物大战僵尸编写的时候都是对象或者结构体成员.

例如:

代码语言:javascript
复制
struct Plant
{
   
    ......
    int sunNumber;  
}

而在汇编指令中则是 结构体到地址 + 偏移 得出 阳光的个数.

所以我们要继续寻找结构体首地址. 也就是谁保存了结构体首地址.所以根据上图汇编得出.我们需要继续寻找eax

继续寻找eax

CE 以16进制搜索eax的值

根据上图可以得出. 一个地址里面保存了结构体的值. 那么猜想这个可能就是结构体的首地址了.我们使用CE的手动添加地址添加我们的偏移看一下.

我们也不知道上面的地址那个是保存了结构体的地址. 不过CE一般都是前五个.当前也不一定.可以尝试一下.

根据上图我们可以得出 0299a4a0地址的内容是结构体首地址. 根据CE的手动添加指针.我们加上我们的偏移.可以得出阳光的地址.(对地址取内容则是阳光的值)

现在我们找的这个地址还是一个动态地址. 所以我们要找一下什么访问了这个地址为什么是访问? 因为要操作阳光.肯定会访问这个地址. 如果修改阳光则会修改这个阳光的值.

因为这个地址保存了结构体首地址.那么他肯定不会改写了.所以肯定会访问.所以我们找一下访问的地址.

 根据上图的值, 看汇编代码得出 mov esi[edi + 0x768] 访问了这个地址.

那么同理 [edi + 0x768]保存了结构体的地址. 那么edi 是一个新的结构体的地址. 而我们进行搜索的时候会发现其实这是一个结构体的嵌套.

例如:

代码语言:javascript
复制
struct aaa
{
    .......
    struct plant plant    //0x768
    {
        int SunNumber;  //0x5560
    }
}

所以我们要继续寻找edi是谁保存了.

继续寻找edi的值我们发现有几个绿色的值.一般遇到这个很有可能是基址了.

那么我们尝试一下.使用CE自带的手动添加地址.

确实是我们的地址.那么我们继续看谁访问.

发现我们地址都是这样了.汇编指令 mov reg,[常量地址]   那么则确定我们找到了我们的基址了.

原理:

  如果对基址不太熟悉.那么熟悉C++语法的大概能明白.

代码语言:javascript
复制
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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-08-21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一丶静态基址. 动态基址. 基址的区别
  • 二丶以植物大战僵尸为例.寻找当前动态地址.
    • 三丶寻找基址.
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档