Data-Oriented Programming: On the Expressiveness of Non-Control Data Attacks(S&P 2016)
根据控制流的攻击我们知道有ROP和JOP,分别利用包含ret和jmp的Gadgets进行攻击,劫持控制流。
非控制数据攻击通过攻击程序内存,达到信息泄露或者权限提升等目的。文中提出了DOP攻击,利用程序中的Gadgets,构造任意x86程序的非控制数据攻击,并且这种攻击是图灵完备的。
Introduction#
控制流劫持攻击是目前主流的攻击,例如ROP及其变种,但对此人们也有很多防御措施:CFI、CCFI、CPI、TASR、ASLR、DEP等。
从程序的执行角度,我们可以想到程序是存在控制流和数据流的,而以上只能保证控制流部分的安全,对于数据流则无无能为力,所以非控制数据流攻击就成了额外的攻击方法,只要修改内存中的几个字节,就能达成攻击目的。
本文方法:
- 找DOP的gadgets——模拟图灵运算
- 找gadgets dispatcher——串联Gadgets
实验结果:
- 9个程序中找到了7518个gadget和5092个gadgets dispatcher
- 其中8个程序能模拟任意计算,2个可以达成图灵完全攻击
最后也实现了3种端到端的攻击,并且ASLR和DEP对攻击无作用。
Problem#
Background: Non-control Data Attacks#
通过直接攻击数据流来达到攻击目的,例如下图中,我们只要修改变量pw->pw_uid
的值,就能达到提权的目的
Example of Data-oriented Programming#
能看懂啊line 7 存在溢出,因此buf溢出能控制局部变量(tyoe,size,connect_limie),同时局部变量又能修改指针(line12,line13)这种就称为data-oriented gadgets
,同时可以注意到它们都在while循环中,因此可以连续的利用,称为gadget dispatchers
通过对上图中的DOP利用,能够更新Code3链表中的函数,并且这种攻击时满足CFG完整性的
Questions#
- DOP gadgets和gadgets dispatcher存在普遍吗?
- 能否根据需要链式gadgets达到攻击,是否图灵完备?
- 能否突破当期的防御机制?
DATA-ORIENTED PROGRAMMING#
DOP Overview#
DOP主要是模拟表达式计算,因此定义了如下DOP语言
包括六种虚拟指令,实现算术、逻辑、赋值、加载、存储、跳转、条件跳转等操作。
Data-Oriented Gadgets#
DOP的gadgets不能使用寄存器,使用内存来模拟寄存器。面向数据的gadgets模拟了三种micro-operation:加载,运算和写入。
DOP和ROP很像,他们的区别主要在于以下两点:
- DOP的gadgets只能使用内存来传递操作的结果,而ROP的gadgets可以使用寄存器。
- DOP的gadgets必须符合控制流图(CFG),不能发生非法的控制流转移,而且无需一个接一个的执行。而ROP的gadgets必须成链,顺序执行。
模拟算数运算:
模拟赋值运算:
模拟加载,存储运算:
Gadgets Dispatcher#
Dispatcher用来对gadgets进行迭代调度,在每一轮迭代中选用不同的gadgets对上一轮的结果进行处理,为了将第i次迭代的输出和第 i+1 次迭代的输入对应,gadgets将第 i+1 的加载地址设置为第 i 次迭代的存储地址。
除了上述多轮的攻击,还存在一种非交互式的DOP攻击。这种攻击要求攻击者一次性将攻击载荷输入,为了支持这样的攻击,MINDOP中也保留了两个跳转指令,能实现跳转
模拟跳转:
关键是找到一个合适的变量,可以在每次循环迭代中修改的虚拟 PC 指针,如上述代码,有一个内存指针 pubf -> current
,指向了恶意网络输入的缓冲区。在每一次循环迭代中,代码从该缓冲区读取一行,然后在循环体中处理它,因此这个指针可以用来模拟虚拟 PC 指针。对于模拟非条件跳转,攻击者只需要配置好内存,来触发另一个操作 gadgets(如加法、赋值)来改变虚拟 PC 指针的值。
DOP ATTACK CONSTRUCTION#
这里总结一下在DOP过程中需要解决的三个问题:
- DOP gadgets识别
- DOP gadgets dispatcher识别
- DOP gadgets的拼接利用,在保证程序不崩溃的前提下进行攻击
Gadget Identification#
一个有用的DOP gadgets需要满足一下两个条件:
- 满足MINDOP语义。包含加载、存储、运算指令
- 在顺序上应该满足加载、运算、存储的顺序。
使用LLVM实现对DOP gadgets的识别 (https://github.com/melynx/DOP-StaticAssist):LLVM IR提供了比二进制更多的程序语义,同时避免了对程序源码的解析。它还允许对任何有LLVM前端的语言编写的源码进行语言诊断分析。
gadgets分类:根据语义和运算的变量分为三类,并且在使用优先级上全局变量gadgets>函数参数gadgets>局部变量gadgets
- 全局变量gadgets:操作全局变量
- 函数参数gadgets:操作函数参数
- 局部变量gadgets:操作局部变量
Dispatcher Identification#
同样也基于LLVM IR 实现(https://github.com/melynx/DOP-StaticAssist)
Attack Contruction#
前提:需要攻击者能够控制第一个gadget加载的地址或者第一个gadget存储的地址
攻击步骤:
- Gadget preparation (Semi-automated).:根据一个程序错误,定位到漏洞函数,然后找函数中的gadget dispatcher
- Exploit chain construction (Manual):将预期的恶意 MinDOP 程序输入,每一个 MinDOP 操作由DOP gadgets 实现,并根据优先级选择合适的 gadgets
- Stitchability verification (Manual):验证是否成功,如果不行回到上一步
Evaluation#
在Evalution中回答了三个问题:
- DOP gadgets和gadgets dispatcher存在普遍吗?
- 能否根据需要链式gadgets达到攻击,是否图灵完备?
- 能否突破当期的防御机制(ASLR/DEP)?
Q1#
在9个程序中找到了7518个gadgets和5052个gadgets dispatcher,因此是普遍存在的
Q2&Q3#
通过对实际漏洞的攻击完成说明,见论文部分
Discussion#
DOP目前已经实现了对ASLR、DEP、TASR防御的突破,但也可能可以通过以下方法进行防御
- memory security:通过检测恶意内存损坏来防止出现内存错误。
- Data-Flow Integrity:类似于CFI在控制流完整性上的防御。
- Fine-grained Data-Plane Randomization:细粒度的数据面随机化可以缓解 DOP 攻击,因为 DOP 仍然需要获取某些非控制数据指针的地址。
- Hardware and Software Fault Isolation:内存隔离被广泛用于防止未经授权访问高权限资源,只有合法的代码区域才能访问特定的资源,这样可以防止一些直接的数据破坏攻击。
总体来说,上述保护措施都会对程序执行带来极大的开销,只是能用来防御,但也需要考量效率问题。