矛与盾基址

1.  基址的概念

       基址是什么? 从C++内存模型上来讲, 基址就是一个全局变量, 也就是第一次申明的类的地址。比如有一个类

1 class test
2 {
3 test();
4 ~test();
5
6 private:
7 char* name_;
8 int hp_;
9 int mp_;
10 role* role_;
11 }

    C++的内存模型是这样的。在new test()的时候, 其对象的地址为 this(比如:0x0040320),那成员变量 name的地址为this(因为没有虚函数列表),hp_的地址为this+0x4, mp_的地址为this+0x8, role_的地址就为this+oxC;有比如有如下代码:

1 struct role
2 {
3 string name;
4 int hp;
5 int mp;
6 };
7
8  class game
9 {
10  public:
11
12 game()
13 {
14 role_ = new role;
15 role_->hp = 100;
16 role_->mp = 50;
17 role_->name = "hello";
18 }
19 ~game()
20 {
21 if (role_)
22 {
23 delete role_;
24 role_ = 0;
25 }
26 }
27
28 void start();
29
30 private:
31 role* role_;
32
33 };
34
35 int _tmain(int argc, _TCHAR* argv[])
36 {
37
38 game* myGame = new game();
39
40
41 cout<<"hello world"<<endl;
42 return 0;
43 }
      我们要读写role::hp的时候, 我们必定要知道 game::role_, 从而必定得知道 game对象的地址。 如果 在 game* myGame = new game();  中, myGame是一个全局变量的话, 其就是所谓的基址了(base_addr).我们最终血(hp)的地址则为: [base_addr+0]+sizeof(string)。    当然如上的例子中,只有一级偏移, 如果多套嵌几个类就会有几次偏移了。

  2. 某游戏例子

    逆向分析都是从数据开始的, 所以我们要找基址的时候就从人物的血、蓝入手,分析出基址。这里以某游戏为列子。

    1. 用CE 查找数据。

           image

    2. 然后用OD 看谁写入了这个地址。

image

        3. 下硬件断点,看谁往这块内存写东西了。发现是这里:

10A8E9DB    4A              DEC EDX
10A8E9DC    23C2            AND EAX,EDX
10A8E9DE    8941 0C         MOV DWORD PTR DS:[ECX+C],EAX
10A8E9E1    83C4 14         ADD ESP,14
10A8E9E4    C2 0400         RETN 4

看到代码: MOV DWORD PTR DS:[ECX+C],EAX , 就是往[ecx+c]地址写入血值。

4. 继续看ecx 的值是哪里来的的。此时ecx= 0x091ed200, 用ce 搜索这个值。

image

       5. 取出一个值(0x0aa3e9a8), 看谁访问了这块地址。

image

        这里就可以看出基址为[110F7B58],当前血的地址为[[110F7B58]+0x7F0]+0x0C

原文地址:https://www.cnblogs.com/sld666666/p/2047133.html