
语言运行时编译器移动开发【免费下载链接】hermesA JavaScript engine optimized for running React Native.项目地址https://gitcode.com/gh_mirrors/hermes/hermes点击查看免费下载Fuzzilli 是 Google Project Zero 推出的基于 JavaScript 语法感知的覆盖引导模糊测试引擎本指南面向希望系统性挖掘 Hermes 引擎漏洞的开发者讲解如何在当前仓库中把 Hermes 接入 Fuzzilli 并投入实战。读完本文你将掌握完整流程获取 Fuzzilli、安装 Hermes 专属 Profile、开启 trace-pc-guard 插桩构建fuzzilli目标、启动模糊测试并深入理解fuzzilli.cpp中 REPRL 协议与覆盖率共享内存的实现细节。Fuzzilli 与 Hermes 的接入概览Fuzzilli 与普通黑盒模糊器的核心差异在于它语法感知它通过内部语言模型生成、变异出始终语法合法的 JavaScript 程序并配合覆盖率反馈edge coverage持续探索新的执行路径。Hermes 仓库在 tools/fuzzers/fuzzilli 目录中提供了完整的接入实现主要包括三部分fuzzilli.cpp一个实现 Fuzzilli REPRLREPRL即 REPRL 持久化执行协议Reusable Process REPL协议的可执行文件作为被模糊测试的目标进程profile/目录下的 Swift Profile 文件描述 Hermes 引擎暴露给 Fuzzilli 的语法、内建函数与启动参数策略CMakeLists.txt定义HERMES_ENABLE_FUZZILLI构建开关与fuzzilli目标。官方 README.md 给出了五步上手流程下文将逐步展开并补充源码级细节。第一步获取 Fuzzilli 并安装 Hermes ProfileFuzzilli 本体托管在 Google Project Zero 的独立仓库中需要单独克隆git clone https://github.com/googleprojectzero/fuzzilli.git克隆完成后将 Hermes 仓库中预置的 Swift Profile 复制到 Fuzzilli 的 Profile 目录。假设$FUZZILLI_LOCATION为 Fuzzilli 仓库根目录mv profile/*.swift $FUZZILLI_LOCATION/Sources/FuzzilliCli/Profiles/当前仓库的 profile 目录下提供了 4 个文件其中 3 个是可直接注册的 Profile文件Profile 名称用途HermesProfile.swifthermes标准 Hermes 引擎模糊测试 ProfileHermesW2CSandboxProfile.swiftw2c面向 Hermes W2C 沙箱内存布局的模糊测试 ProfileSparkARProfile.swiftspark面向 Spark AR 场景脚本 API 的模糊测试 ProfileProfile.swift—Profile 数据结构定义与注册表profiles字典复制完成后Profile 即通过 Profile.swift 底部的注册表生效let profiles [ hermes: hermesProfile, spark: sparkARProfile, w2c: w2cProfile, ]这意味着启动 Fuzzilli 时传入--profilehermes、--profilespark或--profilew2c即可选用对应配置。第二步构建带覆盖率插桩的 Hermes 二进制Fuzzilli 的覆盖引导依赖目标引擎编译时开启-fsanitize-coveragetrace-pc-guard插桩。在 Hermes 仓库根目录执行mkdir fuzzilli_build cd fuzzilli_build cmake .. -DHERMES_ENABLE_FUZZILLION -DHERMES_ENABLE_TRACE_PC_GUARDON $OTHER_FLAGS make fuzzilli两个关键 CMake 开关在根 CMakeLists.txt 中定义# Enable Trace PC Guard set(HERMES_ENABLE_TRACE_PC_GUARD OFF CACHE BOOL Enable -fsanitize-coveragetrace-pc-guard) set(HERMES_ENABLE_FUZZILLI OFF CACHE BOOL Enable fuzzilli)它们默认均为OFF必须在配置阶段显式打开。开启HERMES_ENABLE_TRACE_PC_GUARD后构建系统会向编译器与链接器追加插桩标志见 CMakeLists.txtif (HERMES_ENABLE_TRACE_PC_GUARD) append(-fsanitize-coveragetrace-pc-guard CMAKE_CXX_FLAGS CMAKE_C_FLAGS CMAKE_EXE_LINKER_FLAGS) endif()$OTHER_FLAGS位置可按需追加常规构建选项如-DCMAKE_BUILD_TYPEDebug、-DHERMESVM_SANITIZEaddress等建议配合 AddressSanitizer / UndefinedBehaviorSanitizer 以便捕获内存类崩溃。fuzzilli目标的定义位于 tools/fuzzers/fuzzilli/CMakeLists.txtif(HERMES_ENABLE_FUZZILLI) set(HERMES_ENABLE_EH ON) set(HERMES_ENABLE_FUZZILLI ON) add_hermes_tool(fuzzilli fuzzilli.cpp ${ALL_HEADER_FILES} ) target_include_directories(fuzzilli PRIVATE ${HERMES_SOURCE_DIR}/API) target_link_libraries(fuzzilli hermesapi) endif()值得注意的细节开启 Fuzzilli 的同时会强制打开HERMES_ENABLE_EHC 异常支持。这是因为fuzzilli.cpp的主循环依赖try/catch捕获JSIException把脚本执行抛出异常与进程崩溃区分开只有后者才是需要上报的 bug。该目标编译自 fuzzilli.cpp链接hermesapi输出一个名为fuzzilli的可执行文件它就是后续传给 Fuzzilli 的$BINARY_LOCATION。整个 fuzzers 目录含 libfuzzer 入口由 tools/fuzzers/CMakeLists.txt 统一组织add_subdirectory(libfuzzer) add_subdirectory(fuzzilli)第三步理解 fuzzilli.cpp 的 REPRL 实现构建出的fuzzilli可执行文件并不是一个普通的 Hermes REPL而是一个实现了 Fuzzilli REPRL 协议的被引导进程。只有以--replr参数启动时它才进入模糊测试模式int main(int argc, char **argv) { if (argc ! 2 || strcmp(argv[1], --replr) ! 0) return 0;REPRL 协议与进程生命周期REPRL 让 Fuzzilli 的 worker 进程与目标引擎通过固定文件描述符通信从而复用进程、避免反复 fork 开销。协议使用的描述符常量定义在 fuzzilli.cpp#define REPRL_CRFD 100 #define REPRL_CWFD 101 #define REPRL_DRFD 102 #define REPRL_DWFD 103其中CRFD/CWFD是控制读/写通道DRFD/DWFD是数据读/写通道。启动时双方先交换 4 字节的HELO握手char helo[] HELO; if (write(REPRL_CWFD, helo, 4) ! 4 || read(REPRL_CRFD, helo, 4) ! 4) { printf(Invalid HELO response from parent\n); exit(-1); } if (memcmp(helo, HELO, 4) ! 0) { printf(Invalid response from parent\n); exit(-1); }随后进入无限模糊测试循环每轮迭代的流程如下通过CRFD读取 4 字节 action当前实现仅支持cexe即 execute再读取 8 字节脚本长度script_size通过DRFD分块读入完整的脚本源码在当前 Hermes Runtime 中执行脚本通过CWFD写回 4 字节状态码(exceptionThrew ? 1 : 0) 8重置覆盖率 edge guard进入下一轮。覆盖率插桩的运行时支持fuzzilli.cpp中实现了两个__sanitizer_cov_*回调它们是 trace-pc-guard 插桩代码在运行时调用的钩子__sanitizer_cov_trace_pc_guard_init编译器生成的 edge guard 数组初始化入口。它检查SHM_ID环境变量若存在则通过shm_openmmap打开 Fuzzilli 传入的共享内存大小SHM_SIZE 0x100000即 1 MiB否则退化为malloc此时无覆盖率反馈同时将 edge 总数写入共享内存头部的numEdges字段shmem-numEdges stop - start; printf([COV] edge counters initialized. Shared memory: %s with %u edges\n, shm_key, shmem-numEdges);__sanitizer_cov_trace_pc_guard每执行一条被插桩的边edge都会调用。它把 edge 索引对应的位图位置置 1shmem-edges[index / 8] | 1 (index % 8);随后将该 guard 清零保证同一条边在一轮执行中只统计一次uint32_t index *guard; if (!index) return; shmem-edges[index / 8] | 1 (index % 8); *guard 0;每轮执行结束后调用__sanitizer_cov_reset_edgeguards()重新填充 guard为下一轮做准备。每轮执行如何构建 Runtime循环体内每轮都新建一个独立的 Hermes Runtime配置项见 fuzzilli.cppauto runtime makeHermesRuntime( ::hermes::vm::RuntimeConfig::Builder() .withES6Proxy(true) .withEnableGenerator(true) .withEnableHermesInternal(true) .build());即开启 ES6 Proxy、Generator 以及HermesInternal全局对象后者正是 Profile 中大量内建函数所依赖的入口。随后向全局对象注入名为fuzzilli的宿主函数CrashFunction它承担两个职责fuzzilli(FUZZILLI_PRINT, ...)通过REPRL_DWFD通道把数值或字符串输出回 Fuzzilli用于断言与结果记录fuzzilli(FUZZILLI_CRASH, code)按 code 触发确定性崩溃code 0时写非法地址*((int *)0x1) 2code 1时触发assert(1 0)供 Fuzzilli 验证崩溃检测通路是否正常。脚本执行被包在try/catch (const JSIException )中JavaScript 异常被吞掉并记录exceptionThrew只有原生层面的崩溃段错误、断言失败、ASan 报告等才会真正杀死进程从而被 Fuzzilli 捕获为候选 bug。MemoryBuffer类把传入的原始字节直接包装成 JSIBuffer避免多余的拷贝开销。第四步解析 Hermes 的 Fuzzilli ProfileProfile 是 Fuzzilli 的语言模型边界它告诉 Fuzzilli 目标引擎支持哪些语法特性、暴露哪些内建 API、以怎样的参数启动。以 HermesProfile.swift 为例其关键配置逐项说明如下。启动参数随机化processArgs闭包在每次生成新 worker 时被调用以 50% 概率随机追加 Hermes 命令行选项从而覆盖不同的编译与运行时路径组合processArgs: { randomize in var args [--reprl] guard randomize else { return args } if probability(0.5) { args.append(--compile) } if probability(0.5) { args.append(--lazy-compilation) } if probability(0.5) { args.append(--eager-compilation) } if probability(0.5) { args.append(--optimize) } if probability(0.5) { args.append(--async-break) } if probability(0.5) { args.append(--block-scoping) } if probability(0.5) { args.append(--random-mem-layout) } return args },注意首参固定为--reprl与fuzzilli.cpp的入口校验严格对应。--random-mem-layout可提升堆布局随机性增大发现内存破坏类漏洞的概率--lazy-compilation与--eager-compilation互斥概率组合则覆盖延迟编译的两种模式。执行环境与进程管理processEnv: [UBSAN_OPTIONS: handle_segv0], maxExecsBeforeRespawn: 1000, timeout: 2000,processEnv关闭 UBSan 对 SIGSEGV 的处理避免其干扰崩溃检测maxExecsBeforeRespawn为 1000即每个 worker 进程执行 1000 个样本后重启防止状态漂移timeout为 2000 毫秒超时的样本会被标记为超时也可能暗示死循环类 bug。代码前缀/后缀与语言版本codePrefix: function main(){ , codeSuffix: }; main(); , ecmaVersion: ECMAScriptVersion.es6,Fuzzilli 生成的所有样本都会被包裹进function main(){ ... }; main();中执行并限定为 ES6 语法。启动自检与内建 API 建模startupTests在模糊测试正式开始前执行用于验证引擎与 Fuzzilli 的握手、崩溃检测通道是否就绪startupTests: [ (fuzzilli(FUZZILLI_PRINT, test), .shouldSucceed), (fuzzilli(FUZZILLI_CRASH, 0), .shouldCrash), (fuzzilli(FUZZILLI_CRASH, 1), .shouldCrash), (fuzzilli(FUZZILLI_CRASH, 2), .shouldCrash), ],additionalBuiltins则把 Hermes 特有的全局 API 以类型签名形式暴露给 Fuzzilli 的语法模型使其能生成调用这些 API 的合法程序。这些 API 多数来自HermesInternal包括 Promise 任务队列enqueueJob、Promise rejection 追踪钩子setPromiseRejectionTrackingHook/enablePromiseRejectionTracker、运行时诊断getRuntimeProperties/getInstrumentedStats/getFunctionLocation以及gc、print等。其中getInstrumentedStats还精确描述了返回对象的属性集js_numGCs、js_gcTime、js_heapSize等 GC 统计字段使 Fuzzilli 生成的属性访问始终合法。此外还注册了TextEncoder及其encodeInto/encode方法签名见additionalObjectGroups。disabledCodeGenerators排除了对 Hermes 意义不大的生成器如JITFunctionGenerator、GrowableSharedArrayBufferGenerator等。W2C 沙箱 Profile内存模糊测试扩展HermesW2CSandboxProfile.swift 与标准 Profile 结构一致额外向additionalBuiltins注入一组 W2C 沙箱专用 APIw2c_mutate_pointers : .function([] .undefined), w2c_move_sandbox_memory : .function([] .undefined), w2c_flip_bits : .function([] .undefined), w2c_flip_bytes : .function([] .undefined), w2c_move_bytes : .function([] .undefined), w2c_send_values : .function([.plain(.anything)] .undefined), w2c_recv_value : .function([] .anything),这些 API 用于在运行时主动扰动沙箱内存布局翻转位、移动字节、移动沙箱内存、在 worker 与引擎间传递值以覆盖 W2CWasm-to-C / Wasm-Connected 沙箱场景下指针与内存布局相关的安全面。文件中还标注了两个尚未实现的 APIw2c_mutate_value、w2c_swap_functions说明该 Profile 仍在演进中。Spark AR Profile场景脚本 API 建模SparkARProfile.swift 针对 Spark AR 平台codePrefix预先构造一组场景对象Scene.root.findFirst(scene0)、Animation.animationClips.findFirst(aclip0)、Materials.findFirst(mat0)等再通过additionalBuiltins建立完整的 AR 脚本 API 类型模型包括Scene、Units、CameraInfo、Blocks、Fonts、Svgs、Animation、Diagnostics、Materials、Shaders、Time、Prefabs、Textures以及响应式编程库R含大量数学与信号函数。由于生成器在 AR API 建模下可能抛出异常其codeSuffix额外用try { main(); } catch(e) { report_exception(...); }包裹避免异常中断样本执行。第五步启动模糊测试完成构建与 Profile 安装后回到 Fuzzilli 仓库根目录启动cd $FUZZILLI_LOCATION swift run FuzzilliCli --profilehermes $BINARY_LOCATION其中$BINARY_LOCATION指向上一节make fuzzilli产出的可执行文件。Fuzzilli 会运行startupTests验证引擎握手与崩溃通道按processArgs随机化生成 worker 启动参数通过SHM_ID环境变量建立共享内存覆盖率通道通过 REPRL 协议持续下发语法合法的 JavaScript 样本并收集边覆盖率引导变异方向一旦发现崩溃、断言失败或超时即保存复现样本并报告。若需要模糊测试 W2C 沙箱或 Spark AR 场景只需将--profile换成w2c或spark。与其他模糊测试入口的关系Hermes 同时维护了另一条 libFuzzer 模糊测试链路入口为 tools/fuzzers/libfuzzer/fuzzer-jsi-entry.cpp由LLVMFuzzerTestOneInput驱动。两套方案互补libFuzzer 入口进程内执行适合快速回归与持续集成每轮新建 Runtime并注意排除了 Hermes 字节码输入HermesRuntime::isHermesBytecode检查因为字节码被视为可信输入且缺乏校验Fuzzilli 入口语法感知 覆盖率引导生成质量更高、更能触及深层解释器路径的样本适合长期安全攻坚。两者的构建开关HERMES_ENABLE_LIBFUZZER/HERMES_ENABLE_FUZZILLI均在根 CMakeLists.txt 中独立控制可以按需启用。崩溃复现与验证流程当 Fuzzilli 报告一个崩溃时可以按以下思路复现与验证从 Fuzzilli 的输出目录取出最小化后的复现样本通常以crash_前缀命名使用fuzzilli二进制直接运行该样本./fuzzilli_build/fuzzilli --reprl sample.js或借助 Fuzzilli 自带的--reproduce模式配合 AddressSanitizer / UndefinedBehaviorSanitizer 构建确认崩溃是否为 Hermes 引擎自身的真实缺陷而不是 Profile 建模导致的误报借助fuzzilli(FUZZILLI_PRINT, ...)输出在崩溃前的执行轨迹定位触发路径。总结Hermes 通过 tools/fuzzers/fuzzilli 目录提供了一套开箱即用的 Fuzzilli 接入方案fuzzilli.cpp实现了 REPRL 协议、共享内存覆盖率回调与崩溃注入宿主函数profile/下的三个 Swift Profile 分别覆盖标准引擎、W2C 沙箱与 Spark AR 场景CMakeLists.txt则把这一切收敛为HERMES_ENABLE_FUZZILLIHERMES_ENABLE_TRACE_PC_GUARD两个开关下的make fuzzilli单命令构建。对希望深入理解或扩展该链路的开发者建议从阅读 fuzzilli.cpp 的主循环与 HermesProfile.swift 的 API 建模入手这两份文件定义了整个模糊测试闭环的绝大部分行为。赞分享语言运行时编译器移动开发【免费下载链接】hermesA JavaScript engine optimized for running React Native.项目地址https://gitcode.com/gh_mirrors/hermes/hermes点击查看免费下载相关推荐使用 Fuzzilli 对 workerd 进行 JavaScript 模糊测试REPRL 集成与配置实战使用 Fuzzilli 对 workerd 进行 JavaScript 模糊测试REPRL 集成与配置实战 导读 本文基于 workerd 仓库中的 fuzz后端语言运行时WebAssemblySerenityOS 中使用 Fuzzilli 对 LibJS 进行 JavaScript 引擎模糊测试FuzzilliJs 完整构建与运行指南SerenityOS 中使用 Fuzzilli 对 LibJS 进行 JavaScript 引擎模糊测试FuzzilliJs 完整构建与运行指南 导读 Fuz操作系统内核驱动eSpeak NG 模糊测试实战指南使用 libFuzzer 对 espeak_Synth 进行持续模糊测试与覆盖率分析eSpeak NG 模糊测试实战指南使用 libFuzzer 对 espeak_Synth 进行持续模糊测试与覆盖率分析 本指南以 eSpeak NG 仓库中语音音频创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考