0x00前言
这是Windows kernel exploit系列的第二部分 先从UAF开始 因为之前有过pwn的经验 所以堆UAF的原理也是清楚 所以我也就直接从漏洞开始了
0x01漏洞原理
UAF
其实UAF跟其名字一样 释放后重利用 在内存块释放之后 其对应的指针没有被设置为NULL 但是在下次使用之前 有代码堆这块内存进行了修改 比如将内存指针修改为dangling pointer 从而执行我们的shellcode
函数分析
我们来分析几个对堆块操作的函数
首先这个函数是分配一个非分页的池块(内存中的池分配机制是按块来的 假如每个块的大小是64bytes 需要分配70bytes的内存 就会分配两个块 虽然比较浪费内存 但速度快)并用’A’填充 并将池块编辑为”Hack”(在调试的时候方便识别)
AllocateUaFObject
1 | NTSTATUS AllocateUaFObjectNonPagedPool(VOID){ |
FreeUaFObject
这个函数是用来释放池块 图中是安全版本 所以将g_UseAfterFreeObjectNonPagedPool = NULL 而漏洞驱动中 未将此置为NULL
1 | FreeUaFObjectNonPagedPool( |
UseUaFObject
其实函数名已经很明显了 就是使用UAF对象 即就是使用刚才的g_UseAfterFreeObject
1 | NTSTATUS UseUaFObjectNonPagedPool(VOID){ |
AllocateFakeObject
该函数分配fake对象 将对象分配到UAF对象所在的位置
1 | NTSTATUS |
0x02 漏洞分析
我们对上面的函数分别下断点 来观察利用过程
1 | bp HEVD!AllocateUaFObjectNonPagedPool |
然后执行exp WinDbg断下 然后单步执行到这里查看池的状态 已经被’A’占用
再次g 运行到第二个断点 单步执行到这里再次查看池的状态 我们的”HACK”已经是Free了 但没有置为NULL
再次g 运行到第三个断点处 将对象分配到UAF对象所在的位置
再次g 此时已经完成堆喷射 执行回调函数 我们再次观察池 可见callbake地址被覆盖为shellcode的地址 自此 我们就完成了利用
0x03漏洞利用
我们就根据上面的流程来利用编写exp 我们只要将自己申请的池块大小跟内核中池块大小相同 就有可能会利用它 只伪造一块的话肯定是不够的 我们可以通过在0day2上面学到的“堆喷射”技术 多伪造一些堆块来增加概率 然后释放的时候指向我们的shellcode即可利用漏洞
shellcode
1 | void ShellCode() |
堆喷
1 | for (int i = 0; i < 5000; i++) |
调用函数
1 | // 调用 UseUaFObject() 函数 |
对于IO控制码 我们可以用IDA来查看IrpDeviceIoCtlHandler函数
创建CMD
1 | static VOID CreateCmd() |
最后我们发现利用成功了
0x04补丁分析
其实在分析过程中我已经提到过就是补丁版本用完后将g_UseAfterFreeObjectNonPagedPool置为NULL了 导致无法利用
0x05经验总结
这次的UAF漏洞是在我看完漏洞战争之后的 这个也简单 容易理解 我主要是参考TJ师傅的文章 wjllz师傅和0x2l师傅指导 wjllz和0x2l师傅带好人哇!!!人不但技术好还耐心!!!