MacOS 下fuzz学习&踩坑点
前言
最近在学习fuzz,发现macos下有一些和windows下不同的点导致学的不是很顺畅,于是把我踩过的坑记录一下。
主要教程:https://github.com/antonio-morales/Fuzzing101 基本上就是跟着这个为主线的,下文简称fuzz101
前置知识点:
- Liunx操作
- docker 部署
- ***上网环境
接下来默认使用***上网环境环境,并使用虚拟网卡(TUN模式)以保证网络连通性。
但是还是要一台x86_64 的windows作为备用机才好,毕竟教程是面向x86_64下的,arm编译会出现亿点问题要倒腾。
后期补充
一台x86_64的打工机+ssh才是版本答案!
笔者后面用ssh到打工机了
一、环境安装
俗话说,对于计算机,0到1的突破比1到100难多了,因为第一步配环境就能搞死人。
1.1 docker环境准备
推荐使用docker容器安装,因为fuzz过程中会编译大量的旧版本库,或者依赖于旧版本组建,使用docker用完就丢才是正确选择。
后期补充
真正头疼的是编译环境,fuzz要设置编译环境,会把环境搞得一团糟,真心建议丢虚拟机或者容器里
macos安装docker:https://docs.docker.com/desktop/setup/install/mac-install/

我这里使用的是M3,直接安装苹果芯片版,然后就是常规的安装docker.app,这里没啥坑点,做一遍流程就好

如果遇到docker已损坏,尝试以下办法
- 输入密码并回车,然后重新打开 系统设置 -> 安全性与隐私,选择“任何来源”。
sudo spctl --master-disable
- 允许运行
sudo xattr -r -d com.apple.quarantine /Applications/docker.app
1.2 docker镜像拉取
- 拉取镜像(仅需做一次,之后不用做)。
如果拉取失败检查是否***上网环境。docker pull aflplusplus/aflplusplus:latest
1.2.1 如果拉不到架构

方法一:模拟x86_64运行(不推荐)
2025/10/04更新
如果拉不到架构,那就必须搭配qume模拟运行
请注意如果您使用此方法启动运行相当于在x86_64上运行,本文剩余的部分可能不再适用!
拉x86_64,用qume运行
brew install qemu
docker run --platform linux/amd64 -ti aflplusplus/aflplusplus
运行:
docker run --platform linux/amd64 -ti aflplusplus/aflplusplus
转译运行会损失大量性能,在fuzz这种对性能高度敏感场景不推荐!优点显而易见:不必为了arm架构发愁
方法二:使用旧版本号(推荐)

https://hub.docker.com/r/aflplusplus/aflplusplus
截止2025/10/04,目前官方推出的最后支持arm的是v4.32c,拉下来就好
docker pull aflplusplus/aflplusplus:v4.32c
需要注意的是:旧容器 != 旧软件,可以在容器内更新软件包。
-
启动 AFLPlusPlus docker 容器:
docker run -ti aflplusplus/aflplusplus出现这样就是成功

-
更新软件索引
apt update apt upgrade -y apt install sudo -y前面两句是老熟人了,这里解释一下为什么要安装
sudo,因为有些ai生成出来的带一大堆sudo,懒得一个个删除,反正sudo加不加都无所谓就干脆安装上了。
1.3 一些优化
这部分是笔者个人爱好,可以跳过,用eza代替ls
apt update
apt upgrade -y
apt install sudo -y
apt install eza -y
alias ls='eza --icons --group-directories-first'
alias ll='eza -lh --icons --group-directories-first'
二、 一些常见问题的解决
建议先去跟着教程做,做到出问题再来看,这一块是用来解决问题的,和上文关联性不是很强,但是又经常遇到就放在这里快速查阅了
2.1 出现./configure出错
报错大概长这样:

这是因为项目太老了(2008-01-08),没办法识别aarch64(arm64)架构
解决方案:
更新config.guess和config.sub
GNU的config.guess和config.sub是独立维护的,可以替换掉旧版本。
下载最新版本:
wget -O config.guess 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess'
wget -O config.sub 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub'
再运行:<your_install_pwd>替换为你的安装目录
./configure --prefix="<you_install_pwd>" --disable-shared
就能看到正常识别了

2.3 intltool 太老了

