Eswlnk Blog Eswlnk Blog
  • 资源
    • 精彩视频
    • 破解专区
      • WHMCS
      • WordPress主题
      • WordPress插件
    • 其他分享
    • 极惠VPS
    • PDF资源
  • 关于我
    • 论文阅读
    • 关于本站
    • 通知
    • 左邻右舍
    • 玩物志趣
    • 日志
    • 专题
  • 热议话题
    • 游戏资讯
  • 红黑
    • 渗透分析
    • 攻防对抗
    • 代码发布
  • 自主研发
    • 知识库
    • 插件
      • ToolBox
      • HotSpot AI 热点创作
    • 区块
    • 快乐屋
    • 卡密
  • 乱步
    • 文章榜单
    • 热门标签
  • 问答中心反馈
  • 注册
  • 登录
首页 › 代码发布 › 将libfuzzer移植为动态链接库的实践:增强灵活性与应用场景拓展

将libfuzzer移植为动态链接库的实践:增强灵活性与应用场景拓展

Eswlnk的头像
Eswlnk
2023-07-10 13:19:25
将libfuzzer移植为动态链接库的实践:增强灵活性与应用场景拓展-Eswlnk Blog
智能摘要 AI
本文介绍了将LLVM项目中的libfuzzer从静态链接移植为动态链接库的方法。libfuzzer通常是静态链接到可执行文件中,但为了增加灵活性,文中提出了一种动态链接的方式。通过修改CMake配置,将`add_compiler_rt_component(libfuzzer)`改为`add_compiler_rt_component(libfuzzer SHARED)`,生成动态库`libclang_rt.fuzzer_no_main-x86_64.so`。对于不同版本的LLVM(如8.0和9.0及以上),操作略有差异,但核心步骤相似。此外,还需调整示例代码以确保`LLVMFuzzerRunDriver`函数可见性。这种方法避免了静态链接的限制,适用于特定场景。

在llvm中,libfuzzer是llvm-project下的compiler-rt的一部分。通常情况下,我们将libfuzzer静态链接到可执行文件中。本文将介绍一种将libfuzzer移植为动态链接库的实践方法。

将libfuzzer移植为动态链接库的实践:增强灵活性与应用场景拓展-Eswlnk Blog

背景知识介绍

下面是一个官方的示例代码,非常简单易懂:

#include <stdint.h>
#include <stddef.h>

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  if (size > 0 && data[0] == 'H')
    if (size > 1 && data[1] == 'I')
       if (size > 2 && data[2] == '!')
       __builtin_trap();
  return 0;
}

编译命令如下:

clang++ -fsanitize=address,fuzzer test_fuzzer.cc

这里的address用于检测内存破坏,与libfuzzer本身无关。真正起作用的是-fsanitize=fuzzer。

通过添加-v参数打印编译细节,如果添加了-fsanitize=fuzzer,就会在编译期进行插桩,并在连接期将其与/usr/lib/llvm-14/lib/clang/15.0.0/lib/linux/libclang_rt.fuzzer-x86_64.a进行连接。而main函数是由libclang_rt.fuzzer-x86_64.a提供的。

如果不想使用libfuzzer提供的main函数,需要使用-fsanitize=fuzzer-no-link,表示只进行编译期插桩,并且需要将其与/usr/lib/llvm-14/lib/clang/15.0.0/lib/linux/libclang_rt.fuzzer_no_main-x86_64.a进行连接。开发者需要提供自己的main函数,并在适当的时机调用约定好的LLVMFuzzerRunDriver函数。

下面是一个简单的示例代码:

// clang++ -fsanitize=fuzzer-no-link test_fuzzer.cc /usr/lib/llvm-14/lib/clang/15.0.0/lib/linux/libclang_rt.fuzzer_no_main-x86_64.a
#include <stdint.h>
#include <stddef.h>

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  if (size > 0 && data[0] == 'H')
    if (size > 1 && data[1] == 'I')
       if (size > 2 && data[2] == '!')
       __builtin_trap();
  return 0;
}

extern "C" int LLVMFuzzerRunDriver(int *argc, char ***argv, int (*UserCb)(const uint8_t *Data, size_t Size));

int main(int argc, char** argv){
    return LLVMFuzzerRunDriver(&argc, &argv, LLVMFuzzerTestOneInput);
}

无论使用哪种方式,最终都要进行静态链接的步骤。但并不是所有的二进制文件都能将libfuzzer静态链接进去,因此本文提出了一个实验性的方案。

思路

目标:获取与libclang_rt.fuzzer_no_main-x86_64.a对应的动态链接库libclang_rt.fuzzer_no_main-x86_64.so,并成功使用它。

llvm本身是由cmake组织的,虽然compiler-rt是它的子项目,但compiler-rt的功能是在运行时实现的,比如asan功能、libfuzzer功能。而cmake通过STATIC和SHARED来区分静态库和动态库。我们的初步想法是简单地将STATIC改为SHARED,看看运气如何。

阅读官方文档https://compiler-rt.llvm.org/后,编译命令如下:

cd llvm-project
mkdir build-compiler-rt
cd build-compiler-rt
cmake ../compiler-rt -DLLVM_CONFIG_PATH=/path/to/llvm-config
make

阅读https://github.com/llvm/llvm-project/tree/main/compiler-rt后,cmake也很好理解。我们从CMakeLists.txt和lib/fuzzer/CMakeLists.txt入手。

另外,由于https://github.com/llvm/llvm-project/commit/50a1c697127749eec567d14819d549b63af1242f,在llvm版本小于等于8时,接受trace-c、trace-pc-guard插桩和inline-8bit-counters插桩,而在llvm版本大于等于9时,只支持inline-8bit-counters插桩。

在许多情况下,被测目标不能在指定的clang下进行编译,因此我们需要验证libfuzzer在这两种情况下的表现。

compiler-rt 8.0

第一步:正常编译通过

只编译相关内容:

cmake /path/to/compiler-rt-8.0.0 -DCOMPILER_RT_BUILD_BUILTINS=OFF -DCOMPILER_RT_BUILD_SANITIZERS=OFF -DCOMPILER_RT_BUILD_XRAY=OFF -DCOMPILER RT_BUILD_LIBFUZZER=ON -DCOMPILER_RT_BUILD_PROFILE=OFF
make libfuzzer

编译参数的含义:

编译参数的含义:

- `-DCOMPILER_RT_BUILD_BUILTINS=OFF`:不编译builtins(该选项用于asan功能,与libfuzzer无关)
- `-DCOMPILER_RT_BUILD_SANITIZERS=OFF`:不编译sanitizers(该选项用于asan功能,与libfuzzer无关)
- `-DCOMPILER_RT_BUILD_XRAY=OFF`:不编译xray(与libfuzzer无关)
- `-DCOMPILER_RT_BUILD_LIBFUZZER=ON`:编译libfuzzer
- `-DCOMPILER_RT_BUILD_PROFILE=OFF`:不编译profile符号表(与libfuzzer无关)

生成的libclang_rt.fuzzer_no_main-x86_64.so在`build-compiler-rt/lib/clang/8.0.0/lib/linux`目录下。

将其复制到当前目录下,并用来编译示例代码:
cp build-compiler-rt/lib/clang/8.0.0/lib/linux/libclang_rt.fuzzer_no_main-x86_64.so .
clang++ -fsanitize=fuzzer-no-link test_fuzzer.cc ./libclang_rt.fuzzer_no_main-x86_64.so

运行编译后的可执行文件,可以看到正常输出。

第二步:修改CMakeLists.txt

将lib/fuzzer/CMakeLists.txt中的add_compiler_rt_component(libfuzzer)改为add_compiler_rt_component(libfuzzer SHARED)。

重新编译:

make libfuzzer

生成的libclang_rt.fuzzer_no_main-x86_64.so在build-compiler-rt/lib/clang/8.0.0/lib/linux目录下。

将其复制到当前目录下,并用来编译示例代码:

cp build-compiler-rt/lib/clang/8.0.0/lib/linux/libclang_rt.fuzzer_no_main-x86_64.so .
clang++ -fsanitize=fuzzer-no-link test_fuzzer.cc ./libclang_rt.fuzzer_no_main-x86_64.so

运行编译后的可执行文件,可以看到正常输出。

第三步:修改libfuzzer示例代码

将示例代码中的extern "C" int LLVMFuzzerRunDriver改为extern "C" __attribute__((visibility("default"))) int LLVMFuzzerRunDriver。

重新编译示例代码:

