## Sunday, 30 July 2017

### Practical Reverse Engineering Exercise Solutions: Page 35 / Exercise 7

Exercise 7 on page 35:

Sample H. The function sub_10BB6 has a loop searching for something.
First recover the function prototype and then infer the types based on the
context. Hint: You should probably have a copy of the PE specifi cation
nearby.

Due to alignment issues, our routine is located at 10BB2 and has the following disassembly:

sub_10BB2:

mov     eax, [esp+4]
push    ebx
push    esi
mov     esi, [eax+3Ch]
movzx   eax, word ptr [esi+14h]
xor     ebx, ebx
cmp     [esi+6], bx
push    edi
lea     edi, [eax+esi+18h]
jbe     short loc_10BEB

loc_10BCE:
push    [esp+0Ch+arg_4]
push    edi
call    ds:dword_169A4
test    eax, eax
pop     ecx
pop     ecx
jz      short loc_10BF3
movzx   eax, word ptr [esi+6]
inc     ebx
cmp     ebx, eax
jb      short loc_10BCE

loc_10BEB:
xor     eax, eax

loc_10BED:
pop     edi
pop     esi
pop     ebx
retn    8

loc_10BF3:
mov     eax, edi
jmp     short loc_10BED

The PE file format and offsets have been described in detail here: http://www.sunshine2k.de/reversing/tuts/tut_pe.htm

Other useful sites are:

http://www.csn.ul.ie/~caolan/pub/winresdump/winresdump/doc/pefile2.html
https://github.com/corkami/pics/blob/master/binary/pe101/pe101.pdf
https://sourceforge.net/p/mingw/mingw-org-wsl/ci/master/tree/include/winnt.h

Firstly, we notice that the program contains the statement retn 8, which means it takes two arguments that are passed on the stack. Thus, its abstract prototype looks as follows:

sub_10BB2(param1, param2);

The first parameter seems to be a pointer that fetches a value from the offset 0x3C. Looking at the PE file format specification, we see the offset at 0x3C of the DOS header structure contains a pointer to the PE header structure. Therefore, we assume that param1 points to a DOS header file structure.

We refine the function prototype to:

Below, the disassembly including the provisional decompilation is provided:

mov     eax, [esp+4]   // function has first argument at esp+4, which means it is located on the stack
push    ebx
push    esi
xor     ebx, ebx // int countSections = 0;
push    edi      // save edi for later
data structure, i.e. the first section! SectionTable is located at offset(OptionalHeader) + SizeOfOptionalHeader
jbe     short loc_10BEB   // when we have no sections (countSections == numSections) , go to exit routine

loc_10BCE:
push    dword ptr [esp+14h]
push    edi
call    ds:dword_169A4 // dword_169A4(sectionTable, param2)
test    eax, eax // check if returned 0
pop     ecx // pop value from stack to ecx
pop     ecx // pop value from stack to ecx
jz      short loc_10BF3 // if eax == 0 , jump
add     edi, 28h // sectionTable += 0x28; // one section table has a size of 0x28 bytes (40 bytes)
inc     ebx // countSections += 1;
cmp     ebx, eax // if countSections < numSections goto loc_10BCE:
jb      short loc_10BCE

loc_10BEB:
xor     eax, eax // int* retVal = 0;

loc_10BED:
// clean up stack (stdcall convention)
pop     edi
pop     esi
pop     ebx
retn    8    // function has two parameters, 2 x 4 bytes

loc_10BF3:
mov     eax, edi // int* retVal = sectionTable;
jmp     short loc_10BED

Finally, we arrive at the following decompiled function:

int countSections = 0;

while (countSections < numSections) {
int retVal = dword_169A4(sectionTablePtr, param2); // call unknown function
if (retVal == 0) {
return sectionTablePtr;
}

sectionTablePtr += 0x28; // get the next sectionTable
countSections += 1; // set the number of processed sections
}