当线程在内核模式下执行时,在FS寄存器中加载的是选择子30,用于寻址PCR结构体(基址0
xFFDFF000,界限0x00001FFF)。在NTDDK.H中远没有描述结构体所有的成员,只是其中不多
的部分。为了说明PCR中的成分信息,这里列出用于i386的结构体(Windows NT 4.0)
typedef struct _KPCR { // Size: 0xB10
/*000*/ NT_TIB NtTib;
/*01C*/ struct _KPCR* SelfPcr;
/*020*/ struct _KPRCB* Prcb; // Current PCB
/*024*/ KIRQL Irql; // Current IRQL
/*028*/ ULONG IRR;
/*02C*/ ULONG IrrActive;
/*030*/ ULONG IDR;
/*034*/ ULONG Reserved2;
/*038*/ struct _KIDTENTRY* ULONG IDT;
/*03C*/ struct _KGDTENTRY* GDT;
/*040*/ struct _KTSS* TSS;
/*044*/ USHORT MajorVersion; // 1
/*046*/ USHORT MinorVersion; // 1
/*048*/ KAFFINITY SetMember;
/*04C*/ ULONG StallScaleFactor;
/*050*/ UCHAR DebugActive;
/*051*/ UCHAR Number;
// End of official portion of KPCR
/*052*/ BOOLEAN VdmAlert;
/*053*/ UCHAR Reserved;
/*054*/ UCHAR KernelReserved[0x90-0x54];
/*090*/ ULONG SecondLevelCacheSize;
/*094*/ UCHAR HalReserved[0xD4-0x94];
/*0D4*/ ULONG InterruptMode;
/*0D8*/ ULONG Spare1;
/*0DC*/ UCHAR KernelReserved2[0x120-0xDC];
// Note that current thread is at offset 0x124 (pointer to KTHREAD)
// This essentially means that the 1st PRCB must match the active CPU
/*120*/ UCHAR PrcbData[0xB10-0x120]; // PCBs for all CPUs supported
} KPCR, *PKPCR;
PCR包含着指向PCRB(Processor Control Region)的指针,但实际上,PCRB位于PCR的偏移
0x120处,并且所有的向PCRB域的转换都是相对于PCR的起点的。在WINNT.H中描述了PCRB结构
体。这里给出整个结构体(Windows NT 4.0):
// 0x120 from KPCR
typedef struct _KPRCB {
/*000*/ USHORT MinorVersion;
/*002*/ USHORT MajorVersion;
/*004*/ struct _KTHREAD *CurrentThread;
/*008*/ struct _KTHREAD *NextThread;
/*00c*/ struct _KTHREAD *IdleThread;
/*010*/ CCHAR Number;
/*011*/ CCHAR Reserved;
/*012*/ USHORT BuildType;
/*014*/ KAFFINITY SetMember;
/*015*/ struct _RESTART_BLOCK *RestartBlock;
/*018*/ CCHAR CpuType;
/*019*/ CCHAR CpuID;
/*01A*/ CCHAR CpuStep;
/*01C*/ KPROCESSOR_STATE ProcessorState;
/*13C*/ CCHAR KernelReserved[0x40];
/*17C*/ CCHAR HalReserved[0x40];
/*1BC*/ ULONG NpxThread;
/*1C0*/ ULONG InterruptCount;
/*1C4*/ ULONG KernelTime;
/*1C8*/ ULONG UserTime;
/*1CC*/ ULONG DpcTime;
/*1D0*/ ULONG InterruptTime;
/*1D4*/ ULONG ApcBypassCount;
/*1D8*/ ULONG DpcBypassCount;
/*1DC*/ ULONG AdjustDpcThreshold;
/*1E0*/ UCHAR Spare2[0x14];
/*1F4*/ ULONG64 ThreadStartCount;
/*1FC*/ SINGLE_LIST_ENTRY FsRtlFreeSharedLockList;
/*200*/ SINGLE_LIST_ENTRY FsRtlFreeExclusiveLockList;
/*204*/ ULONG CcFastReadNoWait;
/*208*/ ULONG CcFastReadWait;
/*20C*/ ULONG CcFastReadNotPossible;
/*210*/ ULONG CcCopyReadNoWait;
/*214*/ ULONG CcCopyReadWait;
/*218*/ ULONG CcCopyReadNoWaitMiss;
/*21C*/ ULONG KeAlignmentFixupCount;
/*220*/ ULONG KeContextSwitches;
/*224*/ ULONG KeDcacheFlushCount;
/*228*/ ULONG KeExceptionDispatchCount;
/*22C*/ ULONG KeFirstLevelTbFills;
/*230*/ ULONG KeFloatingEmulationCount;
/*234*/ ULONG KeIcacheFlushCount;
/*238*/ ULONG KeSecondLevelTbFills;
/*23C*/ ULONG KeSystemCalls;
/*240*/ SINGLE_LIST_ENTRY FsRtlFreeWaitingLockList;
/*244*/ SINGLE_LIST_ENTRY FsRtlFreeLockTreeNodeList
/*248*/ CCHAR ReservedCounter[0x18];
/*260*/ PVOID SmallIrpFreeEntry;
/*264*/ PVOID LargeIrpFreeEntry;
/*268*/ PVOID MdlFreeEntry
/*26C*/ PVOID CreateInfoFreeEntry;
/*270*/ PVOID NameBufferFreeEntry
/*274*/ PVOID SharedCacheMapEntry
/*278*/ CCHAR CachePad0[8];
/*280*/ CCHAR ReservedPad[0x200];
/*480*/ CCHAR CurrentPacket[0xc];
/*48C*/ ULONG TargetSet;
/*490*/ PVOID WorkerRoutine;
/*494*/ ULONG IpiFrozen;
/*498*/ CCHAR CachePad1[0x8];
/*4A0*/ ULONG RequestSummary;
/*4A4*/ ULONG SignalDone;
/*4A8*/ ULONG ReverseStall;
/*4AC*/ ULONG IpiFrame;
/*4B0*/ CCHAR CachePad2[0x10];
/*4C0*/ ULONG DpcInterruptRequested;
/*4C4*/ CCHAR CachePad3 [0xc];
/*4D0*/ ULONG MaximumDpcQueueDepth;
/*4D4*/ ULONG MinimumDpcRate;
/*4D8*/ CCHAR CachePad4[0x8];
/*4E0*/ LIST_ENTRY DpcListHead;
/*4E8*/ ULONG DpcQueueDepth;
/*4EC*/ ULONG DpcRoutineActive;
/*4F0*/ ULONG DpcCount;
/*4F4*/ ULONG DpcLastCount;
/*4F8*/ ULONG DpcRequestRate;
/*4FC*/ CCHAR KernelReserved2[0x2c];
/*528*/ ULONG DpcLock;
/*52C*/ CCHAR SkipTick;
/*52D*/ CCHAR VendorString[0xf];
/*53C*/ ULONG MHz;
/*540*/ ULONG64 FeatureBits;
/*548*/ ULONG64 UpdateSignature;
/*550*/ ULONG QuantumEnd;
} KPRCB, *PKPRCB, *RESTRICTED_POINTER PRKPRCB;
PCRB中最有用的就是指向当前线程的指针(KTHREAD结构体)。通常内核代码以以下代码取得
此指针:
xFFDFF000,界限0x00001FFF)。在NTDDK.H中远没有描述结构体所有的成员,只是其中不多
的部分。为了说明PCR中的成分信息,这里列出用于i386的结构体(Windows NT 4.0)
typedef struct _KPCR { // Size: 0xB10
/*000*/ NT_TIB NtTib;
/*01C*/ struct _KPCR* SelfPcr;
/*020*/ struct _KPRCB* Prcb; // Current PCB
/*024*/ KIRQL Irql; // Current IRQL
/*028*/ ULONG IRR;
/*02C*/ ULONG IrrActive;
/*030*/ ULONG IDR;
/*034*/ ULONG Reserved2;
/*038*/ struct _KIDTENTRY* ULONG IDT;
/*03C*/ struct _KGDTENTRY* GDT;
/*040*/ struct _KTSS* TSS;
/*044*/ USHORT MajorVersion; // 1
/*046*/ USHORT MinorVersion; // 1
/*048*/ KAFFINITY SetMember;
/*04C*/ ULONG StallScaleFactor;
/*050*/ UCHAR DebugActive;
/*051*/ UCHAR Number;
// End of official portion of KPCR
/*052*/ BOOLEAN VdmAlert;
/*053*/ UCHAR Reserved;
/*054*/ UCHAR KernelReserved[0x90-0x54];
/*090*/ ULONG SecondLevelCacheSize;
/*094*/ UCHAR HalReserved[0xD4-0x94];
/*0D4*/ ULONG InterruptMode;
/*0D8*/ ULONG Spare1;
/*0DC*/ UCHAR KernelReserved2[0x120-0xDC];
// Note that current thread is at offset 0x124 (pointer to KTHREAD)
// This essentially means that the 1st PRCB must match the active CPU
/*120*/ UCHAR PrcbData[0xB10-0x120]; // PCBs for all CPUs supported
} KPCR, *PKPCR;
PCR包含着指向PCRB(Processor Control Region)的指针,但实际上,PCRB位于PCR的偏移
0x120处,并且所有的向PCRB域的转换都是相对于PCR的起点的。在WINNT.H中描述了PCRB结构
体。这里给出整个结构体(Windows NT 4.0):
// 0x120 from KPCR
typedef struct _KPRCB {
/*000*/ USHORT MinorVersion;
/*002*/ USHORT MajorVersion;
/*004*/ struct _KTHREAD *CurrentThread;
/*008*/ struct _KTHREAD *NextThread;
/*00c*/ struct _KTHREAD *IdleThread;
/*010*/ CCHAR Number;
/*011*/ CCHAR Reserved;
/*012*/ USHORT BuildType;
/*014*/ KAFFINITY SetMember;
/*015*/ struct _RESTART_BLOCK *RestartBlock;
/*018*/ CCHAR CpuType;
/*019*/ CCHAR CpuID;
/*01A*/ CCHAR CpuStep;
/*01C*/ KPROCESSOR_STATE ProcessorState;
/*13C*/ CCHAR KernelReserved[0x40];
/*17C*/ CCHAR HalReserved[0x40];
/*1BC*/ ULONG NpxThread;
/*1C0*/ ULONG InterruptCount;
/*1C4*/ ULONG KernelTime;
/*1C8*/ ULONG UserTime;
/*1CC*/ ULONG DpcTime;
/*1D0*/ ULONG InterruptTime;
/*1D4*/ ULONG ApcBypassCount;
/*1D8*/ ULONG DpcBypassCount;
/*1DC*/ ULONG AdjustDpcThreshold;
/*1E0*/ UCHAR Spare2[0x14];
/*1F4*/ ULONG64 ThreadStartCount;
/*1FC*/ SINGLE_LIST_ENTRY FsRtlFreeSharedLockList;
/*200*/ SINGLE_LIST_ENTRY FsRtlFreeExclusiveLockList;
/*204*/ ULONG CcFastReadNoWait;
/*208*/ ULONG CcFastReadWait;
/*20C*/ ULONG CcFastReadNotPossible;
/*210*/ ULONG CcCopyReadNoWait;
/*214*/ ULONG CcCopyReadWait;
/*218*/ ULONG CcCopyReadNoWaitMiss;
/*21C*/ ULONG KeAlignmentFixupCount;
/*220*/ ULONG KeContextSwitches;
/*224*/ ULONG KeDcacheFlushCount;
/*228*/ ULONG KeExceptionDispatchCount;
/*22C*/ ULONG KeFirstLevelTbFills;
/*230*/ ULONG KeFloatingEmulationCount;
/*234*/ ULONG KeIcacheFlushCount;
/*238*/ ULONG KeSecondLevelTbFills;
/*23C*/ ULONG KeSystemCalls;
/*240*/ SINGLE_LIST_ENTRY FsRtlFreeWaitingLockList;
/*244*/ SINGLE_LIST_ENTRY FsRtlFreeLockTreeNodeList
/*248*/ CCHAR ReservedCounter[0x18];
/*260*/ PVOID SmallIrpFreeEntry;
/*264*/ PVOID LargeIrpFreeEntry;
/*268*/ PVOID MdlFreeEntry
/*26C*/ PVOID CreateInfoFreeEntry;
/*270*/ PVOID NameBufferFreeEntry
/*274*/ PVOID SharedCacheMapEntry
/*278*/ CCHAR CachePad0[8];
/*280*/ CCHAR ReservedPad[0x200];
/*480*/ CCHAR CurrentPacket[0xc];
/*48C*/ ULONG TargetSet;
/*490*/ PVOID WorkerRoutine;
/*494*/ ULONG IpiFrozen;
/*498*/ CCHAR CachePad1[0x8];
/*4A0*/ ULONG RequestSummary;
/*4A4*/ ULONG SignalDone;
/*4A8*/ ULONG ReverseStall;
/*4AC*/ ULONG IpiFrame;
/*4B0*/ CCHAR CachePad2[0x10];
/*4C0*/ ULONG DpcInterruptRequested;
/*4C4*/ CCHAR CachePad3 [0xc];
/*4D0*/ ULONG MaximumDpcQueueDepth;
/*4D4*/ ULONG MinimumDpcRate;
/*4D8*/ CCHAR CachePad4[0x8];
/*4E0*/ LIST_ENTRY DpcListHead;
/*4E8*/ ULONG DpcQueueDepth;
/*4EC*/ ULONG DpcRoutineActive;
/*4F0*/ ULONG DpcCount;
/*4F4*/ ULONG DpcLastCount;
/*4F8*/ ULONG DpcRequestRate;
/*4FC*/ CCHAR KernelReserved2[0x2c];
/*528*/ ULONG DpcLock;
/*52C*/ CCHAR SkipTick;
/*52D*/ CCHAR VendorString[0xf];
/*53C*/ ULONG MHz;
/*540*/ ULONG64 FeatureBits;
/*548*/ ULONG64 UpdateSignature;
/*550*/ ULONG QuantumEnd;
} KPRCB, *PKPRCB, *RESTRICTED_POINTER PRKPRCB;
PCRB中最有用的就是指向当前线程的指针(KTHREAD结构体)。通常内核代码以以下代码取得
此指针: