在 C/C++ 反汇编中识别可能的结构

逆向工程 反编译 C++ C 结构
2021-06-22 10:52:01

我目前正在分解游戏(灵魂掠夺者:凯恩的遗产),我经常在反编译器中遇到类似这样的奇怪部分

  *(_DWORD *)(a2 + 16) = a2 + 624;
  *(_DWORD *)(a2 + 38200) = a2 + 8;
  *(_DWORD *)(a2 + 20) = 0;
  *(_DWORD *)(a2 + 37592) = 0;
  *(_DWORD *)(a2 + 37596) = a2 + 36968;
  *(_DWORD *)(a1 + 8) = a2;
  *(_DWORD *)a1 = 0;
  *(_DWORD *)(a1 + 4) = 0;

这些在我看来是结构体中的偏移量,但有些偏移量没有意义,例如36968. 我知道这很难确定,但是非常感谢一些指向正确方向的指针:)

为那些想要它的人组装:)

.text:004B0126                   xor     esi, esi
.text:004B0128                   mov     [ecx+10h], eax
.text:004B012B                   lea     eax, [ecx+8]
.text:004B012E                   mov     [ecx+9538h], eax
.text:004B0134                   mov     eax, [esp+4+arg_0]
.text:004B0138                   lea     edx, [ecx+9068h]
.text:004B013E                   mov     [ecx+14h], esi
.text:004B0141                   mov     [ecx+92D8h], esi
.text:004B0147                   mov     [ecx+92DCh], edx
.text:004B014D                   mov     [eax+8], ecx
.text:004B0150                   mov     [eax], esi
.text:004B0152                   mov     [eax+4], esi
1个回答

内部有大数组或其他结构的结构或对象并没有什么奇怪的。另外我看到大部分大偏移量都是从ecx寄存器开始计算的,这符合__thiscall调用约定的Visual Studio变体的定义。所以我认为它只是大型结构或对象。此外 - IDA 中的结构不打算恢复原始结构,它们旨在在创建的代码中创建结构,所以如果它更好地组织结果代码 - 为什么不使用它呢?

无论如何,您可以检查分配此参数的内存来自哪里。如果你看到它是用 singlemallocnewoperator分配的,它应该是单个对象/结构或对象/结构数组。

(引自x86 调用约定 Wiki 文章

在 Microsoft Visual C++ 编译器上,this 指针在 ECX 中传递,它是清理堆栈的被调用者,反映了 C 中用于此编译器和 Windows API 函数的 stdcall 约定。当函数使用可变数量的参数时,调用者会清理堆栈(参见 cdecl)。thiscall 调用约定只能在 Microsoft Visual C++ 2005 及更高版本上明确指定。在任何其他编译器上 thiscall 都不是关键字。(但是,反汇编程序,例如 IDA,必须指定它。因此 IDA 为此使用关键字 __thiscall。)