首页
社区
课程
招聘
[原创]pspcidtable之旅 (win8.1 x86) [更新:通过KPCR获取pspcidtable地址]
2013-12-4 09:43 11175

[原创]pspcidtable之旅 (win8.1 x86) [更新:通过KPCR获取pspcidtable地址]

2013-12-4 09:43
11175
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直播授课

收藏
点赞1
打赏
分享
最新回复 (4)
雪    币: 110
活跃值: (293)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ling林 2013-12-4 15:43
2
0
Object Address = (Object/ObjectPointerBits & 0xFFFFFFF8) | 0x80000000
能讲解下这个公式吗? 其中"/"表示什么意思,怎么算出了8486e440值的
雪    币: 110
活跃值: (34)
能力值: (RANK:50 )
在线值:
发帖
回帖
粉丝
phpskycn 1 2013-12-4 16:03
3
0
句柄表结构没有大变化么?
雪    币: 241
活跃值: (55)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
wjshome 1 2013-12-4 20:42
4
0
你可以参考这个帖子:
http://bbs.pediy.com/showthread.php?t=170205

估计是作者笔误,我猜测公式应该这样:

WINDBG>dt _HANDLE_TABLE_ENTRY
nt!_HANDLE_TABLE_ENTRY
   +0x000 VolatileLowValue : Int4B
   +0x000 LowValue         : Int4B
   +0x000 InfoTable        : Ptr32 _HANDLE_TABLE_ENTRY_INFO
   +0x000 Unlocked         : Pos 0, 1 Bit
   +0x000 Attributes       : Pos 1, 2 Bits
   +0x000 ObjectPointerBits : Pos 3, 29 Bits
   +0x004 HighValue        : Int4B
   +0x004 NextFreeHandleEntry : Ptr32 _HANDLE_TABLE_ENTRY
   +0x004 LeafHandleValue  : _EXHANDLE
   +0x004 GrantedAccessBits : Pos 0, 25 Bits
   +0x004 ProtectFromClose : Pos 25, 1 Bit
   +0x004 NoRightsUpgrade  : Pos 26, 1 Bit
   +0x004 RefCnt           : Pos 27, 5 Bits

看到ObjectPointerBits是Pos 3, 29 Bits,所以
Object Address = (ObjectPointerBits & 0x3FFFFFF8) | 0x80000000

请验证。
雪    币: 97
活跃值: (141)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
啤酒肚 2014-1-6 23:20
5
0
这不是笔误,作者的意思是,win7 32位用object,win8 32位中用ObjectPointerBits
游客
登录 | 注册 方可回帖
返回