点击查看原文
欢迎回到Windows exploit开发系列教程的第十六部分。今天我们将基于@HackSysTeam's 的驱动漏洞来编写一个池溢出的exp。再一次,我强烈建议读者在阅读本文前,先费些心思回顾一下下面列出的资源列表,以及第十五部分池分配相关的背景知识。调试环境的搭建请参考第十部分。
先看看本次有漏洞的函数(here)。
显而易见的bug!驱动分配了一个大小为X的池块并拷贝了用户提供的数据到其中,然而,他并没有检查用户提供的数据尺寸是否超过了内存分配的池块大小。这导致了一些额外的数据会溢出到非分页内存池中毗邻的池块。我建议你在IDA中进一步探索该函数,该函数的分配的池块大小以及池标签都可以在函数起始不远的位置看到。
我们可以用下面的Powershell POC来调用该函数。注意到我们使用的是最大的可行尺寸,任何超出的数据都将溢出到下一个块。
如我们所见,分配的块大小为0x200,我们的缓冲区刚好停在了下一个毗邻块的头部位置。让我们再次尝试增大用户缓冲区8个字节来覆盖下一个块的头部。
取决于内存池的状态和我们随机覆盖掉了某个块(本例中是二次释放(double free)),我们触发时会遇到各种各样的bug。任意一个都足以触发蓝屏,我们的exp相当粗糙!
先简明扼要的给出一个全盘筹划总是好的。
我强烈推荐你阅读Tarjei的paper并回顾本系列第十五部分的内容。这会帮助你解析重要的细节——我们的块风水是如何工作的。
在前面的文章中我们用IoCompletionReserve对象喷射了非分页内存池,其大小为0x60。但这一次,我们的目标对象是0x200大小因此我们需要喷射该尺寸的某种对象或者一个可以通过乘法达到该尺寸的对象。幸运的是,事件对象的尺寸是0x40,乘上8就是0x200。
下面的POC首先分配了10000个事件对象来填充非分页内存池的碎片,此后分配了5000个对象以达成可预测分配。注意我们转出了最后的10个对象句柄到标准输出,手动在WinDBG中触发了一个断点。
你将看到类似这样的输出并在WinDBG中命中断点。
观察我们转储到标准输出的一个句柄,我们可以看到连续的0x40字节的分配。
为了使得内存池处在一个可信的状态,我们唯一能做的就是从第二次喷射的对象中释放0x200个字节的段。这将为我们的驱动对象挖坑备用。下面的POC展示了这一技术。
如前面所提到的,我们将利用“池内部构件”来达成代码执行。我们已经看过了如果对这些结构乱改一气就会导致BSOD,因此我们需要对池块的布局有一个深入的理解。
下面我们可以看到一个单一的事件对象的完整组件以及组成它的各种结构体。
首先,这里有个WinDBG的bug,他不会真正关心块结构的阐释但却非常烦人。有人发现问题了吗?如果有人可以指出就给你发免费的蛋糕(撒个慌)!无论如何在后面执行溢出时,这3个头需要保持固定(按层级)。
注意到OBJECT_HEADER的TypeIndex为0xC大小,该值是一个指针数组的偏移量,它描述了该块的对象类型。我们可以这样查证。
我们可以进一步通过事件对象指针来枚举OBJECT_TYPE。同样,注意到数组的第一个指针是空的(0x00000000)。
重要的部分就是"OkayToCloseProcedure"的偏移。如果,当对象句柄被释放且块也被释放,该值不为空,内核会跳转到该地址来执行。也可以使用该结构的其他成员,比如"DeleteProcedure"。
问题在于我们要如何利用它?记住池块本身包含了TypeIndex值(0xC),如果我们溢出该块并将该值修改为0x0的话,对象就会尝试在进程的零页上查找OBJECT_TYPE结构体。我们使用的环境是Win7,可以分配一个零页并创建一个伪造的"OkayToCloseProcedure"指针指向我们的shellcode。在释放了被污染的块时,内核就应该会执行到我们的代码了!
很好,我们就要解放了!我们已经控制了池分配并且知晓在0x200字节对象后我们有一个0x40字节的事件对象。我们可以用下面的buffer来精准的覆盖前面看到的三个块头结构。
这里我们修改的唯一的值就是TypeIndex,我们从0xC修改成了0x0。我们可以通过下面的代码,精心构造一个伪造的"OkayToCloseProcedure"指针。
让我们在WinDBG中证实我们的理论。
很棒,游戏基本通关了!再一次,火眼金睛的读者会注意到这个讨厌的WinDBG bug,就像前面那样。
像前面的文章一样,我们重用了shellcode,然而这其中有两个小技巧我留给勤勉的读者来找出!一个是和shellcode结尾相关,另一个和零页内存布局相关。
这就是所有的运行过程,更多细节请参考下面完整的exp。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2018-3-20 20:00
被玉涵编辑
,原因: