Exploit Development

Week 1: Foundations and Fuzzing Basics

Day 1: Introduction to Fuzzing

# Setting up AFL++
sudo apt install build-essential gcc-13-plugin-dev cpio python3-dev libcapstone-dev pkg-config libglib2.0-dev libpixman-1-dev automake autoconf python3-pip ninja-build cmake
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 19 all
curl --proto '=https' --tlsv1.2 -sSf "https://sh.rustup.rs" | sh
mkdir soft
cd soft
git clone --branch dev --depth 1 https://github.com/AFLplusplus/AFLplusplus
cd AFLplusplus
make distrib
sudo make install
# Phase 1
cd ~/ && mkdir tuts && cd tuts
git clone --branch main --depth 1 https://github.com/alex-maleno/Fuzzing-Module.git
cd Fuzzing-Module/exercise1 && mkdir build && cd build
CC=/usr/local/bin/afl-clang-fast CXX=/usr/local/bin/afl-clang-fast++ cmake ..
make && cd ../ && mkdir seeds && cd seeds && for i in {0..4}; do dd if=/dev/urandom of=seed_$i bs=64 count=10; done && cd ../build
afl-fuzz -i /home/dev/tuts/Fuzzing-Module/exercise1/seeds/ -o out -m none -d -- /home/dev/tuts/Fuzzing-Module/exercise1/build/simple_crash
# Phase 2
cd /home/dev/tuts/Fuzzing-Module/exercise2 && mkdir build && cd build
CC=/usr/local/bin/afl-clang-lto CXX=/usr/local/bin/afl-clang-lto++ cmake ..
make && cd ../ && mkdir seeds && cd seeds && for i in {0..4}; do dd if=/dev/urandom of=seed_$i bs=64 count=10; done && cd ../build
afl-fuzz -i /home/dev/tuts/Fuzzing-Module/exercise2/seeds/ -o out -m none -d -- /home/dev/tuts/Fuzzing-Module/exercise2/build/medium

Day 2: Continue Fuzzing with AFL++

cd /home/dev/tuts && git clone --branch master --depth 1 https://github.com/davisking/dlib.git
cd dlib/tools/imglab && mkdir -p build && cd build && export AFL_USE_UBSAN=1 && export AFL_USE_ASAN=1
export ASAN_OPTIONS="detect_leaks=1:abort_on_error=1:allow_user_segv_handler=0:handle_abort=1:symbolize=0"
sudo apt install libx11-dev
cmake -DCMAKE_C_COMPILER=afl-clang-fast -DDLIB_NO_GUI_SUPPORT=0 -DCMAKE_CXX_COMPILER=afl-clang-fast++ -DCMAKE_CXX_FLAGS="-fsanitize=address,leak,undefined -g" -DCMAKE_C_FLAGS="-fsanitize=address,leak,undefined -g" ..
make -j8 && mkdir -p fuzz/image/in && cp /home/dev/tuts/dlib/examples/faces/testing.xml fuzz/image/in/
afl-fuzz -i fuzz/image/in -o fuzz/image/out -M Master -- ./imglab --stats @@
afl-fuzz -i fuzz/image/in -o fuzz/image/out -S Slave -- ./imglab --stats @@
sudo apt install gdb
git clone --branch master --depth 1 https://github.com/jfoote/exploitable.git ~/soft/exploitable
cd ~/soft/exploitable && sudo python3 setup.py install
wget -O ~/.gdbinit-gef.py -q https://gef.blah.cat/py && echo source ~/.gdbinit-gef.py >> ~/.gdbinit
sudo apt install valgrind
afl-collect -d crashes.db -e gdb_script -r -rr ./fuzz/image/out/Master ./afl-collect -j 8 -- ./imglab --stats @@%

Day 3: Introduction to Google FuzzTest

cd /home/dev/tuts && mkdir first_fuzz_project && cd first_fuzz_project
git clone --branch main --depth 1 https://github.com/google/fuzztest.git
cat <<EOT >> CMakeLists.txt
cmake_minimum_required(VERSION 3.19)
project(first_fuzz_project)

# GoogleTest requires at least C++17
set(CMAKE_CXX_STANDARD 17)

add_subdirectory(fuzztest)

enable_testing()