直接更新即可
sudo apt update
sudo apt install intltool
2.4 清理现场
如果编译错误了,要清理现场,方法有两个
- 运行
bash,开一个新的终端,去除手动设置的环境参数 - 运行:
export CC=""
export CXX=""
export CFLAGS=""
export CXXFLAGS=""
export LDFLAGS=""
export AFL_USE_ASAN=0
之后运行
make uninstall
make clean
2.5 找不到安装的库
有时候安装好了库结果下一个要的依赖找不到怎么办,那就输入这个刷新
sudo ldconfig
三、一些经常用到的fuzz命令
3.1 插桩编译
直接走一遍这个流程
<your_install_pwd>替换为你的安装目录
# 设置编译器为 afl-clang-lto(或 afl-gcc/afl-clang-fast/)
export CC=afl-clang-lto
export CXX=afl-clang-lto
export CFLAGS='-O2 -g -fno-omit-frame-pointer'
export CXXFLAGS="$CFLAGS"
export LDFLAGS=''
# 重新 configure
./configure --prefix="<your_install_pwd>" --disable-shared
# 编译并安装
make -j$(nproc)
make install
3.2 启用ASan
如果要启用ASan,做设置编译器后做:<your_install_pwd>替换为你的安装目录
export AFL_USE_ASAN=1
./configure --prefix="<your_install_pwd>" --disable-shared
make -j$(nproc)
make install
3.3 启动fuzz
afl-fuzz -i $HOME/fuzzing_xpdf/pdf_examples/ -o $HOME/fuzzing_xpdf/out/ -s 123 -- $HOME/fuzzing_xpdf/install/bin/pdftotext @@ $HOME/fuzzing_xpdf/output
3.4 代码覆盖率检测
原文:
https://github.com/antonio-morales/Fuzzing101/tree/main/Exercise 4
这里摘抄出命令部分方便快速使用
代码覆盖率
代码覆盖率是一种软件指标,用于显示每行代码被触发的次数。通过使用代码覆盖率,我们将了解模糊器已经到达代码的哪些部分,并可视化模糊测试过程。
首先,我们需要安装 lcov。我们可以使用以下命令来完成:
sudo apt install lcov
现在我们需要使用标志(编译器和链接器)重建 libTIFF:--coverage
<your_install_pwd>替换为你的安装目录
rm -r 源码目录/install
cd 源码目录
make clean
CFLAGS="--coverage" LDFLAGS="--coverage" ./configure --prefix="<your_install_pwd>" --disable-shared
make
make install
然后,我们可以通过键入以下内容来收集代码覆盖率数据:
cd 源码目录
lcov --zerocounters --directory ./
lcov --capture --initial --directory ./ --output-file app.info
#运行要分析的应用程序,按照具体命令来执行
$HOME/fuzzing_tiff/install/bin/tiffinfo -D -j -c -r -s -w $HOME/fuzzing_tiff/tiff-4.0.4/test/images/palette-1c-1b.tiff
lcov --no-checksum --directory ./ --capture --output-file app2.info
主要用法是:fuzz跑出来一些崩溃样本后,挨个运行看其代码覆盖率。
3.5 输入字典
在某些拥有特定结构的文件下(例如<html></html>),预定义一些可以嵌入的标签可以大幅增加进入其他分支的能力
使用字典时候,加入-x <dict_path>参数
常用字典:https://github.com/AFLplusplus/AFLplusplus/tree/stable/dictionaries
3.6 多个行程一起跑
可以利用多核cpu能力,一般来说主线程使用-M master,从线程使用-S slave1,同时设置每个线程不同的种子-s 123 \ -s 456 来获取最大效果
3.7 fuzz持久化模式
在主循环或关键函数插入:
#ifdef __AFL_COMPILER
__AFL_INIT();
while (AFL_LOOP(1000)) {
// do_some();
}
exit(0);
#else
// do_some();
#endif
四、一些感念
虽然说概念又多又杂,但是还是要理解一些非常重要的,至少知道怎么去问ai
4.1 ./configure
./configure 在很多老一点的 C/C++ 项目里都能见到,它是 GNU Autotools 构建系统的一个核心产物。
./configure是什么?
-
它是一个 自动生成的脚本(通常由
autoconf工具生成),主要功能是:- 检查你当前的系统环境(操作系统、CPU 架构、库、编译器、头文件等)。
- 根据环境条件,生成适合本机的
Makefile(或者其他构建配置文件)。
- 为什么要设置一堆参数?
-
在跑
./configure --prefix=... --disable-shared时,就是在告诉它 安装方式和编译选项。 -
常见参数有:
--prefix=DIR
指定最终安装位置(默认是/usr/local,可以改到$HOME/install)。--disable-shared
不编译动态库,只编译静态库。--enable-XXX / --disable-XXX
打开/关闭某些功能模块。CC=clang ./configure
指定用哪个编译器。
这些选项能让用户根据需求定制编译结果。
4.2 config.guess 和 config.sub
4.2.1. config.guess
-
作用:尝试“猜测”当前机器的体系结构和操作系统。
-
输出:一个标准化的三元组(或四元组),表示编译目标。
-
格式:
<CPU>-<VENDOR>-<OS> -
例子:
x86_64-pc-linux-gnuaarch64-unknown-linux-gnuarm-apple-darwin
-
原理:config.guess 会调用 uname -m, uname -s, uname -r 等命令,结合一些规则来拼出一个符合 GNU 规范的“目标平台名字”。
4.2.2. config.sub
- 作用:把
config.guess的输出(或用户手动传给./configure --host=... --build=...的字符串)规范化,检查它是否合法,并展开成标准形式。

浙公网安备 33010602011771号