欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

内核池溢出漏洞利用实战之Windows 7篇

来源:本站整理 作者:佚名 时间:2017-08-04 TAG: 我要投稿

一、前言
本文重点围绕HitmanPro独立扫描版(版本3.7.15-build 281)的内核池溢出漏洞(CVE-2017-6008)展开。这个工具是反病毒软件Hitman.Alert解决方案的一部分,并以SophosClean可执行文件的方式集成在了英国公司Sophos的解决方案中。早在2017年2月,Sophos公司就收到了此漏洞的报告并在2017年5月发布3.7.20-Build 286版本更新了补丁。我们使用Ioctfuzzer(https://github.com/Cr4sh/ioctlfuzzer)发现了首次crash。Ioctfuzzer是一款对输入输出请求包(以下简称IRP)进行模糊测试的强大易用的工具,我们利用此工具捕获到了API函数DeviceIoControlFile并利用该函数作为中间人代理。对于收到的每一个IRP包,它都会先行发送几个伪造的IRP包然后再转发原始IRP包。扫描伊始就出现了崩溃,崩溃发生在BAD_POOL_HEADER代码初始化阶段。阅读下文之前,我们强烈建议读者了解一些windows下的IOCTL和IRP知识。MSDN文档提供了大量可以帮助你更好地理解本文的信息。本文将要利用的是64位系统下的情景,这比32位系统下更难利用。
二、详细分析
2.1 崩溃数据分析
首先需要弄清楚BAD_POOL_HEADER错误码的含义,池是内核中动态分配的常见场所,此代码意味着处理池头部时出现了问题。池头是位于块开头的提供块有关信息的结构,如图1所示。
 

图1 池头结构图
池头很可能已经损坏才导致崩溃,为了验证此设想,我们利用调试器、转储工具还有测试器产生的日志快速找到了有缺陷的IRP包如下:
IOCTL Code: 0x0022e100
Outbuff: 0x03ffe1f4, Outsize: 0x00001050
Inbuff : 0x03ffd988, Insize: 0x00000200
//Device/Hitman Pro 37 [/??/C:/Windows/system32/drivers/hitmanpro37.sys]
这里有几点关键信息:
C:/Windows/system32/drivers/hitmanpro37.sys:处理IRP的驱动程序。由于池损坏导致了崩溃,因此该驱动一定与崩溃有关。
IOCTL Code: 0x0022e100:该IOCTL代码提供了大量信息,稍后会作分析。通过逆向还可以获知以上驱动是如何处理IRP的。
Outsize / Insize:用来在池中分配一些缓冲区,也可能与池损坏有关。
参考MSDN文档,从IOCTL代码中可以得到如下信息:
DeviceType = 0x22
Access = 0x3
Function = 0x840
Method = 0x0
Method 0x0=METHOD_BUFFERED
“对于METHOD_BUFFERED这种传输类型,IRP提供了一个指向位于Irp->AssociatedIrp.SystemBuffer的缓冲区的指针,该缓冲区代表调用DeviceIoControl和IoBuildDeviceIoControlRequest时的输入缓冲区和输出缓冲区,驱动器就在输入输出缓冲区之间传输数据。
对于输入数据,缓冲区大小由驱动器IO_STACK_LOCATION结构中的DeviceIoControl.InputBufferLength参数指定。
对于输出数据,缓冲区大小由驱动器IO_STACK_LOCATION结构中的DeviceIoControl.OutputputBufferLength参数指定。
系统为单个输入/输出缓冲区分配的空间大小是两个值中较大的那个。“
最后,为了弄清楚在正常情况下IOCTL是如何发送的,我们逆向了HitmanPro.exe可执行文件,利用IOCTL代码和逆向工具IDA快速定位到了问题函数。
 

可见,分配给DeviceIoControl的Outsize和Insize与崩溃数据吻合,这种情况下,IRP管理器分配的系统缓冲区大小在正常情况下至少为0x1050字节。
2.2 逆向驱动器
我们已经掌握了很多崩溃有关的信息,是时候逆向驱动器hitmanpro37.sys来看看IOCTL的句柄了。首先,参照IOCTL代码定位调度IRP的函数,通常它是包括一些switch跳转的庞大函数,还好该驱动器并不大我们很快找到了调度器:
 


 
跟踪跳转逻辑,我们找到了处理存在漏洞的IOCTL的函数,IRP提供的SystemBuffer首先被传给IoGetDeviceObjectPointer函数的ObjectName参数:
 

然后,
 

非常不错进行到这里了,还记得IOCTL用到的METHOD_BUFFERED方法吗?
“系统为单个输入/输出缓冲区分配的空间大小是两个值中较大的那个。”
这意味着我们完美控制了SystemBuffer的值,驱动器使用硬编码的值0x1050调用memset,如果SystemBuffer值小于0x1050,调用memset会使池损坏进而导致崩溃,这里我们称之为内核池溢出漏洞。虽然这么说,但是我们到目前为止还没有任何办法控制往此缓冲区写入。它被设置为0然后被DeviceObject中的地址和名字填充,这只有管理员权限才能控制得了,因此此漏洞只会导致操作系统崩溃,该漏洞编号是CVE-2017-6007。
2.3 扭转
到此我们并不甘心,又逆向了更多的处理程序,我们随机挑选了一个处理程序,这真的很有趣:

[1] [2] [3]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载