include(GoogleTest)
fuzztest_setup_fuzzing_flags()
add_executable(
  first_fuzz_test
  first_fuzz_test.cc
)

link_fuzztest(first_fuzz_test)
gtest_discover_tests(first_fuzz_test)
EOT
cat <<EOT >> first_fuzz_test.cc
#include "fuzztest/fuzztest.h"
#include "gtest/gtest.h"

TEST(MyTestSuite, OnePlustTwoIsTwoPlusOne) {
  EXPECT_EQ(1 + 2, 2 + 1);
}

void IntegerAdditionCommutes(int a, int b) {
  EXPECT_EQ(a + b, b + a);
}
FUZZ_TEST(MyTestSuite, IntegerAdditionCommutes);
EOT
mkdir build && cd build
CC=clang-18 CXX=clang++-18 cmake -DCMAKE_BUILD_TYPE=RelWithDebug -DFUZZTEST_FUZZING_MODE=on ..
sudo apt install libssl-dev
cmake --build .
./first_fuzz_test --fuzz=MyTestSuite.IntegerAdditionCommutes

Day 4: Introduction to HonggFuzz

cd /home/dev/soft && git clone --branch master --depth 1 https://github.com/google/honggfuzz.git
sudo apt-get install binutils-dev libunwind-dev libblocksruntime-dev clang
cd honggfuzz && make && sudo make install
cd /home/dev/tuts && git clone --branch master --depth=1 https://github.com/openssl/openssl.git
mv openssl openssl-master && cd openssl-master
CC=/usr/local/bin/hfuzz-clang CXX="$CC"++ ./config \
  -DPEDANTIC no-shared -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -O0 \
  -fno-sanitize=alignment -lm -ggdb -gdwarf-4 --debug -fno-omit-frame-pointer \
  enable-tls1_3 enable-weak-ssl-ciphers enable-rc5 enable-md2 \
  enable-ssl3 enable-ssl3-method enable-nextprotoneg enable-heartbeats \
  enable-aria enable-zlib enable-egd enable-msan
make -j$(nproc)
cat <<EOT >> make.sh
set -x
set -e
echo "Building honggfuzz fuzzers"
for x in x509 privkey client server; do
        hfuzz-clang -DBORINGSSL_UNSAFE_DETERMINISTIC_MODE -DBORINGSSL_UNSAFE_FUZZER_MODE -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -DBN_DEBUG -DLIBRESSL_HAS_TLS1_3 \\
        -O3 -g -DFuzzerInitialize=LLVMFuzzerInitialize -DFuzzerTestOneInput=LLVMFuzzerTestOneInput -I/home/dev/tuts/openssl-master/include \\
        -I/home/dev/soft/honggfuzz/examples/openssl -I/home/dev/soft/honggfuzz -g "/home/dev/soft/honggfuzz/examples/openssl/\$x.c" -o "libfuzzer.openssl-mastermemory.\$x" \\
        ./libssl.a ./libcrypto.a -lpthread -lz -ldl -fsanitize=\$1
done
EOT
bash make.sh memory
honggfuzz --input ~/soft/honggfuzz/examples/openssl/corpus_server/ -- ./libfuzzer.openssl-mastermemory.server
honggfuzz --input ~/soft/honggfuzz/examples/openssl/corpus_privkey/ -- ./libfuzzer.openssl-mastermemory.privkey

Day 5: Introduction to Syzkaller

sudo apt update
sudo apt install make gcc flex bison libncurses-dev libelf-dev libssl-dev
cd ~/soft && git clone --branch v6.11 --depth 1 git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git kernel
cd kernel && make defconfig && make kvm_guest.config
vim .config
# Edit these inside .config file
#CONFIG_KCOV=y
#CONFIG_DEBUG_INFO_DWARF4=y
#CONFIG_KASAN=y
#CONFIG_KASAN_INLINE=y
#CONFIG_CONFIGFS_FS=y
#CONFIG_SECURITYFS=y
#CONFIG_CMDLINE_BOOL=y
#CONFIG_CMDLINE="net.ifnames=0"
make olddefconfig && make -j`nproc`
sudo apt install debootstrap
mkdir ~/soft/image && cd ~/soft/image
wget https://raw.githubusercontent.com/google/syzkaller/master/tools/create-image.sh -O create-image.sh
chmod +x create-image.sh && ./create-image.sh --distribution trixie --feature full
sudo apt install qemu-system-x86
cd /tmp/ && sudo qemu-system-x86_64 \
	-m 2G -smp 2 -kernel ~/soft/kernel/arch/x86/boot/bzImage \
	-append "console=ttyS0 root=/dev/sda earlyprintk=serial net.ifnames=0" \
	-drive file=/home/dev/soft/image/trixie.img,format=raw \
	-net user,host=10.0.2.10,hostfwd=tcp:127.0.0.1:10021-:22 \
	-net nic,model=e1000 -enable-kvm -nographic \
	-pidfile vm.pid 2>&1 | tee vm.log
