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/

image

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

image
如果遇到docker已损坏,尝试以下办法

  1. 输入密码并回车,然后重新打开 系统设置 -> 安全性与隐私,选择“任何来源”。
sudo spctl --master-disable
  1. 允许运行
sudo xattr -r -d com.apple.quarantine /Applications/docker.app

1.2 docker镜像拉取

  1. 拉取镜像(仅需做一次,之后不用做)。
    docker pull aflplusplus/aflplusplus:latest
    
    如果拉取失败检查是否***上网环境。

1.2.1 如果拉不到架构

image

方法一:模拟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架构发愁

方法二:使用旧版本号(推荐)
image

https://hub.docker.com/r/aflplusplus/aflplusplus
截止2025/10/04,目前官方推出的最后支持arm的是v4.32c,拉下来就好

docker pull aflplusplus/aflplusplus:v4.32c

需要注意的是:旧容器 != 旧软件,可以在容器内更新软件包。

  1. 启动 AFLPlusPlus docker 容器:

    docker run -ti aflplusplus/aflplusplus
    

    出现这样就是成功
    image

  2. 更新软件索引

    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出错

报错大概长这样:
image

这是因为项目太老了(2008-01-08),没办法识别aarch64(arm64)架构

解决方案:

更新config.guessconfig.sub

GNUconfig.guessconfig.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 

就能看到正常识别了

image

2.3 intltool 太老了

image

直接更新即可

sudo apt update
sudo apt install intltool

2.4 清理现场

如果编译错误了,要清理现场,方法有两个

  1. 运行bash,开一个新的终端,去除手动设置的环境参数
  2. 运行:
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 构建系统的一个核心产物。

  1. ./configure 是什么?
  • 它是一个 自动生成的脚本(通常由 autoconf 工具生成),主要功能是:

    • 检查你当前的系统环境(操作系统、CPU 架构、库、编译器、头文件等)。
    • 根据环境条件,生成适合本机的 Makefile(或者其他构建配置文件)。
  1. 为什么要设置一堆参数?
  • 在跑 ./configure --prefix=... --disable-shared 时,就是在告诉它 安装方式和编译选项

  • 常见参数有:

    • --prefix=DIR
      指定最终安装位置(默认是 /usr/local,可以改到 $HOME/install)。
    • --disable-shared
      不编译动态库,只编译静态库。
    • --enable-XXX / --disable-XXX
      打开/关闭某些功能模块。
    • CC=clang ./configure
      指定用哪个编译器。

这些选项能让用户根据需求定制编译结果。

4.2 config.guessconfig.sub

4.2.1. config.guess

  • 作用:尝试“猜测”当前机器的体系结构和操作系统。

  • 输出:一个标准化的三元组(或四元组),表示编译目标。

    • 格式:<CPU>-<VENDOR>-<OS>

    • 例子:

      • x86_64-pc-linux-gnu
      • aarch64-unknown-linux-gnu
      • arm-apple-darwin

原理config.guess 会调用 uname -m, uname -s, uname -r 等命令,结合一些规则来拼出一个符合 GNU 规范的“目标平台名字”。

4.2.2. config.sub

  • 作用:把 config.guess 的输出(或用户手动传给 ./configure --host=... --build=... 的字符串)规范化,检查它是否合法,并展开成标准形式。

施工中(。・ω・。)

posted @ 2025-09-20 09:41  归海言诺  阅读(42)  评论(0)    收藏  举报