前言

我们 ring 3 跳转 ring0 另一种方式使用sysenter命令。

sysenter 相比起jmp,int xx方式相比速度更快,因为sysenter指令大量的使用了MSR寄存器 存储跳转地址等。

MSR寄存器相关读/写命令

//读取msr寄存器
rdmsr xxxx
//写入msr寄存器
wrmsr xxxx

其中xxx是msr寄存器的编号比如174h等

为方便记忆我们约定了一些编号的名字
IA32_SYSENTER_CS (MSR address 174H)
IA32_SYSENTER_EIP (MSR address 176H)
IA32_SYSENTER_ESP (MSR address 175H)

上面上个寄存器就是sysenter指令会涉及的msr寄存器。

sysenter 规范

以32位操作系统举例说明这个指令相关流程.

sysenter 段描述符约定

使用这个intel 指令操作系统必须要做出如下妥协:
ring0 的ds段描述符必然是ring0 的 cs+8.我们可以简述成: ds0=cs0+8
ring3 的cs和ds描述如下: cs3= CS0 + 16 ,ds3= CS0 + 24.
也就是我们可以通过任意一个段描述符下标反推出其他段描述符下标。
我们可以利用windbg验证win32系统是否按照如此规定。

上图编号是16进制。

0008 00000000 ffffffff Code RE Ac 0 Bg Pg P  Nl 00000c9b
0010 00000000 ffffffff Data RW Ac 0 Bg Pg P  Nl 00000c93
0018 00000000 ffffffff Code RE Ac 3 Bg Pg P  Nl 00000cfb
0020 00000000 ffffffff Data RW Ac 3 Bg Pg P  Nl 00000cf3

第一个序号0x8是cs0,第二个序号是ds0 也就是 0x8+0x8=0x10.往后递推。

sysenter 调用约定

调用sysenter 前需要准备给以下寄存器准备数据
IA32_SYSENTER_CS (MSR address 174H) 存储跳转到ring0 的cs段描述符下标
IA32_SYSENTER_EIP (MSR address 176H) 存储跳转 ring0 的eip
IA32_SYSENTER_ESP (MSR address 175H) 存储跳转 ring0 的ESP

当调用SYSEXIT 时需要提前填充如下数据
edx 存储返回到ring3 EIP
ecx 存储返回到ring3 ESP

上述便是intel中的一些规范,在windwow中在这个基础做了一层封装。

window 封装sysenter

windowsysenter 构建了一个复杂的数据结构(内部包含函数地址表,参数数量表),所有在sysenter 会首先统一跳转到相同内核处理函数,在跳转前需要将参数提前压入栈中以及调用的函数下标以及服务表数组下标放入eax。内核分发函数首先会读取eax服务表下标,然后读取服务表的下标,然后从这表中( 系统服务描述表(system service descriptor table))根据eax传入的函数下标取出函数地址,以及对应的参数数量,然后拷贝ring3 栈参数到ring0 在执行跳转。

首先需要知道的知识:
window服务表数组,当前有两个数组我们分别取名为KeServiceDescriptorTable,KeServiceDescriptorTableShadow,数组长度上限大小为4。
KeServiceDescriptorTable内部包含非ui内核函数,当前这个数组元素数量只有1个。
KeServiceDescriptorTableShadow包含了ui内核函数和非ui函数,当前元素元素数量只有2个且其中一个元素和KeServiceDescriptorTable相同。

类似结构如下

typedef struct _SYSTEM_SERVICE_TABLE
{PVOID ServiceTableBase; //这个指向系统服务函数地址表PULONG ServiceCounterTableBase;ULONG NumberOfService; //服务函数的个数ULONG ParamTableBase;
}SYSTEM_SERVICE_TABLE,*PSYSTEM_SERVICE_TABLE;typedef struct _SERVICE_DESCRIPTOR_TABLE
{SYSTEM_SERVICE_TABLE ntoskrnel; //ntoskrnl.exe的服务函数SYSTEM_SERVICE_TABLE win32k; //win32k.sys的服务函数,(gdi.dll/user.dll的内核支持)SYSTEM_SERVICE_TABLE NotUsed1;SYSTEM_SERVICE_TABLE NotUsed2;
}SYSTEM_DESCRIPTOR_TABLE,*PSYSTEM_DESCRIPTOR_TABLE;SYSTEM_DESCRIPTOR_TABLE KeServiceDescriptorTable = { ntoskrnel=itemAddr };SYSTEM_DESCRIPTOR_TABLE KeServiceDescriptorTableShadow = { itemAddr,itemAddr2 };

