PspCidTable

 

lkd> dd KdversionBlock

8054c038  0a28000f 00020006 030c014c 0000002d

8054c048  804d7000 ffffffff 8055a420 ffffffff

 

WinDbg understands a variable called KdVersionBlock and tells us that it begins at location 8054c038. This value is the value of i1 in our program. The KdVersionBlock is stored at address 0x0ffdff034. We set variable I to this value and then use a * to pick up the value of the KdVersionBlock variable.

 

We add an offset 0x80 to get a value of 8054c0b8.

 

lkd> dd 8054c0b8

8054c0b8  805605e0 00000000 80562a08 00000000

 

The value stored here is the address of the PspCidTable 805605e0.

 

r.c

#include <ntddk.h>

#include <stdio.h>

#define DWORD long

struct NonExported

{

DWORD KernelBase;

DWORD KiCallUserMode;

DWORD PsActiveProcessHead;

DWORD PsLoadedModuleList;

DWORD PspCidTable;

DWORD ExpNumberOfPagedPools;

DWORD ObpRootDirectoryObject;

DWORD ObpTypeObjectType;

DWORD MmSystemCacheStart;

DWORD MmSystemCacheEnd;

DWORD MmSystemCacheWs;

DWORD MmPfnDatabase;

};

typedef ULONG *LPDWORD;

#define GetAddress( x )   (*(LPDWORD)((*(LPDWORD)0x0ffdff034) + (ULONG)(x)))

void GetNonExportedVariables(struct NonExported *Table )

{

Table->KernelBase = GetAddress( 0x40 );

Table->KiCallUserMode = GetAddress( 0x60 );

Table->PsActiveProcessHead = GetAddress( 0x78 );

Table->PsLoadedModuleList = GetAddress( 0x70 );

Table->PspCidTable = GetAddress( 0x80 );

Table->ExpNumberOfPagedPools = GetAddress( 0x98 );

Table->ObpRootDirectoryObject = GetAddress( 0xC0 );

Table->ObpTypeObjectType = GetAddress( 0xC8 );

Table->MmSystemCacheStart = GetAddress( 0xD0 );

Table->MmSystemCacheEnd = GetAddress( 0xD8 );

Table->MmSystemCacheWs = GetAddress( 0xE0 );

Table->MmPfnDatabase = GetAddress( 0xE8 );

}

VOID OnUnload(PDRIVER_OBJECT DriverObject )

{  

DbgPrint("Unload5");

}

NTSTATUS DriverEntry(PDRIVER_OBJECT d,PUNICODE_STRING r)

{

struct NonExported NPVars;

long i,i1,i2,i3;

GetNonExportedVariables( &NPVars );

DbgPrint( "KernelBase = 0x%X PspCidTable = 0x%X", NPVars.KernelBase, NPVars.PspCidTable);

i = 0x0ffdff034;

i1 = *(long *)i;

i2 = i1 + 0x80;

i3 = *(long *)i2;

DbgPrint("i=%x i1=%x i2=%x i3=%x",i,i1,i2,i3);

d->DriverUnload  = OnUnload;

return STATUS_SUCCESS;

}

KernelBase = 0x804D7000 PspCidTable = 0x805605E0

i=ffdff034 i1=8054c038 i2=8054c0b8 i3=805605e0

Unload5

 

The KdVersionBlock is actually a pointer to a structure called KDDEBUGGER_DATA32. The KdVersionBlock field in turn  is a part of the Process Control Region structure.

 

typedef struct _KDDEBUGGER_DATA32 {
 
    DBGKD_DEBUG_DATA_HEADER32 Header;
    ULONG   KernBase;
    ULONG   BreakpointWithStatus;       // address of breakpoint
    ULONG   SavedContext;
    USHORT  ThCallbackStack;            // offset in thread data
    USHORT  NextCallback;               // saved pointer to next callback frame
    USHORT  FramePointer;               // saved frame pointer
    USHORT  PaeEnabled:1;
    ULONG   KiCallUserMode;             // kernel routine
    ULONG   KeUserCallbackDispatcher;   // address in ntdll
 
    ULONG   PsLoadedModuleList;
    ULONG   PsActiveProcessHead;
    ULONG   PspCidTable;
 
    ULONG   ExpSystemResourcesList;
    ULONG   ExpPagedPoolDescriptor;
    ULONG   ExpNumberOfPagedPools;
 
    [...]
 
    ULONG   KdPrintCircularBuffer;
    ULONG   KdPrintCircularBufferEnd;
    ULONG   KdPrintWritePointer;
    ULONG   KdPrintRolloverCount;
 
    ULONG   MmLoadedUserImageList;
 
} KDDEBUGGER_DATA32, *PKDDEBUGGER_DATA32;

 

Thus in our code we assume that the Process Control Region starts somewhere and at 0x0ffdff034 is a pointer to the kdVersionBlock which is a pointer to the above debugger data32 structure. I is a pointer to the PCR region where the KdVersionBlock pointer is stored, i1 is the KdVersionBlock pointer, i2 is 80 bytes within the debugger structure and i3 is where the PspCidTable starts.

lkd> !pcr

KPCR for Processor 0 at ffdff000:

 

The pcr or Process Control Block extension tells us that it starts at ffdff000. 34 from the start is found the KdVersionBlock field.

 

lkd> dd ffdff034

ffdff034  8054c038 8003f400 8003f000 80042000

 

We thus assume the value of the pcr and from there we an get at the KdVersionBlock and then the PspCidTable.