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环需要哪些寄存器改变

  1. CS的权限由3变为0,意味着需要新的CS
  2. SS与CS的权限永远一致,需要新的SS
  3. 权限发生切换的时候,堆栈也一定会改变,需要新的ESP
  4. 进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环(上)的更多相关文章

  1. Windows系统调用中API的3环部分(依据分析重写ReadProcessMemory函数)

    Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html Windows系统调用中API的3环部分 一.R3环API分析的重 ...

  2. Windows系统调用中API从3环到0环(下)

     Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html Windows系统调用中API从3环到0环(下) 如果对API在 ...

  3. Windows系统调用中的系统服务表描述符

     Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html Windows系统调用中的系统服务表描述符 在前面,我们将解过 ...

  4. Windows系统调用中的现场保存

    Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html Windows系统调用中的现场保存 我们之前介绍过三环进零环的步骤 ...

  5. Windows系统调用中的系统服务表

    Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html Windows系统调用中的系统服务表 如果这部分不理解,可以查看  ...

  6. KiSystemCall64 win10 21h2函数流程分析 3环到0环

    0x00基本信息 系统:windows 10 21h2 工具:ida 7.7 , windbg 10 3环写一个win32k 函数 看访问流程 0x01分析 例如:3环函数 FlattenPath(x ...

  7. WSL2:在Windows系统中开发Linux程序的又一神器

    作 者:道哥,10+年的嵌入式开发老兵. 公众号:[IOT物联网小镇],专注于:C/C++.Linux操作系统.应用程序设计.物联网.单片机和嵌入式开发等领域. 公众号回复[书籍],获取 Linux. ...

  8. 如何在windows 11中安装WSLG(WSL2)

    什么是 WSL WSL(Windows Subsystem for Linux):Windows 系统中的一个子系统,在这个子系统上可以运行 Linux 操作系统. 可以让开发人员直接在 Window ...

  9. 使用 Puppet 在 Windows Azure 中配备 Linux 和 Windows 环境

     发布于 2013-12-11 作者 Ross Gardler 微软开放技术有限公司 (MS Open Tech) 很高兴地宣布发行新的 Windows Azure Puppet 模块.通过这个模 ...

随机推荐

  1. oracle用imp导入dmp文件

    oracle命令行登录 sqlplus 用户名/密码 创建用户 create user 用户 identified by 密码 ; 创建表空间 create tablespace 表空间名 dataf ...

  2. Spring MVC+ajax进行信息验证

    本文是一个ajax结合Spring MVC使用的入门,首先我们来了解一下什么是Ajax AJAX 不是新的编程语言,而是一种使用现有标准的新方法.AJAX 最大的优点是在不重新加载整个页面的情况下,可 ...

  3. Winform中怎样根据Name获取同窗体的控件

    场景 在同一个Winform窗体中,点击一个Button按钮时, 获取同窗体的其他控件的属性. 首先需要对要获取的控件赋予Name属性,然后就可以通过Name进行获取. 实现 在Button的点击事件 ...

  4. HBase介绍、安装与应用案例

    搭建环境 部署节点操作系统为CentOS,防火墙和SElinux禁用,创建了一个shiyanlou用户并在系统根目录下创建/app目录,用于存放 Hadoop等组件运行包.因为该目录用于安装hadoo ...

  5. JDK13,不如温习下Java8

    JDK13于9月17号正式GA,版本新特性可参考: https://www.oschina.net/news/109934/jdk-13-released 虽然JDK更新迅速,但开发者貌似并不买账,据 ...

  6. Java8虚拟机(JVM)内存溢出实战

    前言 相信很多JAVA中高级的同学在面试的时候会经常碰到一个面试题 你是如何在工作中对JVM调优和排查定位问题的? 事实上,如果用户量不大的情况下,在你的代码还算正常的情况下,在工作中除非真正碰到与J ...

  7. Android 使用URLConnection下载音频文件

    本文链接: Android 使用URLConnection下载音频文件 使用MediaPlayer播放在线音频,请参考Android MediaPlayer 播放音频 有时候我们会需要下载音频文件.这 ...

  8. Docker学习之docker架构

    docker架构 解释 1.docker命令提交给docker daemon进行处理,可以拖取镜像,运行容器等等. 2.最右边的实际上是互联网的sass服务,docker daemon可以和Regis ...

  9. [C++] 重载运算符与类型转换(2)——函数调用运算符和类型转换运算符

    1.这两个应该是C++中比较高级的用法了. 一.函数调用运算符   1.重载函数调用运算符(),必须是成员函数,一个类可以定义多个不同版本的调用运算符,相互之间应该在参数数量或者类型上有所区别.   ...

  10. Moonraker 靶机渗透

    0x01 简介 攻击Moonraker系统并且找出存在最大的威胁漏洞,通过最大威胁漏洞攻击目标靶机系统并进行提权获取系统中root目录下的flag信息. Moonraker: 1镜像下载地址: htt ...