KPCR与进程.md

KPCR与进程

KPCR

KPCR1

KPCR2

  • (Kernel) Processor Control Region
  • a KPCR for each logical processor
  • KPCR is the means through which the kernel manages them(processors).
  • 由于Windows需要支持多个CPU, 因此Windows内核中为此定义了一套以处理器控制区(Processor Control Region)即KPCR为枢纽的数据结构, 使每个CPU都有个KPCR. 其中KPCR这个结构中有一个域KPRCB(Kernel Processor Control Block)结构, 这个结构扩展了KPCR. 这两个结构用来保存与线程切换相关的全局信息.
  • 在和进程、线程相关的数据结构中,进程控制块和线程控制块是关键,通过这两个数据结构可以按图索骥找到其余的有关数据结构。Windows提供了一系列的获取进程控制块或者线程控制块的函数,
  • In 32-bit Windows, entering kernel mode gets fs loaded with a GDT selector (0x0030) for a segment whose base address is that of the processor’s KPCR.
  • The KPCR conveniently holds its own address in the SelfPcr or Self member, in 32-bit and 64-bit Windows respectively, so that reading just this one member using a segment register override makes the whole KPCR accessible without overrides(就是说KPCR提供了一个很方便的方式来获取其中的内容)
  • Beware, though, that this is the address of the KPCR for the processor that the thread was running on at the time: it remains the address of the current KPCR only while the thread can ensure it is not switched to another processor. (所以就是说每一个进程都会有一个KPCR;除非是线程保证不会转移到其他的processor,才会保持当前的KPCR不变)
  • Before version 6.0, space for the boot processor’s KPCR is allocated by the loader at the fixed address 0xFFDFF000.

KPCR与进程

KPCR2

浅谈一下FS段寄存器在用户层和内核层的使用

在和进程、线程相关的数据结构中,进程控制块和线程控制块是关键,通过这两个数据结构可以按图索骥找到其余的有关数据结构。Windows提供了一系列的获取进程控制块或者线程控制块的函数

首先Windows内核提供了一个函数KeGetCurrentThread函数,用来或者当前线程的KTHREAD结构指针,这个函数的实现方式将在后文中介绍,windows其他获取控制块的函数都是以此函数为基础进行封装的。

1.KeGetCurrentThread – - > PsGetCurrentThread

后者只是前者定义的一个宏。并加上了强制类型转换,因为ETHREAD的一个成员是KTHREAD结构,所以两者的首地址相同。

#define PsGetCurrentThread() ((PETHREAD)KeGetCurrentThread())

2.PsGetCurrentThread – - >IoGetCurrentProcess

IoGetCurrentProcess是以PsGetCurrentThread为基础,封装的函数。

这样,在“常态”下IoGetCurrentProcess所返回的是当前线程所属进程的EPROCESS结构指针,而在挂靠状态下则所返回的是当前线程所挂靠进程的EPROCESS结构指针。

3.IoGetCurrentProcess – - > PsGetCurrentProcess

后者是前者定义的一个宏。

#defind PsGetCurrentProcess IoGetCurrentProcess

4.PsGetCurrentProcess – - > KeGetCurrentProcess

KeGetCurrentProcess是以PsGetCurrentProcess为基础封装的函数,返回值为KPROCESS指针。

PsGetCurrentThread –>IoGetCurrentProcess

KTHREAD(KPROCESS)有是ETHREAD(EPROCESS)结构中的第一个元素,所以两者的地址是一样的

thread和process之间的关系就是挂靠关系,也就是给一个thread可以找到他所依附的process的地址信息。

ETHREAD.Tcb.ApcState.Process指向了该线程对应(或者挂靠)的进程。
ETHREAD.Tcb指向的就是该线程的KTHREAD结构。
内核如何获得当前运行线程的KTHREAD结构

Windows内核中,为每个CPU分配了一套“处理器控制区(Processor Control Region)”,简称KPCR结构。该结构中存放着与线程切换相关的全局信息,包括所需的寄存器和其他的数据结构。

KPCR第三个变量是指向一个“处理器控制块”,即KPRCB数据结构.

KPRCB结构中的第三个成员变量是KTHREAD类型的CurrentThread变量,该变量指向了当前线程的KTHREAD数据结构.

当CPU运行于内核中时,段寄存器FS(所选择的段描述块)总是指向该CPU的KPCR结构的起点,而KPCR中位移为0x1c的字段为Self,指向其所在的KPCR结构的起点。找到CPU的KPCR结构,就可以找到其KPCRB结构,并进而找到其CurrentThread了。

KTHREAD(KPROCESS)有是ETHREAD(EPROCESS)结构中的第一个元素,所以两者的地址是一样的

thread和process之间的关系就是挂靠关系,也就是给一个thread可以找到他所依附的process的地址信息。

ETHREAD.Tcb.ApcState.Process指向了该线程对应(或者挂靠)的进程。
ETHREAD.Tcb指向的就是该线程的KTHREAD结构。

KPCR—KPCRB----current_thread

