Skip to content

DFSan

DataFlow Sanitizer

http://releases.llvm.org/8.0.0/tools/clang/docs/DataFlowSanitizer.html

Compiling Exiv2 with DFSan

dfsan require all functions (including C++ libraries) to be instructed, given source code or specified ABI list. This is a tiring work, thankfully Angora has paved our way, which utilize dfsan to locate which bytes are related to conditional branch. So, let’s start building in Angora container.

In the following steps, we will compile libcxx using dfsan first, then compile expat and zlib, finally we can build exiv2 with dfsan.

# run the container, this image is based on Ubuntu 16.04.6 LTS, and contain clang-7 and required abi list file.
alias d=docker
d pull zjuchenyuan/angora
d run -it --privileged -v /data:/data -w /data zjuchenyuan/angora /bin/bash

# create our ABI list file
cd /data
cat /angora/llvm_mode/build/dfsan_rt/share/dfsan_abilist.txt > mylist.txt
cat /angora/llvm_mode/dfsan_rt/abilibstdc++.txt >> mylist.txt

# download and compile libc++, ref: https://github.com/AngoraFuzzer/Angora/blob/master/llvm_mode/libcxx/compile.sh
apt install -y ninja-build

LLVM_VERSION=7.0.0
CUR_DIR=/data
CLANG_SRC=${CUR_DIR}/llvm_src

wget http://releases.llvm.org/${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.xz
wget http://releases.llvm.org/${LLVM_VERSION}/cfe-${LLVM_VERSION}.src.tar.xz
wget http://releases.llvm.org/${LLVM_VERSION}/compiler-rt-${LLVM_VERSION}.src.tar.xz
wget http://releases.llvm.org/${LLVM_VERSION}/libcxx-${LLVM_VERSION}.src.tar.xz
wget http://releases.llvm.org/${LLVM_VERSION}/libcxxabi-${LLVM_VERSION}.src.tar.xz
wget http://releases.llvm.org/${LLVM_VERSION}/libunwind-${LLVM_VERSION}.src.tar.xz
wget http://releases.llvm.org/${LLVM_VERSION}/clang-tools-extra-${LLVM_VERSION}.src.tar.xz

tar -Jxf ${CUR_DIR}/llvm-${LLVM_VERSION}.src.tar.xz 
mv llvm-${LLVM_VERSION}.src $CLANG_SRC
cd ${CLANG_SRC}/tools
tar -Jxf ${CUR_DIR}/cfe-${LLVM_VERSION}.src.tar.xz 
mv cfe-${LLVM_VERSION}.src clang
cd ${CLANG_SRC}/tools/clang/tools
tar -Jxf ${CUR_DIR}/clang-tools-extra-${LLVM_VERSION}.src.tar.xz 
mv clang-tools-extra-${LLVM_VERSION}.src extra
cd ${CLANG_SRC}/projects
tar -Jxvf ${CUR_DIR}/compiler-rt-${LLVM_VERSION}.src.tar.xz
mv compiler-rt-${LLVM_VERSION}.src compiler-rt
tar -Jxvf ${CUR_DIR}/libcxx-${LLVM_VERSION}.src.tar.xz
mv libcxx-${LLVM_VERSION}.src libcxx
tar -Jxvf ${CUR_DIR}/libcxxabi-${LLVM_VERSION}.src.tar.xz
mv libcxxabi-${LLVM_VERSION}.src libcxxabi
tar -Jxvf ${CUR_DIR}/libunwind-${LLVM_VERSION}.src.tar.xz
mv libunwind-${LLVM_VERSION}.src libunwind
cp ./libcxxabi/include/*  ./libcxx/include

mkdir -p /data/build_llvm && cd /data/build_llvm
export CC="clang -ldl -lrt -lpthread -fsanitize=dataflow -fsanitize-blacklist=/data/mylist.txt" CXX="clang++ -ldl -lrt -lpthread -fsanitize=dataflow -fsanitize-blacklist=/data/mylist.txt"
cmake -G Ninja ../llvm_src/  -DLIBCXXABI_ENABLE_SHARED=NO -DLIBCXX_ENABLE_SHARED=NO -DLIBCXX_CXX_ABI=libcxxabi
ninja cxx cxxabi

export CC="clang -L/data/build_llvm/lib -stdlib=libc++ -lc++abi -ldl -lrt -lpthread -fsanitize=dataflow -fsanitize-blacklist=/data/mylist.txt -ggdb" CXX="clang++ -L/data/build_llvm/lib -stdlib=libc++ -lc++abi -ldl -lrt -lpthread -fsanitize=dataflow -fsanitize-blacklist=/data/mylist.txt -ggdb"

# download dependency (expat and zlib) source code
cd /data
sed -i 's/# deb-src/deb-src/g' /etc/apt/sources.list
apt update
apt source zlib1g-dev libexpat1-dev

# compile expat
cd /data/expat-2.1.0
./configure --prefix=/data/expat
make install -j

# compile zlib
cd /data/zlib-1.2.8.dfsg/
./configure --prefix=/data/zlib
make install -j

# download source code
cd /data
wget http://exiv2.org/releases/exiv2-0.26-trunk.tar.gz
tar zxvf exiv2-0.26-trunk.tar.gz
cd /data/exiv2-trunk
./configure --disable-shared --with-expat=/data/expat --with-zlib=/data/zlib

# now, we get our binary file: ./bin/exiv2, about 38MB

Q&A

Why docker image zjuchenyuan/angora

Just to use already built-in clang-7, and two abi list files

Why -ldl -lrt -lpthread

It’s required for cmake cxx, otherwise build error like Host compiler appears to require libatomic, but cannot find it

Why compile expat and zlib

exiv2 depends on these two libraries, and DFSan require their source code to be compiled with DFSan.

Or, you can follow instructions here: https://github.com/AngoraFuzzer/Angora/issues/38, to create an abi list for libraries.

/angora/tools/gen_library_abilist.sh  /usr/lib/x86_64-linux-gnu/libz.so  discard >> /data/mylist.txt
/angora/tools/gen_library_abilist.sh  /usr/lib/x86_64-linux-gnu/libexpat.so  discard >> /data/mylist.txt

Why --disable-shared

This is to build a single binary file for easier fuzzing.

Wanna debug? No optimization

Compiling Exiv2 with DFSan, with -O0

# let's continue our building process, use -O0 to facilitate debugging
cd /data/exiv2-trunk
CFLAGS='-O0' CXXFLAGS='-O0' ./configure --disable-shared --with-expat=/data/expat --with-zlib=/data/zlib 
make clean; find . -name '*.o' -delete
make -j
# now we get bin/exiv2, about 44MB