Windows系统调用中API从3环到0环(上)
Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html
Windows系统调用中API从3环到0环(上)
如果对API在三环的部分不了解的,可以查看 Windows系统调用中的API三环部分(依据分析重写ReadProcessMemory函数
这篇文章分为上下两篇,其中上篇初步讲解大体轮廓,下篇着重通过实验来探究其内部实现,最终分析两个函数(快速调用与系统中断),来实现通过系统中断直接调用内核函数。
一、结构体 _KUSER_SHARED_DATA
该结构体看名字可知是用于内核层与用户层来共享数据所使用的结构体。
kd > dt _KUSER_SHARED_DATA
ntdll!_KUSER_SHARED_DATA
+ 0x000 TickCountLowDeprecated : Uint4B
+ 0x004 TickCountMultiplier : Uint4B
+ 0x008 InterruptTime : _KSYSTEM_TIME
+ 0x014 SystemTime : _KSYSTEM_TIME
+ 0x020 TimeZoneBias : _KSYSTEM_TIME
+ 0x02c ImageNumberLow : Uint2B
+ 0x02e ImageNumberHigh : Uint2B
·······
1)在User层和KerNel层分别定义了一个_KUSER_SHARED_DATA结构区域,用于User层和Kernel层共享某些数据。
2)它们使用同一段页,只是映射位置不同。虽然同一页,但User只读,Kernnel层可写。
3)它们使用固定的地址值映射,_KUSER_SHARED_DATA结构在User为:0x7ffe0000,在Kernel层为:0xffdf0000。
通过windbg可以查看其中两块内存完全一样(实质查看的是同一物理页,挂在两块页表PTT中。

二、分析 0X7FFE0300 这个地址
在 <&ntdll.NtReadVirtualMemory> 中调用 ntdll.KiFastSystemCall 函数 ,实质就是调用 0X7FFE0300 这个地址。
77A162F8 > B8 15010000 mov eax,0x115 // 对应操作系统内核中某一函数的编号。
77A162FD BA 0003FE7F mov edx,0x7FFE0300 // 该地方是一个函数,该函数决定了什么方式进零环。
77A16302 FF12 call dword ptr ds:[edx] ; ntdll.KiFastSystemCall
1)_KUSER_SHARED_DATA 在用户层的位置为 0x7FFE0000,该地址为其+0x300位置
+0x300 SystemCall : Uint4B
2)该成员保存着系统调用的函数入口,如果当前CPU支持快速调用。
则存储着ntdll.dll!KiFastSystemCall()函数地址;
如果不支持快速调用,则存储着ntdll.dll!KiIntSystemCall()函数地址。
3)通过实验验证当前CPU是否支持快速调用:
当通过eax=1来执行cupid指令时,处理器特征信息被存放在ecx和edx寄存器中,
其中edx包含了SEP位(11位),该位指明了当前处理器是否支持sysenter/sysexit指令。

