Windows内核重要结构体

  • Post author:
  • Post category:其他


前言

Windows操作系统的内核代码使用C和汇编进行编写,内核中最重要的就是一些结构体和算法,了解了这些结构体后可以帮助我们对内核的代码进行分析。本文将介绍四个非常重要的结构体。


TRAP_FRAME

结构体是由操作系统维护的一块数据,在内核层用来保存用户层现场的结构体(例如线程在用户层进行系统服务函数调用、中断、异常和在内核层执行APC调用时线程都要暂时将用户层的现场保存在TRAP_FRAME中),该结构体地址由每一个线程的KTHREAD.TrapFrame成员指定,Windbg中使用

dt nt!_KTRAP_FRAME

查看其结构。


EPROCESS

结构体是Windows系统中的每一个进程在内核层描述进程信息的结构体, 这个结构体包含了进程所有的重要的信息。在Winbbg中 使用

dt _EPROCESS

查看EPROCESS结构体的信息。


ETHREAD

结构体,每一个线程在内核层都有一个对应的结构体,该结构体保存了与线程相关的所有信息。在Windbg中 使用dt _ETHREAD查看ETHREAD结构体的信息。


KPCR

结构体,描述了当前CPU的各种状态,包括当前CPU正在运行的线程的部分经常使用的信息,每一个CPU都有一个对应的结构体,Windbg中通过

dd KeNumberProcessors

查看当前操作系统的CPU数量,通过d

d KiProcessorBlock Lxxx

查看xxx个KPCR结构体的地址。

注意

: dd KiProcessorBlock 显示的数据对应的是KPCR结尾的地址,应当减去KPCR结构体的大小。

他们的结构关系如下图所示:


注意

:teb.NtTib指向的地址不等于KPCR.NtTib

Trap_Frame

使用Windbg查看TRAP_FRAME的结构:

使用图形来进行表述:

值得注意的是:

在保护模式下,并不使用最下方的紫色4个成员。

在中断模式下如果发生提权,中断门会将用户层的5个寄存器压入对应的5个成员中(Eip,SegCs,EFlags、HardwareEsp和HardwareSegSs);如果未发生提权只会将用户层的3个成员压入对应的成员中(Eip,SegCs和EFlags)。

EPROCESS(进程内核对象)

EPROCESS结构体包含了KPROCESS结构体,使用Windbg查看EPROCESS的结构体如下

对EPROCESS结构体中的重要成员进行说明(使用偏移进行说明到底在KPROCESS中还是在EPROCESS中)

01) +0x000

Header

: _DISPATCHER_HEADER //“可等待”对象,比如Mutex互斥体、Event事件等(WaitForSingleObject)

02) +0x018

DirectoryTableBase

: [2] Uint4B //页目录表的基址

03) +0x020

LdtDescriptor

: _KGDTENTRY

+0x028

Int21Descriptor

: _KIDTENTRY //历史遗留,16位Windows 段选择子不够 每个进程都有一个LDT表,Int21Descriptor 是 DOS下要用的

04) +0x038

KernelTime

: Uint4B

+0x03c

UserTime

: Uint4B //统计信息 记录了一个进程在内核模式/用户模式下所花的时间

05) +0x05c

Affinity

: Uint4B //规定进程里面的所有线程能在哪些个CPU上跑,第i位为1表示能在第i个核上运行。Xp是4个字节共32位,所以最多32核 Windows64位就64核。当设置运行的CPU不存在时进程无法运行。64位的操作系统将不适用。

06) +0x062

BasePriority

: Char //基础优先级或最低优先级 该进程中的所有线程最起码的优先

07) +0x070

CreateTime

: _LARGE_INTEGER

+0x078

ExitTime

: _LARGE_INTEGER//进程的创建/退出时间

08) +0x084

UniqueProcessId

: Ptr32 Void //进程的编号(就是在任务管理器中的PID)

09) +0x088

ActiveProcessLinks

: _LIST_ENTRY//双向链表,将所有的活动进程都连接在一起,构成了一个链表,进程结构体们彼此拴着各自的腰。而PsActiveProcessHead符号指向全局链表头。如下图所示表述了活动的进程

11) +0x090

QuotaUsage

: [3] Uint4B //物理页相关的统计信息

12) +0x09c

QuotaPeak

: [3] Uint4B //物理页相关的统计峰值信息

13) +0x0a8

CommitCharge

: Uint4B

+0x0ac

PeakVirtualSize

: Uint4B

+0x0b0

VirtualSize

