技能使用指南

ruzzy(RuzzySkill)Skill 是什么?如何安装使用?

RuzzySkill 封装了 Trail of Bits 的 Ruzzy——目前唯一生产就绪的 Ruby 覆盖引导模糊测试工具,可测试纯 Ruby 代码与 Ruby C 扩展,内置 AddressSanitizer 与 UBSan 消毒剂。本文详解技能安装命令、harness 编写、运行与崩溃复现流程,并对比 libFuzzer、AFL++ 等替代方案,帮你快速把模糊测试接入 Ruby 项目,立即上手体验。

RuzzySkillruzzy
8 个章节 约 18 分钟阅读 AI 智能生成

RuzzySkill:给 Ruby 代码装上"覆盖引导"的模糊测试雷达

  • 它是什么:RuzzySkill 封装的是 Trail of Bits 开源的 Ruzzy —— 目前唯一生产就绪的覆盖引导 Ruby 模糊测试工具,基于 libFuzzer 构建。
  • 能测什么:既能模糊测试纯 Ruby 代码,也能模糊测试Ruby C 扩展,并内置 AddressSanitizer 与 UndefinedBehaviorSanitizer,用于捕捉内存损坏与未定义行为。
  • 差异化在哪:不是随机乱撞的黑盒测试,而是用 libFuzzer 的覆盖引导反馈,自动探索真正有新代码路径的输入。
  • 上手成本:依赖 Linux x86-64 或 AArch64/ARM64、clang(推荐较新版本,回溯测试到 14.0.0)以及带 gem 的 Ruby;装好后用内置玩具示例几分钟即可验证。
  • 适合谁:Ruby gem 维护者、需要审计第三方 gem 的安全团队、编写解析器/协议处理逻辑的开发者。

1. 该技能叫什么?如何下载安装 AI 技能提升开发效率?

基础信息

项目 内容
中文名 RuzzySkill
英文名 ruzzy
技能 ID 13539
类型 fuzzer(模糊测试器)
来源 Trail of Bits 开源的 Ruby 覆盖引导模糊测试工具

它解决什么问题

Ruby 生态长期缺少成熟的覆盖引导模糊测试工具,很多团队只能靠单元测试手工构造边界用例,或者干脆把 Ruby 代码搬进 C/C++ 环境再用 libFuzzer 测——成本高、还原度差。Ruzzy 直接补上了这块空白:让开发者在原生 Ruby 运行环境里,用 libFuzzer 的引擎和消毒剂(Sanitizer)能力去"喂"随机输入,并且支持模糊测试带本地扩展的 Ruby gems。

"一键安装"AI 技能提升开发效率的思路

这里的"安装"其实分两层,缺一不可:

第一层:安装 AI 技能本体

在支持 AI 技能(Skill)的客户端或 IDE 插件中,通过技能市场检索技能 ID 13539 或英文名 ruzzy 完成加载。不同平台的入口名称、加载命令与权限配置存在差异,具体操作以官方说明为准。技能加载成功后,AI 助手就能理解 Ruzzy 的安装前提、harness 写法、运行命令与常见报错处理,你不需要再翻文档。

第二层:安装 Ruzzy 运行环境(真实命令来自技能详情)

技能详情明确给出了平台与先决条件:

  • 平台支持:Linux x86-64 与 AArch64/ARM64。macOS 与 Windows 需使用官方 Dockerfile 或开发环境。
  • 先决条件:较新版本的 clang(回溯测试到 14.0.0,推荐最新版)、带 gem 安装能力的 Ruby。

使用 clang 编译器标志安装 Ruzzy:

MAKE="make --environment-overrides V=1" \
CC="/path/to/clang" \
CXX="/path/to/clang++" \
LDSHARED="/path/to/clang -shared" \
LDSHAREDXX="/path/to/clang++ -shared" \
    gem install ruzzy

这几个环境变量的作用必须理解清楚:MAKE 用于覆盖 make 以尊重后续环境变量;CC、CXX、LDSHARED、LDSHAREDXX 用于确保走的是正确的 clang 二进制,从而拿到最新特性。

