Windows(IA-32e模式)系统调用

news/2025/1/17 16:02:48/

一、本文主题

        Windows NT是一个面向分层的操作系统,最底层是硬件,最高层使用户接口,Windows采用这种模式来保护内核不被应用程序错误的波及,操作系统核心运行在内核层(Ring 0 ),用户模式运行在应用层(Ring 3)。这只是操作系统分层的抽象概念。而本文旨在讨论Windows操作系统在IA-32e模式下从Ring3进入Ring0的部分具体实现过程,也会对比IA-32模式下的部分差异。本文IA-32e测试系统为Windows 10 2004。

二、系统调用

        Windows操作系统通过任务门、陷阱门、中断门三种途径进入内核。其中任务门通过应用层执行syscall指令后,执行系统调用分发函数KiSystemCall64Shadow,这个函数的地址存放在IA32_LSTAR(0xc0000082)的MSR寄存器中。

        当我们从应用层调用一个API时,会通过应用层的ntdll进入内核,在执行syscall指令时,寄存器按照一些规则改变,本文举例介绍一些:

①将syscall下一条指令地址存放在rcx寄存器中

②将rip设置为IA32_LSTAR寄存器中的值

③cs寄存器中Selector字段值设置为IA32_STAR(0xc0000081)寄存器中32位到47位的值与0xFFFC的值

④SS寄存器Selector字段为IA32_STAR(0xc0000081)寄存器中32位到47位的值与0xFFFC再加8的值

        所以在调用syscall指令之前,还需要一些准备工作,将函数在SSDT表中的索引号存放在rax寄存器中,将rcx的值放入r10寄存器中。

        首先我们在ntdll!NtOpenProcess处下一个断点,在KiSystemCall64Shadow函数内下第二个硬件断点(注意在KiSystemCall64Shadow下断点需要在swapgs指令后下断点,断点处理函数需要用内核堆栈,如果在swapgs处下断点,会卡死)。

        首先在ntdll!NtOpenProcess中下断点,然后运行后windbg在NtOpenProcess中断下,然后在KiSystemCall64Shadow中下一个硬件断点。运行后在KiSytemCall64Shadow中断下。

        接着找到KeServiceDescriptorTable结构体指针,这是一个未公开的结构体,不过已经有人将这个结构体逆出来,结构体如下:

typedef struct _KSERVICE_TABLE_DESCRIPTOR

{

        PVOID  Tablebase;

        PULONG   ServiceCountBase;

        ULONG64  ServiceNumber;

        PVOID ParameterNumer;

}KSERVICE_TABLE_SECRIPTOR,*PKSERVICE_TABLE_DESCRIPTOR;

         在 lea     r10, KeServiceDescriptorTable处下一个断点,动态调试观察代码可了解r11和r10值的关系。

         而这两张表的关系如图所示:

 从图中的关系我们不难理解取SSDT表中函数地址的过程:

        在获得函数地址后,接着便是拷贝参数,执行函数。最后调用sysret,sysret指令和syscall指令情况相反,恢复用户层堆栈,将返回地址放入rcx,执行后会将rcx的值设为rip。

