CSE_lecture22:ROP and CFI

ROP and CFI

security principles

  • least privilege: 只提供完成事件的最小权限
  • least trust: 给组件分配任务时只提供最小的信任,如zero trust,内部也视为外网,使用U盘鉴权
  • users make mistakes: 安全要考虑用户犯的诸多错误
  • cost of security: 安全的成本不能太高

stack buffer overflow

攻击者往往从控制流或数据的角度来攻击

stack buffer overflow通过栈溢出的手段修改return跳转的地址,从而返回到攻击者设计的恶意代码部分

防御手段为DEP(data execution prevention),即数据段不可执行,即设置为non-executable,需要修改NX bit

此时攻击者使用ROP(return-oriented programming),寻找原有的代码碎片(gadget),这些碎片都以return结尾,在栈上注入地址指向这些碎片,从而将这些碎片代码合并在一起

防御手段有:

  • 隐藏binary file,从而无法获取gadget
  • ASLR将代码放在随机的地址
  • 在return addr前面放置canary,覆盖addr时也会覆盖canary,通过检查canary来判断是否被攻击

CFI: control flow integrity

设置合法的控制流,防止控制流被劫持,这需要描述control flow graph,将其和可执行的二进制文件合并后得到一个self-checking program,加入了多个检查点

攻击者往往从跳转部分劫持,大部分都是direct branches,少部分的indirect branches绝大多数也是跳到那一两个地址:

  • direct branches: call或jump后跟着静态的地址
  • indirect branches: call或jump后跟着寄存器,代码运行后才能确定跳转的地址,以及return

CFI通过二进制重写的方法将正确的跳转思路内嵌到代码中做检查

但这需要保证所有的代码都被patch,对于库代码可能出现问题。因此使用prefetchnta,访问内存地址,如果不合法就等价于nop,比较4字节的prefetchnta后的数字即可

假设A可以到C,B可以到C和D,此时C和D的tag一样,这就会导致A可以非法访问D,如果加入判断,会导致性能下降

因此引入shadow call stack,即单独维护一个存放return address的栈,这是由软件实现的,从而通过比较软件和硬件栈中的地址来判断stack over flow是否出现。为了提升性能,直接使用Intel CET维护硬件层面的shadow call stack

CFI保证了stack over flow的防御,但不能防御数据修改,如函数指针,或权限位

blind ROP

流程为:

  • 禁止ASLR,因为在接受socket时会folk,此时地址一样,并没有重启并让地址随机偏移
  • 窃取binary:注入数据测试什么时候触发stack over flow,再继续通过是否崩溃一位一位猜测地址(这是因为canary不变)
  • 寻找gadget:测试获取的地址附近的地址,判断是crash还是hang,有用的gadget时而crash,时而hang,说明结尾是return,只是return后跳转的第二个地址是否有效罢了
  • 设置write的参数,使用BROP和PLT来设置寄存器的值和函数地址

CSE_lecture22:ROP and CFI
http://example.com/2025/12/28/CSE-lecture22-ROP-and-CFI/
作者
jietiDdd
发布于
2025年12月28日
许可协议