从一节的学习,相信大家已经知道了系统调用时,进入内核层时各寄存器的值从哪里来,但是并没有介绍原寄存器的值要存到哪里去,这一节主要就是介绍进入0环前(3环)的所有寄存器的值要存到哪里去
0x01 Trap Frame 结构
无论是通过中断门进入0环,还是通过快速调用进入0环,进入0环前(3环)的所有寄存器的值都会存到这个结构体中。这个结构体本身处于0环,由windows操作系统进行维护。当程序通过中断门从3环进入0环时,ESP指向TrapFrame+0x64的位置。当程序通过快速调用从3环进入0环时,ESP指向TrapFrame+0x78的位置。
在保护模式下,最后四个成员(0x7C~0x88)并没有被使用,因此无需考虑;只有在虚拟8086模式下,才会用到当中断门执行时,3环的SS、ESP、EFLAGS、CS、EIP会被存储到结构体的0x68~0x78中,而执行快速调用时不会
若通过中断门进入0环,在KiSystemService函数开始执行时,3环的SS、ESP、EFLAGS、CS、EIP就已经被存储到 TrapFrame 结构体中了。而TrapFrame 结构体的其它成员通过 KiSystemService 和 KiFastCallEntry 进行赋值。但不管是 KiSystemService 还是 KiFastCallEntry,最终都要执行一部分相同的代码,分为两个函数是因为进入0环时,堆栈里的值不一样,走同一条函数会出问题
0x02 系统服务表
系统服务表(System Service Table,SST),共有两张,第一张表后紧接第二张表,表里的函数都是来自内核文件导出的函数。但它并不包含内核文件导出的所有函数,而仅是3环最常用的内核函数。系统服务表位于 _KTHREAD +00xE0 处,其本质是一个个结构体
|
|
0x03 系统服务描述符表
系统服务描述符表(System Services Descriptor Table,SSDT),SSDT的每个成员叫做系统服务表(SST)。SSDT的第一个成员是导出的,声明一下即可使用;SSDT的第二个成员是未导出的,需要通过其它方式查找。在Windows中,SSDT的第三个成员和第四个成员未被使用。
在WinDbg中查看已导出成员:
在WinDbg中查看未导出成员:
实验:在SSDT中查找内核函数信息
在之前的实验中,我们通过分析三环的ReadProcessMemory函数,一步步了解三环函数是如何进入内核的。我们应该看到了当ReadProcessMemory即将进入内核时,传递了一个系统服务号,为0BAh。本次实验查找编号 0xBA 在 SSDT 表中的相关信息
查SSDT表,找到函数地址表与参数表:
函数地址表:
[函数地址表 + 系统服务号*4] = 内核函数地址
参数表:
[参数表 + 系统服务号] = 内核函数参数个数(单位:字节)
查看内核函数反汇编: