Contents

Practical Reverse Engineering Exercise Solutions: KeInitializeQueue

Contents

We are tasked with decompiling the Windows Kernel routine KeInitializeQueue.

Firstly, we obtain its disassembly:

../images/thumbnails/2017-07-01-practical-reverse-engineering-exercise-solutions-keinitializequeue-001.png 

Secondly, we consult MSDN for its signature:

1
2
3
4
VOID KeInitializeQueue(
  _Out_ PRKQUEUE Queue,
  _In_  ULONG    Count
);

The routine itself does not return anything. 

We learn it takes two parameters and as the assembly contains the ret 8 instruction, the KeInitializeQueue function cleans up the stack and thus, it uses the stdcall convention.

The KQUEUE data structure is defined as follows:

1
2
3
4
5
6
7
8
typedef struct _KQUEUE {
    DISPATCHER_HEADER Header;
    LIST_ENTRY EntryListHead;
    ULONG CurrentCount;
    ULONG MaximumCount;
    LIST_ENTRY ThreadListHead;
} KQUEUE, *PKQUEUE, *RESTRICTED_POINTER PRKQUEUE;

In order to obtain the offsets for the struct parts, we query the data structure in WinDbg:

1
2
3
4
5
6
0: kd> dt nt!_KQUEUE
   +0x000 Header           : _DISPATCHER_HEADER
   +0x010 EntryListHead    : _LIST_ENTRY
   +0x018 CurrentCount     : Uint4B
   +0x01c MaximumCount     : Uint4B
   +0x020 ThreadListHead   : _LIST_ENTRY

Analogously, we investigate the data structure DISPATCHER_HEADER:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
0: kd> dt nt!_DISPATCHER_HEADER
   +0x000 Type             : UChar
   +0x001 TimerControlFlags : UChar
   +0x001 Absolute         : Pos 0, 1 Bit
   +0x001 Coalescable      : Pos 1, 1 Bit
   +0x001 KeepShifting     : Pos 2, 1 Bit
   +0x001 EncodedTolerableDelay : Pos 3, 5 Bits
   +0x001 Abandoned        : UChar
   +0x001 Signalling       : UChar
   +0x002 ThreadControlFlags : UChar
   +0x002 CpuThrottled     : Pos 0, 1 Bit
   +0x002 CycleProfiling   : Pos 1, 1 Bit
   +0x002 CounterProfiling : Pos 2, 1 Bit
   +0x002 Reserved         : Pos 3, 5 Bits
   +0x002 Hand             : UChar
   +0x002 Size             : UChar
   +0x003 TimerMiscFlags   : UChar
   +0x003 Index            : Pos 0, 1 Bit
   +0x003 Processor        : Pos 1, 5 Bits
   +0x003 Inserted         : Pos 6, 1 Bit
   +0x003 Expired          : Pos 7, 1 Bit
   +0x003 DebugActive      : UChar
   +0x003 ActiveDR7        : Pos 0, 1 Bit
   +0x003 Instrumented     : Pos 1, 1 Bit
   +0x003 Reserved2        : Pos 2, 4 Bits
   +0x003 UmsScheduled     : Pos 6, 1 Bit
   +0x003 UmsPrimary       : Pos 7, 1 Bit
   +0x003 DpcActive        : UChar
   +0x000 Lock             : Int4B
   +0x004 SignalState      : Int4B
   +0x008 WaitListHead     : _LIST_ENTRY

The following page provides a clearer overview of the structure, which facilitates the comprehension: http://msdn.moonsols.com/win7rtm_x86/DISPATCHER_HEADER.html

The _LIST_ENTRY structure, in contrast, has only a few members:

1
2
3
0: kd> dt nt!_LIST_ENTRY
   +0x000 Flink            : Ptr32 _LIST_ENTRY
   +0x004 Blink            : Ptr32 _LIST_ENTRY

We try to translate it by introducing some additional variables:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
VOID KeInitializeQueue(
        _Out_ PRKQUEUE Queue,
        _In_  ULONG    Count
        )
{
    Queue->Header.Type = 4;
    Queue->Header.Size  = 0x0A;
    Queue->Header.Abandoned = 0;
    Queue->Header.SignalState = 0;

    Queue->Header.WaitListHead->Blink = &(Queue->WaitListHead);
    Queue->Header.WaitListHead->Flink = &(Queue->WaitListHead);

    Queue->EntryListHead->Blink = &(Queue->EntryListHead)
        Queue->EntryListHead->Flink = &(Queue->EntryListHead)

        Queue->ThreadListHead->Blink = &(Queue->ThreadListHead)
        Queue->ThreadListHead->Flink = &(Queue->ThreadListHead)


        if (Queue->CurrentCount != Count) {
            Queue->MaximumCount = KeNumberProcessors();
        }
        else {
            Queue->MaximumCount = Count;
        }

}