关于 windows 内核漏洞利用教程,玉涵已经将fuzzysecurity
上的那部分翻译完毕, 是很好的学习资料。 因为之前翻译了 池风水那篇文章,发现作者又接着更新了几篇,所以就简单地翻译了一下本篇文章,学习一下。
在上一篇文章中,我们研究了未初始化的栈变量漏洞。在这篇教程中,我们会讨论类似的一个漏洞,未初始化的堆变量。在这篇教程,我们会修改分页池,以便控制流可以指向我们的shellcode。
另外,对于hacksysteam的驱动程序表示万分感谢!
首先,我们先分析一下UninitializedHeapVariable.c文件:
代码虽然看着比较长,但是还是容易理解的。使用pool chunk
的 地址初始化 变量UninitializedHeapVariable
,如果UserValue
等于Magic
的话,那么一切都没有问题,value
和 callback
字段也可以被正确地初始化,然后程序在调用callback
函数前会检查变量是否被初始化。但是,如果不相等的话会怎么样呢?从代码来看,很明显编译的是SECURE
版本, 变量UninitializedHeapVariable
会被置为NULL
, 所以在if
声明中,不会调用callback
函数。而如果是编译为不安全版本的话,则没有类似这样的检查措施,然后会callback
未初始化的变量,从而导致出现漏洞。
(译注:secure 编译相关的一些选项问题,可以参见微软的官方文档)
接着,我们来看一下在UninitializedHeapVariable.h 中_UNINITIALIZED_HEAP_VARIABLE
结构体是如何定义的:
可以看到,上面的结构体中定义了3个成员变量,第二个是一个函数指针类型的变量,命名为callback
,如果我们能想方设法地控制pool chunk
上的数据的话,我们就能够控制UninitializedHeapVariable
结构体和 callback
函数。
可以在IDA
中清楚地看到:
并且, IOCTL
号为 0x222033
。
和前几篇一样,继续使用我们的脚本框架:
成功传递参数,没有发生异常,我们试下传递一些其他的UserValue
,看看会发生什么。
可以看到出现了异常,并且Callback
函数的地址似乎并非一个有效值,现在可以开始写exploit
了。
这里最大的问题就是通过用户空间可以控制的数据来修改分页池,而我们可以使用的一个接口是Named Objects
。如果你记得以前那篇关于 池风水文章的话,就会想起我们曾使用[CreateEvent](https://msdn.microsoft.com/pl-pl/library/windows/desktop/ms682396(v=vs.85).aspx)
对象来修改Lookaside
链表:
这里最重要的一点是,即使event
对象本身被分配给非分页池,最后那个LPCTSTR
类型的参数lpName
实际上也是在分页池中分配的。并且,我们实际上可以定义它的内容和长度。
这里还有几点需要注意:
Lookaside
链表的最大块长是 0x20, 它只能管理256 个块,之外的块由ListHead
负责管理。
我们需要分配256个相同大小的对象,然后释放它们。如果Lookaside
链表不能完成分配的话,会从ListHead
链表中接着分配。
我们需要确保每次调用对象构造函数时对象名称的字符串都是随机的,因为如果将相同的字符串传递给对象构造函数的连续调用的话,那么只有一个Pool chuck
将被用于所有进一步的请求。
我们还需要确保我们的lpName
不应该包含任何NULL
字符,因为这会改变lpName
的长度,导致exploit利用失败。
我们给lpName
分配 0xF0 的大小, 头部大小为 0x8 ,一共是0xF8 字节的块,shellcode
来源于之前的教程中。
我们最终的exploit 如下:
最终获得系统管理员权限:
原文链接:https://rootkits.xyz/blog/2018/03/kernel-uninitialized-heap-variable/
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2019-2-1 20:27
被admin编辑
,原因: