二进制安全用户态 Roadmap
本次目的为研究, RISC-V 架构在用户态执行时的漏洞检测, 分析, 利用, 测试, 逆向, 插桩, 运行时监控能力的可能性. 希望后续能够 proting RISC-V 相关的一套二进制安全工具链, 能覆盖: 从漏洞发现 => 原因分析 => 利用验证 => 运行时约束的完整闭环能力. 为 RISC-V 用户态软件提供从开发到上线的全流程安全维护能力.
TODO: 可以看到本篇中涉及到的软件生态是非常复杂的, 还有很多软件我并没有详细地去介绍和运行, 毕竟不能讲空话, 这个工作量巨大, 需要很多的积累才能一步步补充完整, 如果没有亲自去涉足笔者是不会轻易口嗨的, 因此本篇中的话语都是有依据可信的, 不可信的部分会单独进行一些说明.
0 写在前面的话
再次强调, 本次的调研的目的是为了了解用户态二进制安全领域相关的关键路径, 便于为了后续的探索铺路(后续如果进一步去研究内核态的情况了会另出一版)
本次探索的难点在于两个方面:
第一个难点是我如何得知自己探索的软件在生态内是否是关键软件? 按照老师说的话, “软件是非常多的, 我们不可能把所有软件都做一遍”, 诚然这是事实, 人的精力是有限的. 因此能否透析一个软件的必要性我觉得应该从用户的使用度, 软件的引用量, 软件的 star 量(只是一个参考), 软件的实际功能作为评判, 这个过程如果进行量化是非常耗时的, 我们只能模糊地感知一下, 必要的情况下应该动手去 running code.
第二个难点是我对于安全方面的知识之前了解非常少, 我不断的在盘问自己 “什么是安全? 安全的意义在哪里?”, 安全这个话题是非常抽象的, 我们作为一个产品往往在 “能用, 用的好” 之后才会提及到安全. 安全永远是一个附加品, 对于个人场景而言除了一些 hacker, 还有发烧友, 这些工具似乎是可有可无的. 但是它的生态位在我看来, 如果作为一个服务器的场景, 还是有非常必要的存在.
本次探索的困惑有一个方面:
我是否需要探索架构无关的软件? 是否探索某架构专用软件? 主题是二进制+安全的生态, 理论上来说架构相关性因为二进制的缘故是强匹配的, 但是不得不说的情况是, 仍然有很多优秀的软件是不跟架构绑定的, 既然讨论的目的追根溯源是明确 “如何做生态? 做一个什么样的生态?” 这个问题, 部分架构无关或者强关联某个单独架构相关的软件(这里x86多见)我也可能会置于本篇当中.
本次探索还未详细涉及的有两个方面:
第一个是社区的接受度以及软件的活跃度问题, 我不否认开源软件的力量, 有些开源软件看似开源, 实则很多已经归档了但不明说, 这是潜在的可能, 我没有详细去接触(比如google就归档了很多软件), 另外有些软件更新已经是1年的时间了, 甚至有些追溯到五六年的这些软件我就没有去关注了.
第二个是闭源软件, 对于这类软件, 除非在行业内有强普及性的使用, 基本不会出现在本文, 可能在某处会被提及到.
1 软件生态明细
1.1 模糊测试
所谓模糊测试(Fuzzing), 就是通过大量的输入反复执行软件来查找错误的技术. Fuzzing 技术是安全的基石, 也是软件的保障, 个人认为做好 fuzzing 的 porting 能够帮助挖掘 riscv 生态下更多软件的潜在危险.
1.1.1 AFLplusplus
AFL++ 是当前软件安全分析应用最广泛的工具之一, 因此能够在 riscv 的环境下做 fuzz 是进行软件测试时很重要的一个功能, 它的移植显得尤为重要. 另外它的强大之处在于, 它支持多个模拟引擎, 比如 Qemu, Unicorn, Nyx等. 还支持多个语言的 fuzz, 因此这是一个关键移植路子, 可以先解决一个模拟引擎再对 AFL++ 做一个嵌入. 另外后面,我们可以陆续看出, 很多 Fuzz 软件是依赖于 AFL++ 的.
另外 AFLplusplus 是一个专门针对 fuzzing 的组织, 名下许多针对 fuzz 的模块.
目前进行了静态的分析, 目测 riscv 的支持是不够全面的.
1 | $ grep -Irn riscv |
1.1.2 aflgo
该项目是依托 afl++ 诞生的, 同 afl++ 它进行的也是一个灰盒的测试. 既然是衍生工具, 那么它应该有一些功能上的不同, 实际上, afl++ 进行的更多是覆盖性的测试, 而 aflgo 进行的则是定向的测试.
aflgo 的缺陷是, 它的 fuzz 仅限于 C/C++.
1.1.3 Libfuzzer
Sanitizers 官方文档: AddressSanitizer, ThreadSanitizer, UndefinedBehaviorSanitizer, MemorySanitizer
该项目由 LLVM 维护, 通常伴随 clang 一起发布, 目测它与 afl++ 的一个区别是, 它的测试必须要有源码, 而 afl++ 可以通过 QEMU 进行无源码的测试.
并且该工具常常配合 Sanitizers 一起使用, Sanitizers 原本由 Google 维护, 但是现在合并到了 LLVM 项目当中.
1.1.4 fuzzilli
javascript 的一个 fuzz 工具, 既然存在针对单语言的 fuzzer, 那么必然有其它更多的 fuzzer, 置于这里作为一个扩展的引子, 希望能够关注更多语言专用的 fuzzer.
1.1.5 radamsa
radamsa 是一个黑盒测试工具, 这也是区分于前面 afl++ 的一个情况. 目前没有深入地实践和探索, 只是停留在看方面, 不作更多的评价.
能够查阅到的优势有无需复杂配置, 适合快速验证程序. 作为一个辅助性的软件来使用.
1.1.6 boofuzz
boofuzz 目前看来是架构无关的一个网络测试工具, sulley 是 boofuzz 的前身, 目前已经很少去维护了. boofuzz 是 sulley fork 的一个仓库, 活跃度更高. 放在这里是为了作为一个引子探索更多的可能性, 我们不止是以一个普适性的角度来观测 fuzz 工具, 而可以把探索的路径也放到 fuzz 的用途上.
1.1.7 cargo-fuzzer
该软件是 rust-fuzz 下的一个子仓库, 该仓库提供了一系列工具, 将底层的 fuzzing 引擎包装成 Rust 风格的库.
其实放在这里的本意是作为一个引子, 能够引导关注一下 rust-fuzz 这个 rust fuzzing 的基础设施库.
1.2 插桩工具
动态分析(Dynamic Analysis) 是指在程序实际运行的过程中对其行为进行观察、分析和评估的技术. 我所展现的图谱当中有许多动态分析的工具, 后来加入了一类静态分析的工具, 目前我所搜查的没有很多. 动态的市场反而广泛, 这里种类繁多, 光芒四射, 诞生了无数的 hacking 工具. 这也能理解, 毕竟动态分析能够看到程序最真实深层的执行状态.
第一类是插桩工具.
补充: 这类插桩工具还有一个出名的叫 Intel Pin, 似乎转对于 X86 并且闭源.
1.2.1 QBDI(QuarkslaB Dynamic Binary Instrumentation)
QBDI 是一个 DBI 的框架, 看样子目前没有移植到 riscv 上, 提供了 Python, JS, Frida 接口. 相比于 DynamoRIO, QBDI 似乎更轻量级, 适用于移动端的安全分析, 也就是说它强调移动端的友好.
最初我在想插桩工具的必要性, 这也是我在研究 DBI 这类工具的时候一直在思考的, 它的市场究竟是什么? quarkslab, QBDI 团队的官网: https://qbdi.quarkslab.com/ 给我带来了一点感悟.
我的理解是调试器是二进制文件执行过程的常用方法, 这种方法的问题是运行速度缓慢. 如果用户群体是人, 这种方法可能不会被察觉, 但是这种方法对于工具或者机器而言, 那是缓慢的. 因此可能这些 DBI 面向的对象是一些跟 trace 有关的工具.
另外, 这类 DBI 工具确实,给我们传统一停一看的模型给予了一种改变, 这是非常有价值的事情.
Debuggers are a popular approach to analyze the execution of a binary. While those tools are convenient, they are also quite slow. This performance problem is imperceptible to human users but really takes its toll on automated tools trying to step through a complete program. The only way to get rid of the problem is to place the tool inside the binary being analyzed and this is what DBI does: injecting instrumentation code inside the binary at runtime.
为什么我们选择 QBDI? 官网也给出了介绍.
Existing DBI framework were designed more than 15 years ago, focusing on features and platforms that made sense at the time. Mobile platform support is often unstable or missing and instrumentation features are either simplistic or buried in low-level details. QBDI attempts to retain the interesting features of those frameworks while avoiding their pitfalls and bringing new designs and ideas to the table.
1.2.3 DynamoRIO
已经有了一些移植工作, 目前 PLCT 有老师也做了一些支持工作, 据了解应该是推进的差不多了. 这里我想抛出一个疑问, 为什么选择 DynamoRIO, 可能我的理解是因为它的全能和老牌, 既然已经进行了移植工作, 这里我就没有深入去了解了, 但是后续有必要的话还是会去观察一下.
1.2.4 Dyninst
Dyninst 最早并不是作为一个独立的工具开发的,而是作为 Paradyn 并行性能测量工具的一个核心组件.
到目前为止它已经独立发展起来了, 并且将功能拆分为多个 API(PatchAPI, ParseAPI, InstructionAPI, DataflowAPI).
1.2.5 Frida
1.2.6 Valgrind
1.3 Record & Replay
1.3.1 PANDA
PANDA 是基于 QEMU 的一个仿真框架. 它的亮点正如标题所示, Record and Replay. 目前这类工具的使用场所我不是很明确, 但是他们的另一个价值很显然是作为分析程序而存在的.
PANDA is an open-source Platform for Architecture-Neutral Dynamic Analysis… analyses have access to all code executing in the guest and all data… adds the ability to record and replay executions, enabling iterative, deep, whole system analyses.
下面是一条来自 https://www.youtube.com/watch?v=EJfNUE3JOiI&t=373s 的评论. 我的理解是借助 QEMU 的能力, PANDA 能够实现一个盒外的分析, 也就是说当我们运行一个操作系统时, 根本就不用在里面运行一个程序才能观察另一个程序. 从这个角度看 OS 变成了一个标本也不为过.
This was not highlighted in the video, but it’s important to emphasize what technically occurred here in order to really appreciate why this is cool. We recorded the execution of a full Windows OS and then extracted all of the processes on the system as well as information about the dynamically loaded modules. We did this without deploying any code in the target Windows OS, meaning that all of the information was derived by interpreting the state of the guest system based on it’s hardware. So the analysis was performed “outside-the-box”.
1.3.2 DECAF
它的亮点相比于上面主要是污点分析能力.
缺少 riscv 支持.
1.3.3 rr-debugger
目前没看到移植情况.
1.4 模拟执行
1.4.1 Qiling
riscv 侧目测移植的不够完善, 最早追溯到 2021 年.
1.5 符号执行
1.5.1 angr
符号执行类工具,
无 riscv 移植.
1.5.2 miasm
缺少 riscv 支持.
1.6 静态分析
1.6.1 CodeQL
不清楚是否架构相关.
1.6.2 semgrep
比 CodeQL 轻量.
1.6.3 BinAbsInspector
一个 CWE 分析工具, 缺少 riscv 支持, 但是我看着活跃度很低, https://github.com/KeenSecurityLab/BinAbsInspector/pull/81 去年的 PR 迟迟没有合并.
1.6.4 cwe_checker
1.6.5 bap
目测支持基础的 riscv, 使用的语言是 OCaml, 不太了解这门语言.
1.7 供应链安全
前面针对的都是程序的漏洞问题, 而供应链安全关注的是这个程序它本身的构建, 依赖可信问题. 这类工具的初衷我的理解如下, 现代的软件往往都是第三方库 + 构建工具 + CI/CD 等等关系杂揉而成的, 攻击链可能在于自己没有编写的代码之上, 攻击者选择不直接攻击目标系统,而是攻击软件的来源, 因此这类软件诞生了, 以上是我对这个概念的粗浅理解, 下文的 syft, grype 是一个工具套装, 配合使用, syft 负责软件的清点, grype 则负责 CVE 的发现.
A CLI tool and Go library for generating a Software Bill of Materials (SBOM) from container images and filesystems. Exceptional for vulnerability detection when used with a scanner like Grype.
1.7.1 syft
漏洞检测工具, 目测不支持 riscv
1.7.2 grype
跟着 syft 一同体系的工具, 目测也不支持 riscv
1.8 逆向平台
这类工具比较万能, 覆盖从静态, 动态逆向, 多架构分析到可视化交互的场景. 因此这类软件应该是人手一个的程度.
1.8.1 Ghidra
-
- 这个项目目前已经有移植.
1.8.2 radare2
-
- 已经支持 riscv.
1.8.3 cutter
该项目最初依赖于 Radare2 项目, 只不过后期由于分歧发起了 Rizin 项目, 该项目从 Radare2 fork 而来.
根据调查, 该项目貌似没有专门做 riscv 架构的移植.
1.9 Gadget 分析
Gadget 分析是漏洞利用开发中的一个关键环节,主要服务于 ROP, JOP, COP 等代码重用攻击(击者通过利用程序中已有的代码片段,构造攻击链,以实现恶意目的).
1.9.1 ropper
依赖的ELF库(作者自己写的), filebytes 项目链接
完全没有移植, 想要移植的话第一步要完成 filebytes 的移植.
1.9.2 ROPgadget
已经适配基本的 riscv 架构.
1.10 防护检测
此处的防护检测关注的不是程序有无漏洞, 而是关注程序有哪些安全机制. 对于这类软件的市场我不是很明了, 应该就是一个小的脚本工具.
1.10.1 checksec
目测不支持 riscv.
1.11 利用开发框架
1.11.1 pwntools
pwntools 是一个专门为 CTF竞赛和漏洞利用开发设计的 Python 库. 可以说就是一个基于 python 的 hacking 库.
A CTF framework and exploit development library
1.11.2 metasploit-framework
1.12 内存取证
如果说磁盘取证是存留文件中找信息,那么内存取证就是在看正在发生的动作. 目的很明确, 观察内存当中的系统信息并还原成可读的形式.
1.12.1 volatility3
无明显痕迹支持 riscv, 但是绝对支持 x86.
更多的: https://www.bilibili.com/video/BV1PG411e79E/?spm_id_from=333.337.search-card.all.click
1.12.2 fridump
目测架构无关.
1.12.3 ProcDump-for-Linux
基于 ebpf 的工具, 微软出品, 目测不支持 riscv.
1.12.4 MemProcFS
该工具非常有意思, 将物理内存当作文件系统来查看.
目测不支持 riscv.
MemProcFS is an easy and convenient way of viewing physical memory as files in a virtual file system.
1.13 固件安全
固件安全指的是在一些嵌入式设备当中通过分析这些嵌入式的软件, 防止攻击者利用其中的漏洞获取设备的控制权.
目测这类软件的意义比较明确, 是固件安全的一层保障.
1.13.1 firmadyne
这是一个自动化的仿真框架, 目的是在虚拟机当中提取固件的信息, 主要用于基于 Linux 的嵌入式固件分析.
FIRMADYNE is an automated and scalable system for performing emulation and dynamic analysis of Linux-based embedded firmware.
分析了一下软件架构支持情况, arm, x86 肯定是没问题, riscv 还没有跑过, 因为它不一定是架构关联特别大的软件.
1.13.2 binwalk
1.14 插件
1.14.1 keypatch
目前不支持 riscv
1.14.2 GEF
这是一个 gdb 插件, 支持 riscv
1.14.3 pwndbg
gdb, lldb 的插件
1.15 基础组件
1.15.1 unicorn
官方表示支持 riscv.
1.15.2 capstone
官方描写支持 riscv(rv32G/rv64G).
1.15.3 keystone
官方描写支持 riscv
1.15.4 z3
一个著名的约束求解器, 特别是在符号执行, 逆向工程这一块儿用处很大, 架构无关.
1.15.4 llvm
1.15.5 qemu
2 生态位
2.1 生态层级
下面图中所有的软件在节1中都已经介绍过了, 现在来进行一个整合.
第一个角度就是从功能思考(按照要求, 我更多地是考虑到用户态的事情), 对于安全而言较为重要的一个名词就是 “漏洞”, 对于漏洞而言我们应该拆分地去审视它, 从发现漏洞到漏洞地分析, 再到漏洞的利用和开发这个过程是一个完整的路径, 如果我们从这个视角去审视我们的软件呢? 可以看到软件很清晰地就变成了一个个的 component. 需要解释一下, 这是我目前拆分的模块, 可能一个软件覆盖了多个功能, 可能一个软件有更细分的作用, 这个仁者见仁, 合理即可, 这时我目前看来较为合理的拆分方法. 另外还有更多的功能模块可以塞到整个体系当中, 目前先点到为止.

