0x00前言
现在开始第五部分的池溢出部分 池的话跟堆有些相似 但又有不同 需要进一步了解的 看这里 有人翻译了 这里 还有个好理解的 这儿 看完应该就差不多了
0x01漏洞原理
池是一种动态申请的内存结构 是在内核中存在的 池的大小在分配出来是一定的 如果程序没有对输入长度进行检查 就会导致溢出 此时我们就可以控制程序流程
函数分析
这个函数主要是在调用RtlCopyMemory函数时 未对Size进行控制 导致溢出 溢出到下一个池块的位置 类似于前面的栈溢出
TriggerBufferOverflowNonPagedPool
1 | NTSTATUS |
0x02漏洞分析
我们给函数下断点 先计算下偏移 将断点下在RtlCopyMemory函数之前(其实也可以单步运行到就行。。)
1 | bp HEVD!TriggerBufferOverflowNonPagedPool+f6 |
然后查看池的状态
此时的返回地址为
单步执行后被覆盖
所以只要控制了这里 就可以
0x03漏洞利用
需要注意的是 我们需要伪造Event结构体 伪造指针控制程序劫持流 然后进行池喷射增加命中概率
伪造Event
使用CreateEvent函数在内核中创建一个Event 我们查看一下_OBJECT_HEADER TypeIndex是一个索引 对象类型数组是ObTypeIndexTable 是OBJECT_TYPE数组
我们再去查看ObTypeIndexTable结构 在偏移0x28处为TypeInfo 进一步查看之后 发现在偏移0x38处存在全局回调指针
所以我们也就有了清晰的思路 首先通过池溢出将Event结构体的Typeindex覆盖为0 调用相应函数时将会从0内存处去寻找函数指针 我们在用户模式下可以控制0页内存 导致去找到CloseProcedure的值 我们将其覆盖为shellcode的地址即可
1 | RtlFillMemory((PVOID)UserModeBuffer, UserModeBufferSize, 0x41); |
池喷射
1 | VOID SprayNonPagedPoolWithEventObjects() { |
利用成功
0x04补丁分析
安全版本中 计算了当前池的大小 导致不会产生溢出
0x05经验总结
池之前接触的很少 只是知道时内核中类似于堆的东西 所以在复现之前先学习了些池的东西 只了解了些跟这个漏洞有关的东东。。。。