Windows内核-系统调用

API函数调用过程3环

比较重要的3环DLL:

Kernel32.dll

User32.dll

GDI32.dll

Ntdll.dll

以ReadProcessMemory为例

image20200913200340251.png

对于大部分3环的WinAPI,都只是一个接口,

例如ReadProcessMemory是三环的函数,由kernel32.dll提供,而该函数只是调用了NtReadVirtualMemory

image20200913202520945.png

基本上带Nt开头函数,都是由Ntdll.dll提供,而Ntdll.dll是进0环的一个dll,所以在

image20200913202750493.png

ntdll中可以发现,mov eax, 3Fh,这里提供了一个编号,通过这个编号,找到对应的函数,进入0环

API函数调用过程 3环进0环

_KUSER_SHARED_DATA

在User层和Kernel层分别定义了一个_KUSER_SHARED_DATA结构区域,用于共享数据

使用固定的地址值进行映射,

User层中的地址为0x7FFE0000

Kernel层中的地址为0xFFDF0000

指向的是同一个物理页,但在User层是只读,Kernel层是可写的

进0环需要修改哪些寄存器:

  1. CS的权限由3变为0,意味着需要新的CS
  2. SS与CS的权限永远一致,需要新的SS
  3. 权限发生切换的时候,堆栈也需要切换,需要新的ESP
  4. 进0环后代码的位置,需要EIP

是否支持快速调用

支持:ntdll.dll!KiFastSystemCall

mov edx, esp
sysenter

不支持:ntdll.dll!KiIntSystemCall

该函数通过中断门的方式实现3环进0环,

lea edx, [esp+arg_4]
int 2Eh

retn

不管是通过快速调用还是通过中断门方式,其本质都是一样的,都是通过寻找CS、SS、ESP、EIP四个寄存器的方式进入0环。

中断门的方式进入0环,需要的CS、EIP在IDT表中,所以需要查内存,SS和ESP由TSS提供

而快速调用的本质就是绕过查内存,直接将CS、SS、ESP、EIP的值存储到MSR寄存器中,通过查MSR寄存器提高进入0环的速度,所以称为快速调用

通过中断门进0环:

  1. 固定中断号为0x2E
  2. CS/EIP由门描述符提供 ESP/SS由TSS提供
  3. 进入0环后执行的内核函数:NT!KiSystemService

通过sysenter指令进入0环:

  1. CS/ESP/EIP由MSR寄存器提供,SS不是直接存在MSR寄存器中的,而是通过计算得到的
  2. 进入0环后执行的内核函数:NT!KiFastCallEntry

内核模块:ntoskrnl.exe/ntkrnlpa.exe

未完待续。。。

avatar