如果安装失败,开启调试输出重试:

RUZZY_DEBUG=1 gem install --verbose ruzzy

验证是否生效

先设置运行环境变量:

export ASAN_OPTIONS="allocator_may_return_null=1:detect_leaks=0:use_sigaltstack=0"

再跑官方内置的玩具示例:

LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
    ruby -e 'require "ruzzy"; Ruzzy.dummy'

按预期会很快找到一个崩溃——这正是 Ruzzy 工作正常的证明。如果这一步就报了 cannot open shared object file,说明 LD_PRELOAD 没有正确内联设置,这是最常见的安装"假失败"。

2. 该技能的主要功能和特点

  • 覆盖引导模糊测试:基于 libFuzzer,用代码覆盖率反馈驱动输入变异,避免在无效路径上浪费算力。
  • 同时支持纯 Ruby 与 Ruby C 扩展:纯 Ruby 采用"跟踪脚本 + 测试工具脚本"的双脚本模式;C 扩展则可以用单个 harness 文件直接跑。
  • 内置预编译消毒剂:Ruzzy 自带 AddressSanitizer 与 UBSan 库,通过 Ruzzy::ASAN_PATH / Ruzzy::UBSAN_PATH 取路径。ASan 可检测堆/栈缓冲区溢出、释放后使用、双重释放、内存泄漏(默认关闭);UBSan 可检测有符号整数溢出、空指针解引用、未对齐内存访问、除零。
  • 语料库与崩溃复现闭环:支持传入语料库目录复用历史输入;崩溃输入会自动落盘为 crash-* 文件并输出 Base64,可直接回放复现。
  • 完整透传 libFuzzer 选项:-max_len=1024、-timeout=10 等参数可直接作为命令行参数传给 harness。
  • 输出语义清晰:ERROR: AddressSanitizer: heap-use-after-free 表示检测到内存损坏;SUMMARY: libFuzzer: fuzz target exited 表示发生了 Ruby 异常——两类结果处理方式不同。
  • 与技能生态联动:可与 fuzz-harness-writing、address-sanitizer、undefined-behavior-sanitizer、libfuzzer 等技术技能配合,由 AI 助手给出更细致的 harness 编写与消毒剂配置建议。
  • 和普通工具比强在哪:普通单元测试只能验证"你想得到的输入",Ruzzy 验证的是"你想不到的输入"。而且它不要求你把 Ruby 逻辑重写成 C,测试对象就是线上真正跑的代码。

3. 如何使用该技能?

第 1 步:设置运行环境变量

export ASAN_OPTIONS="allocator_may_return_null=1:detect_leaks=0:use_sigaltstack=0"

三项含义:跳过常见的低影响分配失败(DoS)、忽略 Ruby 解释器自身的内存泄漏报告、按 Ruby 建议在使用 ASan 时禁用 sigaltstack。

第 2 步:编写测试工具(harness)

模糊测试纯 Ruby 代码需要两个脚本。跟踪脚本 test_tracer.rb:

# frozen_string_literal: true
require 'ruzzy'
Ruzzy.trace('test_harness.rb')

测试工具脚本 test_harness.rb:

# frozen_string_literal: true
require 'ruzzy'

def fuzzing_target(input)
  if input.length == 4 && input[0] == 'F' && input[1] == 'U' && input[2] == 'Z' && input[3] == 'Z'
    raise
  end
end

test_one_input = lambda do |data|
  fuzzing_target(data)
  return 0
end

Ruzzy.fuzz(test_one_input)

第 3 步:运行模糊测试活动

LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
    ruby test_tracer.rb

第 4 步(可选):挂载语料库与调整参数

LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
    ruby harness.rb /path/to/corpus -max_len=1024 -timeout=10

第 5 步:复现崩溃

拿到 crash-* 文件后直接回放:

LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
    ruby harness.rb ./crash-253420c1158bc6382093d409ce2e9cff5806e980

