ROP发展

作者: 丿曰 | 来源:发表于2018-07-19 18:07 被阅读0次

    前身——return-to-libc

    目的:

    绕过DEP

    主要思想:

    代码重用攻击。利用进程空间中已经存在的代码,通过注入的异常数据控制其为攻击者服务。

    新的利用点——复杂指令集CISC

    CISC的问题:

    代码中的一个字节的含义取决于上下文,原则上,任何一个字节都可能是一条指令的起始。

    思想:

    通过劫持控制流,攻击者可以令CPU按照其意愿重新解读已经存在的代码。

    需求:

    使用非常规的方式将短小指令片段串联成完整的代码流。
    Galileo算法可为返回导向编程搜索可用的指令资源。

    升级版——精简指令集RISC

    对SPARC构造返回导向编程面临的问题:

    无法利用意外的指令序列;X86下返回导向编程gadget的所有构造特点在RISC中都不存在。

    新思路:

    将函数的后缀作为gadget使用(利用结尾的ret-restore指令序列);利用结构化数据流使得gadget与SPARC的函数调用惯例相吻合;构造内存-内存gadget(寄存器仅在gadget内部使用)。

    新防御——Smashing the gadgets:

    核心思路:
    阻止x86代码中出现以外的gadget。

    手段一:抹掉0xC3字节(ret)
    手段二:指令重新排序
    手段三:寄存器压栈顺序随机化
    手段四:寄存器重新分配

    颠覆版——ROP without return

    核心:

    update-load-branch指令序列“pop x; jmp *x”
    蹦床trampoline

    函数调用步骤:

    在esi中载入call-jmp序列的地址
    在ebp中载入leave-jmp序列的地址
    在eax中载入n+偏移量
    将call-jmp序列的地址存储至地址n
    改写esi,使其存储“返回地址”
    esi值写入result位置后,再读出至edi
    交换使返回值存入ebp,leave指令换入edi
    在esi中载入pop-jmp序列的地址
    在ecx中载入函数入口地址
    在eax中载入地址n
    交换esp和eax,栈指针指向n(函数地址)
    edi处的leave指令将使函数“返回”

    防御新思路——从结构上阻止程序控制流被劫持:

    • 程序控制流完整性保护(CFI)
    • 实用粗粒度CFI
      Springboard段--使得间接控制转移可以通过位校验进行检查,Springboard段内地址的第27位总是为0,且仅有Springboard段满足该条件。间接控制转移只能以Springboard段内的适当存根作为目标。
      缺陷:
      需要改写程序的二进制代码。很难识别出程序中所有合法控制转移目标,对二进制代码的修改困难且易错,兼容性问题在一定程度上依然存在。
    • 基于动态优化的CFI
      在程序执行过程中加以监视和约束。
      缺陷:
      效率太低。
    • 利用硬件特性和虚拟化技术的CFI
      利用虚拟化技术。
      内核模式下作为操作系统的一部分,性能开销低;提供了动态优化工具可能提供的CFI优势。
      监视目标:执行流由足够长的gadget序列组成。
      完整性检查的触发:
      设置滑动窗口,所有窗口外内存均设为不可执行。控制转移指向窗口外时,将触发异常并陷入内核,引起完整性检查;敏感系统调用也会引起完整性检查。
    返回导向编程的基本流程:

    始于对程序控制流的篡改(控制流异常)
    各gadget由ret指令或pop-jump组合代替eip加以链接(大量控制流异常)
    原始栈结构遭到破坏,ROP过程中栈指针单项移动(栈的行为异常)
    有时,栈指针可能被篡改并指向不属于栈区的内存(栈的行为异常)

    CFI基本思想:

    通过预设的运行时校验,确保程序执行与预先定义的控制流图严格吻合;
    通过对二进制码的静态分析来获取CFI所需保证的控制流图;
    借由静态的二进制代码改写为程序添加运行时的自我校验。

    CFI的基本安全性假设:

    控制转移目标的标示符(ID)具有唯一性;
    程序代码不可写;
    程序数据不可执行。

    CFI的搭建:
    • 内存访问控制 SMAC
      通过与运算,确保控制转移目标的最高位字节内容位40h;
      使得间接控制转移总是指向合法的代码区段;
      由此在一定程度上实现软件故障隔离(SFI)。

    • 受保护的影子栈
      专门划定内存区域用于检查ret指令是否响应了正确的call指令;
      为影子栈预设地址前缀,结合SMAC,可确保只有CFI的校验指令可以修改该区域。

    CFI的弱点:

    即使在静态分析中,间接控制转移的合法跳转目标也不唯一,不是排他的;
    受到性能的制约,粗粒度化的CFI对控制流的约束更加松散。

    改进型ROP——针对CFI

    • 利用以函数入口和函数调用点为起始的gadget
    • 图灵完全的改进型gadget集对抗现存最严格的CFI

    改进型gadget的类型(主要来自kernel32.dll):
    具有call指令前缀的gadget(主要);
    call-ret配对的gadget组合;
    “长nop"gadget。

    绕过CFI不会导致返回导向编程的功能性有所缺损。

    ROP变种“数据导向编程”——一切为了绕过CFI

    特点:

    通过污染数据(特别是指针)改变被重用代码的实际语义。借助循环不断注入新的攻击载荷,使得被重用代码的实际执行效果随之改变。

    数据导向编程所重用的代码资源主要来自串操作。

    交互式攻击 - 允许攻击者在每轮循环中输入不同的载荷以激活不同的gadget。

    非交互式攻击 - 攻击者必须一次性输入整个攻击载荷,需要额外的指令元素以支持虚拟的跳转操作。

    新防御——地址空间随机化ASLR

    思想:

    使gadget的位置变得无法确定。

    粗粒度ASLR:

    mmap offset、stack offset、brk offset随机化。


    粗粒度的ASLR

    粗粒度ASLR的改进:偏移量+内存区段的位置置换。

    细粒度ASLR:

    区段间----->区段内
    改变代码文本的具体内容

    实施

    程序在加载时自我随机化;
    通过虚拟机进行动态随机化;
    操作系统的随机化。

    ASLR的无效化:

    场景1:攻击者无法披露目标程序的内存空间;
    场景2:攻击者可以实施内存空间披露,但只能获得一个代码指针。
    限制:对于任何ASLR,程序在执行时不在改变其内存空间结构。

    “页面收割”最终暴露进程中的全部代码、API接口等可利用资源。

    Just-In-Time代码重用

    相关文章

      网友评论

          本文标题:ROP发展

          本文链接:https://www.haomeiwen.com/subject/jxatmftx.html