是否可以使用反汇编器找到静态指针?

逆向工程 拆卸 调试器 指针
2021-06-14 09:53:45

我找到了一个汇编指令:mov [esi+2F],dl. 我认为 ESI 是对结构或类的引用。0x2F是引用结构/类的属性的偏移量。是否可以找到 ESI 寄存器的值?我认为这个类或结构是在游戏开始时初始化的。

例如,我试图逆转 GTA 圣安地列斯。很多GTA SA的内存地址的位置

我在这个网站上找到了这样的信息:0xB6F5F0 - Player pointer (CPed)。

我想这是我现在找到的地址。但是我如何在没有指针扫描的情况下使用像作弊引擎这样的调试器找到它?我想在汇编代码中找到地址。这是可能的?

我试图为指令设置断点。但我认为它没有用,因为 ESI 地址是动态的。据我了解,CPed struct/class 使用动态内存分配。

我很抱歉我的英语不好,并提前致谢。

1个回答

对的,这是可能的

我将向您解释一下大多数游戏是如何做到的(我从未逆转过任何 GTA,但我想无论如何都是这样的)。

我将介绍结构的静态和动态分配。


静态方式:

GlobalGameInfo g_info;
// ...
g_info.some_data = 1;

这就是 IDA 中的静态偏移量,如下所示:

lea eax, [g_info + 0xAABB] ; suppose 0xAABB is the offset for 'some_data'
mov [eax], 1;

g_info总是会保持相同的偏移量,因此一旦找到它,您就可以使用它g_info + offset来获取数据。

动态方式:

Player* players; // can be defined as Player* players[<count>] or Player** players;
                 // it's the same
// ...
players = new Player[players_count];
// ...
players[1].alive = false;

然后导致:

; this is a static location which is actually the "players" variable
; and it contains an address which points to the offset in memory of the
; actual players structure
dword_xxxx dd ?

因此,要在 Cheat Engine 中使用它,您Add a new address,检查Pointer,添加 的xxxx部分dword_xxxx,然后在偏移量中放置所需的偏移量。例如,要获取players[1].alivealive在偏移量(例如 0x100)上,您需要计算:

value_stored_in_dword_xxxx + sizeof(Player) * player_id + 0x100

因此,如果dword_xxxx-> 0xAABBCCDDsizeof(Player)-> 0x204player_id->8offset-> 0x100,您的计算将是:

0xAABBCCDD + (0x204 * 8) + 0x100
// ^base      ^size   ^id  ^offset

这个例子

既然你给了我们mov [esi + 0x2F], dl

  • esi是指向结构的指针。看上面(在拆卸中)。
    • mov esi, dword ptr [dword_xxxx] (最有可能)意味着它正在取消引用一个指针,这意味着该结构是动态分配的。
    • mov esi, offset dword_xxxx(最有可能)意味着它只是将地址(xxxx部分)分配esi,所以这是一个静态地址。

用法

作弊引擎

在作弊引擎中,输入指针和偏移量很容易:

作弊引擎

如您所见,0x5CCB138dword_xxxx,里面的值dword_xxxx0x09021A00,+ 0x142(我的偏移量)导致游戏内名称的开头。

C

如果您想以编程方式执行此操作,您可以在 C 中这样做:

PCHAR my_name = PCHAR (*PDWORD(0x5CCB138) + 0x142);
^save the addr|       | ^deref to get     | add the offset
              | ^cast |    0x09021A00     |

// -> be careful, do not surpass the max length!
// -> also remember that there's 'your name' length + 1 \x00 byte
//    at the end!
char new_name[] = "newName";
strncpy(my_name, new_name, sizeof(new_name)); // again: be careful with the length!

然而,正确的方法是像这样反转整个结构:

struct player_data {
    int ID;
    char name[15];
    int some_data;
    ...;
};
// make sure the order / size of each item is correct!
// a single error can fuck up the entire struct

// I'm going to assume you understand pointers
player_data* data = *(player_data**) 0x5CCB138;

// do your changes
// again, be careful with the length!
// also note that sizeof() will not work if you use char*
char new_name[] = "new name!";
strncpy(data->name, new_name, sizeof(new_name));