Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
target
external/GitAflplusplus
targets
**/fuzzing_campaigns*
.idea
.vscode
**/inputs
**/traces
**/traces
**/binutils-gdb
**/saved_corpus*
56 changes: 14 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,22 @@ This repository contains the source code of the tool, **SeedUI: Understanding In
A demonstration of SeedUI is available in [YouTube](https://youtu.be/qpPjutmIcTs).

- SeedUI requires some [pre-requisites](#pre-requisites) to be installed in your system.
- To skip running AFL++ and gathering fuzzing corpus, you can directly follow the [quick instructions](#seedui-in-action-short) which uses saved corpus in the `examples` directory.
- If you would like to know the complete sequence of steps that can work on any target that can be fuzzed using AFL++, you can follow the [complete instructions](#seedui-in-action-long).
- To skip running fuzzing campaigns and gathering fuzzing corpus, you can directly follow the [quick instructions](#seedui-in-action-short) which uses saved corpus in the `examples` directory.
- If you would like to know the complete sequence of steps that can work on any target that can be fuzzed using AFL++ or Honggfuzz, you can follow the [complete instructions](#seedui-in-action-long).

## Pre-requisites:
- [Rust](https://www.rust-lang.org/tools/install)
- [AflPlusPlus](https://github.com/AFLplusplus/AFLplusplus) compiled after applying `external/rename_seeds.patch`.
- [AflPlusPlus](https://github.com/AFLplusplus/AFLplusplus) compiled after applying `external/rename_seeds_afl.patch`.

[or]

[Honggfuzz](https://github.com/google/honggfuzz.git) compiled after applying `external/rename_seeds_honggfuzz.patch`
- [LLVM](https://github.com/llvm/llvm-project) >= 14.0.6
- [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)

## SeedUI in action (short)
In general, a corpus should be extracted from AFL++ fuzzing campaigns (more information in [run-afl](#1-run-afl-fuzzing-campaign)).
However, to quickly look at SeedUI, we provide a fuzzing corpora that is extracted from two fuzzing campaigns of 5 minutes on `readelf`.
In general, a corpus should be extracted from fuzzing campaigns (more information in [run-fuzzers](#1-run-fuzzing-campaigns)).
However, to quickly look at SeedUI, we provide a fuzzing corpora that is extracted from 5 minutes fuzzing campaigns of AFL++ and Honggfuzz on `readelf`.
We will use this saved corpus in the following steps.

There are three steps to run SeedUI, as follows:
Expand All @@ -40,7 +44,6 @@ There are three steps to run SeedUI, as follows:
cd examples/readelf/
unzip saved_corpus.zip

mkdir traces
python3 extract_binary_traces.py
```

Expand All @@ -54,7 +57,7 @@ There are three steps to run SeedUI, as follows:
[or]

cd server
cargo run -r --package server --bin server ../targets/config_ncurses_multiple_allowlist.ron
cargo run -r --package server --bin server ../examples/readelf.ron
```

### 3. Client
Expand All @@ -71,46 +74,15 @@ There are three steps to run SeedUI, as follows:
## SeedUI in action (long)

There are four steps to run SeedUI, as follows:
1. [Run AFL++ fuzzing campaign(s) on a target](#1-run-afl-fuzzing-campaign)
1. [Run fuzzing campaign(s) on a target](#1-run-fuzzing-campaigns)
2. [Extract `drcov` traces for each of the seed saved in the corpus](#2-extract-line-coverage)
3. [Start SeedUI server](#3-server)
4. [Start SeedUI web client](#4-client)

### 1. Run AFL++ fuzzing campaign
### 1. Run fuzzing campaigns

SeedUI works on the output directory generated by AFL++.
After running the fuzzing campaign make sure you persist the `afl-out` directory.
In the following we explain the general knowledge of running AFL++ on a target.
We use `readelf` from `binutils-gdb` as a target.

#### AFL++ on readelf
We have provided some example scripts for fuzzing `readelf` in the `examples` directory.
We recommend running the fuzzing campaign in a docker container using the following commands:
- Build the docker image (from the root directory of the repository):
`docker build -t readelf_seed_ui -f examples/readelf/docker/Dockerfile.readelf .`
- Start two docker containers in background one for each fuzzing run:
```
cd examples/readelf
docker-compose up -d
```
- Fuzz `readelf` for desired amount of time. Our example script `examples/readelf/docker/readelf.sh` timeouts after 5 minutes (you can edit the value for -V command line argument in line 22 and provide the desired amount of time in seconds).
```
# First fuzzing campaign
docker exec -it readelf_example_1 /bin/bash /home/readelf.sh /home/seeds/cmin-seeds-1
# Second fuzzing campaign
docker exec -it readelf_example_2 /bin/bash /home/readelf.sh /home/seeds/cmin-seeds-2
```
- Copy the generated corpus into host machines:
```
cd examples/readelf
mkdir inputs
docker cp readelf_example_1:/home/binutils-gdb/obj-afl/afl-out inputs/readelf_1
docker cp readelf_example_2:/home/binutils-gdb/obj-afl/afl-out inputs/readelf_2
```
- Stop the docker containers:
```
docker-compose down
```
- Please refer to [Afl++ documentation](./docs/aflplusplus.md) for instructions to run AFL++.
- Please refer to [Honggfuzz documentation](./docs/honggfuzz.md) for instructions to run Honggfuzz.

### 2. Extract line coverage
- Compile AFL++ in your local machine. SeedUI uses `afl-qemu-trace` to extract `drcov` trace information. You can use our handy script in the `external` directory for this purpose or use the instructions mentioned in [AFL++ Wiki]((https://github.com/AFLplusplus/AFLplusplus/tree/stable/qemu_mode#12-coverage-information)).
Expand Down
31 changes: 31 additions & 0 deletions docs/aflplusplus.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
## SeedUI with AFL++

SeedUI expects the file names of the seeds generated during a fuzzing campaign contains a unique identifier, generated time, and its parent information.
As part of this repository, we provided a patch file, in `external/rename_seeds_afl.patch`, that modifies AFL++ source code to provide this information.
You need to apply this patch to AFL++ before running the fuzzing campaign.
We provided a utility shell script, `external/compile_aflpp.sh`, for this purpose.

SeedUI works on the output directory generated by AFL++.
After running the fuzzing campaign make sure you persist the `afl-out` directory.
In the following we explain the general knowledge of running AFL++ on a target.
We use `readelf` from `binutils-gdb` as a target.

### AFL++ on readelf
We have provided some example scripts for fuzzing `readelf` in the `examples` directory.
We recommend running the fuzzing campaign in a docker container using the following commands:
- Build the docker image (from the root directory of the repository):
`docker build -t readelf_seed_ui -f examples/readelf/docker/Dockerfile.readelf .`
- Start a docker container and run fuzzing campaigns in background:
```
cd examples/readelf
docker-compose up -d
```
We have configured the default timeout of 5 minutes. One can change it to the desired timeout by updating the last command line parameter to the `readelf_afl.sh` script in `examples/readelf/docker-compose.yaml` file.
- After the fuzzing campaign, the generated corpus for the fuzzing run can be found in the `examples/readelf/saved_corpus`. You may need to modify the folder permissions to access the files using the following command,
```
sudo chmod -R 775 saved_corpus/*
```
- Stop the docker containers:
```
docker-compose down
```
40 changes: 40 additions & 0 deletions docs/honggfuzz.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
## SeedUI with Honggfuzz

### Run Honggfuzz inside Docker
In the following we explain the general knowledge of running Honggfuzz on a target.
We use `readelf` from `binutils-gdb` as a target.

We have provided some example scripts for fuzzing `readelf` in the `examples` directory.
We recommend running the fuzzing campaign in a docker container using the following commands:
- The same docker image as AFL++ can be used as it also builds Honggfuzz. For convinience, we provide the docker build command here again:
`docker build -t readelf_seed_ui -f examples/readelf/docker/Dockerfile.readelf .`
- Start a docker container and run fuzzing campaigns in background:
```
cd examples/readelf
docker-compose up -d
```
We have configured the default timeout of 5 minutes. One can change it to the desired timeout by updating the last command line parameter to the `readelf_hfuzz.sh` script in `examples/readelf/docker-compose.yaml` file.
We have also configured the command to run `external/post_process_honggfuzz_inputs.py` script after the fuzzing campaign. So, you don't need to run it again.
- After the fuzzing campaign, the generated corpus for each run can be found in the `examples/readelf/saved_corpus`. You may need to modify the folder permissions to access the files using the following command,
```
sudo chmod -R 775 saved_corpus/*
```
- Stop the docker containers:
```
docker-compose down
```
### Run Honggfuzz locally
SeedUI expects the file names of the seeds generated during a fuzzing campaign contains a unique identifier, generated time, and its parent information.
As part of this repository, we provided a patch file, in `external/rename_seeds_honggfuzz.patch`, that modifies Honggfuzz source code to provide the identifier and generated time for each seed.
You need to apply this patch to Honggfuzz before running the fuzzing campaign.
The parent information is logged in a file during the fuzzing campaign.
We provided another script, `external/post_process_honggfuzz_inputs.py`, that parses the log and adds the parent information to the seed filenames.
You need to run this script after the fuzzing campaign is finished as follows:
```python3
python3 post_process_honggfuzz_inputs.py --hfuzz-out=/path/to/hfuzz-out/ --hfuzz-log=/path/to/hfuzz.log --initial-seeds=/path/to/initial_seeds --output-folder=/path/to/store/renamed_seeds
```

After running the fuzzing campaign make sure you persist the `hfuzz-out` directory.
12 changes: 6 additions & 6 deletions examples/readelf.ron
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ UserConfig(
fuzzer_infos: [
(
fuzzer_configuration_id: 1,
fuzzer_configuration: "run1",
traces_directory_path: "../examples/readelf/traces/readelf_1",
inputs_directory_path: "../examples/readelf/saved_corpus/readelf_1",
fuzzer_configuration: "afl++",
traces_directory_path: "../examples/readelf/saved_corpus/afl_traces",
inputs_directory_path: "../examples/readelf/saved_corpus/afl_run/afl-out/default/queue",
),
(
fuzzer_configuration_id: 2,
fuzzer_configuration: "run2",
traces_directory_path: "../examples/readelf/traces/readelf_2",
inputs_directory_path: "../examples/readelf/saved_corpus/readelf_2",
fuzzer_configuration: "hfuzz",
traces_directory_path: "../examples/readelf/saved_corpus/hfuzz_traces",
inputs_directory_path: "../examples/readelf/saved_corpus/hfuzz_run/renamed_seeds",
)
]
)
35 changes: 30 additions & 5 deletions examples/readelf/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,36 @@
version: '3.9'

services:
example:
afl_run:
image: readelf_seed_ui
command: /bin/bash
tty: true
scale: 2
scale: 1
volumes:
- ./saved_corpus/afl_run/:/home/binutils-gdb/obj-afl
command: bash -c "
cd /home/ && bash readelf_afl.sh /home/seeds/cmin-seeds-1 300
"
ulimits:
nofile:
soft: 1000000
hard: 1000000
deploy:
resources:
limits:
cpus: "2"
memory: 2G
reservations:
cpus: "2"
memory: 2G

hfuzz_run:
image: readelf_seed_ui
volumes:
- ./saved_corpus/hfuzz_run/:/home/binutils-gdb-hfuzz/obj-hfuzz
command: bash -c "
cd /home/ && bash readelf_hfuzz.sh /home/seeds/cmin-seeds-1 300 &&
python3 post_process_honggfuzz_inputs.py --hfuzz-out=/home/binutils-gdb-hfuzz/obj-hfuzz/hfuzz-out --hfuzz-log=/home/binutils-gdb-hfuzz/obj-hfuzz/hfuzz.log --initial-seeds=/home/seeds/cmin-seeds-1 --output-folder=/home/binutils-gdb-hfuzz/obj-hfuzz/renamed_seeds
"
tty: true
scale: 1
ulimits:
nofile:
soft: 1000000
Expand Down
35 changes: 30 additions & 5 deletions examples/readelf/docker/Dockerfile.readelf
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ RUN git clone https://github.com/AFLplusplus/AFLplusplus.git GitAflplusplus; \
cd GitAflplusplus; \
git checkout b89727bea903aec80d003b6764fb53c232d33d95

COPY external/rename_seeds.patch /home/GitAflplusplus
COPY external/rename_seeds_afl.patch /home/GitAflplusplus

RUN cd GitAflplusplus; \
git apply rename_seeds.patch; \
git apply rename_seeds_afl.patch; \
make

# AFL++ settings
Expand All @@ -56,10 +56,22 @@ ENV AFL_NO_UI=1
# ENV AFL_QUIET=1
ENV AFL_LLVM_INSTRUMENT=CLASSIC

RUN apt-get update && apt-get install -y binutils-dev libblocksruntime-dev libunwind-dev

RUN git clone https://github.com/google/honggfuzz.git GitHonggfuzz; \
cd GitHonggfuzz; \
git checkout 7c495f834b3c4e25bd4d1b21239a404761bbb29c

COPY external/rename_seeds_honggfuzz.patch /home/GitHonggfuzz

RUN cd GitHonggfuzz; \
git apply rename_seeds_honggfuzz.patch; \
make

RUN apt-get update && \
apt install -y autoconf automake autotools-dev libtool libssl-dev libglib2.0-dev

RUN git clone git://sourceware.org/git/binutils-gdb.git
RUN git clone --depth 1 -b binutils-2_45 https://github.com/bminor/binutils-gdb.git

RUN set -eux; \
cd binutils-gdb; \
Expand All @@ -68,9 +80,22 @@ RUN set -eux; \
CFLAGS="-Wno-error -DHAVE_SYS_STAT_H -DHAVE_SYS_WAIT_H -DHAVE_LIMITS_H -DHAVE_STDLIB_H -DHAVE_STRING_H -DHAVE_FCNTL_H" CC=/home/GitAflplusplus/afl-clang-fast CXX=/home/GitAflplusplus/afl-clang-fast++ ../configure --disable-shared --disable-gdb --disable-gdbserver --disable-gdbsupport --disable-libdecnumber --disable-ld --disable-gold --disable-gprof --disable-gprofng --disable-gas --disable-cpu --disable-intl --disable-libctf --disable-zlib --disable-texinfo --disable-sim --disable-readline --disable-libbacktrace; \
make clean && make

RUN git clone --depth 1 -b binutils-2_45 https://github.com/bminor/binutils-gdb.git binutils-gdb-hfuzz

RUN apt-get install -y libc++-dev

RUN set -eux; \
cd binutils-gdb-hfuzz; \
mkdir build; \
cd build && \
CFLAGS="-Wno-error -DHAVE_SYS_STAT_H -DHAVE_SYS_WAIT_H -DHAVE_LIMITS_H -DHAVE_STDLIB_H -DHAVE_STRING_H -DHAVE_FCNTL_H" CC=/home/GitHonggfuzz/hfuzz_cc/hfuzz-clang CXX=/home/GitHonggfuzz/hfuzz_cc/hfuzz-clang++ ../configure --disable-shared --disable-gdb --disable-gdbserver --disable-gdbsupport --disable-libdecnumber --disable-ld --disable-gold --disable-gprof --disable-gprofng --disable-gas --disable-cpu --disable-intl --disable-libctf --disable-zlib --disable-texinfo --disable-sim --disable-readline --disable-libbacktrace; \
make clean && make

# Seeds taken from https://github.com/HexHive/fuzzing-seed-selection/tree/main/fuzzing/readelf/seeds
COPY examples/readelf/docker/seeds /home/seeds
COPY examples/readelf/docker/readelf.sh /home/
COPY examples/readelf/docker/readelf_afl.sh /home/
COPY examples/readelf/docker/readelf_hfuzz.sh /home/
COPY external/post_process_honggfuzz_inputs.py /home/

RUN chmod +x /home/readelf.sh
RUN chmod +x /home/readelf_afl.sh
RUN chmod +x /home/readelf_hfuzz.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ export AFL_LLVM_INSTRUMENT=CLASSIC

export DRIVER_DIR="${SUBJECT}/obj-afl"

$AFL/afl-fuzz -i "$1" -o "$DRIVER_DIR/afl-out" -V 300 -- "${SUBJECT}/build/binutils/readelf" -a @@
$AFL/afl-fuzz -i "$1" -o "$DRIVER_DIR/afl-out" -V $2 -- "${SUBJECT}/build/binutils/readelf" -a @@
15 changes: 15 additions & 0 deletions examples/readelf/docker/readelf_hfuzz.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash

cd /home

export SUBJECT="/home/binutils-gdb-hfuzz"

cd "${SUBJECT}"

rm -rf obj-hfuzz
mkdir -p obj-hfuzz

export HFUZZ="/home/GitHonggfuzz"
export DRIVER_DIR="${SUBJECT}/obj-hfuzz"

$HFUZZ/honggfuzz --logfile "$DRIVER_DIR/hfuzz.log" -i "$1" --run_time $2 -o "$DRIVER_DIR/hfuzz-out" -- "${SUBJECT}/build/binutils/readelf" -a ___FILE___
6 changes: 3 additions & 3 deletions examples/readelf/extract_binary_traces.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
QEMU_BIN = Path("../../external/GitAflplusplus/afl-qemu-trace")
QEMU_PLUGIN_DIR = Path(f"{QEMU_BIN.parent}/qemu_mode/qemuafl/build/contrib/plugins/libdrcov.so")

for item in ["readelf_1", "readelf_2"]:
INPUTS_DIR = Path(f"./saved_corpus/{item}")
TRACE_DIR = Path(f"./traces/{item}")
for item in [("./saved_corpus/afl_run/afl-out/default/queue", "./saved_corpus/afl_traces"), ("./saved_corpus/hfuzz_run/renamed_seeds", "./saved_corpus/hfuzz_traces")]:
INPUTS_DIR = Path(item[0])
TRACE_DIR = Path(item[1])
if not TRACE_DIR.exists():
os.makedirs(TRACE_DIR, exist_ok=False)

Expand Down
2 changes: 1 addition & 1 deletion examples/readelf/local/compile_binutils_debug.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

git clone git://sourceware.org/git/binutils-gdb.git
git clone --depth 1 -b binutils-2_45 https://github.com/bminor/binutils-gdb.git

set -eux; \
cd binutils-gdb; \
Expand Down
Binary file modified examples/readelf/saved_corpus.zip
Binary file not shown.
4 changes: 2 additions & 2 deletions external/compile_aflpp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
git clone https://github.com/AFLplusplus/AFLplusplus.git GitAflplusplus
cd GitAflplusplus
git checkout b89727bea903aec80d003b6764fb53c232d33d95
cp ../rename_seeds.patch .
git apply rename_seeds.patch
cp ../rename_seeds_afl.patch .
git apply rename_seeds_afl.patch

CC=clang CXX=clang++ make
cd qemu_mode
Expand Down
Loading