Gadget构造:从JIT-ROP到对抗XnR

华盟原创文章投稿奖励计划

*本文原创作者:cuteme,本文属FreeBuf原创奖励计划,未经许可禁止转载

写在前面

简单地说,本文介绍了两种构造gadget的思路。(在浏览器支持JIT的情况下)

演进:关于JIT-ROP

我们知道,最初DEP的出现是为了对抗的栈溢出、堆溢出等这类劫持程序执行流的攻击手法。在这之后,攻击者为了绕过DEP,开始利用libc.so中的函数获取shell,也就是我们所说的Ret2libc攻击。更有效的防御手段还有ASLR地址随机化,使得libc.so加载的基址每次都会发生变化。当然,如果存在地址泄露等,ASLR仍可以被绕过。

于是乎,学术界前几年开始研究细粒度的ASLR,即使基址被泄露,攻击者也得不到准确的地址。

2013年s&p上发表了一篇文章提出JIT-ROP,这项工作极具创新性。其意义在于它提出了在运行时寻找gadget同时构造ROP链的概念。详细的过程是这样的:在存在一个内存泄露漏洞的情况下,得到一个运行时代码指针,它泄露当前4k内存页,因为当前页可能会有分支指向其他页,所以通过这个指针可以得到尽可能多的页。将当前页运行时反汇编后,获得所需要的gadget并构造ROP链。

也就是说,JIT-ROP是通过即时扫描有效内存,即时反汇编搜寻rop gadgets,即时拼接shellcode,从而绕过dep/aslr的,它在程序运行过程中动态执行,所依赖的资源在进程地址空间中获取。所以它和传统rop最大的不同在于:它可以使用任何代码指针初始化攻击环境,而传统的rop需要泄露函数的具体地址。

这种攻击手段可以绕过学术界过去提出的任意粒度的ASLR。

演进:关于XnR

为了针对JIT-ROP,14年ccs有一篇文章提出了XnR,利用软件模拟的方式实现了页的不可读。

既然页不可读,那么JIT-ROP所提出的运行时读内存页然后搜寻可用gadget这一思想就行不通了。

那么如何对抗不可读,提出使JIT-ROP攻击不需要“可读”这一条件,也可达成呢?这就是下面要讨论的内容了。

相关:关于JIT

在进入正题之前,先简单说说JIT引擎是什么。

2008年,浏览器的JavaScript引擎引入JIT技术。JIT是一种即时编译技术,是一种解决浏览器效率低下的方案。例如Javascript,它是典型的解释型语言。程序员写了一个for循环,解释器是不知道这是一个循环的,所以它将会一句一句的去循环执行这个循环。这也是为什么解释型语言的效率特别低,因为它不会预先编译。

JIT引擎的出现就是为了改善这一情况。它通过在运行时将部分语句编译为机器码,于是下次执行不需要再翻译,从而省去了解释开销,使得浏览器性能大幅度改善。

JIT与攻击

早期利用JIT新特性进行攻击的方案是在2010年blackhat大会上提出的**Pointer Inference and JIT Spraying**,将 ActionScript代码中进行大量的XOR操作。然后编译成字节码,并且多次更新到Flash VM中,这样它会建立很多带有恶意Xor操作的内存块。

但一方面这样的方法比较旧,另一方面,学术界中早已提出防御方法JITDefender。

准备工作

攻击模型

(1)存在内存泄露漏洞

(2)不考虑CFI

(3)JavaScript环境

之所以如此,因为这篇文章的中心思想是,攻击者可以通过自己注入gadget实现绕过其他限制手段如XnR。关注点并非实现真实过程的控制流转移。

防御环境

(1)DEP:NX,可写不可执行

(2)ASLR: fine-grained,XnR应用于可执行文件,库,JIT编译而成的代码

(3)Non-Readable Code: 所有代码段不可读

(4)Hidden Code Pointers: 除了JIT-compiled的指针均已匿名

(5)JIT Hardening: JIT上的防御手段,比如randomized JIT pages, constant blinding,guard pages

攻击方法

方法一:利用条件跳转语句

原理:构造if/else,for/while,编译成包含可预知的条件跳转指令。

举例说明一下,如果我们需要的gadget是int 0×80;ret ,翻译成机器码也就是0xcd80c3

那么,则往if中写入0xc380cd字节大小的JS代码。

1.png

如上右图,攻击者是可以确定,编译结果中肯定包含‘je 0xc380cd’这一句的(x86/x64 架构采用小端存储)。所以说,通过变化if中js代码的大小,我们可以修改代码长度,改变跳转的距离。而每句JS代码编译后的大小是已知固定的。所以攻击者可以精确的控制所生成的代码长度。即,je后面的值,可以随意控制。