figure 1
2.2 关键路径
该图并没有包含全部的依赖工具, 诸如一些常用的ELF解析库, glibc 这些运行时的库就没有放上去了, 只是将相关性比较强的工程性比较大的软件放了上去. 另外图中还没有标明的是里面有不少软件有插件的功能, 另外软件之间经常会有一个配合的使用, 并且本图中只标注了强依赖的软件.

figure 2
3 总结
首先, 概念是人去定义的, 我对二进制安全这个词语的理解目前为止就是这么多, 起初我是非常担心自己因为了解不够而去歪曲方向的, 后来我思考了一下, 这是肯定会有的, 但是不要脱离大框架天马行空即可.
其次, 在调研完成之后, 我发现了二进制安全这是一个太大的方向了, 它可以和很多生态做融合, 包括里面很多的软件需要一些虚拟化的支持. 经过这几次调研之后, 我的感悟是, 我们做的不只是系统, 我们做的是围绕系统的生态. 这是粗浅的第一步调研, 个人认为下一步是否该从模糊测试出发, 进行相关的移植?
之后, 还能观察到一个现象, 微软和 Google 貌似对安全类的工具涉猎比较多.
最后, 这个方向非常不容易, 它需要时间的积累去完成, 好在如果凭借 LLM 的帮助去学习效率可能会高, 但是这也是我目前为止对 LLM 最排斥的地方, 诚然它能给我们的理解以及 coding 带来提升(我尝试过面对一些复杂项目使用大模型, 至少 GPT 这类还是不太可信, 甚至网上的博主解释也可能是错误的, cursor 这些专用工具还没尝试用过, 但是也不太敢用这些), 但是很多人对它的使用本末倒置, 效率非常快, 但是通过 LLM 获得的知识是基石不扎实的(更别说它有很多的错误率了).
4 References
Reverse Engineering - Software Engineering: https://www.geeksforgeeks.org/software-engineering/software-engineering-reverse-engineering/
白盒, 灰盒, 黑盒测试: https://zhuanlan.zhihu.com/p/55616948