freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

Windows内核进击之旅-UAF漏洞
2018-11-06 10:32:40
所属地 湖南省



原创: raycp 合天智汇 昨天


内核双机调试环境搭建的教程在网上有很多,值得一提的是mac下通过虚拟机也可以实现双机调试,这次要分析的文章是内核漏洞中的UAF漏洞。在这里主要是通过HEVD这个项目来了解内核漏洞的原理以及利用方式。

需要指出的是,我这里的调试环境是,调试机是win764位,被调试机是win732位。

UAF漏洞

UAF漏洞原理在网上也可以找到很多讲解的文章,具体的原理不再讲解。大致原理是:申请出一个堆块保存在一个指针中,在释放后,没有将该指针清空,形成了一个悬挂指针(danglingpointer),而后再申请出堆块时会将刚刚释放出的堆块申请出来,并复写其内容,而悬挂指针此时仍然可以使用,使得出现了不可控的情况。攻击者一般利用该漏洞进行函数指针的控制,从而劫持程序执行流。

漏洞利用的过程可以分为以下4步:

  1. 申请堆块,保存指针。

  2. 释放堆块,形成悬挂指针。

  3. 再次申请堆块,填充恶意数据。

  4. 使用悬挂指针,实现恶意目的。

下面我们去HEVD项目中具体看如何体现。

申请堆块

首先是0x222013驱动号对应的分配USE_AFTER_FREE结构体的函数,该结构体的定义是

可以看到里面有个函数指针,以及后面有个0x54大小的字符串。分配UAF对象函数的关键代码如下:

可以看到首先调用ExAllocatePoolWithTag申请出PUSE_AFTER_FREE结构体,并将该结构体的函数指针赋值为一个UaFObjectCallback函数地址。并在最后一行代码里,将申请出来的堆块保存在全局指针中。


释放堆块

直接看到0x22201B驱动号对应的释放堆块的FreeUaFObjectIoctlHandler函数。关键代码及注释如下:

漏洞即存在该函数当中,HEVD函数里有安全和漏洞两个版本的选项,通过源代码可以很明显的看到在安全的版本中,释放掉堆块后,有将全局指针清空的操作,而在漏洞的版本中并没有清空指针的操作,从而形成了悬挂指针,导致了漏洞的形成。


再次申请堆块

再次申请堆块对应的是0x22201F驱动号对应的AllocateFakeObjectIoctlHandler函数,该函数中申请出一个与USE_AFTER_FREE同样大小的FAKE_OBJECT结构体。

关键源代码及注释如下:

可以看到再次申请的这个FAKE结构体与前面的区别在于没有前面4字节的函数指针。这里的攻击场景可以理解为,再次申请出来的FAKE结构体与之前的结构体是同一块内存,在最后将用户输入拷贝到结构体的时候就会覆盖结构体里面的函数指针,指向攻击者shellcode的位置。


使用悬挂指针

在上一步中,我们已经做到了FAKE结构体和USE_AFTER_FREE指向同一块内存,同时使用用户输入覆盖了该结构体的函数指针,因此再次使用函数指针时,会导致控制流的劫持,驱动号0x222017对应的UseUaFObjectIoctlHandler函数关键源代码如下:


编写EXP

上一部分通过源代码介绍了漏洞的大致利用过程,这一部分,主要是具体exp的编写,以及实际要解决的一个问题。


需要解决的问题

在这里需要解决的一个问题就是,在我们第二步释放堆块的时候,该结构体有可能会和前面已经释放的堆块合并,如果合并的话,在我们再次申请的时候申请的时候,分配出来的堆块将不再是同一块内存,导致覆盖函数指针失败。

如何解决该问题,有一篇论文写的很好,要详细了解可以去看看,最后解决的方案大致意思是如下:

Windows系统中有个叫IoCompletionReserve的对象大小为0x60,可以通过NtAllocateReserveObject申请出来,需要做的是

1.首先申请0x10000个该对象并将指针保存下来;

2.然后再申请0x5000个对象,将指针保存下来;

3.第二步中的0x5000个对象,每隔一个对象释放一个对象;

第一步的操作是将现有的空余堆块都申请出来,第二步中申请出来的堆块应该都是连续的,通过第三步的操作,使得我们申请UAE_AFTER_FREE结构体其前面的堆块应该不是空闲的,因此在释放的时候不会合并,从而再分配的时候出现意外的可能性基本为0。

下面是具体exp的代码,是python编写的。

首先第一步是申请IoCompletionReserve对象并释放,以此来控制好堆块布局的代码。

接下来是申请UESAFTERFREE堆块

再接着是释放该堆块

紧接着是申请出FAKE结构体,使用shellcode地址填写前四字节,shellcode使用的是提权shellcode,具体原理可以在网上寻找。

最后是调用使用该悬挂指针

完整的exp代码如下:

最终获得system权限

图片.png

# 合天智汇 # 合天网安
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者