首页
论坛
课程
招聘
[原创]Windows内核逆向-----<KiSystemCall64>
2021-9-8 14:38 9049

[原创]Windows内核逆向-----<KiSystemCall64>

2021-9-8 14:38
9049

算是介绍

最近比较懒,已经摸鱼半个月了,以后会把学的东西整理下发出来,算是督促下自己吧,大概周更。主要是对Windows内核中函数的逆向。
应该会用到的东西:Win10_x64 + Windbg + IDA + Xp源代码 + Intel手册
垃圾二本 开学大三 水平有限 还请各位前辈多多指点

算是正文

先从进入内核开始

syscall

在R3使用的Windows API 函数 大多都要进入R0来完成核心工作,所以进入R0的动作也算频繁,因此 (也不一定因此)CPU提供一条指令来用于从用户态切换到内核态,如图
算是个图
以下步骤在执行syscall指令时由CPU完成,是对上图的解释。
1.1)将RIP保存到RCX(因为完成API的功能后程序还是要正常执行的)并将RIP改成一个系统指定好的值(系统中所有线程执行syscall指令后都会跳转到这里执行,这也提供了一种HOOK方案,但不用VT分分钟PG)
1.2)将RFLAGS保存到R11,并参考一个MSR寄存器,改变RFLAGS的值(根据windbg读出来的值NT内核在执行syscall时 将 TF IF DF 位置零)
2)简单理解为更改了CPU当前特权级别,并强制平坦(就是弱化了段机制)

内核接管流程

新的RIP值指向内核层代码 符号名是 KiSystemCall64 (开启页表隔离后会是另一个),此段代码主要功能:
1.切换GS指向KPCR
2.将用户栈切换到内核栈
3.关闭SMAP使得可以在内核态访问用户态数据
4.一段神奇的代码,猜测是参考cpu特征解决下硬件漏洞
5.保存用户态线程上下文到_KTRAP_FRAME
6.根据eax算出用户指定的内核态例程地址(地址计算方法会在下文总结)
7.将用户栈上的参数复制到内核栈(算出复制代码执行地址)
8.调用内核函数
9.执行下用户态APC
10.将函数返回值写入_KTRAP_FRAME.RAX 恢复用户态上下文 使用sysret指令返回用户态执行
<<<<-------下文会根据这10步放上IDA截图,细节在IDA注释上补充------->>>>
个人感觉用图片表述更加直观

接管细节分析

下图主要做了 1 2 3 5步所述内容

1. 2. 3.

下图主要做了 4 5 步所述内容,4步为个人推测,未经验证

4

下图主要做了 6 步所述内容

首先会根据线程特征选用不同的表
6
然后使用选出的表算出函数地址
11

下图表述了函数地址的计算方式

用Excel画图是真的累 ;(
13
CommonThread为普通线程用的表,GuiThread为GUI线程用的表,XX_EntryNumber为表中的偏移个数,ArgNumber为函数的参数个数,

下图主要做了 7 步所述内容

12

下图的代码主要用于复制参数,执行位置由上图代码算出

15

下图主要做了 8 步所述内容

图片描述

下图主要做了 9 10 步所述内容

图片描述
图片描述

sysret

此指令用于从内核态返回用户态,过程可反向参考syscall,执行此指令后CPU回到用户特权级(R3)并执行用户层代码
图片描述

算是废话

以前看一些帖子总觉得讲的不仔细,第一次自己写才知道,所有细节都写出来估计要累死。过两天开学了还要准备英语补考:(((((((((((((((想想都脑子疼。

 

下一篇逆一下内存或者线程切换相关的把,难免有错误还请大佬们多多指点


2021 KCTF 秋季赛 防守篇-征题倒计时(11月14日截止)!

最后于 2021-9-8 19:30 被小白养的菜鸡编辑 ,原因: 改一下...
收藏
点赞4
打赏
分享
最新回复 (4)
雪    币: 137
活跃值: 活跃值 (524)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
niuzuoquan 活跃值 2021-9-8 14:58
2
0
mark
雪    币: 278
活跃值: 活跃值 (108)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
Dstlemoner 活跃值 2021-9-9 01:11
3
0
头发渐少。
雪    币: 152
活跃值: 活跃值 (685)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
huojier 活跃值 2021-9-9 12:03
4
0
最近在做类似的kisystemcall64重定位,有个小坑是sssdt表要+0x20也就是加一个ssdt表大小,才能真正访问到,因为微软设计这玩意的时候就是历史遗留问题,ssdt[0] = ssdt表,ssdt[1] = 不用保留, sssdt[1] = sssdt表,sssdt[0] = ssdt表
雪    币: 152
活跃值: 活跃值 (685)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
huojier 活跃值 2021-9-9 12:05
5
0
huojier 最近在做类似的kisystemcall64重定位,有个小坑是sssdt表要+0x20也就是加一个ssdt表大小,才能真正访问到,因为微软设计这玩意的时候就是历史遗留问题,ssdt[0] = ssdt表 ...
楼上的意思是,如果要做kisystemcall64重定位,在修复sssdt表的时候要注意不能直接跟ssdt一样把lea r11,sssdt取出来。
游客
登录 | 注册 方可回帖
返回