Skip to content

Instantly share code, notes, and snippets.

@revsic
Last active May 4, 2024 07:33
Show Gist options
  • Save revsic/c9744af518a4ea5821a9e4c71e9b8db3 to your computer and use it in GitHub Desktop.
Save revsic/c9744af518a4ea5821a9e4c71e9b8db3 to your computer and use it in GitHub Desktop.
Fuzzing101 Ex06 Tutorial
export BUILD_PATH=./build-asan
rm $BUILD_PATH/lib/gimp/2.0/plug-ins/*
afl-fuzz \
-i sample \
-o results \
-D \
-s 123 \
-t 100 \
-- $BUILD_PATH/bin/gimp-console-2.8 --verbose -d -f @@
# prerequisite
sudo apt install intltool libbabl-dev libatk1.0-dev libgtk2.0-dev
# install gegl 0.2.0
wget https://download.gimp.org/pub/gegl/0.2/gegl-0.2.0.tar.bz2
tar xvfj gegl-0.2.0.tar.bz2
pushd gegl-0.2.0
./configure --prefix=$PREFIX/build
make
make install
popd
# install gimp 2.8.16
wget https://download.gimp.org/gimp/v2.8/gimp-2.8.16.tar.bz2
tar xvfj gimp-2.8.16.tar.bz2
pushd gimp-2.8.16
CC=afl-clang-lto \
CXX=afl-clang-lto++ \
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$PREFIX/gegl-0.2.0/ \
./configure \
--prefix=$PREFIX/build \
--without-libtiff \
--without-libjpeg \
--disable-python \
--enable-gimp-console
# make clean
make -j 8
# AFL_USE_ASAN=1 make -j 8
make install
import json
import os
import re
import subprocess
from time import time
from uuid import uuid4
from tqdm import tqdm
_binary = "./build-asan/bin/gimp-console-2.8"
_base = [
"./results",
]
_base = [os.path.join(p, "default/crashes") for p in _base]
_dump = "./dump"
TIMEOUT = 10
parsed = {}
os.makedirs(_dump, exist_ok=True)
with tqdm(_base) as pbar:
for mother in pbar:
with open(os.path.join(mother, "README.txt")) as f:
lines = f.readlines()
(line,) = (l for l in lines if l.lstrip().startswith("afl-fuzz"))
_, cmd = re.split(r"\s--\s", line.strip())
(_bin, *args) = re.split("\s+", cmd)
args = [_binary] + args
(plc,) = (i for i, arg in enumerate(args) if arg == "@@")
pbar.set_description_str(str(args))
for crash in tqdm(os.listdir(mother), leave=False):
if crash.startswith("README"):
continue
# copy
_args = [*args]
_args[plc] = os.path.join(mother, crash)
p = subprocess.Popen(
_args,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
universal_newlines=True,
)
outputs = ""
start = time()
while p.poll() is None:
if time() - start > TIMEOUT:
break
outputs += p.stdout.readline()
outputs += "#####HANGING#####"
bugs = set(re.findall(r"AddressSanitizer\:\s+(.+?)\s+", outputs))
fns = [
f"{fn}: {_file}#L{_line}"
for _, fn, _file, _line in re.findall(
r"#\d+\s+(0x[a-f0-9]+)\s+in\s+(.+?)\s+.+/([a-zA-z0-9_]+\.c)\:(\d+)\:\d+",
outputs)
]
if len(bugs) > 0:
parsed[crash] = {
"bugs": list(bugs),
"fns": fns,
}
_path = f"{_dump}/{crash}.txt"
while os.path.exists(_path):
print("conflict,", _path)
_path = f"{_dump}/{crash}_{uuid4().hex[:6]}.txt"
with open(_path, "w") as f:
f.write(outputs)
with open(f"{_dump}.json", "w") as f:
json.dump(parsed, f, indent=4)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment