FavoriteLoading
0

在ie8中利用ROP与Heap Spray利用反弹shell

这个漏洞利用程序是针对Windows 7平台上的IE8浏览器开发的。我们关注的焦点是一个使用了Java网络启动协议(JNLP)的插件,这个插件存在有溢出漏洞。为了实现利用,我会使用Heaplib来构造ROP链以实现绕过DEP,并获取对目标机器的控制。
Did it Work?
我的exploit目前不能正常工作,我讨厌这个leave指令(如下图)

我进一步确认了一下反汇编。这个错误看起来是我没有访问此DLL的权限,或者是违反了页面的读、写、执行权限。我进一步的研究了一下,并在运行了“!vprot 7c3411a4”命令之后确认了答案,这个命令可以显示我感兴趣的内存权限。

开发exploit
构造恶意输入
Java网络启动协议(JNLP)使应用程序能够在远程服务器上的客户端桌面上启动。事实上JNLP存在一个缓冲区溢出漏洞,发送的请求的结构对于我们来说不是很重要,我们只需关心传递给JNLP导致溢出的docbase参数。
此外,我们将通过Javascript来触发这个利用是基于以下几个原因。首先,我们可以通过Javascript直接控制DOM。DOM是文档对象模型,它可以美化屏幕上显示的页面。它可以呈现HTML、CSS和Javascript,并且还可以访问浏览器的“Syscalls”,比如QuickTime,Flash等。这使得在浏览器中实现这个exploit变得很方便。
这个exploit使用了很多我们已经见到过的利用技术,所以我不会进行详细介绍。但是需要知道,当我们拥有一个溢出漏洞时,就意味着我们可以控制EIP和ESP处的内存。但是,我们还存在着DEP的问题 - 栈不可以执行。由于存在DEP保护,我们被迫使用ROP来解决。我们之前在其他的漏洞利用中使用过ROP技术,即我们去寻找jump 4或其他东西的地址。我们找到有执行权限的地方,然后直接调用这个地址的我们需要的OPCODE。这里的挑战是我们需要的指令可能不止是一、两条。一般来说ROP链会非常大,而且我们还要插入shellcode。令我担心的是,栈可能没有足够的空间来放置我们的全部载荷,我的方法是通过堆,但是这带来了一些额外的挑战。
堆上的第一个挑战是如何定位我们布置的数据。幸运的是,这个问题可以通过Heaplib.js的帮助来解决,它进行堆喷射并且保证地址对齐。堆喷射指的是将我们需要的内存数据放入堆中,以便我们有机会跳入我们需要的数据中。它看起来像这样:

(译注:这张图有误,DEP环境下不再需要NOP sled)
事实证明,Heaplib.js库可以提供非常精确的堆喷射,并且shellcode(译注:作者似乎分不清payload和shellcode的区别,之后也有几处混用。)存在于每间隔2000个字节的地址上,比如0020,2020,4020等(译注:Heaplib是一个用来进行精准堆喷射的库,作者首次提出并使用了Heap Fengshui技术。但因为存在Nozzle,自IE9之后就不能使用了。)
我们面临的第二个问题是怎么把堆转换成栈。这个听起来有点违反常识,但是相信我,马上你就会明白我们为什么要这样做。很多人将这种做法称为“Stack Pivot”(栈翻转),为了说明堆是怎么转化成栈的,我们只需要改变ESP寄存器的值指向我们堆的地址(由堆喷射得来的,存有payload)。这通常通过调用指令
```
XCHNG EAX,ESP;
RET
```
交换EAX的值来实现,这两条指令本身就是一个ROP gadgets。然而,在这里我们不能控制到EAX寄存器,但是我们可以控制EBP寄存器,那么也能够用
```
LEAVE;
RET
```
指令做栈翻转(译注:因为leave等于mov esp,ebp;pop ebp)。我观察了一下有哪些寄存器会被覆盖,发现只有EIP和EBP这两个。我们费这些麻烦的主要原因是因为RET指令会返回到ESP指向的地址,所以我们需要让ESP指向我们在堆上的数据。
下一个要解决的问题是如何执行我们放在堆中的shellcode。请记住,在执行了栈翻转之后,堆现在成了“栈”,至少它看上去是这么一个东西。那我们如何执行shellcode呢?不幸的是现在的Windows使用了DEP保护(译注:准确的说是自IE8开始才启用,是IE版本的问题与Windows版本无关),这就是说某些地方的内存要么是可读、可写的,要么只是可执行的(互斥)。这是为了阻止我们想要做的事——执行存储在栈上的这些指令。事实上有一个方法可以绕过它。在Windows上,Kernel32.dll中的有一个名为VirtualProtect的函数用于更改内存的保护属性。这对我们来说是很有用的,因为如果我们可以对我们shellcode的内存空间调用这个函数,那么就可以将保护从可读写改为可执行,然后执行shellcode。事实上Kernel32.dll是开启了ASLR的,但我们会在“确定使用的参数”部分中处理这个问题。只需要意识到我们有一种改变内存权限的方法 - 当然这需要通过一个ROP链实现。
确定使用的参数
我需要做的第一件事是弄清楚我们将传递给VirtualProtect函数的参数。Alex直接提供给了我们参数,我们可以结合堆喷射的特性直接使用它。

这些值将是我们放置在栈中以传递给VirtualProtect函数调用的参数。
接下来,我得去寻找VirtualProtect的地址。为此,我使用Windbg来查看不支持ASLR保护的MSVCR71.DLL模块。通过运行命令:`dh msvcr71` 来dump出模块的头,这提供给我们一个VirtualProtect函数的地址表。接下来,我们执行:`dps msvcr71 + 3a000`,它在VirtualProtect之前的表中给出(可能需要多次执行dps)。最后,这给我们提供了一个地址,我们用u poi(7c37a140)确认是我们想要的地址。顺便说一下,这个地址已经在网上列出来了。

分页阅读: 1 2
【声明】:8090安全小组门户(http://www.8090-sec.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱hack@ddos.kim,我们会在最短的时间内进行处理。