测试工具的三条硬规则(技能详情中明确列出):测试 C 扩展时要捕获 Ruby 异常,不要让异常把模糊测试器打崩;test_one_input lambda 必须返回 0;harness 必须保持确定性,禁止使用随机数或基于时间的逻辑。

关于输入输出:输入是任意字节流 data;输出是进程级的消毒剂报告与落盘的崩溃文件,而不是 Ruby 返回值——你需要关注的是 ASan、UBSan 的报错文本。

4. 同类型竞品对比分析

方案名称 定位 核心功能 安装/使用门槛 适用场景 优势与不足
Ruzzy(本技能) 覆盖引导的 Ruby 模糊测试器 基于 libFuzzer;支持纯 Ruby 与 C 扩展;内置 ASan/UBSan 中:需 Linux + clang + Ruby,安装需指定 clang 标志 Ruby 库、Ruby gem、含本地扩展的 gem 优势:唯一生产就绪的 Ruby 覆盖引导模糊测试工具,测试对象即线上代码;不足:平台仅限 Linux x86-64/ARM64,纯 Ruby 需双脚本模式
libFuzzer(原生) 通用 C/C++ 覆盖引导模糊测试引擎 覆盖率反馈、语料库管理、多种消毒剂 中高:需把目标逻辑移到 C/C++ 并自行链接 直接模糊测试 Ruby C 扩展的底层 C 代码 优势:成熟稳定、生态大;不足:需重写/桥接代码,调试符号与 Ruby 层语义脱节
AFL++ 通用型模糊测试框架 插桩式模糊测试、多引擎调度 高:需对解释器做插桩,链路复杂 通过插桩 Ruby 解释器模糊测试 Ruby 的替代方案 优势:极强的吞吐与调度能力;不足:对 Ruby 场景配置成本高,非开箱即用
传统单元测试 / 属性测试(如 RSpec、基于属性的测试库) 手工/半自动用例验证 明确定义的断言与生成策略 低:现有测试框架即可 已知边界与回归验证 优势:上手快、可读性好;不足:无法自动发现未预料的输入路径,没有覆盖率反馈

一句话选型建议:只要目标语言是 Ruby,Ruzzy 几乎是默认选项;只有当你想绕过 Ruby 层直接对 C 代码做深度模糊测试时,才考虑直接用 libFuzzer。

5. 该技能的典型应用场景与实际体验情况

场景一:Ruby gem 维护者排查 C 扩展内存安全问题

角色:维护带本地扩展的 gem(例如 msgpack-ruby 这类解析器)。痛点:Ruby 层测试全绿,但用户偶尔报段错误,无法复现。使用方式:用消毒剂标志重新编译 gem,然后写一个只调用解析函数、并捕获全部 Ruby 异常的 harness。

test_one_input = lambda do |data|
  begin
    MessagePack.unpack(data)
  rescue Exception
  end
  return 0
end
Ruzzy.fuzz(test_one_input)

实际体验:这是 Ruzzy 最有杀伤力的场景。C 扩展只需要单个 harness 文件,没有双脚本负担;一旦 ASan 报出 heap-use-after-free,崩溃输入直接落盘,回放即可定位。

场景二:纯 Ruby 解析器/协议处理逻辑加固

角色:写配置解析、协议报文解析的 Ruby 开发者。痛点:JSON.parse 之后的自研解析逻辑复杂,边界分支众多,人工构造用例覆盖不全。使用方式:按"跟踪脚本 + 测试工具脚本"模式写 harness,在 test_one_input 中调用解析函数并 rescue 掉预期内的 StandardError。

实际体验:必须使用跟踪脚本,否则会看到"无覆盖进度"——这是新手最容易踩的坑,因为纯 Ruby 依赖解释器层面的跟踪机制。写对之后,覆盖率增长是肉眼可见的。

场景三:安全团队审计第三方 gem

角色:甲方安全工程师或供应链安全审计人员。痛点:引入的开源 gem 有本地扩展,无法快速判断其内存安全性。使用方式:把 gem 用消毒剂标志编译,套用官方示例 harness 模板跑一轮短时活动(如数分钟),收集崩溃样本。实际体验:上手成本主要在"编译带消毒剂的 gem"这一步,命令较长但可复用;跑通后可以形成标准化的批量审计流程。

