dyninst是一个纯二进制插桩工具,只需可执行文件即可插桩用于fuzz过程中检测覆盖率
注意: 由于dyninst插桩对二进制文件改动较大,很有可能导致插桩后的二进制程序无法执行

0x1 安装Dyninst

获取源码

1
git clone https://github.com/dyninst/dyninst

安装依赖

1
2
sudo apt-get update
sudo apt-get install cmake libblkid-dev e2fslibs-dev libboost-all-dev libaudit-dev libelf-dev libdwarf-dev libiberty-dev

编译配置

1
2
3
4
5
6
7
8
9
10
cd dyninst
mkdir build
mkdir target # 存储编译出的文件

cd build
cmake .. -DBOOST_LIBRARYDIR=/usr/lib/x86_64-linux-gnu -DCMAKE_INSTALL_PREFIX=../target -DLIBELF_LIBRARIES=/usr/local/lib/libelf.so -DLIBELF_INCLUDE_DIR=/usr/local/include

# 安装
make -j8
make install

0x2 安装AFL++(可选,用AFL也可以)

具体可见 https://github.com/AFLplusplus/AFLplusplus/blob/stable/docs/INSTALL.md

1
2
3
4
5
6
sudo apt-get install -y build-essential python3-dev automake cmake git flex bison libglib2.0-dev libpixman-1-dev python3-setuptools cargo libgtk-3-dev
sudo apt-get install -y ninja-build # for QEMU mode
git clone https://github.com/AFLplusplus/AFLplusplus
cd AFLplusplus
make distrib
sudo make install

0x3 安装AFL-Dyninst

获取源码

1
2
git clone https://github.com/vanhauser-thc/afl-dyninst
cd afl-dyninst

修改Makefile文件

1
2
3
4
5
6
7
8
9
10
11
# 需修改为刚才编译dyninst中的target文件夹
DYNINST_ROOT = /your/path/to/dyninst/target

# 需修改为刚才编译dyninst中的build文件夹
DYNINST_BUILD = /your/path/to/dyninst/target/build

# EDIT: path to afl src if you do not set a symlink from ./afl to the afl directory
AFL_ROOT = /usr/fuzz_pro/AFLplusplus-blogpost/AFLplusplus

...

编译安装

1
2
make
make install

补充共享库路径

程序有可能因找不到共享库而报错,因此要设定库路径
/afl-dyninst: error while loading shared libraries: libdyninstAPI.so.12.3: cannot open shared object file: No such file or directory

1
2
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/your/path/to/dyninst/target/lib
ldconfig

至此即可使用

0x4 AFL-Dyninst使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
afl-dyninst (c) 2017-2021 by Aleksandar Nikolic and Marc Heuse [https://github.com/vanhauser-thc/afl-dyninst] Apache 2.0 License
Usage: ./afl-dyninst -fvxD -i <binary> -o <binary> -e <address> -E <address> -s <number> -S <funcname> -I <funcname> -m <size>
-i: input binary
-o: output binary
-r: runtime library to instrument (path to, repeat for more than one)
-e: entry point address to patch (required for stripped binaries)
-E: exit point - force exit(0) at this address (repeat for more than one)
-s: number of initial basic blocks to skip in binary
-m: minimum size of a basic bock to instrument (default: 10)
-f: fix a dyninst bug that leads to crashes (performance loss, only dyninst9)
-I: only instrument this function and nothing else (repeat for more than one)
-S: do not instrument this function (repeat for more than one)
-D: instrument only a simple fork server and also forced exit functions
-x: experimental performance mode (~25-50% speed improvement)
-v: verbose output
Note: options -l and -d have been deprecated, use -r and -D instead.

二进制插桩

Dyninst 需要令 DYNINSTAPI_RT_LIB 环境变量指向libdyninstAPI_RT.so

1
2
3
4
5
export DYNINSTAPI_RT_LIB=/usr/local/lib/libdyninstAPI_RT.so
afl-dyninst -i bin -o bin_ins ([-e 程序入口] [-m 插桩的最小基本块大小] [-e 效率实验模式])

# 或直接执行
./afl-dyninst.sh -i bin -o bin_ins

fuzz

由于AFL会检查二进制程序是否有通过afl-gcc插桩过, 我们需要将环境变量AFL_SKIP_BIN_CHECK设为1

1
$ export AFL_SKIP_BIN_CHECK=1

这里就和正常的afl-fuzz一样了

1
afl-dyninst -i in_afl -o ou_afl -- ./bin_ins @@
⬆︎TOP