Practical Reverse Engineering Solutions – Page 123 (Part I)
my go at exercise 1 on pages 123ff- Problem Statement
- Solutions
- ► CcAllocateInitializeMbcb
- ► CmpInitCallbacks
- ► ExCreateCallback
- ► ExpInitSystemPhase0
- ► ExpInitSystemPhase1
- ► ExpTimerInitialization
- ► InitBootProcessor
- ► IoCreateDevice
- ► IoInitializeIrp
- ► KeInitThread
- ► KeInitializeMutex
- ► KeInitializeProcess
- ► KeInitializeTimerEx
- ► KeInitializeTimerTable
- ► KiInitializeProcessor
- ► KiInitializeThread
- ► MiInitializeLoadedModuleList
- ► MiInitializePrefetchHead
- ► PspAllocateProcess
- ► PspAllocateThread
This blog post presents my solution to exercise 1 on page 123 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
problem statement
On Windows 8 x64, the following kernel functions have InitalizeListHead
inlined at least once: CcAllocateInitializeMbcb
, CmpInitCallbacks
, ExCreateCallback
, ExpInitSystemPhase0
, ExpInitSystemPhase1
, ExpTimerInitialization
, InitBootProcessor
, IoCreateDevice
, IoInitializeIrp
, KeInitThread
, KeInitializeMutex
, KeInitializeProcess
, KeInitializeTimerEx
, KeInitializeTimerTable
, KiInitializeProcessor
, KiInitializeThread
, MiInitializeLoadedModuleList
, MiInitializePrefetchHead
, PspAllocateProcess
, PspAllocateThread
. Identify where InitializeListHead
is inlined in these routines.
Solutions
To save space I’m removing the raw instruction in hex. I’m also not showing the upper 32 bits of the addresses which are fffff800
for all kernel routines in this exercise.
► CcAllocateInitializeMbcb
InitializeListHead
is inlined here:
`11d632ef lea rax,[rbx+10h] `11d632f3 lea rcx,[rbx+30h] `11d632f7 mov r11d,2FBh `11d632fd mov word ptr [rbx],r11w `11d63301 mov qword ptr [rax+8],rax `11d63305 mov qword ptr [rax],rax
Rbx
points to memory allocated with ExAllocatePoolWithTag
:
`11d632d2 call nt!ExAllocatePoolWithTag (fffff800`11ee8010) `11d632d7 mov rbx,rax
Because the kernel function is named CcAllocateInitializeMbcb
, the memory is probably for an _MBCB
structure:
nt!_MBCB +0x000 NodeTypeCode : Int2B +0x002 NodeIsInZone : Int2B +0x004 PagesToWrite : Uint4B +0x008 DirtyPages : Uint4B +0x00c Reserved : Uint4B +0x010 BitmapRanges : _LIST_ENTRY +0x020 ResumeWritePage : Int8B +0x028 MostRecentlyDirtiedPage : Int8B +0x030 BitmapRange1 : _BITMAP_RANGE +0x060 BitmapRange2 : _BITMAP_RANGE +0x090 BitmapRange3 : _BITMAP_RANGE
Our snippet accesses the member at offset 10h
, which is BitmapRanges
of type _LIST_ENTRY
.
► CmpInitCallbacks
InitializeListHead
is inlined here:
`12165566 lea rax,[nt!CallbackListHead (fffff800`11f5fb80)] `1216556d lea rdx,[nt!`string' (fffff800`11cf31e8)] `12165574 mov dword ptr [nt!CmpCallBackCount (fffff800`11ef9d30)],ecx `1216557a mov qword ptr [nt!CmpCallbackListLock (fffff800`11f5fb70)],rcx `12165581 mov qword ptr [nt!CmpContextListLock (fffff800`11f5fb78)],rcx `12165588 mov qword ptr [nt!CallbackListDeleteEvent (fffff800`11f5fb90)],rcx `1216558f lea rcx,[nt!CmLegacyAltitude (fffff800`11ef9d50)] `12165596 mov qword ptr [nt!CallbackListHead+0x8 (fffff800`11f5fb88)],rax `1216559d mov qword ptr [nt!CallbackListHead (fffff800`11f5fb80)],rax
The first member of the kernel variable CallbackListHead
is indeed a list head:
kd> x nt!CallBackListHead 81b4a8b0 nt!CallbackListHead = <no type information> kd> dt nt!_ERESOURCE 0x81b4a8b0 +0x000 SystemResourcesList : _LIST_ENTRY [ 0x81b4a8b0 - 0x81b4a8b0 ] +0x008 OwnerTable : (null) +0x00c ActiveCount : 0n0 +0x00e Flag : 0 +0x010 SharedWaiters : (null) +0x014 ExclusiveWaiters : (null) +0x018 OwnerEntry : _OWNER_ENTRY +0x020 ActiveEntries : 0 +0x024 ContentionCount : 0 +0x028 NumberOfSharedWaiters : 0 +0x02c NumberOfExclusiveWaiters : 0 +0x030 Address : 0xbee0bee0 Void +0x030 CreatorBackTraceIndex : 0xbee0bee0 +0x034 SpinLock : 0x81b4e36c
► ExCreateCallback
InitializeListHead
is inlined here:
`12138031 lea rax,[rcx+10h] `12138035 mov byte ptr [rcx+20h],r14b `12138039 mov qword ptr [rax+8],rax `1213803d mov qword ptr [rax],rax
► ExpInitSystemPhase0
InitializeListHead
is inlined four times. The first occurrence is:
`12344161 lea rax,[nt!ExpSystemResourcesList (fffff800`11f09b20)] `12344168 lea rcx,[nt!ExpEnvironmentLock+0x18 (fffff800`11f09a78)] `1234416f lea edx,[rbx+1] `12344172 xor r8d,r8d `12344175 mov qword ptr [nt!ExpTimeout (fffff800`11f09b18)],0FFFFFFFFFD9DA600h `12344180 mov qword ptr [nt!ExpSystemResourcesList+0x8 (fffff800`11f09b28)],rax `12344187 mov qword ptr [nt!ExpSystemResourcesList (fffff800`11f09b20)],rax
A second occurrence of InitializeListHead
is here:
`123441aa lea rax,[nt!ExPagedLookasideListHead (fffff800`11f09ab0)] `123441b1 lea rdx,[nt!ExNPagedLookasideListHead (fffff800`11f09aa0)] `123441b8 lea rcx,[nt!ExpFirmwareTableResource (fffff800`11f09b40)] `123441bf mov qword ptr [nt!ExPagedLookasideListHead+0x8 (fffff800`11f09ab8)],rax `123441c6 mov qword ptr [nt!ExPagedLookasideListHead (fffff800`11f09ab0)],rax
Right after ExPagedLookasideListHead
is initialized, there’s a third occurrence of InitializeListHead
:
`123441b1 lea rdx,[nt!ExNPagedLookasideListHead (fffff800`11f09aa0)] `123441b8 lea rcx,[nt!ExpFirmwareTableResource (fffff800`11f09b40)] `123441bf mov qword ptr [nt!ExPagedLookasideListHead+0x8 (fffff800`11f09ab8)],rax `123441c6 mov qword ptr [nt!ExPagedLookasideListHead (fffff800`11f09ab0)],rax `123441cd lea rax,[nt!ExpFirmwareTableProviderListHead (fffff800`11f09bb0)] `123441d4 mov qword ptr [nt!ExNPagedLookasideListHead+0x8 (fffff800`11f09aa8)],rdx `123441db mov qword ptr [nt!ExNPagedLookasideListHead (fffff800`11f09aa0)],rdx
The function InitializeListHead
is used a fourth time to initialize ExpFirmwareTableProviderListHead
:
`123441cd lea rax,[nt!ExpFirmwareTableProviderListHead (fffff800`11f09bb0)] `123441d4 mov qword ptr [nt!ExNPagedLookasideListHead+0x8 (fffff800`11f09aa8)],rdx `123441db mov qword ptr [nt!ExNPagedLookasideListHead (fffff800`11f09aa0)],rdx `123441e2 mov qword ptr [nt!ExNPagedLookasideLock (fffff800`11f09ac0)],rbx `123441e9 mov qword ptr [nt!ExpFirmwareTableProviderListHead+0x8 (fffff800`11f09bb8)],rax `123441f0 mov qword ptr [nt!ExpFirmwareTableProviderListHead (fffff800`11f09bb0)],rax
All four kernel variables ExpSystemResourcesList
, ExNPagedLookasideListHead
, ExpFirmwareTableProviderListHead
and ExpSystemResourcesList
are indeed of type _LIST_ENTRY
which can be easily verified with the kernel debugger:
0: kd> x nt!ExpSystemResourcesList fffff800`11f09b20 nt!ExpSystemResourcesList = <no type information> 0: kd> dt nt!_ERESOURCE fffff800`11f09b20 +0x000 SystemResourcesList : _LIST_ENTRY [ 0xfffff800`11f09b40 - 0xfffffa80`317eaca8 ] ...
► ExpInitSystemPhase1
There’s one instance of InitializeListHead
to initialize the list ExpHostList
:
`123695f9 lea rax,[nt!ExpHostList (fffff800`11f09930)] `12369600 xor ebp,ebp `12369602 mov qword ptr [nt!ExpHostList+0x8 (fffff800`11f09938)],rax `12369609 mov qword ptr [nt!ExpHostList (fffff800`11f09930)],rax
► ExpTimerInitialization
InitializeListHead
is used once to initialize the list ExpWakeTimerList
:
`12338643 lea rax,[nt!ExpWakeTimerList (fffff800`11f09270)] `1233864a lea rdx,[nt! ?? ::PBOPGDP::`string' (fffff800`12377770)] `12338651 lea rcx,[rbp-39h] `12338655 xor ebx,ebx `12338657 mov qword ptr [nt!ExpWakeTimerList+0x8 (fffff800`11f09278)],rax `1233865e mov qword ptr [nt!ExpWakeTimerList (fffff800`11f09270)],rax
► InitBootProcessor
InitializeListHead
is used to initialize the lists WheapPfaList
…
`1236bcb4 lea rax,[nt!WheapPfaList (fffff800`11ef9a90)] `1236bcbb mov qword ptr [nt!WheapPfaLock (fffff800`11ef9aa0)],r13 `1236bcc2 mov qword ptr [nt!WheapPfaList+0x8 (fffff800`11ef9a98)],rax `1236bcc9 mov qword ptr [nt!WheapPfaList (fffff800`11ef9a90)],rax
… and HandleTableListHead
:
`1236c212 lea rax,[nt!HandleTableListHead (fffff800`11f09c30)] `1236c219 mov qword ptr [nt!HandleTableListLock (fffff800`11f09c40)],r13 `1236c220 mov qword ptr [nt!HandleTableListHead+0x8 (fffff800`11f09c38)],rax `1236c227 mov qword ptr [nt!HandleTableListHead (fffff800`11f09c30)],rax
► IoCreateDevice
The following two consecutive blocks of three lines both look like InitializeListHead
:
`1205d019 lea rax,[rcx+50h] `1205d01d mov qword ptr [rax+8],rax `1205d021 mov qword ptr [rax],rax
and
`1205d024 lea rax,[rcx+60h] `1205d028 mov qword ptr [rax+8],rax `1205d02c mov qword ptr [rax],rax
There’s a third occurrence here:
`1205d200 mov rax,qword ptr [rsp+50h] `1205d205 add rax,50h `1205d209 mov qword ptr [rax+8],rax `1205d20d mov qword ptr [rax],rax
► IoInitializeIrp
There’s one instance of InitializeListHead
here:
`11ca0740 lea rax,[rbx+20h] `11ca0744 mov byte ptr [rbx+46h],cl `11ca0747 mov qword ptr [rax+8],rax `11ca074b mov qword ptr [rax],rax
The register rbx
probably points to an IRP which has the following structure:
0: kd> dt _IRP ntdll!_IRP +0x000 Type : Int2B +0x002 Size : Uint2B +0x004 AllocationProcessorNumber : Uint2B +0x006 Reserved : Uint2B +0x008 MdlAddress : Ptr64 _MDL +0x010 Flags : Uint4B +0x018 AssociatedIrp : <unnamed-tag> +0x020 ThreadListEntry : _LIST_ENTRY +0x030 IoStatus : _IO_STATUS_BLOCK +0x040 RequestorMode : Char +0x041 PendingReturned : UChar +0x042 StackCount : Char +0x043 CurrentLocation : Char +0x044 Cancel : UChar +0x045 CancelIrql : UChar +0x046 ApcEnvironment : Char +0x047 AllocationFlags : UChar +0x048 UserIosb : Ptr64 _IO_STATUS_BLOCK +0x050 UserEvent : Ptr64 _KEVENT +0x058 Overlay : <unnamed-tag> +0x068 CancelRoutine : Ptr64 void +0x070 UserBuffer : Ptr64 Void +0x078 Tail : <unnamed-tag>
So the lines are initialize ThreadListEntry
at offset 20h
which is in fact a _LIST_ENTRY
.
► KeInitThread
InitializeListHead
is used in four places, which all set members of the thread structure with type _KTHREAD
:
kd> dt _KTHREAD -b ntdll!_KTHREAD +0x000 Header : _DISPATCHER_HEADER ... +0x008 WaitListHead : _LIST_ENTRY +0x000 Flink : Ptr64 +0x008 Blink : Ptr64 ... +0x098 ApcState : _KAPC_STATE +0x000 ApcListHead : _LIST_ENTRY +0x000 Flink : Ptr64 +0x008 Blink : Ptr64 ... ... +0x308 MutantListHead : _LIST_ENTRY ...
The first instance of InitializeListHead
is:
`11fd735b lea rax,[rcx+8] `11fd735f mov qword ptr [rax+8],rax `11fd7363 mov qword ptr [rax],rax
The register rcx
points to a _KTHREAD
structure. At offset 8
we find the WaitListHead
inside the Header
structure. The second instance follows right after that and initializes MutantListHead
at offset 308h
of _KTHREAD
:
`11fd7366 lea rax,[rcx+308h] `11fd736d mov qword ptr [rax+8],rax `11fd7371 mov qword ptr [rax],rax
The third occurences of InitializeListHead
is:
`11fd73bd lea rcx,[rdi+98h] `11fd73c4 mov qword ptr [rdi+248h],rcx `11fd73cb lea rax,[rdi+258h] `11fd73d2 mov qword ptr [rdi+250h],rax `11fd73d9 mov qword ptr [rcx+8],rcx `11fd73dd mov qword ptr [rcx],rcx
Rdi
holds the same address as rcx
and therefore also points to the _KTHREAD
structure. At offset 98h
of the thread structure is member ApcState
, and at offset and
8
into ApcState
we have indeed a Flink
and Blink
pointers. The fourth and last InitializeListHead
usage follows right after the previous one:
`11fd73e0 lea rax,[rdi+0A8h] `11fd73e7 mov qword ptr [rax+8],rax `11fd73eb mov qword ptr [rax],rax
This time the member at offset 0A8h
is initialized, which is 98h + 10h
or the second _LIST_ENTRY
of ApcState
.
► KeInitializeMutex
This very short routine has the following unassembly. The InitializeListHead
lines are highlighted:
`11cb6cec lea rax,[rcx+8] `11cb6cf0 mov byte ptr [rcx],2 `11cb6cf3 mov word ptr [rcx+2],0Eh `11cb6cf9 mov dword ptr [rcx+4],1 `11cb6d00 xor edx,edx `11cb6d02 mov qword ptr [rcx+28h],rdx `11cb6d06 mov qword ptr [rax+8],rax `11cb6d0a mov qword ptr [rax],rax `11cb6d0d mov word ptr [rcx+30h],100h `11cb6d13 ret
The register rcx
points to a mutex of type _KMUTANT
. At offset 8
into this structure there’s indeed a _LIST_ENTRY
:
0: > nt!_KMUTANT +0x000 Header : _DISPATCHER_HEADER ... +0x008 WaitListHead : _LIST_ENTRY +0x000 Flink : Ptr64 +0x008 Blink : Ptr64
► KeInitializeProcess
InitializeListHead
is first used here:
`11d605b6 lea rax,[rcx+20h] `11d605ba mov word ptr [rcx+18h],1 `11d605c0 mov byte ptr [rcx+1Ah],6 `11d605c4 mov qword ptr [rax+8],rax `11d605c8 mov qword ptr [rax],rax
rcx
points to a _FAST_MUTEX
:
ntdll!_FAST_MUTEX +0x000 Count : Int4B +0x008 Owner : Ptr64 Void +0x010 Contention : Uint4B +0x018 Event : _KEVENT +0x030 OldIrql : Uint4B
Offset 20h
lies inside Event
of type _KEVENT
. At offset 8
(=20h-18h
) there’s sure enough a _LIST_ENTRY
:
0: kd> dt _KEVENT -b nt!_KEVENT +0x000 Header : _DISPATCHER_HEADER ... +0x008 WaitListHead : _LIST_ENTRY +0x000 Flink : Ptr64 +0x008 Blink : Ptr64
The second usage of InitializeListHead
is:
`12111030 lea rax,[rcx+8] `12111034 mov qword ptr [rax+8],rax `12111038 mov qword ptr [rax],rax
This time rcx
is of type _KPROCESS
with a _LIST_ENTRY
at offset 8
:
0: kd> dt _KPROCESS -b nt!_KPROCESS +0x000 Header : _DISPATCHER_HEADER ... +0x008 WaitListHead : _LIST_ENTRY +0x000 Flink : Ptr64 +0x008 Blink : Ptr64
Finally, there are three consecutive uses of InitializeListHead
:
`121110ea lea rax,[rbx+18h] `121110ee mov rdx,rbp `121110f1 mov rcx,rbx `121110f4 mov qword ptr [rax+8],rax `121110f8 mov qword ptr [rax],rax `121110fb lea rax,[rbx+0F0h] `12111102 mov qword ptr [rax+8],rax `12111106 mov qword ptr [rax],rax `12111109 lea rax,[rbx+30h] `1211110d mov qword ptr [rax+8],rax `12111111 mov qword ptr [rax],rax
Rbx
points to a _KPROCESS
and the code above initializes the three lists ProfileListHead
, ThreadListHead
and ReadyListHead
.
0: kd> dt _KPROCESS ntdll!_KPROCESS +0x000 Header : _DISPATCHER_HEADER +0x018 ProfileListHead : _LIST_ENTRY ... +0x030 ThreadListHead : _LIST_ENTRY ... +0x0f0 ReadyListHead : _LIST_ENTRY ...
► KeInitializeTimerEx
Another short routine with obvious InitializeListHead
:
`11d2e5b0 xor r8d,r8d `11d2e5b3 lea rax,[rcx+8] `11d2e5b7 add dl,8 `11d2e5ba mov qword ptr [rcx],r8 `11d2e5bd mov byte ptr [rcx],dl `11d2e5bf mov qword ptr [rax+8],rax `11d2e5c3 mov qword ptr [rax],rax `11d2e5c6 mov qword ptr [rcx+18h],r8 `11d2e5ca mov qword ptr [rcx+38h],r8 `11d2e5ce ret
The register rcx
points to a _KTIMER
structure, which has a _LIST_ENTRY
at offset 8
:
nt!_KTIMER +0x000 Header : _DISPATCHER_HEADER ... +0x008 WaitListHead : _LIST_ENTRY +0x000 Flink : Ptr64 +0x008 Blink : Ptr64
► KeInitializeTimerTable
There’s one potential InitializeListHead
:
`12160caa lea rax,[rbx+3008h] nt!KeInitializeTimerTable+0x91: `12160cb1 mov qword ptr [rax-8],rbp `12160cb5 mov qword ptr [rax+8],rax `12160cb9 mov qword ptr [rax],rax
► KiInitializeProcessor
There’s one potential InitializeListHead
:
`11fdca27 lea rdx,[rsi+2DA0h] `11fdca2e mov qword ptr [rdx+8],rdx `11fdca32 mov qword ptr [rdx],rdx
► KiInitializeThread
There’s one InitializeListHead
to initialize the _LIST_ENTRY
at offset 478h
into KiInitialProcess
:
`11fdccbb lea rdx,[nt!KiInitialProcess+0x470 (fffff800`11fca670)] ... `11fdcd6f mov qword ptr [nt!KiInitialProcess+0x478 (fffff800`11fca678)],rdx `11fdcd76 mov qword ptr [nt!KiInitialProcess+0x470 (fffff800`11fca670)],rdx
0: kd> x nt!ExpSystemResourcesList fffff800`11f09b20 nt!ExpSystemResourcesList = <no type information> 0: kd> dt nt!_ERESOURCE fffff800`11f09b20 +0x000 SystemResourcesList : _LIST_ENTRY [ 0xfffff800`11f09b40 - 0xfffffa80`317eaca8 ] ...
► MiInitializeLoadedModuleList
This routine uses InitializeListHead
once to initialize the PsLoadedModuleList
:
`1236dc44 lea r13,[nt!PsLoadedModuleList (fffff800`11f44aa0)] `1236dc4b mov r8b,1 `1236dc4e lea ecx,[rdx+7Eh] `1236dc51 mov qword ptr [nt!ExpCovPushLock (fffff800`11f092f0)],r15 `1236dc58 mov qword ptr [nt!ExpCovUnloadedModuleList+0x8 (fffff800`11f092e8)],rax `1236dc5f mov qword ptr [nt!PsLoadedModuleList+0x8 (fffff800`11f44aa8)],r13 `1236dc66 mov qword ptr [nt!PsLoadedModuleList (fffff800`11f44aa0)],r13
At offsets and
8
into PsLoadedModuleList
we find the two pointers Flink
and Blink
:
0: kd> x nt!PsLoadedModuleList fffff800`03452890 nt!PsLoadedModuleList = <no type information> 0: kd> dt nt!_ERESOURCE -b fffff800`03452890 +0x000 SystemResourcesList : _LIST_ENTRY [ 0xfffffa80`18dd4e70 - 0xfffffa80`1dbec240 ] +0x000 Flink : 0xfffffa80`18dd4e70 +0x008 Blink : 0xfffffa80`1dbec240
► MiInitializePrefetchHead
The routine uses three consecutive InitializeListHead
functions to set the lists at offset 8
, 18h
and 28h
into the structure that rcx
points to:
`11db2bc4 lea rax,[rcx+8] `11db2bc8 mov qword ptr [rax+8],rax `11db2bcc mov qword ptr [rax],rax `11db2bcf lea rax,[rcx+18h] `11db2bd3 mov qword ptr [rax+8],rax `11db2bd7 mov qword ptr [rax],rax `11db2bda lea rax,[rcx+28h] `11db2bde mov qword ptr [rax+8],rax `11db2be2 mov qword ptr [rax],rax
► PspAllocateProcess
Two locations look like InitializeListHead
:
`120f3a0a lea rax,[r13+5D8h] `120f3a11 mov qword ptr [rax+8],rax `120f3a15 mov qword ptr [rax],rax
and
`120f3a26 lea rax,[r13+470h] `120f3a2d mov qword ptr [rax+8],rax `120f3a31 mov qword ptr [rax],rax
► PspAllocateThread
There are five consecutive InitializeListHead
s:
`120e95c2 lea r11,[rsi+350h] `120e95c9 mov qword ptr [r11+8],r11 `120e95cd mov qword ptr [r11],r11 `120e95d0 lea rax,[rsi+470h] `120e95d7 mov qword ptr [rax+8],rax `120e95db mov qword ptr [rax],rax `120e95de lea rax,[rsi+480h] `120e95e5 mov qword ptr [rax+8],rax `120e95e9 mov qword ptr [rax],rax `120e95ec mov qword ptr [rsi+490h],rdi `120e95f3 lea rax,[rsi+3D0h] `120e95fa mov qword ptr [rax+8],rax `120e95fe mov qword ptr [rax],rax `120e9601 mov qword ptr [rsi+498h],rdi `120e9608 mov qword ptr [rsi+380h],rdi `120e960f lea rax,[rsi+388h] `120e9616 mov qword ptr [rax+8],rax `120e961a mov qword ptr [rax],rax
Archived Comments
Note: I removed the Disqus integration in an effort to cut down on bloat. The following comments were retrieved with the export functionality of Disqus. If you have comments, please reach out to me by Twitter or email.