1. 获取pspcidtable的地址
lkd> dd pspcidtable
812a0314 82006000 00000002 00000200 0000000f
812a0324 0000001e 00000258 00000000 00000000
812a0334 812a0324 8108e4cc 0000001e 812a0320
812a0344 8108e4fc 0000000f 812a0328 8108e528
812a0354 00000258 812a031c 8108e558 00000200
812a0364 8486f520 84873040 8486bb38 00000000
812a0374 ffffffff 00000000 00000000 00000002
812a0384 00000000 00000005 c0000044 00000005
2. pspcidtable 地址为82006000, 是指向一个 _handle_table
lkd> dt _handle_table 82006000
ntdll!_HANDLE_TABLE
+0x000 NextHandleNeedingPool : 0x1000
+0x004 ExtraInfoPages : 0n0
+0x008 TableCode : 0x80901001
+0x00c QuotaProcess : (null)
+0x010 HandleTableList : _LIST_ENTRY [ 0x82006010 - 0x82006010 ]
+0x018 UniqueProcessId : 0
+0x01c Flags : 1
+0x01c StrictFIFO : 0y1
+0x01c EnableHandleExceptions : 0y0
+0x01c Rundown : 0y0
+0x01c Duplicated : 0y0
+0x020 HandleContentionEvent : _EX_PUSH_LOCK
+0x024 HandleTableLock : _EX_PUSH_LOCK
+0x028 FreeLists : [1] _HANDLE_TABLE_FREE_LIST
+0x028 ActualEntry : [20] ""
+0x03c DebugInfo : (null)
3. 其中的TableCode为0x80901001, TableCode 字段的解释与其他系统中一样的,低 3 Bits 表示是几层表结构,低3位清0之后的值就是层表地址。
0x80901001 低3位清零后为 0x80901000 ,是一个二级表
lkd> dd 0x80901000
80901000 82008000 80903000 00000000 00000000
80901010 00000000 00000000 00000000 00000000
80901020 00000000 00000000 00000000 00000000
80901030 00000000 00000000 00000000 00000000
80901040 00000000 00000000 00000000 00000000
80901050 00000000 00000000 00000000 00000000
80901060 00000000 00000000 00000000 00000000
80901070 00000000 00000000 00000000 00000000
4. 二级表是包含指向一级表的指针,发掘第一个一级表82008000
lkd> dd 82008000
82008000 00000000 00000000 8486e441 98000000
82008010 84875bc1 00000000 84875741 00000000
82008020 8487e041 00000000 8487e8c1 00000000
82008030 84880bc1 00000000 84880741 00000000
82008040 8487b041 00000000 00000000 809032a8
82008050 8487b4c1 00000000 848a5a41 00000000
82008060 848a55c1 00000000 848825c1 00000000
82008070 848329c1 00000000 84832581 00000000
5. 一级表是_HANDLE_TABLE_ENTRY数组,第一个为0,我们看看第二个
lkd> dt _handle_table_entry 8486e441
ntdll!_HANDLE_TABLE_ENTRY
+0x000 VolatileLowValue : 0n10240
+0x000 LowValue : 0n10240
+0x000 InfoTable : 0x00002800 _HANDLE_TABLE_ENTRY_INFO
+0x000 Unlocked : 0y0
+0x000 Attributes : 0y00
+0x000 ObjectPointerBits : 0y00000000000000000010100000000 (0x500)
+0x004 HighValue : 0n1207959552
+0x004 NextFreeHandleEntry : 0x48000000 _HANDLE_TABLE_ENTRY
+0x004 LeafHandleValue : _EXHANDLE
+0x004 GrantedAccessBits : 0y0000000000000000000000000 (0)
+0x004 ProtectFromClose : 0y0
+0x004 NoRightsUpgrade : 0y0
+0x004 RefCnt : 0y01001 (0x9)
6. 计算出object 的地址为: 8486e440
Object Address = (Object/ObjectPointerBits & 0xFFFFFFF8) | 0x80000000
lkd> !object 8486e440
Object: 8486e440 Type: (8486bf70) Process
ObjectHeader: 8486e428 (new version)
HandleCount: 5 PointerCount: 305
lkd> dt _eprocess 8486e440
ntdll!_EPROCESS
+0x000 Pcb : _KPROCESS
+0x0a0 ProcessLock : _EX_PUSH_LOCK
+0x0a8 CreateTime : _LARGE_INTEGER 0x01ceec99`1748a0c8
+0x0b0 RundownProtect : _EX_RUNDOWN_REF
+0x0b4 UniqueProcessId : 0x00000004 Void
....
+0x170 ImageFileName : [15] "System"
....
原来是 System 进程, PID 为 4
参考:
http://bbs.pediy.com/showthread.php?t=170205
http://hi.baidu.com/_achillis/item/d76dd19faa660e8d5914611a
-----------------------------------------------------------------------------------
【更新:通过KPCR获取pspcidtable地址】
1. 在windbg里面可以通过!pcr指令获得,ring0下直接读取FS:[0x0]即可.
WINDBG>!pcr 0
KPCR for Processor 0 at 82027000:
Major 1 Minor 1
NtTib.ExceptionList: 83151004
NtTib.StackBase: 00000000
NtTib.StackLimit: 00001f80
NtTib.SubSystemTib: 81379000
NtTib.Version: 000222ee
NtTib.UserPointer: 00000001
NtTib.SelfTib: 00000000
SelfPcr: 82027000
Prcb: 82027120
Irql: 0000001f
IRR: 00000000
IDR: 00000000
InterruptMode: 00000000
IDT: 81375400
GDT: 81375000
TSS: 81379000
CurrentThread: 82036100
NextThread: 00000000
IdleThread: 82036100
DpcQueue: Unable to read nt!_KDPC_DATA.DpcListHead.Flink @ 82029300
WINDBG>dd fs:[0]
0030:00000000 83151004 00000000 00001f80 81379000
0030:00000010 00084b96 00000001 00000000 82027000
0030:00000020 82027120 0000001f 00000000 00000000
0030:00000030 00000000 81ffdd60 81375400 81375000
0030:00000040 81379000 00010001 00000001 00000dad
0030:00000050 00000000 00000000 00000000 00000000
0030:00000060 00000000 00000000 00000000 00000000
0030:00000070 00000000 00000000 00000000 00000000
WINDBG>dt _kpcr 82027000
nt!_KPCR
+0x000 NtTib : _NT_TIB
+0x000 Used_ExceptionList : 0x83151004 _EXCEPTION_REGISTRATION_RECORD
+0x004 Used_StackBase : (null)
+0x008 MxCsr : 0x1f80
+0x00c TssCopy : 0x81379000 Void
+0x010 ContextSwitches : 0x222ee
+0x014 SetMemberCopy : 1
+0x018 Used_Self : (null)
+0x01c SelfPcr : 0x82027000 _KPCR
+0x020 Prcb : 0x82027120 _KPRCB
+0x024 Irql : 0x1f ''
+0x028 IRR : 0
+0x02c IrrActive : 0
+0x030 IDR : 0
+0x034 KdVersionBlock : 0x81ffdd60 Void
+0x038 IDT : 0x81375400 _KIDTENTRY
+0x03c GDT : 0x81375000 _KGDTENTRY
+0x040 TSS : 0x81379000 _KTSS
+0x044 MajorVersion : 1
+0x046 MinorVersion : 1
+0x048 SetMember : 1
+0x04c StallScaleFactor : 0xdad
+0x050 SpareUnused : 0 ''
+0x051 Number : 0 ''
+0x052 Spare0 : 0 ''
+0x053 SecondLevelCacheAssociativity : 0 ''
+0x054 VdmAlert : 0
+0x058 KernelReserved : [14] 0
+0x090 SecondLevelCacheSize : 0
+0x094 HalReserved : [16] 0x1000000
+0x0d4 InterruptMode : 0
+0x0d8 Spare1 : 0 ''
+0x0dc KernelReserved2 : [17] 0
+0x120 PrcbData : _KPRCB
2. KeVersionBlock 指向的是_DBGKD_GET_VERSION64结构体,紧跟在后面的是KDDEBUGGER_DATA64
在wdk8.1中以下位置可以得到这些结构体的定义:
C:\Program Files (x86)\Windows Kits\8.1\Debuggers\inc\wdbgexts.h
WINDBG>dt _dbgkd_get_version64 0x81ffdd60
nt!_DBGKD_GET_VERSION64
+0x000 MajorVersion : 0xf
+0x002 MinorVersion : 0x2580
+0x004 ProtocolVersion : 0x6 ''
+0x005 KdSecondaryVersion : 0 ''
+0x006 Flags : 3
+0x008 MachineType : 0x14c
+0x00a MaxPacketType : 0xc ''
+0x00b MaxStateChange : 0x3 ''
+0x00c MaxManipulate : 0x31 '1'
+0x00d Simulation : 0 ''
+0x00e Unused : [1] 0
+0x010 KernBase : 0xffffffff`81e1c000
+0x018 PsLoadedModuleList : 0xffffffff`82015218
+0x020 DebuggerDataList : 0xffffffff`82313030
3. _DBGKD_GET_VERSION64这个结构体的大小是0x20,最后一个成员DebuggerDataList是一个指向KDDEBUGGER_DATA64指针的指针,所以:
WINDBG>dd 0x81ffdd60 + 0x20
81ffdd80 82313030 ffffffff 00000040 81f1d748
81ffdd90 81f1d76c 00000001 00000007 00000000
81ffdda0 823e1426 823e152a fffff000 000000ff
81ffddb0 fffff000 000000ff 00002728 00100000
81ffddc0 0000000d 00000001 0007ab6e 00000012
81ffddd0 00000001 00000000 00000005 0000016c
81ffdde0 00000000 004c4b40 ffffffff 00000007
81ffddf0 00000000 82156d18 00000000 81eb0498
4. 81ffda00 是一个KDDEBUGGER_DATA64指针,继续
WINDBG>dd 82313030
82313030 81ffda00 81ffda00 00000000 81f1dae4
82313040 00000000 00000000 00000000 00000000
82313050 00000000 00000000 00000000 00000000
82313060 00000000 00000000 00000000 00000000
82313070 00000000 00000000 00000000 00000000
82313080 00000000 00000000 00000000 00000000
82313090 00000000 00000000 00000000 00000000
823130a0 00000000 00000000 00000000 00000000
5. 来到KDDEBUGGER_DATA64结构,这个结构请自己参考: wdbgexts.h
WINDBG>dd 81ffda00
81ffda00 82313030 82313030 00000000 00000000
81ffda10 4742444b 00000360 81e1c000 00000000
81ffda20 81f1dae4 00000000 00000000 00000000
81ffda30 00000000 00010018 81f1cbc0 00000000
81ffda40 00000000 00000000 82015218 00000000
81ffda50 8200cc58 00000000 82045314 00000000
81ffda60 82009398 00000000 820453f0 00000000
81ffda70 820453e8 00000000 820443ec 00000000
6. 在偏移0x58处,找到pspcidtable的地址
WINDBG>dd 81ffda00 + 0x58
81ffda58 82045314 00000000 82009398 00000000
81ffda68 820453f0 00000000 820453e8 00000000
81ffda78 820443ec 00000000 8201aa40 00000000
81ffda88 8201a360 00000000 8201d0b8 00000000
81ffda98 8200e1d0 00000000 8200e1d4 00000000
81ffdaa8 00000000 00000000 00000000 00000000
81ffdab8 820381c0 00000000 82044708 00000000
81ffdac8 00000000 00000000 00000000 00000000
7. 比较: 82045314
WINDBG>dd pspcidtable
82045314 83206000 00000002 00000200 0000000f
82045324 0000001e 00000258 00000000 00000000
82045334 82045324 81e334cc 0000001e 82045320
82045344 81e334fc 0000000f 82045328 81e33528
82045354 00000258 8204531c 81e33558 00000200
82045364 8566c3f0 8566c320 8566af70 00000000
82045374 ffffffff 00000000 00000000 00000002
82045384 00000000 00000005 c0000044 00000005
8. 顺便贴下相关的结构
typedef struct _DBGKD_DEBUG_DATA_HEADER64 {
//
// Link to other blocks
//
LIST_ENTRY64 List;
//
// This is a unique tag to identify the owner of the block.
// If your component only uses one pool tag, use it for this, too.
//
ULONG OwnerTag;
//
// This must be initialized to the size of the data block,
// including this structure.
//
ULONG Size;
} DBGKD_DEBUG_DATA_HEADER64, *PDBGKD_DEBUG_DATA_HEADER64;
//
// This structure is the same size on all systems. The only field
// which must be translated by the debugger is Header.List.
//
//
// DO NOT ADD OR REMOVE FIELDS FROM THE MIDDLE OF THIS STRUCTURE!!!
//
// If you remove a field, replace it with an "unused" placeholder.
// Do not reuse fields until there has been enough time for old debuggers
// and extensions to age out.
//
typedef struct _KDDEBUGGER_DATA64 {
DBGKD_DEBUG_DATA_HEADER64 Header;
//
// Base address of kernel image
//
ULONG64 KernBase;
//
// DbgBreakPointWithStatus is a function which takes an argument
// and hits a breakpoint. This field contains the address of the
// breakpoint instruction. When the debugger sees a breakpoint
// at this address, it may retrieve the argument from the first
// argument register, or on x86 the eax register.
//
ULONG64 BreakpointWithStatus; // address of breakpoint
//
// Address of the saved context record during a bugcheck
//
// N.B. This is an automatic in KeBugcheckEx's frame, and
// is only valid after a bugcheck.
//
ULONG64 SavedContext;
//
// help for walking stacks with user callbacks:
//
//
// The address of the thread structure is provided in the
// WAIT_STATE_CHANGE packet. This is the offset from the base of
// the thread structure to the pointer to the kernel stack frame
// for the currently active usermode callback.
//
USHORT ThCallbackStack; // offset in thread data
//
// these values are offsets into that frame:
//
USHORT NextCallback; // saved pointer to next callback frame
USHORT FramePointer; // saved frame pointer
//
// pad to a quad boundary
//
USHORT PaeEnabled:1;
//
// Address of the kernel callout routine.
//
ULONG64 KiCallUserMode; // kernel routine
//
// Address of the usermode entry point for callbacks.
//
ULONG64 KeUserCallbackDispatcher; // address in ntdll
//
// Addresses of various kernel data structures and lists
// that are of interest to the kernel debugger.
//
ULONG64 PsLoadedModuleList;
ULONG64 PsActiveProcessHead;
ULONG64 PspCidTable;
ULONG64 ExpSystemResourcesList;
ULONG64 ExpPagedPoolDescriptor;
ULONG64 ExpNumberOfPagedPools;
ULONG64 KeTimeIncrement;
ULONG64 KeBugCheckCallbackListHead;
ULONG64 KiBugcheckData;
ULONG64 IopErrorLogListHead;
ULONG64 ObpRootDirectoryObject;
ULONG64 ObpTypeObjectType;
ULONG64 MmSystemCacheStart;
ULONG64 MmSystemCacheEnd;
ULONG64 MmSystemCacheWs;
ULONG64 MmPfnDatabase;
ULONG64 MmSystemPtesStart;
ULONG64 MmSystemPtesEnd;
ULONG64 MmSubsectionBase;
ULONG64 MmNumberOfPagingFiles;
ULONG64 MmLowestPhysicalPage;
ULONG64 MmHighestPhysicalPage;
ULONG64 MmNumberOfPhysicalPages;
ULONG64 MmMaximumNonPagedPoolInBytes;
ULONG64 MmNonPagedSystemStart;
ULONG64 MmNonPagedPoolStart;
ULONG64 MmNonPagedPoolEnd;
ULONG64 MmPagedPoolStart;
ULONG64 MmPagedPoolEnd;
ULONG64 MmPagedPoolInformation;
ULONG64 MmPageSize;
ULONG64 MmSizeOfPagedPoolInBytes;
ULONG64 MmTotalCommitLimit;
ULONG64 MmTotalCommittedPages;
ULONG64 MmSharedCommit;
ULONG64 MmDriverCommit;
ULONG64 MmProcessCommit;
ULONG64 MmPagedPoolCommit;
ULONG64 MmExtendedCommit;
ULONG64 MmZeroedPageListHead;
ULONG64 MmFreePageListHead;
ULONG64 MmStandbyPageListHead;
ULONG64 MmModifiedPageListHead;
ULONG64 MmModifiedNoWritePageListHead;
ULONG64 MmAvailablePages;
ULONG64 MmResidentAvailablePages;
ULONG64 PoolTrackTable;
ULONG64 NonPagedPoolDescriptor;
ULONG64 MmHighestUserAddress;
ULONG64 MmSystemRangeStart;
ULONG64 MmUserProbeAddress;
ULONG64 KdPrintCircularBuffer;
ULONG64 KdPrintCircularBufferEnd;
ULONG64 KdPrintWritePointer;
ULONG64 KdPrintRolloverCount;
ULONG64 MmLoadedUserImageList;
// NT 5.1 Addition
ULONG64 NtBuildLab;
ULONG64 KiNormalSystemCall;
// NT 5.0 hotfix addition
ULONG64 KiProcessorBlock;
ULONG64 MmUnloadedDrivers;
ULONG64 MmLastUnloadedDriver;
ULONG64 MmTriageActionTaken;
ULONG64 MmSpecialPoolTag;
ULONG64 KernelVerifier;
ULONG64 MmVerifierData;
ULONG64 MmAllocatedNonPagedPool;
ULONG64 MmPeakCommitment;
ULONG64 MmTotalCommitLimitMaximum;
ULONG64 CmNtCSDVersion;
// NT 5.1 Addition
ULONG64 MmPhysicalMemoryBlock;
ULONG64 MmSessionBase;
ULONG64 MmSessionSize;
ULONG64 MmSystemParentTablePage;
// Server 2003 addition
ULONG64 MmVirtualTranslationBase;
USHORT OffsetKThreadNextProcessor;
USHORT OffsetKThreadTeb;
USHORT OffsetKThreadKernelStack;
USHORT OffsetKThreadInitialStack;
USHORT OffsetKThreadApcProcess;
USHORT OffsetKThreadState;
USHORT OffsetKThreadBStore;
USHORT OffsetKThreadBStoreLimit;
USHORT SizeEProcess;
USHORT OffsetEprocessPeb;
USHORT OffsetEprocessParentCID;
USHORT OffsetEprocessDirectoryTableBase;
USHORT SizePrcb;
USHORT OffsetPrcbDpcRoutine;
USHORT OffsetPrcbCurrentThread;
USHORT OffsetPrcbMhz;
USHORT OffsetPrcbCpuType;
USHORT OffsetPrcbVendorString;
USHORT OffsetPrcbProcStateContext;
USHORT OffsetPrcbNumber;
USHORT SizeEThread;
ULONG64 KdPrintCircularBufferPtr;
ULONG64 KdPrintBufferSize;
ULONG64 KeLoaderBlock;
USHORT SizePcr;
USHORT OffsetPcrSelfPcr;
USHORT OffsetPcrCurrentPrcb;
USHORT OffsetPcrContainedPrcb;
USHORT OffsetPcrInitialBStore;
USHORT OffsetPcrBStoreLimit;
USHORT OffsetPcrInitialStack;
USHORT OffsetPcrStackLimit;
USHORT OffsetPrcbPcrPage;
USHORT OffsetPrcbProcStateSpecialReg;
USHORT GdtR0Code;
USHORT GdtR0Data;
USHORT GdtR0Pcr;
USHORT GdtR3Code;
USHORT GdtR3Data;
USHORT GdtR3Teb;
USHORT GdtLdt;
USHORT GdtTss;
USHORT Gdt64R3CmCode;
USHORT Gdt64R3CmTeb;
ULONG64 IopNumTriageDumpDataBlocks;
ULONG64 IopTriageDumpDataBlocks;
// Longhorn addition
ULONG64 VfCrashDataBlock;
ULONG64 MmBadPagesDetected;
ULONG64 MmZeroedPageSingleBitErrorsDetected;
// Windows 7 addition
ULONG64 EtwpDebuggerData;
USHORT OffsetPrcbContext;
// Windows 8 addition
USHORT OffsetPrcbMaxBreakpoints;
USHORT OffsetPrcbMaxWatchpoints;
ULONG OffsetKThreadStackLimit;
ULONG OffsetKThreadStackBase;
ULONG OffsetKThreadQueueListEntry;
ULONG OffsetEThreadIrpList;
USHORT OffsetPrcbIdleThread;
USHORT OffsetPrcbNormalDpcState;
USHORT OffsetPrcbDpcStack;
USHORT OffsetPrcbIsrStack;
USHORT SizeKDPC_STACK_FRAME;
// Windows 8.1 Addition
USHORT OffsetKPriQueueThreadListHead;
USHORT OffsetKThreadWaitReason;
} KDDEBUGGER_DATA64, *PKDDEBUGGER_DATA64;
参考:
http://www.cnblogs.com/unixstudio/archive/2012/11/05/2755356.html
[培训]内核驱动高级班,冲击BAT一流互联网大厂工
作,每周日13:00-18:00直播授课