安全路透社
当前位置:安全路透社 > 安全客 > 正文

【技术分享】在ie8中利用ROP与Heap Spray利用反弹shell

http://p4.qhimg.com/t0110d5357a9ec3d6c1.png

翻译:Ox9A82

预估

,或登陆网页版

简介


这个漏洞利用程序是针对Windows 7平台上的IE8浏览器开发的。我们关注的焦点是一个使用了Java网络启动协议(JNLP)的插件,这个插件存在有溢出漏洞。为了实现利用,我会使用Heaplib来构造ROP链以实现绕过DEP,并获取对目标机器的控制。


Did it Work?


我的exploit目前不能正常工作,我讨厌这个leave指令(如下图)

http://p5.qhimg.com/t0160c7451fa211a31e.png

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

http://p5.qhimg.com/t01b192da5d8aa6e6f1.png


开发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的帮助来解决,它进行堆喷射并且保证地址对齐。堆喷射指的是将我们需要的内存数据放入堆中,以便我们有机会跳入我们需要的数据中。它看起来像这样:

http://p7.qhimg.com/t01586fbdc23666fac9.png

这些值将是我们放置在栈中以传递给VirtualProtect函数调用的参数。

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

接下来我们关心的是确保栈翻转按计划实施。我提到过这取决于你能在这个过程中访问到哪个寄存器的值。只需使用Windbg附加IE进程,然后传递足够多的A来溢出缓冲区(在我们的情况下为200),并观察哪个寄存器会被溢出数据控制。我这样做之后,发现EIP和EBP都被A溢出,EAX保持不变。这意味着我们需要使用`LEAVE;RET`gadgets。

还有很重要的一点就是,所有的ROP gadgets都是在MSVCR71.dll上搜素的,因为它不仅不受ASLR的保护,而且Alex也特意告诉我使用这个。


构造恶意输入


在这一节,我将参考下面的图表来寻找那些特定的ROP gadgets:

http://p4.qhimg.com/t016f858ad679d37221.png

简单来说,ROP gadget只是一些共享内存模块(在我们的例子中是MSVCR71.DLL)中的一个内存地址,我们可以引用它来做一些操作,然后返回。有许多不同的工具可以用于搜索这些地址,Alex推荐了两种不同的选择:第一个叫做Skyrack,第二个叫做msfpescan带有正则表达式。这两种工具对于我想做的事来说都不大好用。于是我用Google找到了一个名为Ropper的开源工具。

所以,我使用了ropper。它很好安装,也很容易搜索复合指令,它会返回所有匹配的实例,而不是只返回一个。要使用的命令是:

```
ropper --file〜/ path / to / msvcr71.dll --search“INSTRUCTION;ret”
```

其中INSTRUCTION是你要搜索的指令。这里是我们需要的指令列表:

```
1.POP EAX,RET;
2.MOV EAX,DWORD PTR [EAX]; RET;
3.CALL EAX; RET;
4.POP EAX; POP EDI POP ESI; POP EBX; POP EBP; RET;
```

前三个可以很容易的通过Ropper找到。最后的指令有点困难。对于这一点,我发现了一个名为Fuzzysecurity的源,它使用了IE8的ROP链执行类似的漏洞利用。我试着跟随他的例子,但是我发现他使用了一个知名的通用ROP链,不过我决定不使用这个。但是,我注意到他找到了POP‘s并且列出了一些gadgets。唯一值得注意的是,他使用的gadgets包含五个POP指令,但我们调用的VirtualProtect只有四个参数。但这没有问题,因为我可以在最后添加一个虚拟的值,之后它会被弹出来。

接下来,将ROP gadgets留给栈翻转。如上所述,我们不能访问EAX – 我们知道在检查WINDBG溢出缓冲区时,发现只有EIP和EBP被覆盖。当我们控制EBP时只需要通过`LEAVE; RET`gadgets来翻转栈。我实际上能够使用Skyrack查找这个,因为如果只是搜索一个单独的LEAVE指令,就有很大的可能性它紧接着一个RET。 我使用WINDBG对地址进行反汇编来验证结果。

我们之所以要有POP(x5); RET,是因为ROP链本身的性质(译注:就是要弹出参数)。考虑以下这张图:

http://p1.qhimg.com/t012debdaaffd864d78.png

