Windows系统调用学习笔记(二)—— 3环进0环

要点回顾

上一篇我们分析了ReadProcessMemory这个函数的3环部分

  1. ReadProcessMemory函数存在于kernel32.dll
  2. 它并没有做什么,只是调用了另一个函数(NtReadVirtualMemory),然后设置了一些返回值
  3. NtReadVirtualMemory函数来自ntdll.dll
  4. NtReadVirtualMemory也没做什么,只是提供了一个编号(0BAh)和一个函数地址(7FFE0300h),然后进行了内核调用

本篇将弄清这个 函数地址(7FFE0300h) 是什么

基本概念

_KUSER_SHARED_DATA

  1. 在 User 层和 Kernel 层分别定义了一个 _KUSER_SHARED_DATA 结构区域,用于 User 层和 Kernel 层共享某些数据
  2. 它们使用固定的地址值映射,_KUSER_SHARED_DATA结构区域在User层Kernel层地址分别为:
    User:0x7ffe0000
    Kernnel:0xffdf0000
    _KUSER_SHARED_DATA内存
    注意:虽然指向的是同一个物理页,但在User层是只读的,在Kernnel层是可写

0x7FFE0300

描述
当通过eax=1来执行cpuid指令时,处理器的特征信息被放在ecxedx寄存器中,其中edx包含了一个SEP位(11位),该位指明了当前处理器知否支持sysenter/sysexit指令

  • 支持
    ntdll.dll! KiFastSystemCall()
  • 不支持
    ntdll.dll! KiIntSystemCall()
实验:判断CPU是否支持快速调用
第一步:修改EAX=1

EAX=1

第二步:将当前汇编指令修改为cpuid

cpuid

第三步:清空ECX与EDX

清空ECX与EDX

第四步:执行cpuid,观察结果

执行cpuid

第五步:观察EDX的SEP位(第11位)

0xBFF = 二进制:1011 1111 1111

SEP=1,说明当前CPU支持 sysenter / sysexit 指令

3环进0环

基本步骤

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

中断门进0环

分析 KiIntSystemCall

KiIntSystemCall
该函数函数只执行了两行代码

分析

  1. 第一行将参数的地址放入EDX
  2. 第二行调用了0x2e中断(所有的API进内核时,统一的中断号为0x2e)

注意:在执行KiIntSystemCall函数前,编号已被写入EAX

分析 INT 0x2E
第一步:在IDT表中找到0x2E号门描述符

0x2e门描述符
门描述符:804dee00`0008e7d1
指向地址:804de7d1

第二步:分析CS/SS/ESP/EIP的来源

CS:门描述符的段选择子部分(0008)
SS:从段选择子指向的TSS段描述符指向的TSS表中取出
ESP:从段选择子指向的TSS段描述符指向的TSS表中取出
EIP:804de7d1

第三步:查看门描述符指向的EIP

反汇编
nt表示当前函数为内核函数

快速调用进0环

快速调用

  1. 中断门进0环,需要的CSEIP在IDT表中,需要查内存(SS与ESP由TSS提供)
  2. CPU如果支持sysenter指令,操作系统会提前将CS/SS/ESP/EIP的值存储在MSR寄存器中,sysenter指令执行时,CPU会将MSR寄存器中的值直接写入相关寄存器,没有读内存的过程,所以叫快速调用,它们的本质是一样的
分析 KiFastSystemCall

KiFastSystemCall
该函数函数只执行了两行代码

分析

  1. 第一行将当前栈顶(esp)的值放入edx
  2. 第二行执行了sysenter指令

注意:在执行KiIntSystemCall函数前,编号已被写入EAX

分析 sysenter指令

注意

  1. 在执行sysenter指令之前,操作系统必须指定0环的CS段SS段EIP以及ESP
  2. 其中,CS段EIP以及ESP来自MSR寄存器
MSR寄存器

描述:MSR寄存器非常庞大,这里只列出三个值,详细信息参照Intel白皮书
MSR寄存器
可以通过RDMSR/WRMST来进行读写(操作系统使用WRMST写该寄存器):

  1. kd> rdmsr 174 //查看CS
  2. kd> rdmsr 175 //查看ESP
  3. kd> rdmsr 176 //查看EIP
    rdmsr
    查看EIP所在地址的反汇编
    EIP
    nt表示当前函数为内核函数

注意
4. 在执行sysenter指令时,只有CSESPEIP三个寄存器的值可从MSR寄存器中获得,其中并不包括SS!
5. SS= IA32_SYSENTER_CS + 8
6. 这些操作与操作系统无关,而是硬件(CPU)做的(详情参考Intel白皮书第二卷)

总结

API通过中断门进0环

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

API通过sysenter指令进0环

  1. CS/ESP/EIP由MSR寄存器提供(SS是算出来的)
  2. 进入0环后执行的内核函数:NT!KiFastCallEntry

内核模块

10-10-12分页:ntoskrnl.exe
2-9-9-12分页:ntkrnlpa.exe

练习

要求:通过IDA找到KiSystemServiceKiFastCallEntry函数并分析

问题:

  1. 进0环后,原来的寄存器存在哪里?
  2. 如何根据系统调用号(eax中存储)找到要执行的内核函数?
  3. 调用时参数是存储到3环的堆栈,如何传递给内核函数?
  4. 2种调用方式是如何返回到3环的?

答案:见下篇

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值