看下面一段代码:
结果为:
指针p1指向了一块大小为10字节的堆空间,并存入了一个字符串“hello”,随即释放了该堆空间,但并未将指针p1指向null,这将导致指针p1仍然能够使用。
紧接着指针p2指向了一块新申请为10字节的堆空间,并存入了一个字符串“world”,此时打印p1,p2的地址和字符串,发现p1和p2地址相同,并且此时能通过p1打印出“world”。
在free一块内存后,接着申请大小相同的一块内存,操作系统会将刚刚free掉的内存再次分配。
通过p2能够操作p1,如果之后p1继续被使用,则可以达到通过p2修改程序功能等目的,这也是UAF(use after free)的含义。
利用UAF漏洞,总结如下几个步骤:
申请一块内存以后释放掉它,但是没有清空该内存的指针
重新申请一块同样大小的内存,此时这两个指针对指向同一块内存
对第一步的指针进行操作,它将会影响到第二步申请的指针指向的内存
在释放了g_UseAfterFreeObjectNonPagedPool
对应的堆空间后,并没有将该指针指向null。
导致后续如果有继续使用g_UseAfterFreeObjectNonPagedPool
该全局变量,将会导致UAF漏洞。
该函数名称为FreeUaFObjectNonPagedPool
查看g_UseAfterFreeObjectNonPagedPool
的交叉引用,看还有那些函数使用了该全局变量。
其中AllocateUaFObjectNonPagedPool
的作用是申请一块内存
UseUaFObjectNonPagedPool
为执行g_UseAfterFreeObjectNonPagedPool
指针
FreeUaFObjectNonPagedPool
负责释放堆空间
有了以上函数我们还需要重新申请一块相同大小的内存来控制g_UseAfterFreeObjectNonPagedPool
AllocateFakeObjectNonPagedPoolIoCtrlHandler