Featured image of post 基于LLVM分析的令牌捕获技术

基于LLVM分析的令牌捕获技术

本文介绍了一种基于LLVM框架的静态分析pass,用于在编译时自动捕获程序中的硬编码字符串和整数常量,生成适用于模糊测试的字典文件,提升fuzzing效率。

Token capture via an llvm-based analysis pass

引言

三年前,LLVM框架因其模块化设计和多领域应用潜力引起了我的兴趣。这个工业级编译器技术集合支持代码优化、混淆、静态插桩、静态分析等多种功能。其强大之处在于允许开发者在三个主要阶段(前端、中端、后端)插入自定义代码。

背景

受AFL(American Fuzzy Lop)模糊测试工具的启发,本文实现了一个LLVM pass来自动化生成fuzzing字典。传统方法(afl-tokencap)需要运行时捕获,而我们的解决方案在编译时完成。

实现细节

AFLTokenCap类

这个BasicBlockPass子类遍历LLVM中间表示(IR),寻找特定函数调用(如strcmp、memcmp)中的常量参数:

1
2
3
4
5
6
7
bool AFLTokenCap::runOnBasicBlock(BasicBlock &B) {
  for(auto &I_ : B) {
    if(CallInst *I = dyn_cast<CallInst>(&I_)) {
      // 处理目标函数调用
    }
  }
}

硬编码字符串检测

通过分析llvm::ConstantDataArray来识别硬编码字符串:

1
[+] Call to memcmp with constant "\x00\x00\xf6\xd6\x00\x01\x00\x00\x00\x00\xd3" found

整数立即数捕获

扩展功能以识别比较指令和switch语句中的ASCII常量:

1
2
3
4
5
else if(SwitchInst *SI = dyn_cast<SwitchInst>(&I_)) {
  for(auto &CIT : SI->cases()) {
    dump_integer_token(CIT.getCaseValue());
  }
}

应用示例

在libpng、sqlite3和libxml2上的测试结果:

1
2
3
4
5
6
7
8
libpng捕获示例:
"abst", "acsp", "bKGD", "\x00\x00\xf6\xd6\x00\x01..."

sqlite3捕获示例:
"SQLite format 3", ":memory:", "unixepoch"

libxml2捕获示例:
"UTF-8", "ISO-8859-1", "validate", "xpath"

局限性

  1. 会捕获测试代码中的常量
  2. 通过排除main函数减少噪声
  3. 性能影响约0.3秒(以libpng为例)

结论

这个不足400行的LLVM pass实现了编译时字典生成,兼容AFL和libFuzzer。欢迎读者在自己的项目上测试并反馈效果。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计