欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

Sigreturn Oriented Programming (SROP) Attack攻击原理

来源:本站整理 作者:佚名 时间:2015-12-02 TAG: 我要投稿

去年投了一篇文章,介绍BROP攻击。反响还挺好的,也帮助了很多人去理解这个非常smart的攻击原理。当然大家也可以去我的博客看这个攻击的重现。
这次我想介绍另一个类ROP攻击,叫SROP,和BROP一样,这个工作也是发表在国际安全领域最顶级会议Oakland 2014上,被评选为当年的Best Student Papers。论文的题目叫做`Framing Signals — A Return to Portable Shellcode`,作者是来自Vrije Universiteit Amsterdam的Erik Bosman,以下是相关paper和slides的链接:
paper
slides
首先,我觉得这也是一个非常有趣的攻击,虽然在去年就已经发表了,但是我在网上并没有找到太多相关的信息,在最近一年的研究领域也没有太多对它的引用,所以我觉得很有必要推广一下。但是在我看完paper之后,觉得这篇paper写得并不是很容易让人理解,很多句子都晦涩难懂,不过这些都不重要,重要的是,这个攻击确实很有效,里面提到,在不同版本的Unix系统(如GNU Linux,BSD,iOS/Mac OS X等)中被使用了40多年的Signal机制,存在一个很容易被攻击者利用的设计缺陷,而这个缺陷所产生的相应的攻击,即文中所描述的SROP,和传统的ROP攻击相比显得更加简单,可靠,可移植。
接下来,我会从ROP攻击开始讲起,然后引入SROP的攻击原理,其中会涉及到Signal机制的相关背景,最后,我会介绍一些相应的防御措施。
ROP背景介绍
ROP攻击的出现
Stack Overflow 和DEP (Data Execution Prevention)我在这里就不介绍了,简单来说,就是最早的code injection攻击在现在的操作系统中基本上不能使用,因此出现了ROP,也就是所谓的Return Oriented Programming,其中也包括比较早期的Return-to-libc。ROP的主要思想就是攻击者不需要自己注入代码(因为在DEP的保护下,注入的代码不可执行),而是利用系统已有的代码片段来构造攻击。这里之所以叫ROP,是因为其改变控制流的方式是用系统中的return指令(比如x86中的`ret`)。
这里需要说明的是,在栈操作中,return指令是唯一一个可以通过控制栈上的数据改变指令流的指令,它的效果等同于:
pop %eax
jmp %eax
即将IP设置成栈上的某个值。因此如果我们可以控制栈上的数据,就可以控制执行流。
ROP攻击的原理
这里举一个最简单的例子来说明如何利用ROP来实现一条内存赋值语句:`Mem[v2] = v1`,其中`v2`是一个内存地址,`v1`是一个值。

这里我们先把`Mem[v2] = v1`这条内存赋值语句转化成汇编代码:
mov %eax v1;
mov %ebx v2;
mov [%ebx], %eax
将`v1`的值赋给`%eax`,将`v2`的值(即内存地址)赋给`%ebx`,最后将`%eax`的值赋给`%ebx`地址指向的内存。
我们将这段代码翻译成可以通过ROP的方式执行的代码:
addr1: pop eax; ret
addr2: pop ebx; ret
addr3: mov [ebx], eax
其中`addr1`、`addr2`、`addr3`都是相应指令的内存地址,我们将每一行称为一个“gadget”。通过像上图中那样构造栈上的数据就可以完成和上面汇编相同的效果。如果不清楚可以自己代入试一试,这里就不详述了。
你可能会问,单纯构造一个内存赋值语句有什么用呢?其中最广泛的应用就是为参数赋值。假设我们希望用ROP的方式调用一个system call,那么我们就可以用上面的这种方式为这个system call填上参数,最后在栈上填上`syscall`(或者`int 80`)指令的内存地址就可以了。
ROP攻击的前提条件
讲到这里,如果你对上面有了初步的理解,就可能会觉得好像ROP确实很厉害,能够随意调用system call(比如调用`execve`来开启一个shell;或者调用`mprotect`来将栈设置成可执行,等等)。然而事实上ROP并没有想象中的那么简单。要完成一个成功的ROP攻击,需要有很多前提条件,这里列举几个最重要的:
1. 首先必须要有一个buffer overflow的漏洞(当然这个前提基本上所有攻击都必须得有);
2. 攻击者需要事先决定好完成攻击过程的所有gadgets。对于上面提到的赋值操作,总共只需要3个gadgets,每个gadget最长两条指令,但是如果需要进行一些复杂的操作,就有可能需要有很多gadgets;除了gadgets的数量多之外,单个gadget的指令数也需要考虑;
3. 攻击者需要在被攻击程序所在的进程地址空间中找到所有的这些gadgets的首地址,并且将其填在栈的合适位置上。
这三个前提条件,造成了传统的ROP对于攻击者来说具备了一定的难度,加上现在操作系统中的一系列保护机制(比如ASLR),使得寻找gadgets的地址变得更难了。而且对于攻击者来说,他攻击每个不同的应用程序都需要单独精心构造大量的gadgets,这也使得ROP的可复用性变得很差。
以上的这些,都是我们接下来将要介绍的SROP所想要解决的问题。
SROP攻击原理
SROP的全称是Sigreturn Oriented Programming。在这里`sigreturn`是一个系统调用,它在unix系统发生signal的时候会被间接地调用。
在开始介绍SROP的攻击原理之前,我们需要先对signal的背景进行一个简单的说明。
Signal in Unix-like System
Signal这套机制在1970年代就被提出来并整合进了UNIX内核中,它在现在的操作系统中被使用的非常广泛,比如内核要杀死一个进程(`kill -9 $PID`),再比如为进程设置定时器,或者通知进程一些异常事件等等。
如下图所示,当内核向某个进程发起(deliver)一个signal,该进程会被暂时挂起(suspend),进入内核(1),然后内核为该进程保存相应的上下文,跳转到之前注册好的signal handler中处理相应signal(2),当signal handler返回之后(3),内核为该进程恢复之前保存的上下文,最后恢复进程的执行(4)。

[1] [2] [3]  下一页

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