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

2020-12-08 5,857

(接上文)

在上一篇文章中,我们为读者介绍了驱动程序以及其中的栈溢出漏洞方面的知识,在本文中,我们将为读者介绍该漏洞的利用过程。

漏洞利用过程——Windows 7 SP1 (x86)

利用该漏洞的第一步是打开驱动对象的句柄。如前所述,这是必不可少的,因为它是用于客户端与设备驱动程序进行交互。这个过程可以通过CreateFileA()  API函数来完成。

image.png 

在上面的代码段中,第一个参数(lpFileName)是我们将传递设备驱动程序所公开的符号链接的名称的地方。获得驱动程序对象的句柄,我们还必须通过DeviceIoControl() API函数启动与驱动程序的交互。 

image.png 

我们需要将在CreateFileA()中设置的驱动对象的句柄作为第一个参数传递给DeviceIoControl()。此外,在第二个参数中,我们需要提供我们希望对其进行请求的IO代码;前面我们已经确定为0x222003。最后,第三和四个参数(lpInBuffer和nInBufferSize)是我们需要传递用户提供的缓冲区的地方。考虑到所有这些因素,下面是我们的初始代码的样子。

 

C语言版本的初始exploit代码:

image.png 

Python语言版本的初始exploit代码:

image.png 

现在我们的初始PoC已经准备好了,让我们转至上一篇文章中设置的测试环境。一旦我们的环境启动并运行,并且我们在WinDBG中的Debugger和Debuggee机器之间建立了一个成功的COM,就可以把初始PoC复制到我们的Debuggee机器上。在运行代码之前,我们先在WinDBG中的TriggerStackOverflow处设置一个断点,来验证我们是否达到了预期的目标。

 

设置好断点后,我们现在可以在Debuggee机器上运行我们的PoC来查看运行结果。

image.png 

正如我们所看到的,我们击中了我们想要的断点。然而,如果我们允许继续执行,驱动程序就会响应客户端的请求,但是并没有触发底层的漏洞。那是因为我们传递的缓冲区大小不足以溢出到调用堆栈中的相邻内存中,从而导致关键数据被覆盖。在目前的情况下,我们只是填满了整个缓冲区。

 

在下一个案例中,让我们尝试传递一个更大的用户提供的缓冲区,看看是否会导致我们正在寻找的行为。这次,我们不传递大小为0x800h的缓冲区,而是传递一个大小为0x900h的缓冲区(十进制值为2304)。 

 

C语言版本:

image.png 

Python语言版本:

image.png 


更新我们的PoC后,将其复制到debuggee机器上并运行它们,以分析其行为。

image.png 

image.png 

Bingo! 我们已经成功地用更新后的用户提供的缓冲区大小覆盖了EIP,并发现了一个访问违规错误。太棒了!所以,我们触发了一个普通的EIP覆盖漏洞,但是接下来该怎么做呢?

我们需要在用户提供的缓冲区中找到我们控制EIP的偏移量。通过找到EIP的偏移量,我们就可以控制执行的流程,并且能引入我们自己的代码并执行之。

但是,我们如何才能找到偏移量呢?我们可以引入一个由独特模式组成的字符串来代替我们的“A”序列。有了这个唯一的模式,当触发访问违规时,我们就可以通过将EIP中存储的字节,与我们的唯一字符串进行比较,来识别EIP的偏移量。

实际上,目前有很多很棒的资源可以帮助我们创建具有唯一字符串的模式,我个人喜欢使用Metasploit。具体来说,我个人喜欢使用Metasploit的pattern_create和pattern_offset的Ruby脚本,但对于读者来说,大家可以根据自己的喜好选择相应的脚本。下面,让我们用pattern_create.rb脚本来创建字符串。 

 

现在,请执行下面的命令,即./pattern_create.rb -l 2304,因为我们设法覆盖了EIP,并造成了用户提供的缓冲区大小为0x900的访问违规错误。

image.png 

用生成的模式替换PoC中的“A”序列,然后将更新后的PoC复制到Debuggee机器上。

让我们运行更新后的PoC,并确定EIP中存储的内容。

image.png 

如上面的截图所示,我们成功地用0x72433372覆盖了EIP。让我们找出这个字节序列在我们生成的模式中的位置。为此,我们将使用pattern_offset.rb脚本。

 

在这里,我们要运行的命令是./pattern_offset -q 72433372。

image.png 

太棒了!Ruby脚本在偏移量为0x820h(或2080十进制)处识别了我们的字节序列实例。让我们更新PoC来验证我们是否在这个偏移处控制了EIP。为此,我们将重新引入一个“A”的序列,以替换生成的模式。然而,这次我们将把“A”写到相应的偏移量处,然后写四个字节的“B”。通过使用这种方法,我们将能够验证我们的“B”是否覆盖了EIP,从而验证我们对执行流程的控制是否得手。

 

下面是我们更新后的PoC的代码。

C语言版本:

image.png 

Python语言版本:

image.png 

运行更新后的PoC,看看是否得到了我们想要的结果。 

image.png 

image.png 

厉害!我们已经用我们的四个字节“B”覆盖了EIP。也就是说,我们已经成功地通过用户提供的数据将EIP的值改为0x820h,从而控制了执行流。但是,我们怎样才能将权限提升至系统管理员级别呢?别急,我们将在下一节介绍特权提升方法。

小结

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

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



本文作者:mssp299

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

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

mssp299

文章数:51 积分: 662

安全问答社区

安全问答社区

脉搏官方公众号

脉搏公众号