一、回顾

前两篇博客,我逆向分析了 KiSystemService 和 KiFastCallEntry 填充_KTRAP_FRAME 结构体的代码,二者大同小异,主要的区别是 sysenter 只改了eip,cs,ss,虽然esp也改了,但是windows不使用,而是从TSS里取esp0;另外sysenter并没有像中断门那样压栈,所以3环的 ss, esp, eflags, cs,eip都要在函数里依次保存到 _KTRAP_FRAME 。

这次课后作业是逆向 KiSystemService / KiFastCallEntry 调用内核函数部分,放在一块讲是因为这两个函数虽然入口不同,但是填充完 _KTRAP_FRAME 后,就会执行相同的代码。他们两个函数就像两头蛇一样,有两个入口,初始化的工作有区别,但是往后就共用一个函数体。

在逆向之前,先介绍所需的前置知识。同时,思考两个问题:

  • 如何根据系统服务号(eax中存储)找到要执行的内核函数?
  • 调用时参数是存储到3环的堆栈,如何传递给内核函数?

二、SystemServiceTable 系统服务表SST

SST:系统服务表
SSDT:系统服务调度表
SSPT:系统服务参数表
关系:

首先强调,SystemServiceTable 系统服务表不是SSDT。

看示意图:

通过此图,我们可以得知以下信息:

  • 通过 _KTHREAD 可以找到系统服务表
  • 系统服务表又指向了函数地址表和函数参数表
  • 有两张系统服务表,第一张是用来找内核函数的,第二张是找Win32k.sys驱动函数的。

通过逆向,我们还可以判定,其实两张系统服务表是线性地址连续的,每张16字节。

说明一下表的4个属性:
ServiceTable 指向函数地址表,Count没有用,ArgmentTable 指向函数参数表,ServiceLimit 是这两张表的长度。

要注意函数参数表每项存储的是对应函数参数占的字节数,每项只有1字节。 这个在逆向中也可以验证。

最后补充一点,我们之前逆向API三环部分时,它进0环之前,无论是中断门还是快速调用,都会在 eax 里存一个值,我们称之为系统调用号或者服务号,这个东西的低12位就是函数参数表和函数地址表的下标,而第13位(下标12)如果是0,表示找第一张系统服务表(绿色的表),如果是1,那么找第二张表(黄色的表)。这点可以先记住,待会逆向的时候可以印证这个结论。

三、逆向分析 KiSystemService / KiFastCallEntry 调用内核函数部分

从Kernel32.dll中的某个函数开始分析其执行流程(怎么找到对应的内核函数 怎么找到参数 如何将参数传递到0环)

这是作业要求,我这里就只贴了0环逆向部分,至于3环那些,我在之前的博客已经详细分析了,有需要可以查看前面的博客。

直接贴结果了,比较简单,看注释就能看懂了。