当我们从调用VirtualProtect返回时,我们伪造了一个栈帧。这意味着我们需要将VirtualProtect的所有参数POP出来,然后在这些POP之后,我们返回到栈中下一个地址。就是说当我们从VirtualProtect返回时,首先返回到`POP(x5); RET;`它负责删除参数,然后再返回到shellcode。

最初,我打算使用我自己手工生成的ROP链来演示,但是它没有工作。所以我决定采取Chandan的建议,使用Mona.py自动生成的ROP链。

在这里,我还想发出一些推荐给我的“幻影”地址。在课堂上,Alex给我们一些关于我们漏洞利用的结构的“提示”。首先,他说我们的缓冲区溢出应该包含栈翻转。接下来,我们得到一个模糊的提示,在我们的ROP链之前应该有一个地址:1)字节对齐或2)它可能是别的东西 – 我决定只使用Heaplib.js承诺的shellcode地址,因为为什么不呢?我不知道还应该放置什么在那里!最后的提示是,在我们的ROP链和shellcode之后,我们应该包括我们shellcode的“硬编码”地址。这对我没有意义,因为如果它正在执行ROP链,我们应该能够正确地击中shellcode,在我们调用VirtualProtect完成后,我们可以立即开始执行shell。所以基本上,每次我需要的“shellcode地址”使用的是0x0a0a2020。

最后我使用Metasploit来生成我的shellcode。 命令是:generate -t js_be,它提供了可以粘贴到Javscript函数中的shellcode。 一个重要的注意是确保shellcode可以被4整除,以便它可以正确排列。 我的是324字节长,可以被4整除,所以没有什么我需要做的。


未解决的问题


关于这个任务,我还有几个问题没能够弄清楚。下面,我将详细说明我的关注和我的结论,试图说服那些读者,其中至少有一些想法会被纳入这个领域。

1. 我不完全确定在缓冲区溢出时用什么去覆盖EIP的地址。我知道在幻灯片中,讨论了堆上对齐的地址,因为我们要么会命中NOP要么会命中我们的shellcode。但是,我不知道这是如何工作的,因为这个漏洞的整个点是获取和执行我们在堆上的代码。这意味着,如果我们命中的是NOPs或shellcode的开始(基本上除了pivot的一切)我们就会被卡住,因为我们没有移动ESP到我们的位置或改变保护。在与Alex讨论之后,他说用我们的堆栈枢轴覆盖EIP,这就是我所做的。(译注:不知道作者为啥会提出这个问题,估计是没能理解到精准堆喷射的意义所在。)

2. 我认为pivot的地址是我们最初溢出到EIP的地址,但这对我来说没有意义,因为发生在堆栈枢轴(LEAVE; RET)的操作代码只是移动ESP到EBP(译注:move the ESP into EBP???),但是如果我们仍然在栈上,我们就不会将其替换为堆上的地址。(译注:在ret返回之前就已经控制了ebp,可以直接更改成堆地址,为什么非要把EIP覆盖成pivot,实在看不懂作者咋想的。)所以我最终解决了这个问题,用shellcode和pivot的地址溢出初始缓冲区,因为我知道EIP会指向pivot。这以后通过WINDBG确认。

3. Alex基本上告诉我们在我们的ROP链之前插入一个地址,然后立即跟踪它。但是这是不明确的,它的目的是什么 – 我到现在仍然不知道。我获取的信息并没有表明这是必须要去做的。也许只是为了对齐?(译注:插入地址可以对齐???)ROP链后面的第二个地址应该是我们shellcode的“硬编码”地址。再次,我不明白为什么必须要这么做,而不是紧接着放置shellcode(译注:不放地址,你直接把指令ret了能执行吗?),但在这一点上,我盲目地采取了亚历克斯的建议。

4. 为什么我无法执行LEAVE;指令?我的主要想法是EBP有问题或有些东西指向无效的内存。我不是很确定到底是发生了什么,也没有能够解决它。



原文链接:https://woumn.wordpress.com/2016/12/07/rop-heap-spray-for-a-reverse-shell-in-ie8/

未经允许不得转载:安全路透社 » 【技术分享】在ie8中利用ROP与Heap Spray利用反弹shell

赞 (0)
分享到:更多 ()

评论 0

评论前必须登录!

登陆 注册