当然需要注意的是KeServiceDescriptorTable 是一个被ntoskrnel导出的变量(KeServiceDescriptorTableShadow并没有在win32k.sys导出)

所以你可以在代码中直接使用类似如下的代码直接找到地址

    extern SYSTEM_DESCRIPTOR_TABLE KeServiceDescriptorTable;

关于如何获取另一个表可参阅:
Windows下如何获得KeServiceDescriptorTableShadow地址

我们用windbg验证我们的想法

我们查看这个两个数据结构第一个地址的存储的函数地址


你会发现当前进程对应的ui函数地址都是空的,是因为当前进程是没有ui的只有KeServiceDescriptorTable表,因此第二个选项地址无法查询。
我们可以切换到一个有ui进程的程序上

传入eax规范:
eax会传入两个参数,服务表的下标,以及函数下标:

图片从转载

bits 0-11: the system service number (SSN) to be invoked.(译 被调用所在服务表的函数下标)
bits 12-13: the service descriptor table (SDT).(译 服务表下标)
bits 14-31: not used. (未使用)

查看一个记事本的案例:
我们断点一个记事本ntdll.dll的createFile函数

ntdll!NtCreateFile:
# 赋值对应的函数下标 和服务表
77313820 mov     eax,16Eh
77313825 call    ntdll!NtCreateFile+0xd (7731382d)
7731382a ret     2Ch7731382d mov   edx,esp
7731382f sysenter # 这行运行完成后跳转到7731382a

首先我们先分析 eax的数值

从上面可以得知这个函数会调用最原始非UI的函数表,下标为0x16。

call ntdll!NtCreateFile+0xd目的为了作为一个桩代码,存储返回地址7731382a到栈中,而后在内核中可以轻易读取到返回地址方便调用SYSEXIT 读取ring 3返回地址。

77313825 call  ntdll!NtCreateFile+0xd
//存储到edx寄存器中,方便内核读取ring 3 读取到栈区地址
7731382d mov edx,esp

当我们运行到7731382f代码时,一些寄存器堆栈数据

