HEVD驱动程序利用之道,Part 2:栈缓冲区溢出(三)

2020-12-09 8,477

(接上文)

在上一篇文章中,我们为读者介绍了驱动程序中的栈溢出漏洞的利用方法,在本文中,我们将为读者详细介绍利用该漏洞实现特权提升的方法。

特权提升

现在我们成功地控制了执行流程,接下来,我们需要引入shellcode,从而获得本地Windows系统的更高权限。虽然已经有不少已知的技术可以用来达到我们的目标,但就这里来说,我将使用令牌窃取技术。

令牌窃取特权升级技术的目标是用更高特权的令牌(即SYSTEM)定位并替换所选进程的令牌。

Windows系统中,一切都可以被概念化为一个对象。每个对象都有一个安全描述符,它指定了一个实体可以在对象上进行哪些活动。一个令牌,或者说访问令牌,包含了所有与给定实体的权利和特权相关的信息。

为了用更高权限的访问令牌来替换我们选定的进程令牌,我们必须首先了解一些关键的数据结构。下面,让我们先来介绍一下相关的数据结构。 

KPCR结构体

Windows系统中,处理器信息被存储在内核处理器控制区域(KPCR)数据结构中。KPCR结构总是使用FS段寄存器进行索引,在Windows x86中为FS:[0](或在Windows x64中为GS:[0])。我们可以在WinDBG中用以下命令查看该结构体:dt nt!_KPCR。

image.png 

经过分析,在KPCR数据结构中,有不少成员。不过,列表中我们感兴趣的成员是偏移量为0x120的PrcbData。这个成员指向KPRCB数据结构。

KPRCB结构体

KPCR数据结构中,我们标识了指向内核处理器控制块(KPRCB)数据结构的指针。KPRCB结构体拥有内核资源管理所需的大部分信息。下面是WinDBG中KPRCB数据结构的可视化表示——为此,我们可以使用以下命令:dt nt!_KPRCB。

image.png 

在上面的代码片段中,我们在KPRCB数据结构中感兴趣的成员是CurrentThread。CurrentThread成员位于偏移量0x004处,指向当前的KTHREAD数据结构。

KTHREAD结构体

KTHREAD数据结构是一个更大的数据结构的一部分,称为ETHREAD结构。在这里,我们会发现当前执行的线程的信息。我们可以通过dt nt!_KTHREAD命令将该表转储到WinDBG中,以便于进行查看。

image.png 

虽然这个数据结构拥有令人生畏的信息量,但就技术而言,我们感兴趣的是指向KAPC_STATE数据结构的ApcState成员的偏移量。

KAPC_STATE结构体

KAPC_STATE数据结构用于线程查找其关联的进程。注意,它与我们的特权提升技术紧密相关,因为这个结构保存了一些我们需要的重要信息。我们可以在WinDBG中运行dt nt!_KAPC_STATE命令来分析这个数据结构及其成员。

image.png 

如上图所示,该数据结构包含的成员很少。Process成员是我们这里的兴趣所在。这个成员含有一个指向KPROCESS数据结构的指针。与KTHREAD结构体类似,KPROCESS结构体也是一个更大的数据结构EPROCESS结构的一部分。现在,我们来看看EPROCESS结构体。 

EPROCESS结构体

EPROCESS数据结构中包含了我们需要的大量有用信息。例如,这个结构体包含了我们的令牌窃取技术所需的数据成员。接下来,让我们通过下面的命令来看看这个数据结构及其成员:dt nt!_EPROCESS。

image.png

在上面的代码片段中,EPROCESS结构体内有三个成员是我们的兴趣所在。

EPROCESS.UniqueProcessId

该成员拥有当前进程的PID。它将起到识别SYSTEM进程的作用。方便的是,SYSTEM进程总是以PID值4来运行,为了验证这一点,我们可以查询SYSTEM进程的地址,并将偏移量添加到EPROCESS.UniqueProcessId中。

