1.从一个问题开始:
操作系统如何得知当下正在运行的线程或者进程以及如何做到下一个将要运行的进程或线程?
“Windows内核有一个特殊的基本要求,就是只要CPU在内核中运行,就得使段寄存器Windows系统中段寄存器FS在用户空间指向TEB、而在系统空间则指向KPCR。”关于FS段寄存器有什么作用以及如何指向KPCR和TEB数据结构那就是另外一个回事了,下面我们先来看一下KPCR的定义吧,之所以如此是因为在之后我们介绍的线程里有关于TEB的调用,KPCR在WRK-v1.2\base\ntos\inc\i386.h或者是amd64.h里都有这个重要结构的定义:
typedef struct _KPCR {
union {
NT_TIB NtTib;
struct {
struct _EXCEPTION_REGISTRATION_RECORD *Used_ExceptionList;
PVOID Used_StackBase;
PVOID PerfGlobalGroupMask;
PVOID TssCopy;
ULONG ContextSwitches;
KAFFINITY SetMemberCopy;
PVOID Used_Self;
};
};
struct _KPCR *SelfPcr; // flat address of this PCR
struct _KPRCB *Prcb; // pointer to Prcb
KIRQL Irql; // do not use 3 bytes after this as
// HALs assume they are zero.
ULONG IRR;
ULONG IrrActive;
ULONG IDR;
PVOID KdVersionBlock;
struct _KIDTENTRY *IDT;
struct _KGDTENTRY *GDT;
struct _KTSS *TSS;
USHORT MajorVersion;
USHORT MinorVersion;
KAFFINITY SetMember;
ULONG StallScaleFactor;
UCHAR SpareUnused;
UCHAR Number;
UCHAR Spare0;
UCHAR SecondLevelCacheAssociativity;
ULONG VdmAlert;
ULONG KernelReserved[14]; // For use by the kernel
ULONG SecondLevelCacheSize;
ULONG HalReserved[16]; // For use by Hal
ULONG InterruptMode;
UCHAR Spare1;
ULONG KernelReserved2[17];
struct _KPRCB PrcbData;
} KPCR, *PKPCR;
从这个结构我是看不懂什么的,但是细心的我发现了一件事,这里面出现了一个KPRCB的结构,和我们的KPCR如此相似,所以立马找到这个结构的定义,在同一个文件里我们发现了它:
typedef struct _KPRCB {
USHORT MinorVersion;
USHORT MajorVersion;
struct _KTHREAD *CurrentThread;
struct _KTHREAD *NextThread;
struct _KTHREAD *IdleThread;
...
CCHAR CpuType;
CCHAR CpuID;
USHORT CpuStep;
struct _KPROCESSOR_STATE ProcessorState;
...
struct _KTHREAD *NpxThread;
ULONG InterruptCount;
ULONG KernelTime;
ULONG UserTime;
ULONG DpcTime;
ULONG DebugDpcTime;
ULONG InterruptTime;
...
volatile ULONGLONG IsrTime;
ULONGLONG SpareField1;
FX_SAVE_AREA NpxSaveArea;
PROCESSOR_POWER_STATE PowerState;
} KPRCB, *PKPRCB, *RESTRICTED_POINTER PRKPRCB;
这个结构是非常非常的长啊,也侧面的说明这个结构是非常重要的,我只是简单的选取了一部分内容,在这里我们发现有很多重要的信息,接下来就是对这个结构的很长的解释了,这个结构里我们终于可以简单的解答一下第一个问题了,KPRCB结构里有个专门指向CurrentThread的指针,还有下一个将要执行的线程指针了,简单的回顾一下:操作系统通过FS段寄存器指向KPCR结构,KPCR结构里有个指向KPCRB结构的内容项,而在KPCRB里面外面发现了一个KTHREAD结构的指针,指向当前正在运行的线程和接下来要运行的线程。
操作系统如何得知当下正在运行的线程或者进程以及如何做到下一个将要运行的进程或线程?
“Windows内核有一个特殊的基本要求,就是只要CPU在内核中运行,就得使段寄存器Windows系统中段寄存器FS在用户空间指向TEB、而在系统空间则指向KPCR。”关于FS段寄存器有什么作用以及如何指向KPCR和TEB数据结构那就是另外一个回事了,下面我们先来看一下KPCR的定义吧,之所以如此是因为在之后我们介绍的线程里有关于TEB的调用,KPCR在WRK-v1.2\base\ntos\inc\i386.h或者是amd64.h里都有这个重要结构的定义:
typedef struct _KPCR {
union {
NT_TIB NtTib;
struct {
struct _EXCEPTION_REGISTRATION_RECORD *Used_ExceptionList;
PVOID Used_StackBase;
PVOID PerfGlobalGroupMask;
PVOID TssCopy;
ULONG ContextSwitches;
KAFFINITY SetMemberCopy;
PVOID Used_Self;
};
};
struct _KPCR *SelfPcr; // flat address of this PCR
struct _KPRCB *Prcb; // pointer to Prcb
KIRQL Irql; // do not use 3 bytes after this as
// HALs assume they are zero.
ULONG IRR;
ULONG IrrActive;
ULONG IDR;
PVOID KdVersionBlock;
struct _KIDTENTRY *IDT;
struct _KGDTENTRY *GDT;
struct _KTSS *TSS;
USHORT MajorVersion;
USHORT MinorVersion;
KAFFINITY SetMember;
ULONG StallScaleFactor;
UCHAR SpareUnused;
UCHAR Number;
UCHAR Spare0;
UCHAR SecondLevelCacheAssociativity;
ULONG VdmAlert;
ULONG KernelReserved[14]; // For use by the kernel
ULONG SecondLevelCacheSize;
ULONG HalReserved[16]; // For use by Hal
ULONG InterruptMode;
UCHAR Spare1;
ULONG KernelReserved2[17];
struct _KPRCB PrcbData;
} KPCR, *PKPCR;
从这个结构我是看不懂什么的,但是细心的我发现了一件事,这里面出现了一个KPRCB的结构,和我们的KPCR如此相似,所以立马找到这个结构的定义,在同一个文件里我们发现了它:
typedef struct _KPRCB {
USHORT MinorVersion;
USHORT MajorVersion;
struct _KTHREAD *CurrentThread;
struct _KTHREAD *NextThread;
struct _KTHREAD *IdleThread;
...
CCHAR CpuType;
CCHAR CpuID;
USHORT CpuStep;
struct _KPROCESSOR_STATE ProcessorState;
...
struct _KTHREAD *NpxThread;
ULONG InterruptCount;
ULONG KernelTime;
ULONG UserTime;
ULONG DpcTime;
ULONG DebugDpcTime;
ULONG InterruptTime;
...
volatile ULONGLONG IsrTime;
ULONGLONG SpareField1;
FX_SAVE_AREA NpxSaveArea;
PROCESSOR_POWER_STATE PowerState;
} KPRCB, *PKPRCB, *RESTRICTED_POINTER PRKPRCB;
这个结构是非常非常的长啊,也侧面的说明这个结构是非常重要的,我只是简单的选取了一部分内容,在这里我们发现有很多重要的信息,接下来就是对这个结构的很长的解释了,这个结构里我们终于可以简单的解答一下第一个问题了,KPRCB结构里有个专门指向CurrentThread的指针,还有下一个将要执行的线程指针了,简单的回顾一下:操作系统通过FS段寄存器指向KPCR结构,KPCR结构里有个指向KPCRB结构的内容项,而在KPCRB里面外面发现了一个KTHREAD结构的指针,指向当前正在运行的线程和接下来要运行的线程。