: Uint4B //虚拟内存相关的统计信息

14) +0x11c

VadRoot

: Ptr32 Void //一颗平衡二叉树,标识0-2G哪些地址没占用了,记录了模块映射信息。

15) +0x0bc

DebugPort

: Ptr32 Void

+0x0c0

ExceptionPort

: Ptr32 Void //调试相关,如果被调试了DebugPort保存调试对象的地址

16) +0x0c4

ObjectTable

: Ptr32 _HANDLE_TABLE//句柄表,记录了被当前进程打开的所有的句柄

17) +0x174

ImageFileName

: [16] Uchar//进程镜像文件名 最多16个字节

18) +0x1a0

ActiveThreads

: Uint4B//活动线程的数量

19) +0x1b0

Peb

: Ptr32 _PEB//PEB((Process Environment Block 进程环境块):进程在3环的一个结构体,里面包含了进程的模块列表、是否处于调试状态等信息。

PEB(进程环境块)

PEB是处在用户层的一个数据结构,记录了进程的相关信息,该结构留在用户层主要是减少频繁的进入内核层查询数据,以提高系统的运行速度。PEB结构体成员如下图所示,部分重要成员已在图中进行说明。

ETHREAD(线程内核对象)

ETHREAD结构体包含了KTHREAD结构体,使用Windbg查看ETHREAD结构体如下:

对ETHREAD结构体中的重要成员进行说明(使用偏移进行说明到底在KTHREAD中还是在ETHREAD中)

01) +0x000

Header

: _DISPATCHER_HEADER//“可等待”对象,比如Mutex互斥体、Event事件等(WaitForSingleObject)

02) +0x018

InitialStack

: Ptr32 Void

+0x01c

StackLimit

: Ptr32 Void

+0x028

KernelStack

: Ptr32 Void//与线程切换相关

03) +0x020

Teb

: Ptr32 Void //TEB,Thread Environment Block,线程环境块。大小4KB,位于用户地址空间。线程在用户层FS:[0] = TEB,线程在内核层FS[0]=KPCR(线程在3环时FS[0]指向它的teb,在0环时FS[0]指向KPCR结构体)

04) +0x02c

DebugActive

: UChar//如果值为-1,将不能使用调试寄存器:Dr0 – Dr7

05) +0x034

ApcState

: _KAPC_STATE

+0x0e8

ApcQueueLock

: Uint4B

+0x138

ApcStatePointer

: [2] Ptr32 _KAPC_STATE

+0x14c

SavedApcState

: _KAPC_STATE//与APC相关

06) +0x02d

State

: UChar //线程状态:就绪、等待还是运行

07) +0x06c

BasePriority

: Char//其初始值是所属进程的BasePriority值(KPROCESS->BasePriority),以后可以通过KeSetBasePriorityThread()函数重新设定

08) +0x070

WaitBlock

: [4] _KWAIT_BLOCK//记录了当前线程在进行同步时等待了哪些个对象(WaitForSingleObject)

09) +0x0e0

ServiceTable

: Ptr32 Void //指向系统服务表基址(Windows vista后已弃用)

10) +0x134

TrapFrame

//进0环时保存环境

11) +0x140

PreviousMode

: Char//某些内核函数会判断程序是0环调用还是3环调用的

12) +0x1b0

ThreadListEntry

: _LIST_ENTRY//双向链表 一个进程所有的线程 都挂在一个链表中挂的就是这个位置,一共有两个这样的链表

13) +0x1ec

Cid

: _CLIENT_ID //线程ID

14) +0x220

ThreadsProcess

: Ptr32 _EPROCESS//指向自己所属进程的EPROCESS地址

15) +0x22c

ThreadListEntry

: _LIST_ENTRY//是一个双向链表,一个进程所有的线程都挂在这个链表中,挂的就是这个位置,一共有两个这样的链表。(如下图所示,进程的所有线程通过链表拴住各自的腰)

KPCR(CPU控制区)

简介:

1) 当线程从3环进入0环时,FS:[0]指向KPCR(3环时FS:[0] 指向TEB结构体)

2) 每个CPU都有一个KPCR结构体(一个核一个)

3) KPCR中存储了CPU本身要用的一些重要数据:GDT、IDT以及线程相关的一些信息。(只是为了快而使用KPCR),在Windbg中使用命令dt _kpcr查看KPCR结构体的成员,如下图所示

KPCR内的重要成员已在下图中进行说明

转载于:https://www.cnblogs.com/wf751620780/p/10588949.html