-
-
[原创]HEVD学习笔记之UAF
-
发表于: 2021-11-9 11:46 21296
-
实验环境以及HEVD介绍请看:HEVD学习笔记之概述
释放重引用漏洞(UAF)产生的原因是对已经释放的内存区域进行使用,导致了内存崩溃或者任意代码的执行。比如下面这段代码
由于free掉buf1以后,没有及时地将buf1的指针清空,导致随后对buf1的操作将会有效,从而影响了buf2的数据。最终输出如下图:
所以要利用UAF漏洞,需要以下的几个步骤:
申请一块内存以后释放掉它,但是没有清空该内存的指针
重新申请一块同样大小的内存,此时这两个指针对指向同一块内存
对第一步的指针进行操作,它将会影响到第二步申请的指针指向的内存
在HEVD中,有4个函数是用来实现本次的漏洞,分别是
AllocateUAFObjectNonPagedPoolIoCtrlHandler:用来申请一块内存
UseUAFObjectNonPagedPoolIoCtrlHandler:对申请的内存的使用
FreeUAFObjectNonPagedPoolIoCtrlHandler:释放申请的内存
AllocateFakeObjectNonPagedPoolIoCtrlHandler:申请和第一步同样大小的内存并对其进行修改
该函数是函数地址表中的第5个函数,所以对应的IOCTL为0x222003 + 4 * 4。
程序将参数入栈以后就调用了AllocateUAFObjectNonPagedPoolCtrlHandler,继续看该函数
在该函数中,只是调用了AllocateUAFObjectNonPagedPool,继续跟进这个函数。
可以看到,该函数中首先申请了一块0x58大小,tag为Hack的内存,并将指针赋给ebx。
随后程序会将这段内存的前4个字节赋值为UAFObjectCallbackNonPagedPool,后面的字节赋值为'A',并将申请到的内存保存在全局变量中。而前4字节保存的函数只是一个简单的输出函数。
由此可知,AllocateUAFObjectNonPagedPoolIoCtrlHandler做的事情是,申请一块0x58大小的内存。该内存的前4字节赋值为一个函数地址,后面的字节赋值为'A'。而这块内存的地址也会被赋值到全局变量g_UseAfterFreeObjectNonPagedPool中。
该函数是函数表中的第6个函数,对应的IOCTL是0x222003 + 5 * 4。而该IOCTL的操作是对UseUAFObjectNonPagedPoolIoCtrlHandler的调用,而在该函数中会调用UseUAFObjectNonPagedPool。
在UseUAFObjectNonPagedPool中,函数首先会对全局变量g_UseAfterFreeObjectNonPagedPool进行判断,判断该变量中是否保存了内存地址
随后就是对地址的前四字节进行判断,是否保存了函数地址,如果保存了就调用这个函数
该函数是地址表中的第7个函数,对应的IOCTL是0x222003 + 6 * 4。而该IOCTL的操作是对FreeUAFObjectNonPagedPoolIoCtrlHandler的调用,而在该函数中会调用FreeUAFObjectNonPagedPool。
而在FreeUAFObjectNonPagedPool函数中,函数首先会判断g_UseAfterFreeObjectNonPagedPool保存的地址是否为0
如果地址不为0,函数就会调用ExFreePoolWithTag将这段内存释放掉
该函数在函数地址表中的第8个函数,对应的IOCTL为0x222003 + 7 * 4。
将IRP和CurrentStackLocation指针入栈以后就调用了AllocateFakeObjectNonPagedPoolIoCtrlHandler。
在该函数中,函数会将输入缓冲区的地址取出以后入栈,接着在调用AllocateFakeObjectNonPagedPool函数。
函数会申请一块0x58大,tag为Hack的内存,并将内存地址保存到edi和局部变量中。
接着函数会验证输入缓冲区的指针是否可读,然后将输入缓冲区的内容赋值到申请到的0x58字节的内存中,在对申请到的内存的最后一个字节赋值为0。
由上面分析可以知道,申请的0x58大小的内存中的前4个字节保存了一个函数地址。正常情况下,通过对UseUAFObjectNonPagedPoolIoCtrlHandler的调用就会调用程序分配的那个函数,如下图所示
可是,在释放内存的时候,程序没有对全局变量进行处理。这样,如果释放完内存以后,调用AllocateFakeObjectNonPagedPoolIoCtrlHandler的时候,程序会申请0x58大小的内存,这个时候就会得到和全局变量所指地址一样的内存区域,而此时我们通过构造输入缓冲区的前4字节来指定为ShellCode的函数地址,这样就会改变全局变量所指的内存的前4字节,这个时候在调用UseUAFObjectNonPagedPoolIoCtrlHandler的时候,就会调用指定的ShellCode函数地址。
完整的exp代码如下:
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
- [原创]CVE-2022-21882提权漏洞学习笔记 16382
- [原创]CVE-2021-1732提权漏洞学习笔记 19489
- [原创]CVE-2014-1767提权漏洞学习笔记 15192
- [原创]CVE-2018-8453提权漏洞学习笔记 18526
- [原创]CVE-2020-1054提权漏洞学习笔记 13542