看了几个视频都发现就只会让你一级一级的找偏移而不是告诉你为什么CE不能直接搜索到一个数据的基址,为什么会有多级偏移,为什么通过多级偏移就能找到一个数据
所以这里就主要探究下原理
因为X64DBG内存断点是真的拉跨,这里还里还是OD了
为什么不能直接扫描到阳光数量的基地址?
静态地址(基址) 和 动态地址
话不多说CE开扫,改变阳光数量,得到本次进程阳光的动态地址0x12A473A0
CE中静态地址(或者说基址)以绿色字体显示,静态地址可以理解为全局变量或静态变量在内存空间中的地址,在一个程序编译时,就已经确定其在进程的内存中空间地址了,除非更改代码,静态地址在每次加载程序中都不会改变,学过PE结构的应该都知道,其值大多数都放在data段中。
12A473A0这个字体是黑色的,在CE中代表动态地址,可以理解成局部变量,是在栈里面的,每次加载程序地址是会改变,是不确定的,关于栈以及局部变量为什么地址是动态的可以看这篇文章C/C++的反汇编表示详解(1)函数调用,栈平衡,变量与参数的内存布局中的局部变量
所以在游戏逆向中的基址,不是指PE结构中程序载入基地址ImageBase,而是指一个结构或变量的静态地址,其可能是一个全局指针的地址,也有可能是一个全局变量的地址,还有可能是一个全局对象的首地址,只要其结构或变量是的地址是静态的,即可称为一个基址
因为阳光数是一个局部变量,其地址值是动态的,所以无法用CE直接找到其静态地址(基址)
但很明显,如果阳光数为一个局部变量是不可取的,因为其重要性必定会在程序的许多代码段中都会被调用
既然如此那肯定有个全局的数据类型可以找到阳光这个局部变量的值,那这就肯定是一个全局指针啦
多级指针 和 多级偏移
这里我们写个Demo来模拟一下怎么通过一个全局指针来找到局部变量阳光的值
#include <stdio.h>
/*僵尸类 里面有僵尸的各类属性*/
class Zombies{
public:
int type;
int hP;
};
/*植物类里面包含有阳光值这个属性*/
class Plant{
public:
int type;
int hp;
int sun;//模拟的阳光值
};
/*一个集合类 里面包含了指向各类的指针*/
class Game{
public:
Zombies* pZombies;
Plant* pPlant;
};
/*一个全局执政game 指向一个全局对象Game */
Game* game=new Game;
int main()
{
/*
对象Plant是动态new出来的 但game其地址是确定的
*/
game->pPlant