Practical Reverse Engineering Exercise Solutions: ObFastDereferenceObject
First of all a quick reminder: This series of blog posts relates to exercises from the book Practical Reverse Engineering by Dang et al. Although it is called reverse engineering in general, it actually is mostly relevant to Microsoft Windows operating systems. This is simply due to the fact that Microsoft Windows is closed source in contrast to the Linux/Unix families, which means its source code is publicly available and so no reverse engineering endeavours are necessary.
Our next task is to decompile the ObFastDereferenceObject
routine, with special consideration to be paid to its calling convention.
The most common calling conventions for functions are:
- stdcall (arguments are pushed from right to left to the stack, the called function has to clean up the stack at the end of the routine)
- cdecl (arguments are pushed from right to left to the stack, the calling function has to clean up the stack at the end of the routine)
- fastcall (arguments are passed in registers ecx and/or edx first, the other arguments are pushed from right to the left onto the stack)
MSDN describes these and more conventions excellently: https://msdn.microsoft.com/en-us/library/984x0h58.aspx
Microsoft seems, however, not to have documented the function in question publicly. Yet, there is an unofficial resource at http://gate.upm.ro/os/LABs/Windows_OS_Internals_Curriculum_Resource_Kit-ACADEMIC/WindowsResearchKernel-WRK/WRK-v1.2/base/ntos/ob/fastref.c
It states:
|
|
We show the disassembly of the function of interest:
We notice two indicators that the function utilizes the fastcall convention: Firstly, the register value at edx is read without prior initialization. This means that arguments have been passed in these registers beforehand, thereby conforming to the fastcall convention. Secondly, the function name contains the keyword fast. Moreover, the last line of the routine specifies that 4 bytes are removed from the stack (ret 4
instruction). This means that one of the two function arguments is passed via the stack rather via a register value. A quick glimpse into the disassembly shows that the value from [ebp+8] is read at the beginning of part +0x21
. With fastcall, the first parameter(s) are passed in registers while the remaining ones are pushed on the stack. So we can infer that edx is the FastRef
variable, while Object
is saved at ebp+8
.
According to
https://www.nirsoft.net/kernel_struct/vista/EX_FAST_REF.html the PEX_FAST_REF
datatype is defined as follows:
|
|
Notice that this data structure is of type union. As I have learned C a couple of years ago and the type is not completely famililar to me any more, it is worthwhile to recapitulate its meaning. It basically allows to store multiple data types at the same memory location, so the meaning of the memory content varies depending on the referenced variable. While this can be memory-efficient, it is essential that the program always reads the variable that has been set for the last time, as it could otherwise contain invalid and potentially dangerous contents.
The Disassembly contains a somewhat peculiar function, namely lock cmpxchg dword ptr [edi],esi
.
According to its name, cmpxchg
seems to exchange something and its semantics are explained in detail at http://x86.renejeschke.de/html/file_module_x86_id_41.html.
Translating the instruction from above to C-pseudo code yields:
|
|
The LOCK
prefix means the instruction will be executed atomically and ensure that the processor has exclusive access to the memory region. It is thus a basic primitive for managing multi-processor / multi-threading environments and synchronization protocols. (see also http://x86.renejeschke.de/html/file_module_x86_id_159.html)
The first attempt to translate the function to C:
|
|