# ssh to QEMU instance in another terminal.
ssh -i ~/soft/image/trixie.id_rsa -p 10021 -o "StrictHostKeyChecking no" root@localhost
wget https://dl.google.com/go/go1.23.3.linux-amd64.tar.gz
tar -xf go1.23.3.linux-amd64.tar.gz && sudo mv go /usr/local
cd ~/soft/ && git clone --branch master --depth 1 https://github.com/google/syzkaller
cd syzkaller && export PATH=$PATH:/usr/local/go/bin && make
cat <<EOT >> my.cfg
{
	"target": "linux/amd64",
	"http": "127.0.0.1:56741",
	"workdir": "/home/dev/soft/syzkaller/workdir",
	"kernel_obj": "/home/dev/soft/kernel",
	"image": "/home/dev/soft/image/trixie.img",
	"sshkey": "/home/dev/soft/image/trixie.id_rsa",
	"syzkaller": "/home/dev/soft/syzkaller",
	"procs": 8,
	"type": "qemu",
	"vm": {
		"count": 4,
		"kernel": "/home/dev/soft/kernel/arch/x86/boot/bzImage",
		"cmdline": "net.ifnames=0",
		"cpu": 2,
		"mem": 2048
	}
}
EOT
mkdir workdir && sudo ./bin/syz-manager -config=/home/dev/soft/syzkaller/my.cfg
sudo apt install w3m w3m-img && w3m http://127.0.0.1:56741

Day 6: Analyzing Fuzzing Outputs

# Install required tools
sudo apt update
sudo apt install gdb python3-pip

# Install 'exploitable' GDB plugin
git clone https://github.com/jfoote/exploitable.git
cd exploitable
sudo python3 setup.py install

# Ensure AddressSanitizer is available (comes with Clang)
which clang
# If not installed, install Clang
sudo apt install clang

# Set up environment variables for AddressSanitizer
export ASAN_SYMBOLIZER_PATH=$(which llvm-symbolizer)
export ASAN_OPTIONS=symbolize=1:abort_on_error=1

# Compile a target program with AddressSanitizer
cd ~/tuts/ && git clone --branch master --depth 1 https://github.com/hardik05/Damn_Vulnerable_C_Program vuln
# change int main(char *argv,int argc) to int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
# use size instead of argc and data instead of argv
cd vuln && echo "IMG" > crash_input && clang -g -O1 -fsanitize=address,fuzzer -o target_asan dvcp.c

# Example: Analyze a crash using GDB and 'exploitable'
gdb -ex "run < crash_input" \
    -ex "exploitable" \
    -ex "quit" --args ./target_asan
# Script to automate crash analysis
mkdir analyzed_crashes
for crash in crash-*; do
    echo "Analyzing $crash"
    gdb -batch -ex "run < $crash" \
        -ex "exploitable" \
        --args ./target_asan &> analyzed_crashes/$(basename $crash).log
done

curl --proto '=https' --tlsv1.2 -sSf "https://sh.rustup.rs" | sh
cargo install casr
casr-san -o asan.casrep -- ./test_asan_df

# Install afl-collect if using AFL++
sudo apt install afl-utils

# Collect and deduplicate crashes
afl-collect -rr --crashdir crashes_deduped \
            --workdir afl_output -j 4 \
            -- ./target_asan @@
# Compile with UBSan
clang -g -O1 -fsanitize=undefined -o target_ubsan target.c

Day 7: Review and Recap

Week 2: Crash Analysis