Saturday, 1 July 2017

Practical Reverse Engineering Exercise Solutions: KeInitializeQueue

We are tasked with decompiling the Windows Kernel routine KeInitializeQueue.

Firstly, we obtain its disassembly:

 

Secondly, we consult MSDN for its signature:

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:

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:

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:

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:

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:



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;
}

}

No comments:

Post a Comment