这是 Windows kernel exploit 系列的最后一篇,如果你按顺序观看我之前文章并且自己调过的话,应该对各种漏洞类型在Windows 7 下的利用比较熟悉了,其他的话我放在最后说把,现在进入我所谓的最后一个专题,未初始化的堆变量利用,看此文章之前你需要有以下准备:
传送门:
[+] 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)-空指针解引用
[+] Windows Kernel Exploit 内核漏洞学习(6)-未初始化栈利用
我们还是先用IDA分析HEVD.sys
,找到相应的函数TriggerUninitializedHeapVariable
,这里首先还是初始化了异常处理机制,验证我们传入的UserBuffer
是否在 user mode ,然后申请了一块分页池,将我们的UserBuffer
给了UserValue
,判断是否等于 0xBAD0B0B0 ,如果相等则给回调函数之类的赋值,如果不相等则直接调用回调函数,根据前一篇的经验,这里肯定是修改回调函数为我们shellcode的位置,最后调用提权
我们查看一下源码文件是如何说明的,安全的方案先检查了是否存在空指针,然后将UninitializedMemory
置为NULL,最后安全的调用了回调函数,而不安全的方案则在不确定 Value 和 Callback 的情况下直接调用了回调函数
漏洞的原理我们很清楚了,现在就是如何构造和利用的问题了,如果你没有看过我之前的文章,建议看完这里之后去看看池溢出那一篇,最好是读一下文章中所提到的Tarjei Mandt 写的 Kernel Pool Exploitation on Windows 7,对Windows 7 内核池有一个比较好的认识
我们还是从控制码入手,在HackSysExtremeVulnerableDriver.h
中定位到相应的定义
然后我们用python计算一下控制码
我们验证一下我们的代码,我们先传入 buf = 0xBAD0B0B0 观察,构造如下代码
这里我们打印的信息如下,如我们所愿,并没有异常发生
我们尝试传入不同的值观察是否有异常发生
我们在调用运行效果如下,这里被异常处理所接受,这里我们Callback有一个值,我们查看之后发现是一个无效地址,我们希望的当然是指向我们的shellcode,所以就需要想办法构造了
现在我们已经有了思路,还是把Callback指向shellcode,既然上一篇类似的问题能够栈喷射,那这里我们自然想到了堆喷射,回想我们在池溢出里堆喷射所用的函数CreateEventA
,这里我们多研究一下这个函数,要知道我们这里是分页池而不是非分页池,如果你用池溢出那一段申请很多Event对象的代码的话,是看不到一个Event对象存在分页池里面的(并且会蓝屏),但是函数中的lpName
这个参数就比较神奇了,它是分配在分页池里面的,并且是我们可以操控的
为了更好的理解这里的利用,让我们复习一下 Windows 7 下的Lookaside Lists
快表结构,并且我们知道最大块大小是0x20,最多有256个块(前置知识来自Tarjei Mandt的Kernel Pool Exploitation on Windows 7文章),这里要清楚的是我们是在修改快表的结构,因为申请池一开始是调用的快表,如果快表不合适才会去调用空表(ListHeads)
我们还需要知道的是,我们申请的每一个结构中的lpName
还不能一样,不然两个池在后面就相当于一个在运作,又因为pool size为0xf0,加上header就是0xf8,所以我们这里考虑将lpName
大小设为0xf0,因为源码中我们的堆结构如下:
我们可以确定回调函数在 +0x4 的位置,放入我们的shellcode之后我们在利用循环中的 i 设置不同的 lpname 就行啦
最后我们整合一下代码就可以提权了,总结一下步骤
提权的过程中你可以参考下面几个地方查看相应的位置是否正确
提权效果如下,详细的代码参考这里
到这里我的Windows Kernel exploit系列也就结束了,这个过程比较艰辛,也阅读了许多的资料,其实有些地方我也搞的不是很懂,但我一般的方法是如果一天对这个问题没有丝毫的进展,我就不会再去死磕了(貌似是坏习惯?),因为后面我还是继续学内核,学到后面一些知识以后说不定这里的问题就豁然开朗了,当然前提是没有忘记这个问题,其实有些漏洞的篇幅可能比较短,有些地方的措词和代码可能不是很好,也可能有一些错误存在,希望读者大大们多多包容,也希望初学者能够自己去阅读资料把exp调试出来,其实有些地方我也适当的进行了省略(比如这篇为啥用的是CreateEventW函数喷射而不是CreateEventA),需要你自己多多去尝试思考,非常感谢wjllz师傅以及Sakura师傅,给了我很大的引导,当然这并不是获奖感言啥的。。。只是对自己这一阶段的总结,自己对内核的研究也并不会结束(其实是刚刚开始),越来越意识到自己要学的东西很多,还是慢慢努力吧,最后说一句,这不是教程,只是我分享的一个学习过程
[注意]APP应用上架合规检测服务,协助应用顺利上架!
最后于 2019-8-2 09:31
被Thunder J编辑
,原因: