Case Study 2 -- Binutils
The GNU Binutils are a collection of binary tools widely used in GNU/Linux. We use this to demonstrate how to use Hakweye to fuzz with binaries with a given build script. In this case, we deal with the CVE-2016-4487 case, where the target site is according to the bug report page.
- Get Binutils-2.26 source code
mkdir 4487
export INFO_DIR=$PWD/4487
wget https://ftp.gnu.org/gnu/binutils/binutils-2.26.tar.gz && tar xf binutils-2.26.tar.gz
export SRC_DIR=$PWD/binutils-2.26
- Prepare "llvm.toml" and "tgt_lines.in" in
$INFO_DIR
:
# llvm.toml
[tgt]
infile = "tgt_lines.in"
out_dir = "."
[ins]
proj_name = "binutils-4487"
dist_file = "bb.dist"
# tgt_lines.in
/home/hawkeye/test-ccs/binutils-2.26/libiberty/cplus-dem.c:4300
- Preprocessing with he-pp
cd $SRC_DIR
export CFLAGS="-Wno-error -g $HE_FLAGS"
export CXXFLAGS="-Wno-error -g $HE_FLAGS"
export LDFLAGS="-ldl"
../configure --disable-shared --disable-werror --prefix=$PWD/install
make -j
There will be an LLVM Bitcode file "cxxfilt.0.0.preopt.bc".
- Analyze the bitcode with "libhe-tgt.so"
cp cxxfilt.0.0.preopt.bc $INFO_DIR
cd $INFO_DIR
opt-6.0 -mem2reg -load /usr/local/lib/hawkeye/libhe-tgt.so -he-conf ./llvm.toml -he-analyze ./cxxfilt.0.0.preopt.bc -o /dev/null
- Generate distances:
he-dists -b ./cxxfilt.0.0.preopt.bc -i $PWD
- Compile and Instrument
export HE_FLAGS="-he-conf=$INFO_DIR/llvm.toml"
cd $SRC_DIR
make clean
export CFLAGS="-Wno-error -g $HE_FLAGS"
export CXXFLAGS="-Wno-error -g $HE_FLAGS"
export LDFLAGS="-ldl"
../configure --disable-shared --disable-werror --prefix=$PWD/install
make
- Map function traces:
cd $INFO_DIR
he-funcs extract -p binutils-4487
he-funcs score -d funcs.dist -m funcs.txt -p proj_trace_funcs.json -o trace_funcs.json
- Specify configuration for fuzzing:
[io]
in_folder = "in"
out_folder = "out"
[exec]
use_forkserver = true
mem_limit = 200
timeout = 50
qemu_mode = false
[exec.sa]
trace_func_file = "trace_funcs.json"
callgraph_file = "callgraph.yaml"
tgt_func_file = "tgt_funcs.txt"
[record]
proj_name = "binutils-4487"
interval = 2000
url = "redis://127.0.0.1/"
log_entry_info = false
[calibration]
# for simple regular case calibration
normal_cycles = 7
# for variable behaviors calibration
var_behavior_cycles = 37
[minimize]
ck_redundant_file = false
[mutation]
# ops = ["det", "dict", "havoc", "splice"]
# ops = ["havoc", "splice", "sem"]
max_file_length = 128
#dict_folder = "dicts_test"
dict_level = 0
# max_token_length: 64
# min_token_length: 2
# max_dict_size: 256
# in minutes
havoc_adjust_duration = 12
[fz]
workers = 1
bind_cpu = false
# "normal"/"crash"
keep_mode = "normal"
# "simple"/...
scorer = "simple"
exit_nonzero_as_crash = false
ignored_signals = []
[fz.conductor]
# in minutes
report_duration = 3
[fz.sync]
duration = 200
execs = 5
- Run the fuzzer:
mkdir in
echo "" > in/file
he-fuzz -c ./Config.toml -- $SRC_DIR/binutils/cxxfilt
# cxxfilt accepts input from stdin