首页
社区
课程
招聘
[原创]内核漏洞学习[6]-HEVD-UninitializedStackVariable
发表于: 2021-11-21 14:42 28225

[原创]内核漏洞学习[6]-HEVD-UninitializedStackVariable

2021-11-21 14:42
28225

# HEVD-UninitializedStackVariable

一: 概述

HEVD:漏洞靶场,包含各种Windows内核漏洞的驱动程序项目,在Github上就可以找到该项目,进行相关的学习

 

Releases · hacksysteam/HackSysExtremeVulnerableDriver · GitHub

环境准备:

Windows 7 X86 sp1 虚拟机

使用VirtualKD和windbg双机调试

HEVD 3.0+KmdManager+DubugView

二:漏洞点分析

TriggerUninitializedMemoryStack函数存在漏洞,内核函数栈中的变量未初始化,如果用户传入的UserValue==MagicValue(0xBAD0B0B0),就会赋值参数value和回调函数callback地址,并在后面调用callback。如果uservalue不等MagicValue,就存在利用点。

 

在非安全版本中UninitializedMemory变量定义但是没有初始化,由于该变量布局在栈上,它会拥有一个之前调用函数遗留的随机垃圾值。

 

源码:

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
NTSTATUS
TriggerUninitializedMemoryStack(
    _In_ PVOID UserBuffer
)
{
    ULONG UserValue = 0;
    ULONG MagicValue = 0xBAD0B0B0;
    NTSTATUS Status = STATUS_SUCCESS;
 
#ifdef SECURE
    //
    // Secure Note: This is secure because the developer is properly initializing
    // UNINITIALIZED_MEMORY_STACK to NULL and checks for NULL pointer before calling
    // the callback
    //
 
    UNINITIALIZED_MEMORY_STACK UninitializedMemory = { 0 };//安全版本: 栈变量初始化了
#else
    //
    // Vulnerability Note: This is a vanilla Uninitialized Memory in Stack vulnerability
    // because the developer is not initializing 'UNINITIALIZED_MEMORY_STACK' structure
    // before calling the callback when 'MagicValue' does not match 'UserValue'
    //
 
    UNINITIALIZED_MEMORY_STACK UninitializedMemory;//不安全版本: 栈变量未初始化
#endif
 
    PAGED_CODE();
 
    __try
    {
        //
        // Verify if the buffer resides in user mode
        //
 
        ProbeForRead(UserBuffer, sizeof(UNINITIALIZED_MEMORY_STACK), (ULONG)__alignof(UCHAR));
 
        //
        // Get the value from user mode
        //
 
        UserValue = *(PULONG)UserBuffer;
 
        DbgPrint("[+] UserValue: 0x%p\n", UserValue);
        DbgPrint("[+] UninitializedMemory Address: 0x%p\n", &UninitializedMemory);
 
        //
        // Validate the magic value
        //
 
        if (UserValue == MagicValue) {
            UninitializedMemory.Value = UserValue;
            UninitializedMemory.Callback = &UninitializedMemoryStackObjectCallback;
        }
 
        DbgPrint("[+] UninitializedMemory.Value: 0x%p\n", UninitializedMemory.Value);
        DbgPrint("[+] UninitializedMemory.Callback: 0x%p\n", UninitializedMemory.Callback);
 
#ifndef SECURE
        DbgPrint("[+] Triggering Uninitialized Memory in Stack\n");
#endif
 
        //
        // Call the callback function
        //
 
        if (UninitializedMemory.Callback)//在此处判断回调函数是否为0,否则可利用0页内存,
        {
            UninitializedMemory.Callback();
        }
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Status = GetExceptionCode();
        DbgPrint("[-] Exception Code: 0x%X\n", Status);
    }
 
    return Status;
}

逆向HEVD.sys
在这里插入图片描述

 

if (UninitializedMemory.Callback) //此处判断回调函数是否为空,否则含有空指针漏洞,可利用在0页内存上构造payload,相关HEVD:

 

[原创]内核漏洞学习[5]-HEVD-NullPointerDereference-二进制漏洞-看雪论坛-安全社区|安全招聘|bbs.pediy.com

 

那么既然有判断,就要换个方法,回调函数地址修改为不为0的地址,然后该地址指向payoad,

三:漏洞利用

HEVD_IOCTL_UNINITIALIZED_MEMORY_STACK控制码对应的派遣函数UninitializedMemoryStackIoctlHandlercase

1
2
3
4
5
case HEVD_IOCTL_UNINITIALIZED_MEMORY_STACK:
DbgPrint("****** HEVD_IOCTL_UNINITIALIZED_MEMORY_STACK ******\n");
Status = UninitializedMemoryStackIoctlHandler(Irp, IrpSp);
DbgPrint("****** HEVD_IOCTL_UNINITIALIZED_MEMORY_STACK ******\n");
break;

UninitializedMemoryStackIoctlHandlercase 函数调用TriggerUninitializedMemoryStack触发漏洞

 

逆向获得IO控制码0x22202f

 

在这里插入图片描述

 

sub_4460E8-->sub_445FFA(漏洞函数)

 

(1)测试

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
#include
#include
HANDLE hDevice = NULL;
 
#define HEVD_IOCTL_UNINITIALIZED_MEMORY_STACK CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80B, METHOD_NEITHER, FILE_ANY_ACCESS)
//#define HEVD_IOCTL_UNINITIALIZED_MEMORY_STACK                    IOCTL(0x80B)
int main()
 
{
 
    hDevice = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver", GENERIC_READ | GENERIC_WRITE,
        NULL,
        NULL,
        OPEN_EXISTING,
        NULL,
        NULL
        );
    if (hDevice == INVALID_HANDLE_VALUE || hDevice == NULL)
    {
        printf("[-]failed to get device handle !");
        return FALSE;
 
    }
    printf("[+]success to get device  handle");
 
    if (hDevice) {
 
        DWORD bReturn = 0;
        char buf[4] = { 0 };
        *(PDWORD32)(buf) = 0xBAD0B0B0;
 
        DeviceIoControl(hDevice, 0x22202f, buf, 4, NULL, 0, &bReturn, NULL);
    }
 
 
 
}

因为uservalue=0xBAD0B0B0,所以打印出信息,

 

在这里插入图片描述

 

*(PDWORD32)(buf) = 0x12345678;

 

将值修改为0x12345678,再次运行

 

我们传入值与MagicValue值不匹配时,则会触发漏洞

 

在这里插入图片描述

 

在cmp处下断点,

 

在这里插入图片描述

 

HEVD!TriggerUninitializedMemoryStack偏移 0x53处,下断点,运行

1
2
kd> bp HEVD!TriggerUninitializedMemoryStack+0x53
kd> g

执行我们的测试exp 断下来后查看

 

在这里插入图片描述

 

在这里插入图片描述

 

stack_init-callback=94083ed0-940839cc=504(1284 bytes)

 

在这里插入图片描述

 

如果我们比较失败了,继续下行调用函数的时候,我们调用的将是一个内核栈上的垃圾值!此值是不固定的,它会拥有一个之前调用函数遗留的随机垃圾值。

 

我们已经知道了该变量距离当前栈起始位置有多远,在驱动程序源代码中看到,易受攻击的代码被try/except包围,目标操作系统不会崩溃。无法用测试exp触发系统BSOD,


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2021-11-21 16:14 被pyikaaaa编辑 ,原因:
收藏
免费 5
支持
分享
最新回复 (1)
雪    币: 732
活跃值: (197)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢分享。
2022-1-17 20:25
0
游客
登录 | 注册 方可回帖
返回