1

In Chapter 5 of the book "Secrets of Reverse Engineering" (by Eldad Eilam), the author goes about reversing an undocumented "table" API functions in the NTDLL library. The logic behind his reasoning in one particular function bothers me. Here is the relevant portions of the function:

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

From some other "table" functions, he surmises that the structure of the table must look like this:

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;
};

Looking at the last 10 lines before the big jump (so from 7C9624EC to 7C9624FF), he comes up with the following conclusion:

Recall that EDX was loaded from offset +14 in the structure, and that this is the member that stores the total number of elements in the table. This indicates that the second parameter passed to RtlGetElementGenericTable is an index into the table. These last two instructions simply confirm that it is a valid index by comparing it against the total number of elements. This also sheds some light on why the index was incremented. It was done in order to properly compare the two, because the index is probably zero-based, and the total element count is certainly not.

It is this conclusion that I fail to understand, this leap of logic. I fail to see how the second argument is an index into the table. All I can see is that the final two lines of the code chunk translate into if (arg2+1 > numberOfElements) { return 0; } . Looking at it backwards it makes sense (i.e. a confirmation of the conclusion), but looking at it forwards makes no sense to me (i.e. from premise to conclusion). How was simply that conditional on line 7C9624FF indicate that the second argument must be an index and not something else? In other words, how did the author piece the evidence together into a logical high-level conclusion?

1
  • it is an inference some argument is comparing itself with a structures member and a decision is made to either return NULL or execute the else clause one can also infer that the members value must be greater than the arguments value based on these inferences it is concluded that itmight indicate that second argument is an index you can call it middle,ring,small or thumb too it is like if (i > foo.totnum) {return 0;} else {do something}
    – blabb
    Jun 11 at 20:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.