关于 LEA 的困惑以及为什么它在这种情况下意味着什么

逆向工程 拆卸 反编译
2021-06-21 21:06:25

我正在阅读 Eldad Eilam 的逆向工程书籍,并试图遵循他的 RtlInitializeGenericTable 示例。

它的第一部分相当简单——

7C921A39 MOV EDI,EDI
7C921A3B PUSH EBP
7C921A3C MOV EBP,ESP
7C921A3E MOV EAX,DWORD PTR SS:[EBP+8] ; eax = UnknownStruct->Member1
7C921A41 XOR EDX,EDX
7C921A43 LEA ECX,DWORD PTR DS:[EAX+4] ; ecx = UnknownStruct->Member2

7C921A46 MOV DWORD PTR DS:[EAX],EDX   ; UnknownStruct->Member1 = 0;
7C921A48 MOV DWORD PTR DS:[ECX+4],ECX ; UnknownStruct->Member3 = &UnknownStruct->Member2;
7C921A4B MOV DWORD PTR DS:[ECX],ECX   ; UnkownStruct->Member2  = &UnknownStruct->Member2;
7C921A4D MOV DWORD PTR DS:[EAX+C],ECX ; UnknownStruct->Member4 = &UnknownStruct->Member2;

我感到困惑的是第二部分:

7C921A50 MOV ECX,DWORD PTR SS:[EBP+C] ; ecx = UnknownStruct->Member2
7C921A53 MOV DWORD PTR DS:[EAX+18],ECX; UnknownStruct->Member7 = UnknownStruct->Member2;
7C921A56 MOV ECX,DWORD PTR SS:[EBP+10]; ecx = UnknownStruct->Member3
7C921A59 MOV DWORD PTR DS:[EAX+1C],ECX; UnknownStruct->Member8 = UnknownStruct->Member3; 

在这部分中,EBP 的偏移量用于访问变量并设置它们的值。然而,在他的 decompiled-c-equivalent 输出中,显示内存地址没有被用作初始化值,即

UnknownStruct->Member7 = UnknownStruct->Member2;

而在第一部分,它们是:

UnknownStruct->Member3 = &UnknownStruct->Member2;

为什么会这样?据我所知,这两个部分应该是相同的——第一个和第二个之间的唯一区别是 LEA 指令,但这应该只计算基指针的偏移量,与第二部分中所做的相同。

谢谢。

1个回答

如果 eax = 1000 ecx 在第一部分中将是 1004 uf ebp = 1000 ecx 在第二部分中将是 *(dword *) 100c

简单地放入伪c

ecx = foo 在第一部分是简单的赋值

ecx = * foo 在第二部分它是取消引用

注意两个注释中 &(addressof 运算符)的区别

在问题的功能有原型

NTSYSAPI VOID RtlInitializeGenericTable(
  PRTL_GENERIC_TABLE            Table,
  PRTL_GENERIC_COMPARE_ROUTINE  CompareRoutine,
  PRTL_GENERIC_ALLOCATE_ROUTINE AllocateRoutine,
  PRTL_GENERIC_FREE_ROUTINE     FreeRoutine,
  PVOID                         TableContext
);

所以调用那个函数的人会做这样的事情

rettype callingconv comp(...);  //prototype for actual function implemented elsewhere
rettype callingconv alloc(...);
rettype callingconv free(...);

RTL_GENERIC_TABLE mytable = {0}; 

RtlInitializeGenericTable(&mytable,comp,alloc,free,NULL);

所以[EBP + 8] FirstArgument到功能将持有MYTABLE的地址
即结构第一构件或通过设计地址
PRTL_SPLAY_LINKS TableRoot; 记录为 SystemReserved,
因此在其中填充 NULL (xor edx,edx, mov [eax],edx)

lea ecx 是 [eax+4] 的加载有效地址

所以 ecx 将被设计为地址 LIST_ENTRY InsertOrderList;

所以有ECX,ECX + 4,其指向弗林克眨眼的的LIST_ENTRY被初始化与ECX

eax + c RTL_GENERIC_TABLE 的第三个成员是

PLIST_ENTRY 有序指针; 也用 ecx 初始化