系统调用-KiFastCallEntry逆向分析

   

Sysenter

在旧的CPU架构中操作系统使用中断(Windows使用:int 0x2E)实现系统调用,现在的CPU都支持快速系统调用(Fast System Call)。

   

快速调用使用指令sysenter进0环,下面是《Intel白皮书》对sysenter执行过程的描述:

1. Loads the segment selector from the IA32_SYSENTER_CS into the CS register.

2. Loads the instruction pointer from the IA32_SYSENTER_EIP into the EIP register.

3. Adds 8 to the value in IA32_SYSENTER_CS and loads it into the SS register.

4. Loads the stack pointer from the IA32_SYSENTER_ESP into the ESP register.

5. Switches to privilege level 0.

6. Clears the VM flag in the EFLAGS register, if the flag is set.

扫描二维码关注公众号,回复: 10238507 查看本文章

7. Begins executing the selected system procedure.

简单总结一下就是:从多个MSR寄存器中获取CS、EIP、SS、ESP的值并填充,其中SS是通过公式:CS+8计算出来的。

   

在用WinDbg可以使用命令(Read MSR):rdmsr Address 查看MSR内容。

kd> rdmsr 174

msr[174] = 00000000`00000008

   

kd> rdmsr 175

msr[175] = 00000000`f8ac2000

   

kd> rdmsr 176

msr[176] = 00000000`8053e540

   

中断和sysenter都可以到到进入0环的目的,sysenter由于数据通过MSR寄存器读取而不是读取内存,所以执行效率上相对的速度要高。

但执行后结果会有一定的差别:堆栈的内容不同。通过中断的方式进入0环,3环的SS、ESP、EFLAGS、CS、EIP会把CPU压入到堆栈,但sysenter则并不会压入这几个寄存器的值。 这也是为什么Windows要分别给中断和快速调用准备0环入口。

   

   

找到KiFastCallEntry

通过上面获取到的MSR[IA32_SYSENTER_EIP]可以得知Windows快速调用的0环入口函数地址为:0x8053e540。

   

kd> u 8053e540

nt!KiFastCallEntry:

8053e540 b923000000 mov ecx,23h

8053e545 6a30 push 30h

8053e547 0fa1 pop fs

8053e549 8ed9 mov ds,cx

8053e54b 8ec1 mov es,cx

8053e54d 8b0d40f0dfff mov ecx,dword ptr ds:[0FFDFF040h]

8053e553 8b6104 mov esp,dword ptr [ecx+4]

8053e556 6a23 push 23h

   

   

   

切换寄存器

一进入KiFastCallEntry会立即修改fs/ds/es/esp这几个寄存器.

 

比较有意思的是

  1. fs使用的是立即数0x30,
  2. ds/es则是立即数0x23.
  3. esp则直接切换成了TSS.Esp0.

 

    

保存现场

int2e会自动把ss/esp/eflags/cs/eip这5个寄存器压入堆栈, 但快速调用不会, 所以要手动push这5个寄存器到堆栈.

值得注意的是:KTRAP_FRAME.Eip被设置成了SystemCallReturn的地址.

   

   

   

   

   

最后

最后的代码和KiSystemService非常相似. 在这段代码执行完毕后, 会直接跳到SharedCode.

   

猜你喜欢

转载自www.cnblogs.com/joneyyana/p/12585503.html
今日推荐