三、异常

         异常分为中断、错误、陷阱。

        在处理器执行一条指令时,有可能会陷入异常。比如除0错误。异常一般分为错误和陷阱。比如缺页异常,当页面从pagefile写入物理内存,挂上物理页面之后,会从原指令处执行。比如syscall这样的指令,属于陷阱,返回后从下一条指令处开始执行。在Intel的x64中,定义了一个表项为256的IDT表。而中断和异常的区别为,中断和陷阱的区别在于,中断处理函数执行时会关中断(清IF标记位),而陷阱则不会清IF标志位。中断门描述符各部分如下。

        DPL为触发中段权限检查,如处于Ring3,只能触发DPL为3的中断,而Ring0则可以触发DPL为0或者3的中断。

        下图为Windows 10 2004中断的部分中断门描述符和函数地址。

         比如第0项,门描述符为6b628e00`0010a100 00000000`fffff801函数地址为0xfffff8016b62a100,P为1,DPL为0(这个中断3环不能触发),TYPE为6,IST为0(IST为0,说明使用的为IST0栈,这个值需要在GDT表所指向的TSS中索引),在x64中intel芯片手册中写到Segmentation is not used,在GDT表中也只有一个TSS段。

        第2项,门描述符为6b628e03`0010a240 00000000`fffff801函数地址为0xfffff8016b62a240P为1,DPL为0,TYPE为6,IST为3,这个不可屏蔽中断使用的栈指针为0xFFFFF8016E7567D0,为上图中IST3的数值,寻找这个表,首先读取tr寄存器的值,其大小为TSS段描述符在GDT表中的偏移,TSS段描述符有128位,解析得到地址,这个地址就为上图地址。

        本文参考: Intel® 64 and IA-32 Architectures Software Developer’s Manual

学习过程中还有很多不足,还望朋友们指正!

 


http://www.ppmy.cn/news/892691.html

相关文章

Windows x64内核学习笔记(二)—— IA-32e模式

Windows x64内核学习笔记(二)—— IA-32e模式 IA-32e模式模式检测强制平坦段任务切换中断门描述符FS / GS模式切换32位程序进内核64位程序进内核 实验:模式切换第一步:编译以下代码第二步:运行程序至第一次暂停处第三步…

手把手教玩转你动态内存管理(InsCode Stable Diffusion 美图活动一期)

目录https://inscode.csdn.net/inscode/Stable-Diffusion 一、动态内存管理的意义 二、动态内存管理函数 1.malloc和free 1.1认识malloc和free 1.2malloc和free的作用 1.3使用malloc和free时应注意的事项 1.3.1使用malloc注意事项 1.3.2使用free注意事项 1.4使用free和…

github进不去的解决办法

github就凭运气进吧,偶尔能进去。 介绍几个可以快速进的办法: 第一个,安装插件:(在microsoft搜索watt toolkit插件并安装) 然后勾选github选项: 接着返回你github网站就可以了。 第二个&#…

【Python爬虫案例学习8】python爬取淘宝里的手机报价并以价格排序

第一步: 先分析这个url,”?“后面的都是它的关键字,requests中get函数的关键字的参数是params,post函数的关键字参数是data, 关键字用字典的形式传进去,这样我们就可以自己改关键字去搜索别的…

linux centos7 静默安装 oracle 11g,【亲测有效】,包含远程连接、提供安装包

Centos7 安装oracle11g 环境准备 操作系统 centos7 oracle版本 oracle11g 终端软件 MobaXterm 192.168.46.61 oracleMaster 安装包 网盘地址 一、安装前准备 1、关闭selinux [rootoracleMaster ~]# vim /etc/selinux/config修改 SELINUX 为 disabled # This file controls …

Django实现简单的音乐播放器 4

在原有音乐播放器功能基础上,增加上传音乐功能。 效果: 目录 配置上传路径 配置路由 视图处理歌曲 引入类库 保存歌曲文件 模板上传 设置菜单列表 设置菜单列表样式 脚本设置 上传效果 1.显示菜单列表 2.点击上传歌曲 3.上传完成 4.查看保…

Html5视频video标签中调用blob地址,实现视频安全

Html5视频video标签中调用blob地址,实现视频安全 后端代码参考: /** 在这里可以进行权限验证等操作*///创建文件对象 File f new File("E:\\test.mp4"); //获取文件名称 String fileName f.getName(); //导出文件 String agent getRequest…

Html5视频video标签中使用blob实现视频播放加密

后端代码: /** 在这里可以进行权限验证等操作*///创建文件对象 File f new File("E:\\test.mp4"); //获取文件名称 String fileName f.getName(); //导出文件 String agent getRequest().getHeader("User-Agent").toUpperCase(); InputStre…