7731382f sysenter
msr寄存器:
msr[174] = 00000000`00000008
msr[175] = 00000000`89f7d000
msr[176] = 00000000`8234ba50寄存器:
edx = 03d7f614
esp = 03d7f614
ebp = 03d7f6e0栈区信息:
03d7f614  7731382a 74696b04 03d7f664 80100080
03d7f624  03d7f6a8 03d7f674 00000000 00000000
03d7f634  00000000 00000001 00000040 00000000
03d7f644  00000000 03d7f808 03d7f850 000004e8
03d7f654  00000000 00000040 00000000 00000001
03d7f664  000001bc 80100080 00000000 00000000
03d7f674  00000384 0000038c 00000000 00120010
03d7f684  03fad9f0 03fad9f0 00000000 00000000

然后我们在执行sysenter后跳转到msr[176] 地址,这个是一个内核地址
在执行windbgt命令,不会跳转到内核,而是到7731382a ret 2Ch

这个函数会跳入内核nt!KiFastCallEntry函数。

这个函数分析不想写了。。。。网上有


参考命令


//寻找内核的notepad程序
!process 0 0//切换到notepad程序
.process /r /p b060d780//下断点
bp ntdll!NtCreateFile//条件断点
bp 773e3825  ".if (@eax & 0x0`ffffffff) = 0x0`16E  { r eax} .else {gc}"

参考

操作系统 实验2 windbg双机调试+系统调用过程

System_Service_Descriptor_Table

wiki Model-specific_register

rdmsr–read-msr-

osdev SYSENTER

sysenter

System Service Descriptor Table - SSDT

静态分析nt!KiFastCallEntry

x86 CPU的MSR寄存器

hooking-system-service-dispatch-table-ssdt

HOOK SSDT

系统调用篇——SSDT

What is REX prefix in Instruction Encoding?

Model_Specific_Registers

windows ssdt相关推荐

  1. Windows Dll Injection、Process Injection、API Hook、DLL后门/恶意程序入侵技术

    catalogue 1. 引言 2. 使用注册表注入DLL 3. 使用Windows挂钩来注入DLL 4. 使用远程线程来注入DLL 5. 使用木马DLL来注入DLL 6. 把DLL作为调试器来注入 ...

  2. 学习笔记-Volatility

    Volatility 文章作者 r0fus0d & Lorna Dane 免责声明 本文档仅供学习和研究使用,请勿使用文中的技术源码用于非法用途,任何人造成的任何负面影响,与本人无关. 简介 ...

  3. linux使用wdm设备驱动模型,驱动开发(WDM) - thomas_more的个人空间 - OSCHINA - 中文开源技术交流社区...

    windows 设备对象名称(内核对象必须命名才能被用户层访问产生句柄) \Driver\ 内核模式下访问 \.\ 用户模式下访问 winObj(symbollink设备名称的别名,各个节点查看)和d ...

  4. Windows内核新手上路1——挂钩SSDT

    Windows内核新手上路1--挂钩SSDT 这个系列记录学习我学习windows内核的点点滴滴,高手请直接无视. 文章核心内容:挂钩SSDT中函数列NtOpenProcess,NtDuplicate ...

  5. Windows内核新手上路2——挂钩shadow SSDT

    Windows内核新手上路2--挂钩shadow SSDT 文章核心内容:安全软件窗口保护.安全输入.截屏保护的一些思路.挂钩NtUserFindWindowEx.NtUserGetForegroun ...

  6. Windows驱动开发学习笔记(五)—— SSDT HOOK

    Windows驱动开发学习笔记(五)-- SSDT HOOK 系统服务表 系统服务描述符表 实验一:通过代码获取SSDT表地址 通过页表基址修改页属性 方法1:修改页属性 方法2:修改CR0寄存器 实 ...

  7. Windows系统调用学习笔记(四)—— 系统服务表SSDT

    Windows系统调用学习笔记(四)-- 系统服务表&SSDT 要点回顾 系统服务表 实验:分析 KiSystemService 与 KiFastCallEntry 共同代码 SSDT 实验: ...

  8. 使用WinDbg获取SSDT 系统服务描述表的函数服务号(索引)

    今天研究了一下午SSDT的东东,最尴尬的是起初我不知道如何获取到SSDT的函数服务号,而这个玩意儿在不同版本的windows是不一样的,后面经过研究还是找到了正确的方法.这里简单的分享一下. ·    ...

  9. VC++实现恢复SSDT

    SSDT(System Services Descriptor Table),系统服务描述符表.这个表就是一个把ring3的Win32 API和ring0的内核API联系起来.SSDT并不仅仅只包含一 ...

最新文章

  1. windows禁用/启用hyper-V,解决hyper-V与模拟器同时启用时造成冲突
  2. Linux下独立添加PHP扩展模块 mssql
  3. python处理多个excel文件-python多个excel文件合并成一个sheet
  4. ssh问题:ssh_exchange_identification: Connection closed by remote host
  5. VB中使用MD5算法
  6. l2tp pptp相关的一些记录
  7. 上周热点回顾(11.27-12.3)
  8. 记录一次线上mysql事务隔离级别引发的思考
  9. oracle的执行图标不见了,开始菜单oracle集成管理工具的图标没了怎么办
  10. 学习opencv:PS滤镜—浮雕
  11. Oracle PLSQL单行数据的处理
  12. 电脑改成,如何把电脑变成无线路由器
  13. 操作操作操作操作操作操作
  14. 软件测试之BUG描述
  15. 题目:我立志成为一名好销售,万万没想到,我还是走了程序员的路,原因竟然是....
  16. JavaFx之TableView表格操作----增删改及行多选
  17. UVA - 1103:Ancient Messages
  18. 6、尺寸和定位的相关属性
  19. 云邮箱登陆,如何登录企业邮箱?电子邮箱如何登陆?
  20. VC6.0的工程设置解读Project--Settings - 查志强(转载)

热门文章

  1. 少数人的智慧:基于专家意见的协同过滤
  2. linux pureftpd 教程,Pureftpd攻略之建立账号
  3. springBoot 启动指定配置文件环境多种方案
  4. conda安装onnx
  5. notepad++搜索结果窗口不见了,怎么找回?
  6. 二分查找法+左右边界搜索
  7. php sku联动,php-SKU的WooCommerce管理产品搜索
  8. 站长爆料:部分地区备案需提供纳税证明
  9. MiniUI快速入门教程(五)主框架布局
  10. CentOS7镜像文件下载地址