-
-
[原创]初探内核漏洞:HEVD学习笔记——UninitializedMemoryPagedPool
-
发表于:
2022-7-20 19:55
10860
-
[原创]初探内核漏洞:HEVD学习笔记——UninitializedMemoryPagedPool
Win 10 64位 主机 + win 7 32位虚拟机
调试器:Windbg
工具:VirtualKD-3.0、IDA
目标驱动:HEVD
池块的指针未初始化为NULL时,会指向池块上的脏数据,若不加判断对其进行调用,会导致不可预知的后果。

反汇编TriggerUninitializedMemoryPagedPool函数,可以看到,先使用ExAllocatePoolWithTag在分页池中申请了内容大小为0xF0的池块,定义为UNINITIALIZE_MEMORY_POOL结构,将指针保存到UninitializedMemory中。若池块申请成功,即UninitializedMemory不为NULL的情况下,验证用户缓冲区是否为0x0BAD0B0B0h,若不是,调用UninitializedMemory->Callback()。


明显,程序并未对UninitializedMemory指向的池块的内容进行初始化和赋值,那么UninitializedMemory->Callback()将访问池块里的脏数据并执行。如果我们能控制池块里的脏数据为shellcode地址,就能利用这个漏洞。
如何控制池块中的数据呢?
这里要来理解一下Lookaside List
的概念。Lookaside List提供了一个比较简单的提高小块内存分配和申请效率的机制,用来进行固定大小内存块的小内存块的动态申请和释放。当我们使用 ExAllocatePoolWithTag 申请一个小块内存(<256字节
)时,系统会首先尝试从KPRCB
中的PP(N)PagedLookasideList
分配内存。
Lookaside List的结构
看KPRCB的结构,分页内存和非分页内存各自有一个lookaside列表。lookaside列表中的块最大为256字节,大小以8字节递增,所以每个lookaside列表共有32个节点,每个节点是一条相同大小的块组成的单向链表。

每个节点定义成GENERAL_LOOKASIDE_POOL 结构,节点之间通过LIST_ENTRY形成双向链表。节点内部通过SINGLE_LIST_ENTRY将大小相同的块组织成单向链表。MaximumDepth为单链中块的最多个数,默认为256.

每个块的上方还有一个8字节的HEADER。
[招生]科锐逆向工程师培训(2025年3月11日实地,远程教学同时开班, 第52期)!