举个更具体的例子,在Chrome 33 (32-bit)/Chrome 51(64-bit)上,如果需要一个gadget:0xcd80c3。

S1: v=v1+v2, compiling to 0×10 bytes(64位 v=v)

S2: v=0×01010101, compiling to 0xd bytes.

使用S1 0c380c次(得到结果0xc380c0),

再使用S2 一次,求和即得到0xc380cd。

以上步骤可以注入自己想要的gadget,接下来就是要找到gadget所在的位置。

(1)首先通过内存泄露漏洞,得到JIT所编译的JavaScript代码的函数地址

(2)将这个函数的作为参数传给另一个函数,这样它就被push到stack中了(javascript的特性)。

(3)得到栈的信息,得到函数对象的指针,它包含了指向实际地址的指针。

方法二:利用直接调用语句

上一种方法对IE基本是无效的。IE部署了JIT-hardening策略,会随机插入NOP,改变条件跳转语句的值。这样,编译后的语句就不可控了。于是作者又提出使用直接调用指令实现攻击。如:call 0×1234560

原理:任何两个直接调用指令即时调用同一个函数,机器码是不一样的。其实和条件跳转的原理差不多。之前控制的是je指令后边的值,那它控制的是什么呢。其实利用的是call后面的这个值是一个相对地址,第一次调用产生的机器码是被调用者和下一次所调用的差。如下图。

2.png

3.png

假设FUN函数在2000的位置。那么在图中,连续CALL FUN_1,所以这个常数代表FUN1和第二条CALL FUN1(即0×5)的距离。即**0×2000-0×5=0x1ffb**。(0×5是一条call指令的大小)。这个例子里,攻击者得到的是0xe8fb1f0000。

嗯,以上是大概思路。具体攻击流程有三步:

(1)找到call指令后那个被调用函数的地址。

再列一遍这个式子,0×2000-0×5=0x1ffb。在这里0×2000就是被调用函数的地址。

总之,一般来说,在javascript环境下,可以利用当然是地址已知的helper函数或built-in函数(比如Math.random,String.substring)。

另外不得不说到IE,它的built-in函数在library中,而且采用了细粒度的ASLR。但是它们所产生的JS对象,未启用随机化,而且包含指向这个函数的指针。所以对于IE也是可行的。

(2)把call指令放到指定位置。

再列一遍这个式子,0×2000-0×5=0x1ffb

还是假设我们需要的gadget是int 0×80;ret (即0xcd80c3)。

0xcd80c3,包含三个字节。也就是说,上面那个减法式子的结果必须保证位数满足要求,要是你的距离才两位是怎么也构造不出三位的gadget的。于是为保证三字节距离,需要创建一个由直接调用语句组成的JS函数,使它在编译后覆盖0×100 00 00字节。即我们要求第一次和最后一次CALL之间的距离,至少为0×1 00 00 00字节指令。

(3)检查机制

还是要说到IE,它在编译时会随机插入NOP,所以基本上不能知道函数会被编译到哪个地址。而且,前提条件存在XnR,我们是不可以通过读取代码段来确定那个位置是否是所需要的gadget的。

那么,只能通过取得足够大小的代码空间,全部填满call指令,从而确保计算结果在距离范围内。

Javascript中的check address函数会读栈中数据,直到找到call指令放置的ret,可知是否放置正确。如果没有,重新编译,重复之前的步骤。

其他

这攻击主要针对的是x86 (32- or 64-bit)架构。在RISC架构中,如ARM,MIPS,由于硬件层次的原因,利用上文所述的方法不能成功攻击。除非在ARM架构下,攻击者强制切换为16-bit THUMB模式。

另外,虽然论文中作者是以浏览器为例,但其实采用jit引擎的东西应该都适用(?)。比如pdf阅读器是可以的。

总结

实际上本文的核心思想很简单:

(1)攻击者通过构造JS代码产生一个jit-compile gadget

(2)由于所产生的gadget是攻击者控制的,所以不需要搜索,不需要读页,即可被攻击者用来构造ROP链

(3)以上过程发生在运行时

参考文献

[1] What Cannot Be Read, Cannot Be Leveraged? Revisiting Assumptions of JIT-ROP Defenses. USENIX 2016

[2] Just-In-Time Code Reuse: On the Effectiveness of Fine-Grained Address Space Layout Randomization. IEEE S&P 2013

*本文原创作者:cuteme,本文属FreeBuf原创奖励计划,未经许可禁止转载

本文原创,作者:小龙,其版权均为华盟网所有。如需转载,请注明出处:https://www.77169.net/html/152752.html

发表评论