首页
论坛
课程
招聘
[原创]HEVD池溢出系列
2021-5-20 11:06 4484

[原创]HEVD池溢出系列

2021-5-20 11:06
4484

A TALE OF HEVD -- WINDOWS 7 KERNEL POOL OVERFLOW

由于新接触到了一个知识点,花了些时间去学习windows7内核池的一些知识。

 

这个漏洞的复现过程实在是太过于精美,并且在这过程间补充到了不少的知识,打算就池溢出做一期笔记。

从堆溢出再到池溢出

内核池实际上是windows中类似于堆的一种动态内存结构。两者的利用在我看来是十分相似的。

 

将池溢出之前,我们不妨先回顾以下堆溢出

 

有CTF经验的朋友们应该不陌生堆溢出

 

那么如何完成一次堆溢出利用呢?

 

可以做出如下的假设:

 

堆块是系统分配给程序的空间,堆块在系统中是连续的一段内存,那么如果我们可以为某个带函数指针的对象申请一段内存空间,并且通过堆溢出修改我们的函数指针指向shellcode,那么我们即可完成堆溢出利用。

 

hevd池溢出

 

但是理想和现实总是存在差距的,好在可以将理想照进现实

 

那么不妨从这个思路开始

 

按照我的思路,分析漏洞时需要有三个部分的思考

  • 它是谁:函数是哪里出现问题的,我们可以判断出它是哪种类型的漏洞。
  • 到哪里去:函数会导致什么后果,从而触发漏洞
  • 从哪里来:如何去调用到目标函数。

但是由于HEVD本身就是一个漏洞复现的靶场,由于存在源码,所以我们可以省去最后一步做分析。

 

但我认为,复现或者挖掘漏洞的过程中,从哪里来也是很重要且具有挑战性的工作

它是谁

使用IDA定位到漏洞位置

 

image-20210511153023958

 

那么我们先简单的编制一个poc,证明漏洞的存在

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<stdio.h>
#include<windows.h>
 
int main() {
    ULONG bReturn = 0;
    HANDLE hevDevice;
    ULONG BytesReturned;
    hevDevice = (HANDLE)CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver", 0xC0000000, 0, NULL, 0x3, 0, NULL);
    char buf[0x1f8] = { 0 };
    if (!hevDevice) {
        printf(" failed to get handle");
    }
    RtlFillMemory(buf, 0x1f8, 'a');
    DeviceIoControl(hevDevice, 0x22200f, buf, 0x1f8, NULL, 0, &bReturn, NULL);
 
    return 0;
}

在之前的分析中,我们已经知道了是由于HEVD!memcpy没有对size进行判断从而导致了漏洞的发生,那么我们首先通过windbg下断点到HEVD!memcpy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
kd> u HEVD!TriggerBufferOverflowNonPagedPool+0xf0
HEVD!TriggerBufferOverflowNonPagedPool+0xf0 [c:\projects\hevd\driver\hevd\bufferoverflownonpagedpool.c @ 137]:
839f3dbe ff750c          push    dword ptr [ebp+0Ch]
839f3dc1 ff7508          push    dword ptr [ebp+8]
839f3dc4 53              push    ebx
839f3dc5 e812c4fbff      call    HEVD!memcpy (839b01dc)
839f3dca 6886659f83      push    offset HEVD! ?? ::NNGAKEGL::`string' (839f6586)
839f3dcf 6a03            push    3
839f3dd1 6a4d            push    4Dh
839f3dd3 ffd7            call    edi
 
kd> u HEVD!TriggerBufferOverflowNonPagedPool+0xf7
HEVD!TriggerBufferOverflowNonPagedPool+0xf7 [c:\projects\hevd\driver\hevd\bufferoverflownonpagedpool.c @ 137]:
839f3dc5 e812c4fbff      call    HEVD!memcpy (839b01dc)
839f3dca 6886659f83      push    offset HEVD! ?? ::NNGAKEGL::`string' (839f6586)
839f3dcf 6a03            push    3
839f3dd1 6a4d            push    4Dh
839f3dd3 ffd7            call    edi
839f3dd5 681a619f83      push    offset HEVD! ?? ::NNGAKEGL::`string' (839f611a)
839f3dda 688e649f83      push    offset HEVD! ?? ::NNGAKEGL::`string' (839f648e)
839f3ddf 6a03            push    3
kd> bp HEVD!TriggerBufferOverflowNonPagedPool+0xf7