.text:004665CD loc_4665CD:                             ; CODE XREF: _KiBBTUnexpectedRange+18j
.text:004665CD                                         ; _KiSystemService+6Fj
.text:004665CD                 mov     edi, eax        ; 这里是 KiSystemService 和 KiFastCallEntry 的汇合处
.text:004665CD                                         ; edi = eax = 系统调用号
.text:004665CF                 shr     edi, 8
.text:004665D2                 and     edi, 30h        ; 检测系统调用号12位
.text:004665D2                                         ; 如果等于1,那么 edi == 0x10
.text:004665D2                                         ; 如果等于0,那么 edi == 0x00
.text:004665D5                 mov     ecx, edi
.text:004665D7                 add     edi, [esi+0E0h] ; edi += CurrentThread.ServiceTable
.text:004665D7                                         ; 此时 edi 指向了API对应的系统服务表
.text:004665D7                                         ;
.text:004665D7                                         ; 他这个设计 0x10 刚好是系统服务表的大小
.text:004665D7                                         ; 系统服务表有 ServiceTable, Count, ServiceLimit 和 ArgmentTable
.text:004665D7                                         ; 4项共0x10字节,所以通过这里的代码也可以推断,内核和win32k.sys的系统服务表是连续的
.text:004665D7                                         ; 第一张是内核的,第二张是win32k.sys的
.text:004665DD                 mov     ebx, eax        ; ebx = 系统调用号
.text:004665DF                 and     eax, 0FFFh      ; eax = 系统服务表下标
.text:004665E4                 cmp     eax, [edi+8]
.text:004665E7                 jnb     _KiBBTUnexpectedRange ; 检查系统调用号是否超过系统服务表的范围,超过就跳到异常处理
.text:004665ED                 cmp     ecx, 10h
.text:004665F0                 jnz     short loc_46660C ; 跳转条件:系统服务(ntdll.dll 的API)
.text:004665F0                                         ; 不跳转条件:图形及用户界面(gdi.dll 的API)
.text:004665F2                 mov     ecx, ds:0FFDFF018h ; ecx 指向 _KPCR
.text:004665F8                 xor     ebx, ebx
.text:004665FA
.text:004665FA loc_4665FA:                             ; DATA XREF: _KiTrap0E+113o
.text:004665FA                 or      ebx, [ecx+0F70h]
.text:00466600                 jz      short loc_46660C
.text:00466602                 push    edx
.text:00466603                 push    eax
.text:00466604                 call    ds:_KeGdiFlushUserBatch
.text:0046660A                 pop     eax
.text:0046660B                 pop     edx
.text:0046660C
.text:0046660C loc_46660C:                             ; CODE XREF: _KiSystemService+16Fj
.text:0046660C                                         ; _KiSystemService+17Fj
.text:0046660C                 inc     dword ptr ds:0FFDFF638h ; _KCPR.KPRCB.KeSystemCalls += 1, 系统调用计数加1
.text:00466612                 mov     esi, edx        ; esi = edx = 3环参数指针
.text:00466614                 mov     ebx, [edi+0Ch]  ; edi 指向系统服务表
.text:00466614                                         ; ebx 指向函数参数表
.text:00466614                                         ; eax 是系统服务表下标
.text:00466617                 xor     ecx, ecx
.text:00466619                 mov     cl, [eax+ebx]   ; cl = 参数字节数
.text:0046661C                 mov     edi, [edi]      ; edi 指向函数地址表
.text:0046661E                 mov     ebx, [edi+eax*4] ; ebx 指向函数
.text:00466621                 sub     esp, ecx        ; 从这句开始,到call为止,完成了复制3环参数的工作
.text:00466621                                         ; 这句是模拟压栈操作
.text:00466623                 shr     ecx, 2          ; 参数字节数 / 4,得到参数个数
.text:00466626                 mov     edi, esp
.text:00466628                 cmp     esi, ds:_MmUserProbeAddress ; 越界检查
.text:00466628                                         ; 如果 esi(3环参数指针)大于等于 0x7fff0000,则返回 c0000005 异常
.text:0046662E                 jnb     loc_4667DC
.text:00466634
.text:00466634 loc_466634:                             ; CODE XREF: _KiSystemService+35Fj
.text:00466634                                         ; DATA XREF: _KiTrap0E+109o
.text:00466634                 rep movsd               ; 复制参数:复制 esi 到 edi,每次复制4字节,次数由 ecx 决定
.text:00466634                                         ; 方向由DF决定,DF=0,故每次复制后,edi 和 esi 都加4
.text:00466636                 call    ebx             ; 调用内核函数

至此,系统调用过程,除了0环返回3环(涉及APC知识),我们都已经分析完成了。

