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

HEVD池溢出分析

来源:本站整理 作者:佚名 时间:2019-01-29 TAG: 我要投稿

环境准备
Win 10 64位 主机  + win 7  32位虚拟机
Windbg:调试器
VirtualKD-3.0:双击调试工具
InstDrv:驱动安装,运行工具
HEVD:一个Windows内核漏洞训练项目,里面几乎涵盖了内核可能存在的所有漏洞类型,非常适合我们熟悉理解Windows内核漏洞的原理,利用技巧等等
 
windows内核池简介
想要研究windows内核漏洞,需要对windows池有一定的认识,其管理结构、分配、释放都需要有很深的了解。这里我不会详细介绍池的一些知识,只推荐一些网站以供参考。
https://media.blackhat.com/bh-dc-11/Mandt/BlackHat_DC_2011_Mandt_kernelpool-wp.pdf
https://www.cnblogs.com/flycat-2016/p/5449738.html
下面给一个内核pool page的图,知道这个图,对于该池漏洞的分析,基本足够。

Windows内核中有很多以4k为单位的pool page,每个pool page会被划分为大小不一的pool chunk以供内核程序使用。每个pool chunk有一个pool header结构(8个字节大小),用来描述pool chunk的一些基本信息。
Pool header结构如下:
kd> dt nt!_POOL_HEADER
   +0x000 PreviousSize     : Pos 0, 9 Bits
   +0x000 PoolIndex        : Pos 9, 7 Bits
   +0x002 BlockSize        : Pos 0, 9 Bits
   +0x002 PoolType         : Pos 9, 7 Bits
   +0x000 Ulong1           : Uint4B
   +0x004 PoolTag          : Uint4B
   +0x004 AllocatorBackTraceIndex : Uint2B
   +0x006 PoolTagHash      : Uint2B
 
当我们运行代码:
KernelBuffer = ExAllocatePoolWithTag(NonPagedPool,
                                             (SIZE_T)POOL_BUFFER_SIZE,
                                             (ULONG)POOL_TAG);
该函数回返回一个pool chunk,返回的地址KernelBuffer = pool header + 8的空间。也就是说我们返回的空间前面有8个字节的头部,只是我们看不到。Pool header 后面紧跟的是我们的数据,当我们的数据过程长时,就会向下覆盖到其他chunk。
 
HEVD池漏洞代码分析
漏洞代码如下:
#define POOL_BUFFER_SIZE 504
    __try {
        DbgPrint("[+] Allocating Pool chunk\n");
        // Allocate Pool chunk
        KernelBuffer = ExAllocatePoolWithTag(NonPagedPool,
                                             (SIZE_T)POOL_BUFFER_SIZE,
                                             (ULONG)POOL_TAG);
        if (!KernelBuffer) {
            // Unable to allocate Pool chunk
            DbgPrint("[-] Unable to allocate Pool chunk\n");
            Status = STATUS_NO_MEMORY;
            return Status;
        }
        else {
            DbgPrint("[+] Pool Tag: %s\n", STRINGIFY(POOL_TAG));
            DbgPrint("[+] Pool Type: %s\n", STRINGIFY(NonPagedPool));
            DbgPrint("[+] Pool Size: 0x%X\n", (SIZE_T)POOL_BUFFER_SIZE);
            DbgPrint("[+] Pool Chunk: 0x%p\n", KernelBuffer);
        }
        // Verify if the buffer resides in user mode
        ProbeForRead(UserBuffer, (SIZE_T)POOL_BUFFER_SIZE, (ULONG)__alignof(UCHAR));

[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14]  下一页

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