AFLGo环境搭建

AFLGo搭建及使用

2017年,Directed fuzzing这个概念在 B¨ohme等人的论文 Directed Greybox Fuzzing 中第一次被提出,文章开源了一个名为 AFLGo 的工具,是在 AFL 的基础上,实现了一个可以快速到达指定目标点的模糊测试工具。后续出现的 Directed fuzzing,基本都无法完全脱离 AFLGo 的方法,可以说,AFLGo 开创了导向型模糊测试的先河。

环境搭建

为了方便各种编译环境的管理,这里使用docker搭建

aflgo/aflgo: Directed Greybox Fuzzing with AFL (github.com)

根据官方文档,使用ubuntu20.04的镜像进行搭建

sudo docker pull ubuntu:20.04

拉取完成后,构建容器

sudo docker run -it --privileged --name aflgo [image id]

需要加上 --privileged参数,否则执行fuzzing时会失败。

因为在执行 afl-fuzz前,如果系统配置为将核心转储文件(core)通知发送到外部程序,将导致将崩溃信息发送到Fuzzer之间的延迟增大,进而可能将崩溃被误报为超时。所以得临时修改 core_pattern文件:

echo core > /proc/sys/kernel/core_pattern

如果没有加上 --privileged参数,会报错:

bash: /proc/sys/kernel/core_pattern: Read-only file system

大约在0.6版,privileged被引入docker。使用该参数,container内的root拥有真正的root权限。否则,container内的root只是外部的一个普通用户权限。
使用privileged启动的容器,可以看到很多host上的设备,并且可以执行mount。甚至允许你在docker容器中启动docker容器。引自

这个容器只提供了最基本的ubuntu运行环境,一些使用到的工具需要进行手动安装,比如vim,git等等,需要先使用 apt update更新一下软件包,然后再安装软件。

尽量在宿主机设置外网代理避免因网络问题安装失败。

进入到容器里的home下,直接使用脚本安装aflgo,export是临时环境变量,每次fuzzing前需要进行设置。

git clone https://github.com/aflgo/aflgo.git
cd aflgo
export AFLGO=$PWD

# Build AFLGo
sudo ./build.sh

# When you fuzz for the very first time...
sudo sh -c 'echo core > /proc/sys/kernel/core_pattern'

漫长的等待后安装成功!

使用--以libxml2为例

aflgo给了几个模糊测试样例,都在examples目录下,直接执行里面的脚本文件即可运行。

这里以libxml2为例(也是官网的默认示例),详细的跟进每个步骤。

下载libxml2项目

# Clone subject repository
git clone https://gitlab.gnome.org/GNOME/libxml2
export SUBJECT=$PWD/libxml2

设置fuzzing目标

设置要进行fuzzing的目标,即设置要进行fuzzing的函数或代码行,这里以libxml2的ef709ce2这次变更点为fuzzing目标。

这次提交应该是修复了一个空指针引起的bug,更改详情查看上面的链接。

由于目标点是通过项目提交记录获取的,所以这里使用了而外的辅助工具,目标点根据需求自定义,所以下面的步骤并不是通用的。

# Setup directory containing all temporary files
mkdir temp
export TMP_DIR=$PWD/temp

# Download commit-analysis tool
wget https://raw.githubusercontent.com/jay/showlinenum/develop/showlinenum.awk
chmod +x showlinenum.awk
mv showlinenum.awk $TMP_DIR

# Generate BBtargets from commit ef709ce2
pushd $SUBJECT
  git checkout ef709ce2
  git diff -U0 HEAD^ HEAD > $TMP_DIR/commit.diff
popd
cat $TMP_DIR/commit.diff |  $TMP_DIR/showlinenum.awk show_header=0 path=1 | grep -e "\.[ch]:[0-9]*:+" -e "\.cpp:[0-9]*:+" -e "\.cc:[0-9]*:+" | cut -d+ -f1 | rev | cut -c2- | rev > $TMP_DIR/BBtargets.txt

# Print extracted targets. 
echo "Targets:"
cat $TMP_DIR/BBtargets.txt

使用git将记录回溯到ef709ce2更改处,即漏洞点。

然后将更改记录提取了出来。

设置fuzzing目标,格式为 代码文件:代码行

到这一步,关于BBtargets.txt文件我们完全可以自己手动写入需要进行fuzzing的点。

生成函数调用图和控制流图

# Set aflgo-instrumenter
export CC=$AFLGO/instrument/aflgo-clang
export CXX=$AFLGO/instrument/aflgo-clang++

# Set aflgo-instrumentation flags
export COPY_CFLAGS=$CFLAGS
export COPY_CXXFLAGS=$CXXFLAGS
export ADDITIONAL="-targets=$TMP_DIR/BBtargets.txt -outdir=$TMP_DIR -flto -fuse-ld=gold -Wl,-plugin-opt=save-temps"
export CFLAGS="$CFLAGS $ADDITIONAL"
export CXXFLAGS="$CXXFLAGS $ADDITIONAL"

# Build libxml2 (in order to generate CG and CFGs).
# Meanwhile go have a coffee ☕️
export LDFLAGS=-lpthread
pushd $SUBJECT
  ./autogen.sh
  ./configure --disable-shared
  make clean
  make xmllint
popd

这里第一次编译软件源代码是为了获取函数调用图和控制流图,为后面计算距离做准备。

$SUBJECT/xmllint --valid --recover $SUBJECT/test/dtd3
ls $TMP_DIR/dot-files
echo "Function targets"
cat $TMP_DIR/Ftargets.txt

验证编译成功。

距离计算

先清理代码块文件和函数调用块文件,其实就是清理插桩点,以便后面计算插桩点到fuzzing目标的距离。

# Clean up
cat $TMP_DIR/BBnames.txt | grep -v "^$"| rev | cut -d: -f2- | rev | sort | uniq > $TMP_DIR/BBnames2.txt && mv $TMP_DIR/BBnames2.txt $TMP_DIR/BBnames.txt

cat $TMP_DIR/BBcalls.txt | grep -Ev "^[^,]*$|^([^,]*,){2,}[^,]*$"| sort | uniq > $TMP_DIR/BBcalls2.txt && mv $TMP_DIR/BBcalls2.txt $TMP_DIR/BBcalls.txt

开始距离计算。

# Generate distance ☕️
# $AFLGO/distance/gen_distance_orig.sh is the original, but significantly slower, version

$AFLGO/distance/gen_distance_fast.py $SUBJECT $TMP_DIR xmllint

已经成功生成了对应的文件。

重新构建项目

加入距离信息后重新编译fuzzing对象。

export CFLAGS="$COPY_CFLAGS -distance=$TMP_DIR/distance.cfg.txt"
export CXXFLAGS="$COPY_CXXFLAGS -distance=$TMP_DIR/distance.cfg.txt"

# Clean and build subject with distance instrumentation ☕️
pushd $SUBJECT
  make clean
  ./configure --disable-shared
  make xmllint
popd

得到插桩后的程序。

开始fuzing

# Construct seed corpus
mkdir in
cp -r $SUBJECT/test/dtd* in
cp $SUBJECT/test/dtds/* in

$AFLGO/afl-2.57b/afl-fuzz -S ef709ce2 -z exp -c 45m -i in -o out $SUBJECT/xmllint --valid --recover @@

将示例拷贝到temp目录下的in目录中。

提示这个输入样本执行太慢,这里我们直接删除目录下这个文件即可。

11分钟跑出了43个crashes。

posted @ 2025-01-12 23:35  略略略zjr  阅读(126)  评论(0)    收藏  举报