(49)逆向分析KiSystemService/KiFastCallEntry调用内核函数部分(SST,SSDT,SSPT)相关推荐

  1. (47)逆向分析 KiSystemService 函数填充 _KTRAP_FRAME 部分

    一.回顾 之前的课程,我们学习了API系统调用在3环部分做的事情,有两种方式进0环,分别是中断门和快速调用,分别调用两个不同的函数 KiSystemService 和 KiFastCallEntry. ...

  2. linux应用调用内核函数,Hooking linux内核函数(一):寻找完美解决方案

    前言 我们最近参与了一个Linux系统安全相关项目,需要hooking几个重要的Linux内核函数调用,例如打开文件和启动进程,并利用它来启用系统活动监控并抢先阻止可疑进程. 最后,我们发明了一种有效 ...

  3. Linux驱动小技巧 | 利用DRIVER_ATTR实现调用内核函数

    1. 前言 很多朋友在调试驱动的时候,都会遇到这样一个场景:修改一个参数,然后调用某个内核中的函数. 比如将某个gpio的值拉高/拉低,修改某个寄存器的值等等. 如果每一个参数都通过字符设备的ioct ...

  4. (48)逆向分析 KiFastCallEntry 函数填充 _KTRAP_FRAME 部分

    一.回顾 上一篇博客我逆向了 KiSystemService 函数填充 _KTRAP_FRAME 部分. 逆向分析 KiSystemService 函数填充 _KTRAP_FRAME 部分 里面涉及了 ...

  5. PyCUDA内核函数

    元素级内核函数 import pycuda.gpuarray as gpuarray import pycuda.driver as drv from pycuda.elementwise impor ...

  6. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 二 | 准备参数 | 远程调用 mmap 函数 )

    文章目录 一.准备 mmap 函数的参数 二.mmap 函数远程调用 一.准备 mmap 函数的参数 上一篇博客 [Android 逆向]Android 进程注入工具开发 ( 注入代码分析 | 远程调 ...

  7. 系统调用002 KiSystemService函数逆向分析

    文章目录 前言 保存现场 _KTRAP_FRAME KRPC ExceptionList _KTHREAD结构体 先前模式 抬高堆栈 判断当前权限 更新_KTRAP_FRAME 保存三环的寄存器环境 ...

  8. 【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmContinueOptimizati() 函数分析 )

    文章目录 前言 一.DexPrepare.cpp 中 dvmContinueOptimizati() 方法分析 前言 上一篇博客 [Android 逆向]整体加固脱壳 ( DEX 优化流程分析 | D ...

  9. 【Android 逆向】函数拦截原理 ( 通过修改 GOT 全局偏移表拦截函数 | 通过在实际被调用的函数中添加跳转代码实现函数拦截 )

    文章目录 一.通过修改 GOT 全局偏移表拦截函数 二.通过在实际被调用的函数中添加跳转代码实现函数拦截 一.通过修改 GOT 全局偏移表拦截函数 使用 GOT 全局偏移表 拦截函数 , 只需要将 G ...

最新文章

  1. 对口令协议的几种攻击方式
  2. 笔记2 自定义文件上传
  3. HPAIC人类蛋白质图谱分类挑战赛金牌经验分享
  4. ADSL断流问题分析
  5. .NET Core 3.0 部署在docker上运行
  6. (二)注册服务提供者
  7. 【Linux】字符转换命令join
  8. 技术圈儿002---高并发整体可用性:一文详解降级、限流和熔断
  9. ipad中的active失效?
  10. vivado2018.3根据板卡Boards直接创建工程(比如basys3和Arty A7)
  11. JS开发工具WebStorm使用快捷键
  12. 图片转文字,手机摇身一变就是万能扫描仪!
  13. ssm大型分布式商城项目实战视频教程下载java分布式开发教程
  14. Unity笔记-29-ARPG游戏项目-03-攀爬系统
  15. 小程序开发工具绑定服务器,微信小程序绑定到第三方平台流程
  16. 前端练习——弹窗、判断语句 (星座测试)
  17. Qt入门-QLabel类
  18. Vue+高德地图API的使用(插件的使用)
  19. 将一根木棍分成三段,求这三段构成三角形的概率
  20. 文献—Emergent simplicity in microbial community assembly--论文全过程详细阅读整理与翻译

热门文章

  1. 成功解决TypeError: ‘tuple‘ object is not callable
  2. Py之pandas:对dataframe型数据排序相关的问题总结之按照多个字段的多个条件进行排序(先打乱再排序)
  3. VM:如何向vmware虚拟机中传输文件(或者共享文件夹)之详细攻略(图文教程)
  4. DL之DNN优化技术:自定义MultiLayerNetExtend算法(BN层使用/不使用+权重初始值不同)对Mnist数据集训练评估学习过程
  5. MAT之NN:实现BP神经网络的回归拟合,基于近红外光谱的汽油辛烷值含量预测结果对比
  6. Anaconda多环境多版本python配置指导
  7. 《疯狂Java讲义》10
  8. SQLServer之分离数据库
  9. Help:立体图绘制以及根据X,Y,Z三坐标值,在图上描点
  10. 人的执念真的是非常的可怕