image.png 

EPROCESS.ActiveProcessLinks

EPROCESS.Token.EPROCESS结构中的这个成员是一个双向链表(指向前一个节点和后一个节点的指针),包含了本地系统中所有其他活动的进程。

image.png 

EPROCESS.Token

EPROCESS结构体中的Token成员包含分配给进程的访问令牌。这是我们要复制到我们选择的进程中的权限数据。

image.png 

image.png 

实现令牌窃取功能的Shellcode

就这里来说,虽然编写payload的方法有很多,但我还是坚持介绍HackSys的版本。

image.png 

从上面的代码片断中可以看出,我们需要向前面提到的一些关键数据结构内的成员提供偏移量。我们现在就来介绍相关偏移量的计算过程。

image.png 

上面可视化的信息呈现了我们需要提供给代码的偏移量。我们来讨论一下这些偏移值是如何计算出来的。 

1. SYS_PID - 这是为SYSTEM进程静态分配的PID值。

2. PID_OFFSET - 这个值是UniqueProcessId成员位于_EPROCESS数据结构中的偏移量。

3. TOKEN_OFFSET - 这个值是Token成员位于_EPROCESS数据结构中的偏移量。

4. FLINK_OFFSET - 这个值是ActiveProcessLinks成员位于_EPROCESS数据结构中的偏移量。

5. KTHREAD_OFFSET - 这个值是通过_KPCR.ProcData(0x120h)和_KPRCB.CurrentThread(0x004h)的偏移量相加计算出来的。

6. EPROCESS_OFFSET - 这个值是通过取_KTHREAD.ApcState(0x040h)和_KAPC_STATE.Process(0x010h)的偏移量之和来计算的。

现在,我们已经对这些值是如何构成的了如指掌了,接下来,让我们来分析一下payload所执行的操作。

image.png 

payload的第一部分,我们只是设置了一些寄存器,使其指向CurrentThread和CurrentProcess成员的位置。在ECX寄存器中,我们要保存当前线程的进程(cmd.exe)的副本。在EDX寄存器中,我们要存储静态分配的系统PID。

image.png 

我们将抓取本地系统上的每一个活动进程,直到找到SYSTEM进程。如果索引的PID不等于4的值,我们会递增索引,检查下一个PID。

image.png 

找到SYSTEM进程后,我们跳转到上面视觉图中看到的代码片段。在这里,我们将复制SYSTEM进程的访问令牌,并用SYSTEM令牌替换目标进程的访问令牌。 

下面,让我们回顾一下在实现令牌窃取功能的payload代码所执行的步骤:

1. 获取KTHREAD和EPROCESS的指针。

2. 遍历ActiveProcessLinks双向列表,直到找到SYSTEM的PID。

3. 保存SYSTEM令牌,并用SYSTEM令牌替换目标进程(攻击者的进程)中的令牌。

4. 恢复执行/维护完整性。

需要注意的是,在不同的Windows版本中,所识别的偏移量并不是一成不变的! 对于Windows 7 SP1之外的系统,一定要遵循上面的步骤,验证偏移量。如果你不这样做的话,很可能会使系统崩溃。

注意,上面的“恢复执行/维护完整性”步骤现在还没有介绍。接下来,我们将深入探讨一下这一步。

小结

在本文中,我们为读者介绍了实现提权过程中需要了解的关键数据结构,以及实现提权的相关shellcode;在接下来的文章中,我们将为读者介绍如何维护驱动程序的完整性。

 

原文地址:https://jb05s.github.io/HEVD-Driver-Exploitation-Part-2-Stack-Overflow-Presented-in-Python-and-C/


本文作者:mssp299

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/149152.html

Tags:
评论  (0)
快来写下你的想法吧!

mssp299

文章数:51 积分: 662

安全问答社区

安全问答社区

脉搏官方公众号

脉搏公众号