运行我们的poc

 

image-20210512130333268

 

查看池状态,当然,之前我们下了断点,此时记得执行p命令

 

查看当前池块内容

 

image-20210512130549097

 

试着多发送8个字节的内容

 

image-20210512131326451

 

我们发现后续的池块由于结构被破坏,导致了无法被识别

 

image-20210512131425613

 

此时系统也会发生蓝屏

 

image-20210512131609406

 

此时我们已经彻底明白了,漏洞“是谁”

 

但是,我们简单布置的poc,多溢出的字节会由于破坏的后续池块的结构而导致系统的BSOD

 

也就是,我们的“到哪去”并不顺利

 

那么,我们应该更具体地构想,这段内存应该到哪里去

到哪里去

根据之前所讲的,由于C++面向过程的特性,我们可以向申请的堆块(池)中为某些特定对象申请空间,进而通过溢出控制其函数指针从而执行shellcode

 

当然,对象的大小也必须是合适的,由于我们的池块大小为0x1F8+8=0x200

 

因此选择CreateEventA函数,CreateEventA申请出Event对象的大小为0x40,0x40 * 8 == 0x200

 

先申请大量的event对象,再释放掉部分的event,这将会在内存中造成一些空洞,从而得以在这段空间中申请到kernel buffer,此时再申请kernel buffer将会保证下一个位置是一个Event对象

 

利用思路

 

申请大量的event对象后

 

image-20210512162804191

 

那我们随便取出一个event对象查看内部结构,首先我们查看windows中object的结构

 

image-20210514150809834

 

index的值为0xC,所在obTypeIndexTable表中的偏移为0xC

 

image-20210512163719395

 

所谓obTypeIndexTable表是指,xp直接在OBJECT_HEADER里保存了POBJECT_TYPE指针,而Win7里把所有的对象类型放在了一个表里,这个表叫做obTypeIndexTable

 

查看该表内容,并定位到0xC的位置

 

image-20210512164344595

 

可见Event对象保存在此处

 

查看该对象结构

 

image-20210520110533734

 

这里我们选用CloseProcedure函数作为修改的函数,理由是,在之后的源码中,我们发现会有

 

image-20210514143221988

 

函数来释放这段空间

 

可是接下来的问题,怎么能够去修改到CloseProcedure函数的呢?我们并不能通过池溢出直接修改到这个函数的指针

 

但是我们能修改到index的索引

 

ObTypeIndexTable第0个索引指向0地址(0x00000000)

 

利用此思路,我们可以构建如下的利用思路

 

最终利用思路

利用:

exp写的不是很优雅,建议从参考链接中获取两位师傅的博客

 

image-20210514153916435

道别时想说些什么

​ 拖了很久才完成这一部分的利用,emmmm,总体收获还是蛮大的,离不开50u1w4y师傅的帮助,exp也是参考了他的exp,故而就不张贴出来了。

 

当然复现的过程中也从这些师傅的博客中获取了很多知识,十分感谢他们

参考链接:

https://50u1w4y.github.io/site/HEVD/nonPagedpooloverflow/#0x00

 

https://bbs.pediy.com/thread-252665.htm


[培训] 优秀毕业生寄语:恭喜id:一颗金柚子获得阿里offer《安卓高级研修班》火热招生!!!

上传的附件:
收藏
点赞1
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回