这是 Windows kernel exploit 系列的第六部分,前一篇我们讲了空指针解引用,这一篇我们讲内核未初始化栈利用,这篇虽然是内核栈的利用,与前面不同的是,这里需要引入一个新利用手法 => 栈喷射,需要你对内核栈和用户栈理解的比较深入,看此文章之前你需要有以下准备:
传送门:
[+] Windows Kernel Exploit 内核漏洞学习(0)-环境安装
[+] Windows Kernel Exploit 内核漏洞学习(1)-UAF
[+] Windows Kernel Exploit 内核漏洞学习(2)-内核栈溢出
[+] Windows Kernel Exploit 内核漏洞学习(3)-任意内存覆盖漏洞
[+] Windows Kernel Exploit 内核漏洞学习(4)-池溢出
[+] Windows Kernel Exploit 内核漏洞学习(5)-空指针解引用
我们还是先用IDA分析HEVD.sys
,找到相应的函数TriggerUninitializedStackVariable
我们仔细分析一下,首先函数将一个值设为0,ms_exc
原型如下,它其实就是一个异常处理机制(预示着下面肯定要出异常),然后我们还是将传入的UserBuffer
和 0xBAD0B0B0 比较,如果相等的话就给UninitializedStackVariable
函数的一些参数赋值,后面又判断了回调函数的存在性,最后调用回调函数,也就是说,我们传入的值不同的话可能就存在利用点,所以我们将聚焦点移到UninitializedStackVariable
函数上
我们来看一下源码里是如何介绍的,显而易见,一个初始化将UninitializedMemory
置为了NULL,而另一个没有,要清楚的是我们现在看的是内核的漏洞,与用户模式并不相同,所以审计代码的时候要非常仔细
我们还是从控制码入手,在HackSysExtremeVulnerableDriver.h
中定位到相应的定义
然后我们用python计算一下控制码
我们验证一下我们的代码,我们先传入 buf = 0xBAD0B0B0 观察,构造如下代码
这里我们打印的信息如下,可以看到对UninitializedStackVariable
的一些对象进行了正确的赋值
我们尝试传入不同的值
运行效果如下,因为有异常处理机制,所以这里并不会蓝屏
我们在HEVD!TriggerUninitializedStackVariable+0x8c
比较处下断点运行查看
我们断下来之后用dps esp
可以看到我们的 Value 和 Callback ,单步几次观察,可以发现确实已经被SEH异常处理所接手
因为程序中会调用回调函数,所以我们希望的是把回调函数设置为我们shellcode的位置,其实如果这里不对回调函数进行验证是否为0,我们可以考虑直接在0页构造我们的shellcode,但是这里对回调函数进行了限制,就需要换一种思路
我们需要把回调函数的位置修改成不为0的地址,并且地址指向的是我们的shellcode,这里就需要用到一个新的方法,栈喷射,j00ru师傅的文章很详细的讲解了这个机制,我简单解释一下,我们始终是在用户模式干扰内核模式,首先你需要了解内核栈和用户栈的结构,然后了解下面这个函数是如何进行栈喷射的,函数原型如下
因为COPY_STACK_SIZE
的大小是1024,函数的栈最大也就 4096byte ,所以我们只需要传 1024 * 4 = 4096 的大小就可以占满一页内存了,当然我们传的都是我们的shellcode的位置
我们来看看我们完整的exp的运行情况,我们还是在刚才的地方下断点,可以清楚的看到我们的shellcode已经被喷上去了
最后我们整合一下代码就可以提权了,总结一下步骤
提权效果如下,详细的代码参考这里
这个漏洞利用的情况比较苛刻,但是挺有意思的,也是第一次见栈喷射,还是从j00ru的文章中学到了许多新奇的东西,多看看国外的文档自己的英语水平也慢慢好起来了
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)