您现在的位置是:首页 > 编程 > 

ROP攻击缓解新思路——减少ROP Gadgets的数量

2025-07-27 23:38:40
ROP攻击缓解新思路——减少ROP Gadgets的数量 在今天的玄武实验室的安全推送中,看到了Removing ROP Gadgets from OpenBSD这个议题的PPT,一开始看了下标题,感觉有点疑惑,但是没马上看,后来下午抽实践看了看,感觉这个操作还是可以的。注意下面针对的是系统是OpenBSD,而且是kernel,思路值得借鉴这个我之前没看到过,所以把它叫做新思路ROP简介说到ROP

ROP攻击缓解新思路——减少ROP Gadgets的数量

在今天的玄武实验室的安全推送中,看到了Removing ROP Gadgets from OpenBSD这个议题的PPT,一开始看了下标题,感觉有点疑惑,但是没马上看,后来下午抽实践看了看,感觉这个操作还是可以的。

注意下面针对的是系统是OpenBSD,而且是kernel,思路值得借鉴

这个我之前没看到过,所以把它叫做新思路

ROP简介

说到ROP就得说说ROP Gadgets

ROP Gadgets就是汇编代码中的片段,一般是ret或者jmp结尾的

他们可能完成下面的一些功能: 1、寄存器赋值 2、给寄存器加上一个数 、寄存器置0 4、调用函数 5、改变esp的指向 6、。。。。。。

ROP Gadgets还可以分为对齐的,还有不对齐的,不对其就是地址偏移了

比如下面的

代码语言:javascript代码运行次数:0运行复制
8a 5d c 	movb -61(%rbp), %bl

但是假如你将汇编解析的起始地址指向5d的位置,那么汇编的意思就变了

代码语言:javascript代码运行次数:0运行复制
5d	 popq %rbp
c	 retq

比如你想执行

代码语言:javascript代码运行次数:0运行复制
execve(“/bin//sh”, ULL, ULL)

你可能需要布置下面的ROP链

目的就是将寄存器赋值为相应的值,进行系统调用

ROP Gadgets查工具有ROPGadget、ropper等

作者使用ROPGadget去生成直接可利用的ROP链

enter description here

如何减少ROP Gadgets

作者讲了两个思路: 1、编译出非预期的returns(就是不是我们经常看到的pop pop ret) 2、使正常的returns难以构成ROP链

并不需要使ROP Gadgets的数量变为0,只需要减少ROP Gadgets的数量使得构建一个可用的ROP链变得困难或者不可能(我们可以用上面的ROP Gadgets查工具来衡量效果)

Polymorphic Gadget的减少

Polymorphic Gadget 中文直接翻译叫多态Gadget

看了下作者的例子就是通过地址偏移来获得Gadget

在x86/amd64有四种ret类型

抓主要矛盾:C ret是最常见的,也是最容易用在Gadget上的

从两方面减少polymorphic gadgets

1、寄存器的选择 2、代码的生成

寄存器的选择

常见的带c结尾的gadgets,ret前面的汇编指令的ModR/M字节(汇编指令中,Opcode之后就是ModR/M)经常使用的寄存器如下:(这里说的比如常见的汇编:mov ebx,eax)

  • 源寄存器使用RAX/EAX/AX/AL
  • 目的寄存器使用RBX/EBX/BX/BL

此外下面的指令也经常操作RBX / EBX / BX / BL,比如inc, dec, test

而带B系列的寄存器代理很多c字节

所以一个idea就是避免使用RBX/EBX/BX/BL

Clang按此顺序分配寄存器:RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, RBX, R14, R15, R12, R1, RBP

可以将RBX寄存器几乎挪到最后:RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, R14, R15, R12, R1, RBX, RBP

当然ebx的顺序也是要改变的

这样,性能的损耗为0,代码的字节可以忽略不计(因为有一些REX prefix字节)

最终减少了kernel的大概4500个唯一gadgets(约为6%),效果还是有的

代码的生成

我们知道有哪些指令会有return的字节(比如c) 1、ModR/M, SIB或者特殊的指令 2、还有就是常量包含了return字节

我们可以实现相同的功能,但是不使用rerun字节或者要求强制对齐

对于ModR/M, SIB会出现return字节的如下

减少的方法就是 1、先交换寄存器 2、用寄存器进行操作 、再交换回来

例子如下:

如果上面的方法不能使用,我们就要使用强制对齐,比如我们可以在指令前插入一个陷阱来减少gadget

  • 正常的程序会跳过我们的陷阱
  • return字节前面的int会使得gadget受限

例子如下:

损耗总结: 1、效率损耗约为1%,因为xchg指令很快 2、代码方面,影响较小,多了6个字节,一对xchg指令 、用来强制对齐的字节在4-11个 4、总的来说增大了kernel的大小约为2.5%

最终减少了kernel约60%的gadgets

但是我们还有一些可做 1、清理一些汇编函数 2、一些常量可能需要转换 、重定向地址

对齐的gadget的减少(Aligned Gadget Reduction)

就是没有进行地址偏移的gadget

首先介绍下RETGUARD(小写好看一点retguard,这个其实跟windows和linux的GS/CAARY的是一样的)

实现如下: 1、给每个函数分配一个随机的cookie(用openbsd.randomdata section来分配) 2、函数开始处:计算cookie^return address,放在栈帧上,记为saved value

、在函数返回时,计算saved value^return address,再跟cookie比较,不相等就终止程序运行

值得注意的是在返回前加了je还有int 指令,这才是减少gadgets的功臣

因为你要把这当做gadget,你必须跳过int ,再往前就是必须满足cookie的比较,而cookie无法预测,那就没法用了啊

方法小结: 1、损耗:运行时间多了约2%,还有就是初始化cookie的时间是可变的(跟函数的数量有关) 2、代码方面:每个函数多了1个byte,而kernel大约大了7%

最终减少了50%的gadget,15-25%的唯一gadget

针对于Arm64

arm64是有固定的指令长度,所以没有不对齐的gadget,只有对齐的gadget

对于对齐gadget的减少同样也可以是上面int 的思路,只不过arm64是brk #0x1

这样就几乎删除绝大多数gadget了

在6.-release arm64 kernel中ROP gadgets的数量:6995 在6.4-release arm64 kernel中ROP gadgets的数量:46

而剩余的gadget是在引导代码中的汇编中,具体如下:

  • create_pagetables
  • link_l0_pagetable
  • link_l1_pagetable
  • build_l1_block_pagetable
  • build_l2_block_pagetable

引导后OpenBSD可以unlink或粉碎引导代码,那么这些功能在系统运行时就不可用

那么在用户层,那么gadget也几乎为0了,可能存在于crt0,ld.so

最后看看效果图,先看统计的

看看常用的库还有d服务

最后看看ROPGadget查效果,已经不能自动化构成利用链了

这是6.4的libc

6.5的更加惨不忍睹

结尾

还有更多东西可做

比如重定向地址,剩余的可用于gadget的汇编,JOP还没有动

参考

AsiaBSDCon 2019 —— Removing ROP Gadgets from OpenBSD

.pdf

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2019-10-28,如有侵权请联系 cloudcommunity@tencent 删除函数系统性能重定向工具

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1207304.html

相关标签:无
上传时间: 2025-07-24 13:15:43
留言与评论(共有 5 条评论)
本站网友 股票操作软件
13分钟前 发表
R12
本站网友 你从春风中走来
7分钟前 发表
在函数返回时
本站网友 纯爱婚纱摄影
23分钟前 发表
R8
本站网友 中华通
24分钟前 发表
RBP可以将RBX寄存器几乎挪到最后:RAX