This blog post presents my solution to exercises 10 and 11 on page 78ff from the book Practical Reverse Engineering by Bruce Dang, Alexandre Gazet and Elias Bachaalany (ISBN: 1118787315). The book is my first contact with reverse engineering, so take my statements with a grain of salt. All code snippets are on GitHub. For an overview of my solutions consult this progress page.

Problem Statement

For the code in each exercise, do the following in order (whenever possible):</br> 1. Determine whether it is in Thumb or ARM state.</br> 2. Explain each instruction’s semantic. If the instruction is LDR/STR</br> explain the addressing mode as well., 3. Identify the types (width and signedness) for every possible object. For structures, recover field size, type, and friendly name whenever possible. Not all structure fields will be recoverable because the function may only access a few fields. For each type recovered, explain to yourself (or someone else) how you inferred it.</br> 4. Recover the function prototype.</br> 5. Identify the function prologue and epilogue.</br> 6. Explain what the function does and then write pseudo-code for it.</br> 7. Decompile the function back to C and give it a meaningful name.

ARM or Thumb

Instruction Semantic

The code uses BL and BLX to call subroutines. The latter – BLX – switches state from Thumb to ARM.

The instruction BCC branches on unsigned lower.

In instructions like LDR R3, [SP,#0x1C+var_1C] in line 15, the value var_1C comes from the disassembler and probably has the value -0x1C. So the instruction boils down to LDR R3, [SP,#0]

Types

The first function parameter in R0 is never read. The second function parameter in R1 is used to determine which calls to execute, it is an unsigned integer type (we know this because of the BCC comparisons). The third parameter in R3 points to a structure that holds the return values of the four system calls:

The function returns the number of bytes placed in the above structure.

Function Prototype

The function prototype is:

unsigned int mystery10(UNKNOWN, unsigned integer, struct1*);

Prologue and Epilogue

The prologue and epilogue save and restore all registers that the function modifies, except of course the first three registers that hold function parameters. The function returns by pushing/popping LR.

Purpose and Pseudo-code

The function calls up to four different API functions and stores their return value in a structure passed as the third function parameter. Depending on the value of the third function parameter, API calls are made or not:

Value of R1

Get SystemTime

Get CurrentProcessID

Get TickCount

Query PerformanceCounter

R1 ≥ 26

executed

executed

executed

executed

26 > R1 ≥ 18

executed

executed

executed

-

18 > R1 ≥ 14

executed

executed

-

-

14 > R1 ≥ 10

executed

-

-

-

10 > R1 ≥ 8

-

executed

executed

-

8 > R1 ≥ 4

-

executed

-

-

4 > R1 ≥ 0

-

-

-

-

The value of R1 is probably supposed to be between 26 (meaning all four API calls are made) and 10 (only GetSystemTime is executed. If R1 is less than 10, then the result values are placed at the wrong location in struct1. The four API calls are well documented:

GetSystemTime

Get the current system time and store it in the structure passed as the first function parameter, see MSDN. The structure is

Our code passes the stack pointer arg3 to GetSystemTime. In line 5 it created a 16 byte stack frame that can hold the 8 two byte values of SYSTEMTIME. The code then loads members at offset , 4, 8 and 12. The code uses LDR which loads 32 bits or two members of SYSTEMTIME. So the four LDR/STR pairs copy the entire structure to arg3.

GetCurrentProcessId

This API call takes no parameters and returns a DWORD with the process id, see MSDN. In line 40 the return value (the process id) is placed in the structure at arg3->dwProcessId (again, assuming that arg2 is not smaller than 10).

GetTickCount

Another easy function with no parameters that returns “the number of milliseconds that have elapsed since the system was started”, see MSDN. The return value is stored in arg3->dwTickCount.

QueryPerformanceCounter

The function takes “a pointer to a variable that receives the current performance-counter value, in counts” as the only parameter. The type of this parameter is LARGE_INTEGER, which has 8 bytes. The function stores those 8 bytes with two STR instructions in arg1->liPerformanceCounter.

Instruction Semantic

Types

The first function parameter arg1 in R0 is a pointer to a complicated structure. Let this structure be struct1. One can infer a couple of members of this structure from the different LDR instructions. I came up with the following picture, but again, since I couldn’t figure out what the function does the picture could be completely off:

The second parameter arg2 is pointer to a 32bit integer. The third parameter arg3 is only compared to zero and could be almost anything, e.g., a pointer, an integer or a boolean. The return value of mystery11 is an integer.

Function Prototype

The function prototype might look like this:

int mystery11(struct1*, int*, unknown*)

Prologue and Epilogue

The function preserves registers R3 to R11 with PUSH.W/POP.W instructions. It uses the same two instructions to store LR and to return.

Purpose and Pseudo-code

I have no clue what the function does. Most lines just access different members of the structure in arg1. The three instructions starting in line 22 are interesting:

They load two bytes from memory location R3, multiply the value of the first byte by 255 and add the second byte to the result. So this snippet is essentially loading a big-endian 16bit short. This could indicate that the function is operating on external data structure with big-endian shorts, like TCP/IP data.