如下图,我们执行cupid指令,获取edx 178BFBFF,拆分 11-8位 B 1011,故其11位为1,支持快速调用。
这也验证了我们上一篇文章中的分析结果。(最后是快速调用并非使用中断门)
三、从3环进0环需要哪些寄存器改变
- CS的权限由3变为0,意味着需要新的CS
- SS与CS的权限永远一致,需要新的SS
- 权限发生切换的时候,堆栈也一定会改变,需要新的ESP
- 进0环后的代码位置,需要EIP
四、ntdll.dll!KiIntSystemCall() 分析
我们使用ida来分析ntdll.dll!KiIntSystemCall()
.text:77F070C0
.text : 77F070C0 public KiIntSystemCall
.text : 77F070C0 KiIntSystemCall proc near; DATA XREF : .text : off_77EF61B8↑o
.text : 77F070C0
.text : 77F070C0 arg_4 = byte ptr 8
.text : 77F070C0 // 之前调用该函数时 mov eax, 0x115,向eax传入一个函数号
.text : 77F070C0 lea edx, [esp + arg_4] // 当前参数的指针存储在 edx中
.text : 77F070C4 int 2Eh; // 通过中断门的形式进入到内核中
.text:77F070C4; DS:SI->counted CR - terminated command string
.text : 77F070C6 retn
.text : 77F070C6 KiIntSystemCall endp
其在触发 int 2eh中断前用到两个寄存器,一个是内核中调用函数的函数号,另外一个就是传入参数的指针。
五. ntdll.dll!KiFastSystemCall()函数分析
当CPU支持快速调用,则使用这个函数。(我们在上篇文章中已经用到了这个来重构WriteProcessMemory函数)
.text:77F070B0 public KiFastSystemCall
.text:77F070B0 KiFastSystemCall proc near ; DATA XREF: .text:off_77EF61B8↑o
.text:77F070B0 // 之前调用该函数时 mov eax, 0x115,向eax传入一个函数号
.text:77F070B0 mov edx, esp // 将当前堆栈放入edx,用它来存储参数
.text:77F070B2 sysenter
.text:77F070B2 KiFastSystemCall endp
触发sysenter指令后,也用到两个寄存器eax,edx,作用与使用中断一样。
为什么叫快速调用?
中断门进入0环,需要的CS、EIP在IDT表中,需要查内存(SS与ESP由IDT表提供);
而CPU如果支持sysenter指令时,操作系统会提前将CS/SS/ESP/EIP的值存储在MSR寄存器中,
sysenter指令执行时,CPU会将MSR寄存器中的值直接写入寄存器中,没有读内存过程,本质时一样的。
下一篇,我们探究其中的详细细节。
Windows系统调用中API从3环到0环(上)的更多相关文章
- Windows系统调用中API的3环部分(依据分析重写ReadProcessMemory函数)
Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html Windows系统调用中API的3环部分 一.R3环API分析的重 ...
- Windows系统调用中API从3环到0环(下)
Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html Windows系统调用中API从3环到0环(下) 如果对API在 ...
- Windows系统调用中的系统服务表描述符
Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html Windows系统调用中的系统服务表描述符 在前面,我们将解过 ...
- Windows系统调用中的现场保存
Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html Windows系统调用中的现场保存 我们之前介绍过三环进零环的步骤 ...
- Windows系统调用中的系统服务表
Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html Windows系统调用中的系统服务表 如果这部分不理解,可以查看 ...
- KiSystemCall64 win10 21h2函数流程分析 3环到0环
0x00基本信息 系统:windows 10 21h2 工具:ida 7.7 , windbg 10 3环写一个win32k 函数 看访问流程 0x01分析 例如:3环函数 FlattenPath(x ...
- WSL2:在Windows系统中开发Linux程序的又一神器
作 者:道哥,10+年的嵌入式开发老兵. 公众号:[IOT物联网小镇],专注于:C/C++.Linux操作系统.应用程序设计.物联网.单片机和嵌入式开发等领域. 公众号回复[书籍],获取 Linux. ...
- 如何在windows 11中安装WSLG(WSL2)
什么是 WSL WSL(Windows Subsystem for Linux):Windows 系统中的一个子系统,在这个子系统上可以运行 Linux 操作系统. 可以让开发人员直接在 Window ...
- 使用 Puppet 在 Windows Azure 中配备 Linux 和 Windows 环境
发布于 2013-12-11 作者 Ross Gardler 微软开放技术有限公司 (MS Open Tech) 很高兴地宣布发行新的 Windows Azure Puppet 模块.通过这个模 ...
随机推荐
- SpringBoot系列——Security + Layui实现一套权限管理后台模板
前言 Spring Security官网:https://spring.io/projects/spring-security Spring Security是一个功能强大且高度可定制的身份验证和访问 ...
- eclipse搭建springmvc
https://www.cnblogs.com/qixing/p/qixing.html
- 【学习笔记】第二章 python安全编程基础---正则表达式
一.python正则表达式 定义:正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式相匹配: 1.1RE模块:是python语言拥有全部的正则表达式功能的一个正则模块: 常见 ...
- rocketmq学习(一) rocketmq介绍与安装
1.消息队列介绍 消息队列本质上来说是一个符合先进先出原则的单向队列:一方发送消息并存入消息队列尾部(生产者投递消息),一方从消息队列的头部取出消息(消费者消费消息).但对于一个成熟可靠的消息队列来说 ...
- request的请求转发
1.请求转发和重定向的区别 重定向: 请求转发: 可以看出,请求转发只需要发起一次请求,与重定向不同,请求转发发生在服务器内部.请求转发后浏览器的地址不会改变. 2.request请求转发 需要建立两 ...
- 为什么使用B+Tree索引?
什么是索引? 索引是一种数据结构,具体表现在查找算法上. 索引目的 提高查询效率 [类比字典和借书] 如果要查"mysql"这个单词,我们肯定需要定位到m字母,然后从下往下找到y字 ...
- 13 (OC)* SDWebImage
IOS SDWebImage实现原理详解 在之前我写过SDWebImage的使用方法,主要是用与获取网络图片,没有看过的朋友可以看看. 这篇文章将主要介绍SDWebImage的实现原理,主要针对于 ...
- nginx如何配置负载均衡
自己学习用 面试回答如下: 在nginx里面配置一个upstream,然后把相关的服务器ip都配置进去.然后采用轮询的方案,然后在nginx里面的配置项里,proxy-pass指向这个upstream ...
- BCD 码、Gray 码、ASCII 码都是什么呢?
BCD 码:即(Binary Coded Decimal)码,也称为 8421 码,是十进制代码中最常见的一种.每一位的 1 代表的十进制数称为这一位的权.BCD 码中每一位的权都是固定不变的,它属于 ...
- 抓住那只牛!Catch That Cow POJ-3278 BFS
题目链接:Catch That Cow 题目大意 FJ丢了一头牛,FJ在数轴上位置为n的点,牛在数轴上位置为k的点.FJ一分钟能进行以下三种操作:前进一个单位,后退一个单位,或者传送到坐标为当前位置两 ...