clang++ -fsanitize=fuzzer-no-link -shared -fPIC test_fuzzer.cc -o test_fuzzer.so ./libclang_rt.fuzzer_no_main-x86_64.so

运行编译后的动态链接库,可以看到正常输出。

compiler-rt 9.0及以上版本

与compiler-rt 8.0的操作类似,只是在cmake命令中使用了不同的路径:

cmake /path/to/compiler-rt-9.0.0 -DCOMPILER_RT_BUILD_BUILTINS=OFF -DCOMPILER_RT_BUILD_SANITIZERS=OFF -DCOMPILER_RT_BUILD_XRAY=OFF -DCOMPILER_RT_BUILD_LIBFUZZER=ON -DCOMPILER_RT_BUILD_PROFILE=OFF
make libfuzzer

其他步骤与compiler-rt 8.0相同。

结论

通过将libfuzzer移植为动态链接库的实践,我们可以在使用libfuzzer的同时,避免了静态链接到二进制文件中的限制。这种方式可以提供更大的灵活性,并且在一些特定情况下可能会有所帮助。需要注意的是,移植过程可能因llvm版本的不同而有差异,需要根据具体情况进行调整。

本站默认网盘访问密码:1166
本站默认网盘访问密码:1166
声明:本站原创文章文字版权归本站所有,转载务必注明作者和出处;本站转载文章仅仅代表原作者观点,不代表本站立场,图文版权归原作者所有。如有侵权,请联系我们删除。
libfuzzer日志移植链接库
0
0
Eswlnk的头像
Eswlnk
一个有点倒霉的研究牲站长
赞赏
开发日志跟进 | 修复网盘搜索问题
上一篇
「主题通用」全站文章评论增加验证码
下一篇

评论 (0)

请登录以参与评论
现在登录
    发表评论

猜你喜欢

  • 「日志」IG无缘S15总决赛
  • 来自谷歌27岁的生日涂鸦
  • 科研记录:ecCodes处理grib文件问题
  • 本站上线邀请码免费兑换系统
  • 开发日志:解决Windows平台无法使用Metview解析数据的难题
Eswlnk的头像

Eswlnk

一个有点倒霉的研究牲站长
1108
文章
319
评论
679
获赞

随便看看

如何利用GO中的泛型实现客户端分页API
2022-05-19 22:41:18
关于BT面板如何绕过验证升级专业版和企业版
2021-07-17 15:59:37
「教程分享」在Debian上使用Docker轻松安装Emby
2024-03-01 13:09:07

文章目录

专题展示

WordPress53

工程实践37

热门标签

360 AI API CDN java linux Nginx PDF PHP python SEO Windows WordPress 云服务器 云服务器知识 代码 免费 安全 安卓 工具 开发日志 微信 微软 手机 插件 攻防 攻防对抗 教程 日志 渗透分析 源码 漏洞 电脑 破解 系统 编程 网站优化 网络 网络安全 脚本 苹果 谷歌 软件 运维 逆向
  • 首页
  • 知识库
  • 地图
Copyright © 2023-2025 Eswlnk Blog. Designed by XiaoWu.
本站CDN由 壹盾安全 提供高防CDN安全防护服务
蜀ICP备20002650号-10
页面生成用时 0.875 秒   |  SQL查询 42 次
本站勉强运行:
友情链接: Eswlnk Blog 网站渗透 倦意博客 特资啦!个人资源分享站 祭夜博客 iBAAO壹宝头条
  • WordPress142
  • 网络安全64
  • 漏洞52
  • 软件52
  • 安全48
现在登录
  • 资源
    • 精彩视频
    • 破解专区
      • WHMCS
      • WordPress主题
      • WordPress插件
    • 其他分享
    • 极惠VPS
    • PDF资源
  • 关于我
    • 论文阅读
    • 关于本站
    • 通知
    • 左邻右舍
    • 玩物志趣
    • 日志
    • 专题
  • 热议话题
    • 游戏资讯
  • 红黑
    • 渗透分析
    • 攻防对抗
    • 代码发布
  • 自主研发
    • 知识库
    • 插件
      • ToolBox
      • HotSpot AI 热点创作
    • 区块
    • 快乐屋
    • 卡密
  • 乱步
    • 文章榜单
    • 热门标签
  • 问答中心反馈