《FUZZIFICATION: Anti-Fuzzing Techniques》论文阅读
记录时间:2019.11.22,仅供帮助快速阅读与回忆使用,如有翻译或逻辑错误以原github为准。
论文链接:https://www.usenix.org/system/files/sec19fall_jung_prepub.pdf
github链接:
https://github.com/sslab-gatech/fuzzification
传统模糊技术
- 两种方法
- 软件多样化
- 改变目标应用的结构与接口减轻攻击
- 不能对分析隐藏原有漏洞
- 混淆 obfuscation
- 随机化二进制阻碍静态分析
- 运行时会带来巨大开销
- 可以减慢fuzz,但是每次执行的路径与原本相同
- 软件多样化
- 快速执行
- 定制系统和硬件加速模糊执行:afl-pt,kafl,honggfuzz:intel进程追踪PT与分支跟踪存储BTS等硬件特性收集覆盖率
- 并行模糊分摊绝对执行时间,如 afl使用fork服务器与持久模式避免进程创建
- 覆盖引导
- 更高的路径覆盖表明暴露bug机会更高
- 改变触发新路径输入可能触发另一新路径
- honggfuzz,vuzzer:块覆盖
- afl:分支覆盖
- 源码可用:afl-llvm,libfuzzer
- 静态或动态二进制:afl-qemu
- angora:分支覆盖与栈调用
- 硬件特性
- afl,honggfuzz:固定大小数组
- vuzzer:python的set
- 混合模糊
- 不能区别不同类型输入字节(magic number,length specifier),可能浪费时间修改不重要字节
- 污点分析查找哪些输入字节确定分支条件
- 难以解决magic number和checksum
- 符号执行执行复杂约束,但可能高开销
fuzzification特性
- 有效阻碍现有的fuzz工具,固定时间内发现更少的bug
- 受保护程序正常状态下仍可正常运行
- 不应当通过分析技术轻易从被保护的二进制代码中删除
Fuzzification Design
威胁模型
- 敌手拥有最先进的模糊技术但有限资源
- 敌手得到的是防护后的文件并且明白其存在
- 敌手能使用现成二进制分析技术消除受保护文件的fuzzification
设计目标
- 有效保护 effective
- 通用 generic
- 高效 efficient :执行开销较小
- 健壮 robust:抵抗对抗性分析
阻碍恶意fuzz的四种设想
- packing/obfuscation
- 打包混淆软件针对逆向工程
- 程序开销提升,妨碍正常使用 efficient
- bug injection
- 触发不可利用崩溃
- 额外开销,意外终止影响 efficient robust
- fuzzer identification
- 检测fuzz进程并相应更改行为绕过
- 无法列举所有fuzzer类型或技术 generic robust
- emulator bug
- 动态工具触发bug中断fuzzing
- 专门fuzzer深入理解 generic
fuzzification生效流程
- source code,test cases,overhead budge(开销预算)输入
- 源代码编译程序生成正常二进制文件,给定用例运行收集基本的块频率(哪些块很少被正常执行使用)
- 在该频率基础上使用三种技术生成临时保护文件,正常用例测试开销,超出预算则返回减少程序运行速度,如更少延迟与插装,若远低于预算则增加开销,最后生成最终文件
1.speedbump:amplify delay
-
目标:对于fuzz程序来讲执行速度降低数百倍
-
流程
- 给定用例正常执行来识别冷路径(正常执行很少访问或不访问但模糊测试经常访问的路径(如错误处理中错误的magic bytes))
- 基本块频率分析
- 产生基本的块频率剖面(profile)
- 检测目标程序以统计访问过的基本块,并生成用于分析的二进制文件
- 使用用例运行二进制文件并收集输入访问的基本块
- 用例无需覆盖全部合法路径,只需要大部分常用功能(回归测试)
- 一组触发不常见特性的用例(如readelf解析elf收集有/无效数据集)
- 分析信息识别出冷路径
- 基本块频率分析
- 工具自动确定注入延迟代码数量与延迟长度,注入冷路径,受保护二进制代码执行时在用户定义的预算下产生开销并进行对比,若未超出预算则注入更多的延迟注入,否则以上一轮为最终结果。经测验,延迟30ms注入最少执行的基本块的3%
- 给定用例正常执行来识别冷路径(正常执行很少访问或不访问但模糊测试经常访问的路径(如错误处理中错误的magic bytes))
-
开发者参数
- MAX_OVERHEAD:定义开销预算
- DELAY_LENGTH:指定延迟范围
- INCLUDE_INCORRECT:是否将延迟注入到错误执行基本块(仅无效输入运行的位置)
- INCLUDE_NON-EXEC与NON_EXEC_RATIO:指定是否将延迟注入测试时从不执行的基本块内
-
抗分析延迟原语
- CSmith可生成一个接受参数执行拟算术操作并返回特定类型值的函数。基于CSmith,使用改进选项生成随机的无bug代码片段,包含算术运算并与原始代码库相连接
- 修改生成具有数据依赖项与原始代码的代码依赖项的代码
- 变量作为参数从原始代码传递给生成的代码,将引用从生成的代码传递给原始代码并使用返回值修改原始代码全局变量,以引入数据依赖关系且不影响原程序状态下更改程序状态
-
安全性分析
- CSmith默认安全检查
- 整数,类型,指针,效果,数组,初始化,初始化,全局变量
- 指针解析检测范围外栈变量或空指针访问,显式初始化防止未初始化使用,数学包装防止意外整数溢出,分析限定符避免不匹配
- fuzzification自检
- 固定参数多次运行,执行出现错误则丢弃,最后将生成原语嵌入相同的固定参数避免错误
- CSmith默认安全检查
-
有效性
- vuzzer与tfuzz剖析识别错误块并排除在代码覆盖率计算之外避免重复执行,影响有效性。
- 解决方案:冷路径包含包含错误块与很少运行块,可使用类似方法处理错误块并提供无视选项,且重点在于减少运行块以最大化有效性
2.branchtrap:block coverage feedback
- 两种思路
- 代码重用实现健壮的分支陷阱,类似于面向返回编程(ROP)
- 插入大量输入敏感跳转,input drift 显著改变执行路径,使得基于覆盖的fuzzers关注无bug路径而非真正路径;并频繁路径冲突来饱和代码覆盖存储,使无法识别触发新路径的interesting输入。
- 1.fabricate fake path 用户输入内制造假路径
- 条件分支 conditional branch:依赖于输入字节决定是否执行分支
- 间接跳转 indirect jump : 用户输入计算目标
- 诱导设计:足够数量伪路径影响模糊策略,提供不同的覆盖并直接受输入影响,同时使得新路径开销最小,并对于确定的用户输入,使得相同输入对应相同路径,不容易被发现与清除。
- implement
- simple:注入跳转表并使用输入字节作为索引访问
- CFG distortion CFG畸变
- 根据用户输入分散注入分支的返回地址
- 程序集收集函数epilogue(编译时生成)
- 相同指令序列的函数epilogue分组到跳转表
- 重写程序集,函数从相关跳转表检索等价的epilogue实现原始函数的返回,并使用输入字节作为索引
- 使用等价函数替换epilogue时保证了原始程序相同操作
- 有效性
- 控制流随输入敏感变化,引入足够数量的非生产路径降低覆盖反馈的效率,保证输入与流的一致性避免忽略
- 低开销
- 轻量级操作(xor存储参数,跳转gadget解决跳转地址)
- 健壮性
- 基于ROP设计增加对手识别与修补二进制文件复杂性
- 2.saturating fuzzing state 饱和模糊路径
- 少访问基本块引入大量确定性分支,fuzz时迅速填满覆盖表,在接下来的执行时发现大多新路径都被视为已访问,进而丢弃实际上探索有趣路径的输入
- afl维护固定大小位图,位图碰撞概率提升,降低了覆盖的不准确性,饱和位图导致更少路径发现
- collision mitigation 碰撞缓解:路径覆盖分配唯一标识符缓解冲突,但需要源代码链接时分配唯一标识符,根据模型无法访问未保护的源码文件,可拦截id分配算法。且覆盖存储大小固定,饱和大部分位图内容便可造成巨大影响。
- design factors :基于ROP的分支陷阱与饱和覆盖的接口实现最佳保护
- 伪路径数量随机配置,依赖于函数数量实现扭曲控制流
- 对功能少的二进制文件将基本块分割,通过条件分支链接
- 饱和覆盖的路径数也可配置,为避免高开销将大量分支注入到很少运行的一两个基本块内
3.antihybrid:thwarting hybrid fuzzers
- Hybrid fuzzing 混合模糊
- 符号执行(symbolic execution)解决复杂的分支条件(magic num,checksum)
- 污染分析(taint analyse)查找与分支条件相关的输入字节
- 符号执行与污染分析消耗大量资源(CPU,内存),只能进行简单分析
- 路径爆炸限制符号执行,大多数引擎无法运行到执行路径的末端
- DTA分析难以跟踪隐式数据依赖关系,如隐式通道,控制通道,基于时间通道。为控制通道覆盖数据深度,条件分支后DTA将污染属性积极传播到任何变量,准确低且昂贵
- 1.implicit data-flow-dependencies 隐式数据流依赖
- 显示数据流转换为隐式防止污染分析(DTA)数据流跟踪
- 识别分支条件与有趣信息接收器,根据变量类型注入数据流转换代码,妨碍跟踪直接数据传播的数据流分析
- 缺点:无法防止微分分析的数据依赖推理
- redqueen通过模式匹配推断输入与分支潜在关系,绕过隐式数据转换;但要求输入中显示分支条件值,容易被数据修改骗过
- 2.exploding path constraints 爆炸路径约束
- 符号执行时期插入大量假符号触发路径爆炸
- 比较原始比较操作数的哈希值替换比较指令(符号执行不容易用给定的哈希值确定原始操作数)
- 避免哈希函数的不可忽略开销,利用轻量级循环冗余检查(CRC)循环迭代来转换分支条件减少性能开销,若符号执行解决则产生超时错误
Evulation
由于这部分基本为图片比较,所以用思维导图直接记录了,可以对比原论文内的图进行剖析功能对比。
Discussion
本部分为未来的拓展与完善考虑
关于代码复现
- install内安装afl时会缺失文件plugin.h,自行安装就能用了
- 文档很详细,但是路径很混乱,注意AFL_PATH与conf.py内的工作目录的各种路径。