场景四:CI 中做崩溃回归

角色:DevOps 与测试工程师。痛点:线上偶发崩溃修复后,缺少防止复发的自动化手段。使用方式:把已发现的 crash-* 文件作为固定输入,在 CI 中回放复现。实际体验:稳定性好、耗时可控;注意 LD_PRELOAD 一定要内联在 ruby 命令上,不要 export,否则可能干扰流水线中的其它程序。

上手难度总结:安装阶段中等偏上(平台与编译器限制是主要门槛),写 harness 阶段简单(不到 20 行),调优阶段需要理解 libFuzzer 选项。

6. 该技能能为用户带来的价值

  • 效率提升:把"人工猜边界用例"变成"机器自动探索代码路径"。libFuzzer 的覆盖引导能持续发现新的分支组合,等价于一支不知疲倦的测试员在帮你枚举输入空间。
  • 门槛降低:不需要把 Ruby 逻辑重写成 C/C++,也不需要自己搭建 ASan 环境——Ruzzy 自带预编译消毒剂库,Ruzzy::ASAN_PATH 一行取路径即可注入。加上 AI 技能提供 harness 模板、报错解释和故障排查表,从零到跑通第一个活动的路径被显著压缩。
  • 可量化的收益:每一轮活动产出的崩溃都是可直接回放的 crash-* 文件,配上 Base64 编码便于工单系统流转;这些文件沉淀成语料库后,就成为长期回归资产,修复一次即可永久防复发。
  • 长期价值:在 Ruby 生态中建立"内存安全 + 未定义行为"的持续检测能力。对维护者而言,是发布前的质量闸门;对使用方而言,是供应链安全的判断依据。Ruzzy 是当前唯一生产就绪的覆盖引导 Ruby 模糊测试工具,这项能力几乎没有替代方案。

7. 常见问题 FAQ

Q1:RuzzySkill 怎么安装?需要先装什么?

分两层:先在 AI 客户端或 IDE 插件中通过技能 ID 13539 或英文名 ruzzy 加载技能本体(具体入口以官方说明为准);再装 Ruzzy 运行时——要求 Linux x86-64 或 AArch64/ARM64、较新版本 clang(回溯测试到 14.0.0)和带 gem 的 Ruby,然后用 MAKE=... CC=... gem install ruzzy 的形式安装。macOS 与 Windows 请走官方 Dockerfile 或开发环境。

Q2:收费吗?

Ruzzy 是 Trail of Bits 开发并开源的模糊测试工具,具体授权条款与使用条件以项目官方仓库说明为准。技能本身的使用方式同样以你所使用平台的官方说明为准。

Q3:为什么我跑起来没有覆盖进度,或者立刻退出?

两种典型原因:一是纯 Ruby 代码没有使用跟踪脚本,必须用 Ruzzy.trace('test_harness.rb') 的 tracer 模式启动,不能直接跑 harness;二是缺少语料库目录,需要创建目录或显式传入路径。如果出现 cannot open shared object file,则是 LD_PRELOAD 没设置。

Q4:和直接用 libFuzzer 或 AFL++ 相比,我该选哪个?

如果被测目标是 Ruby 代码或带本地扩展的 gem,选 Ruzzy——不用重写代码,还能拿到 Ruby 层的异常语义;如果只想深度模糊测试某个 C 扩展的底层 C 实现,用 libFuzzer 更直接;AFL++ 适合需要通过插桩解释器做 Ruby 模糊测试且能承担较高配置成本的团队。

Q5:跑出来的 SUMMARY: libFuzzer: fuzz target exited 算漏洞吗?

通常不算。这条信息表示 harness 中发生了 Ruby 异常,说明输入非法但代码没崩。真正的内存安全问题对应的是 ERROR: AddressSanitizer: ... 这类报错。正确做法是在 harness 中用 rescue Exception 捕获 Ruby 异常,只让真正的内存损坏触发崩溃——这样模糊测试器才能把算力集中在有价值的路径上。