avatar

Catalog
KPCR
  • 进程在内核中对应结构体:EPROCESS
  • 线程在内核中对应结构体:ETHREAD
  • CPU在内核中也有一个对应的结构体:KPCR(Processor Control Region)

KPCR结构我们已经很熟悉了,在API函数的调用过程中,多次使用到了KPCR,也简要介绍过一点。在保存现场之前有一个步骤就是将fs寄存器写入0x30,并根据GDT表,让fs寄存器指向KPCR。

KPCR介绍

  1. 当线程进入0环时,FS:[0]指向KPCR(3环时FS:[0] -> TEB)
  2. 每个CPU都有一个KPCR结构体(一个核一个)
  3. KPCR中存储了CPU本身要用的一些重要数据:GDT、IDT以及线程相关的一些信息。
  4. 在Windbg中执行指令:dt _KPCR 查看KPCR结构
  5. 结构图:

KPCR成员

+0x000 NtTib

  • 成员名:NtTib
  • 数据类型:_NT_TIB
  • 说明:KPCR的第一个成员,存储部分关键信息(TEB的第一个成员也是这个结构
  • 结构图:

+0x000 ExceptionList

  • 成员名:ExceptionList
  • 数据类型:Ptr32 _EXCEPTION_REGISTRATION_RECORD
  • 说明:指向当前线程的异常链表(SEH),包含了当前线程的异常处理函数。Ring0(KPRC的ExceptionList)和Ring3(TEB的ExceptionList)的异常处理函数不同

+0x004 StackBase/+0x008 StackLimit

  • 成员名:StackBase/StackLimit
  • 数据类型:Ptr32 Void
  • 说明:当前线程内核栈的基址和大小(KPCR中的是Ring0相关,TEB中就是Ring3相关

+0x018 Self

  • 成员名:Self
  • 数据类型:Ptr32 _NT_TIB
  • 说明:指向自己(也就是指向_NT_TIB结构)这样设计的目的是为了查找方便。Ring0->KPCR,Ring3->TEB

+0x01c SelfPcr

  • 成员名:SelfPcr
  • 数据类型:Ptr32 _KPCR
  • 说明:指向自己,方便寻址

+0x020 Prcb

  • 成员名:Prcb
  • 数据类型:Ptr32 _KPRCB
  • 说明:指向扩展结构体KPRCB

+0x038 IDT

  • 成员名:IDT
  • 数据类型:Ptr32 _KIDTENTRY
  • 说明:指向IDT表首地址

+0x03c GDT

  • 成员名:GDT
  • 数据类型:Ptr32 _KGDTENTRY
  • 说明:指向GDT表首地址

+0x040 TSS

  • 成员名:TSS
  • 数据类型:Ptr32 _KTSS
  • 说明:指向TSS,每个CPU都有一个TSS

+0x051 Number

  • 成员名:Number
  • 数据类型:UChar
  • 说明:CPU编号

+0x120 PrcbData

  • 成员名:PrcbData
  • 数据类型:_KPRCB
  • 说明:KPCR的扩展结构体
  • 结构图:

KPRCB结构体

KPRCB(Kernel Processor Control Block)是KPCR的扩展结构体

+0x004 CurrentThread

成员名:CurrentThread

数据类型:Ptr32 _KTHREAD

说明:指向当前线程的KTHREAD

+0x008 NextThread

成员名:CurrentThread

数据类型:Ptr32 _KTHREAD

说明:指向下一个要执行线程的KTHREAD

+0x00c IdleThread

成员名:IdleThread

数据类型:Ptr32 _KTHREAD

说明:指向空闲线程的KTHREAD

+0x88c QuantumEnd

成员名:QuantumEnd

数据类型:Uint4B

说明:CPU时间片标志

关系梳理

在简单了解完进程结构体(EPROCESS)、线程结构体(ETHREAD)、CPU结构体(KPCR)以后,来梳理一下它们之间的关系。

已知进程

遍历进程:PsActiveProcessHead -> ActiveProcessLinks(EPROCESS+0x88)……

遍历线程:PsActiveProcessHead -> ActiveProcessLinks(EPROCESS+0x88) -> ThreadListHead(KPROCESS+0x50 / EPROCESS+0x190) -> ThreadListEntry(KTHREAD+0x1b0 / ETHREAD+0x22c)……

已知线程

遍历进程:ETHREAD+0x220 -> EPROCESS -> ActiveProcessLinks(EPROCESS+0x88)……

遍历线程:ETHREAD+0x22c / ETHREAD+0x1b0 -> ThreadListEntry……

已知KPCR

遍历进程:进入0环后 -> fs:[0] -> KPCR -> PrcbData(KPCR+0x120) -> CurrentThread(KPRCB+0x4) -> EPROCESS(ETHREAD+0x220) -> ActiveProcessLinks(EPROCESS+0x88)……

遍历线程:进入0环后 -> fs:[0] -> KPCR -> PrcbData(KPCR+0x120) -> CurrentThread(KPRCB+0x4) -> ETHREAD+0x22c / ETHREAD+0x1b0 -> ThreadListEntry……

参考教程:https://www.bilibili.com/video/BV1NJ411M7aE?p=45

参考文档:张嘉杰笔记

Author: cataLoc
Link: http://cata1oc.github.io/2020/03/30/KPCR/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
    微信
  • 支付寶
    支付寶