12323

系统调用-KiSystemService

2020年3月16日

17:07

找到KiSystemService

通过分析3环的调用过程可以知道, 系统调用会使用int 2e进入0环. 2e就是中断向量. 对应了IDT中索引为2e的中断描述符.

 

通过WinDbg在IDT中找到索引为2e的中断描述符, 并分析描述符的字段.

可以看到这个中断描述符的目标代码段(CS段)是0008, 这是一个0环的代码段.

中断处理函数地址是 0x8053E481, 这个地址对应的就是 KiSystemService

 

 

 

12323

 

 

保存现场

如果发生了特权等级提升. CPU会依次把3环的SS/ESP/EFLAGS/CS/EIP压入0环的堆栈.这意味着, 当CPU执行到KiSystemService的时候, 堆栈中已经压入了这5个3环的寄存器.

 

进入到KiSystemService首先看到的是6个push. 这是在保存现场.

12323

 

其实Windows用了结构体KTRAP_FRAME来保存现场. Windows设定TSS.Esp0指向的是 KTRAP_FRAME+7C.

+78对应的是字段HardwareSegSs. +74则是HardwareEsp,+70:Eflags, +6C:SegCs, +68:Eip.

 

12323

 

 

 

切换FS

Windows设计FS.Base指向的是KPCR结构, 所以0环处理函数.会切换FS.

Windows对每个处理器都使用一个KPCR结构保存辅助信息.如果你只有一个处理器, 这个KPCR结构有一个固定的地址:0xFFDFF000.

 

可以看到KiSystemService中切换了FS为0x30.这个0x30对应的是GDT中Index为6的段描述符, 这个段描述符的Base刚好就是0xFFDFF0000.

12323

12323

12323

 

 

设置异常链表

KiSystemService会把原本保存在KPCR中的ExceptionList保存在KTRAP_FRAME.Exception中.

并把KPCR的ExceptionList置为-1, 表明当前异常链表为空.

12323

 

设置先前模式

KiSystemService把当前线程的PreviousMode(先前模式)备份到KTRAP.PreviousMode中.并计算PreviousMode后存到当前线程结构ETHREAD.PreviousMode中.

Windows只使用了3环/0环, CS的CPL只有两种情况:3或者0, 3 and 1 = 1;0 and 1 = 0;

所以PreviousMode 为1时表示先前模式是用户模式, 为0时表示先前模式是内核模式.

 

12323

 

 

保存调试相关

在KiSystemService中保存了一些DbgXxx字段.同时还会判断线程的DebugActive, 如果bit0~7有一位不是0, 就会去保存调试相关的寄存器.

12323

 

跳转到SharedCode

可以看到在KiSystemService中并没有开始调用系统函数. 而是在最后跳入到另一份代码中.

在跳转前使用指令sti打开了中断, 这是因为在执行int 2e后CPU会把中断位关闭.

12323

 

Created with Microsoft OneNote 2016.

上一篇:# 《Think Python 2e》学习精粹合集(更新至第七章)


下一篇:《Think Python 2e》作业实现(四): 案例研究—接口设计