理解《逆向工程的秘密》中的逻辑飞跃

逆向工程 接口
2021-06-21 02:13:10

在“逆向工程的秘密”一书(Eldad Eilam 着)的第 5 章中,作者着手反转 NTDLL 库中未记录的“表”API 函数。他对一个特定函数的推理背后的逻辑让我很困扰。这是函数的相关部分:

RtlGetElementGenericTable:
7C9624E0        PUSH EBP
7C9624E1        MOV EBP, ESP
7C9624E3        MOV ECX, DWORD PTR [EBP+8]
7C9624E6        MOV EDX, DWORD PTR [ECX+14]
7C9624E9        MOV EAX, DWORD PTR [ECX+C]
7C9624EC        PUSH EBX
7C9624ED        PUSH ESI
7C9624EE        MOV ESI, DWORD PTR [ECX+10]
7C9624F1        PUSH EDI
7C9624F2        MOV EDI, DWORD PTR [EBP+C]
7C9624F5        CMP EDI, -1
7C9624F8        LEA EBX, DWORD PTR [EDI+1]
7C9624F8        JE SHORT 7C962559
7C9624FD        CMP EBX, EDX
7C9624FF        JA SHORT 7C962559
....
7C962554        ADD EAX, 0C
7C962557        JMP SHORT 7C96255B
7C962559        XOR EAX, EAX
7C96255B        POP EDI
7C96255C        POP ESI
7C96255D        POP EBX
7C96255E        POP EBP
7C96255F        RET 8

从其他一些“表”函数中,他推测表的结构一定是这样的:

struct Table {
    unknown_ptr    member1;    // This is non-zero when table has elements
    unknown_ptr    member2;
    unknown_ptr    member3;
    unknown_ptr    member4;
    unknown        member5;
    ulong          numberOfElements;
    unknown        member7;
    unknown        member8;
    unknown        member9;
    unknown        member10;
};

查看大跳跃前的最后10行(所以从7C9624EC到7C9624FF),他得出以下结论:

回想一下,EDX 是从结构中的偏移量 +14 加载的,这是存储表中元素总数的成员。这表明传递给 RtlGetElementGenericTable 的第二个参数是表中的索引。最后两条指令只是通过将它与元素总数进行比较来确认它是一个有效的索引。这也说明了索引增加的原因。这样做是为了正确比较两者,因为索引可能是从零开始的,而总元素数肯定不是。

正是这个结论,我无法理解,这种逻辑上的飞跃。我看不出第二个参数是如何成为表中的索引的。我只能看到代码块的最后两行转换为if (arg2+1 > numberOfElements) { return 0; }. 向后看它是有道理的(即对结论的确认),但向前看对我来说毫无意义(即从前提到结论)。第 7C9624FF 行的条件如何表明第二个参数必须是索引而不是其他东西?换句话说,作者是如何将证据拼凑成一个合乎逻辑的高级结论的?

0个回答
没有发现任何回复~