typedef struct _KPCR {
  KPCR_TIB	Tib;					/* 00 */
  struct _KPCR	*Self;				/* 1C */
  struct _KPRCB	*Prcb;				/* 20 */
  KIRQL	Irql;						/* 24 */
  ULONG	IRR;						/* 28 */
  ULONG	IrrActive;					/* 2C */
  ULONG	IDR;						/* 30 */
  PVOID	KdVersionBlock;				/* 34 */
  PUSHORT	IDT;						/* 38 */
  PUSHORT	GDT;						/* 3C */
  struct _KTSS	*TSS;				/* 40 */
  USHORT	MajorVersion;				/* 44 */
  USHORT	MinorVersion;				/* 46 */
  KAFFINITY	SetMember;				/* 48 */
  ULONG	StallScaleFactor;			/* 4C */
  UCHAR	DebugActive;				/* 50 */
  UCHAR	ProcessorNumber;			/* 51 */
  UCHAR	Reserved;					/* 52 */
  UCHAR	L2CacheAssociativity;		/* 53 */
  ULONG	VdmAlert;					/* 54 */
  ULONG	KernelReserved[14];			/* 58 */
  ULONG	L2CacheSize;				/* 90 */
  ULONG	HalReserved[16];			/* 94 */
  ULONG	InterruptMode;				/* D4 */
  UCHAR	KernelReserved2[0x48];		/* D8 */
  KPRCB	PrcbData;					/* 120 */
} KPCR, *PKPCR;

/* ProcessoR Control Block */
typedef struct _KPRCB {
  USHORT MinorVersion;
  USHORT MajorVersion;
  struct _KTHREAD *CurrentThread;
  struct _KTHREAD *NextThread;
  struct _KTHREAD *IdleThread;
  . . . . . .
  UCHAR CpuType;
  UCHAR CpuID;
  USHORT CpuStep;
  KPROCESSOR_STATE ProcessorState;
  . . . . . .
  PVOID LockQueue[33];	// Used for Queued Spinlocks
  struct _KTHREAD *NpxThread;
  ULONG InterruptCount;
  ULONG KernelTime;
  ULONG UserTime;
  . . . . . .
  struct _KEVENT *DpcEvent;
  UCHAR ThreadDpcEnable;
  BOOLEAN QuantumEnd;
  . . . . . .
  LONG MmPageReadCount;
  LONG MmPageReadIoCount;
  LONG MmCacheReadCount;
  LONG MmCacheIoCount;
  LONG MmDirtyPagesWriteCount;
  . . . . . .
  FX_SAVE_AREA NpxSaveArea;
  PROCESSOR_POWER_STATE PowerState;
} KPRCB, *PKPRCB;
kd> dt _KPRCB
nt!_KPRCB
   +0x000 MinorVersion     : Uint2B
   +0x002 MajorVersion     : Uint2B
   +0x004 CurrentThread    : Ptr32 _KTHREAD
   +0x008 NextThread       : Ptr32 _KTHREAD
   +0x00c IdleThread       : Ptr32 _KTHREAD
 
kd> dt _KTHREAD
nt!_KTHREAD
   +0x000 Header           : _DISPATCHER_HEADER
   +0x010 MutantListHead   : _LIST_ENTRY
   +0x018 InitialStack     : Ptr32 Void
   +0x01c StackLimit       : Ptr32 Void
   +0x020 Teb              : Ptr32 Void
   +0x024 TlsArray         : Ptr32 Void
   +0x028 KernelStack      : Ptr32 Void
   +0x02c DebugActive      : UChar
   +0x02d State            : UChar
   +0x02e Alerted          : [2] UChar
   +0x030 Iopl             : UChar
   +0x031 NpxState         : UChar
   +0x032 Saturation       : Char
   +0x033 Priority         : Char
   +0x034 ApcState         : _KAPC_STATE
kd> dt _KAPC_STATE
nt!_KAPC_STATE
   +0x000 ApcListHead      : [2] _LIST_ENTRY
   +0x010 Process          : Ptr32 _KPROCESS
   +0x014 KernelApcInProgress : UChar
   +0x015 KernelApcPending : UChar
   +0x016 UserApcPending   : UChar

展开KPRCB结构继续观察可以看到FS:[0x124]指向了KTHREAD结构

fs寄存器在Ring0中指向一个称为KPCR的数据结构,即FS段的起点与KPCR结构对齐。而在Ring0中fs寄存器一般为0x30

这样fs:[124]就指向KPRCB数据结构的第四个字节。由于KPRCB比较大,再此就不列出来了。查看其数据结构可以看到第四个字节指向CurrentThead(KTHREAD类型)。这样fs:[124]其实是指向当前线程的_KTHREAD。

一些名词

TSS

a Task State Segment (TSS), defining the current task on the processor;

ETHREAD

an ETHREAD, representing the system thread for the processor’s initial execution;

GDT

the Global Descriptor Table (GDT) for the processor;

IDT

the Interrupt Descriptor Table (IDT) for the processor.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值