etc.git


etc

~ scripts and random things
git clone https://github.com/djnnvx/etc.git
log | files | refs | archive

build_fuzzers.sh (6671B)

      1 #!/bin/bash
      2 # build_fuzzers.sh — compile AFL++ in-process fuzzing harnesses.
      3 #
      4 # Assumes setup.sh has already run and usbip-src/ exists.
      5 # Can be run standalone after the initial setup to iterate on harnesses.
      6 #
      7 # Outputs: fuzz_protocol, fuzz_devlist, fuzz_urb
      8 #          + *.cmplog variants for AFL++ CmpLog mode
      9 #
     10 # Usage:
     11 #   bash build_fuzzers.sh
     12 #   bash build_fuzzers.sh --clean   # remove all binaries before rebuilding
     13 
     14 set -euo pipefail
     15 
     16 SCRIPT_DIR="$(cd "$(dirname "${0}")" && pwd)"
     17 cd "${SCRIPT_DIR}"
     18 
     19 # Add AFL++ to PATH if installed locally by setup.sh
     20 AFL_BIN="${SCRIPT_DIR}/afl-build/usr/local/bin"
     21 [[ -d "${AFL_BIN}" ]] && export PATH="${AFL_BIN}:${PATH}"
     22 
     23 CC="afl-clang-fast"
     24 USBIP_SRC="${SCRIPT_DIR}/usbip-src/src"
     25 USBIP_LIB="${SCRIPT_DIR}/usbip-src/libsrc"
     26 
     27 log()  { echo "[*] $*"; }
     28 ok()   { echo "[+] $*"; }
     29 die()  { echo "[!] $*" >&2; exit 1; }
     30 
     31 if [[ "${1:-}" == "--clean" ]]; then
     32     log "Cleaning build artifacts..."
     33     rm -f fuzz_protocol fuzz_devlist fuzz_urb fuzz_stub_client
     34     rm -f fuzz_protocol.cmplog fuzz_devlist.cmplog fuzz_urb.cmplog
     35     rm -f usbip_network.o usbip_common.o mock_syscalls.o names.o
     36     ok "Clean done."
     37 fi
     38 
     39 # ── sanity checks ─────────────────────────────────────────────────────────────
     40 command -v "${CC}" > /dev/null 2>&1 \
     41     || die "afl-clang-fast not found. Run setup.sh first (or add AFL++ to PATH)."
     42 
     43 [[ -d "${USBIP_SRC}" ]] \
     44     || die "usbip-src/src not found. Run setup.sh first."
     45 
     46 # ── ensure corpus and dict exist ─────────────────────────────────────────────
     47 [[ -d "corpus" ]] || python3 gen_corpus.py
     48 
     49 # ── common compiler flags ─────────────────────────────────────────────────────
     50 CFLAGS="-fsanitize=address,undefined -g -O1 -fno-omit-frame-pointer"
     51 CFLAGS+=" -I fuzz-include"
     52 CFLAGS+=" -I ${SCRIPT_DIR}/usbip-src"   # for config.h (HAVE_CONFIG_H / USBIP_VERSION)
     53 CFLAGS+=" -I ${USBIP_SRC}"
     54 CFLAGS+=" -I ${USBIP_LIB}"
     55 CFLAGS+=" -Wno-implicit-function-declaration"
     56 CFLAGS+=" -Wno-int-conversion"
     57 CFLAGS+=" -Wno-pointer-to-int-cast"
     58 CFLAGS+=" -Wno-incompatible-pointer-types"
     59 CFLAGS+=" -DFUZZ_BUILD -DHAVE_CONFIG_H"
     60 
     61 # glib-2.0 is needed by usbip_common.c
     62 GLIB_CFLAGS="$(pkg-config --cflags glib-2.0 2>/dev/null || echo '')"
     63 GLIB_LIBS="$(pkg-config --libs glib-2.0 2>/dev/null || echo '-lglib-2.0')"
     64 CFLAGS+=" ${GLIB_CFLAGS}"
     65 
     66 LDFLAGS="-Wl,--wrap=recv -Wl,--wrap=send -Wl,--wrap=write"
     67 LDFLAGS+=" -ludev"
     68 LDFLAGS+=" ${GLIB_LIBS}"
     69 
     70 # ── Step 1: compile shared usbip objects ─────────────────────────────────────
     71 log "Compiling usbip_network.o..."
     72 ${CC} ${CFLAGS} -c "${USBIP_SRC}/usbip_network.c" -o usbip_network.o
     73 
     74 log "Compiling usbip_common.o..."
     75 ${CC} ${CFLAGS} -c "${USBIP_LIB}/usbip_common.c" -o usbip_common.o 2>/dev/null || \
     76     ${CC} ${CFLAGS} -c "${USBIP_SRC}/usbip_common.c" -o usbip_common.o
     77 
     78 log "Compiling mock_syscalls.o..."
     79 ${CC} ${CFLAGS} -c mock_syscalls.c -o mock_syscalls.o
     80 
     81 log "Compiling names.o..."
     82 ${CC} ${CFLAGS} -c "${USBIP_LIB}/names.c" -o names.o
     83 
     84 COMMON_OBJS="usbip_network.o usbip_common.o mock_syscalls.o names.o"
     85 
     86 # ── Step 2: build each in-process harness (standard + CmpLog) ────────────────
     87 
     88 build_harness() {
     89     local name="$1"
     90     local src="$2"
     91 
     92     log "Building ${name}..."
     93     ${CC} ${CFLAGS} ${src} ${COMMON_OBJS} ${LDFLAGS} -o "${name}"
     94 
     95     log "Building ${name}.cmplog (CmpLog variant)..."
     96     AFL_LLVM_CMPLOG=1 ${CC} ${CFLAGS} ${src} ${COMMON_OBJS} ${LDFLAGS} -o "${name}.cmplog"
     97 
     98     ok "  ${name}  ${name}.cmplog"
     99 }
    100 
    101 build_harness fuzz_protocol fuzz_protocol.c
    102 build_harness fuzz_devlist  fuzz_devlist.c
    103 build_harness fuzz_urb      fuzz_urb.c
    104 
    105 # fuzz_stub_client: malicious USB-IP client targeting usbipd stub_rx.c
    106 # No ASAN / usbip library linkage — connects over TCP to the QEMU VM.
    107 if [[ ! -f "fuzz_stub_client" ]] || [[ "fuzz_stub_client.c" -nt "fuzz_stub_client" ]]; then
    108     log "Building fuzz_stub_client (malicious client targeting stub_rx.c)..."
    109     ${CC} -O2 -o fuzz_stub_client fuzz_stub_client.c
    110     ok "  fuzz_stub_client"
    111 fi
    112 
    113 # ── Step 3: build QEMU-mode network tools ─────────────────────────────────────
    114 # net_send: blind TCP relay (original QEMU mode — server side)
    115 if [[ ! -f "net_send" ]] || [[ "net_send.c" -nt "net_send" ]]; then
    116     log "Building net_send (blind TCP relay for QEMU server-side mode)..."
    117     ${CC} -O2 -o net_send net_send.c
    118     ok "  net_send"
    119 fi
    120 
    121 # fuzz_vhci_server: two-sided fuzzer targeting vhci-hcd in QEMU client mode
    122 if [[ ! -f "fuzz_vhci_server" ]] || [[ "fuzz_vhci_server.c" -nt "fuzz_vhci_server" ]]; then
    123     log "Building fuzz_vhci_server (two-sided server targeting vhci-hcd)..."
    124     ${CC} -O2 -o fuzz_vhci_server fuzz_vhci_server.c
    125     ok "  fuzz_vhci_server"
    126 fi
    127 
    128 # ── Step 4: build KCOV shim (for kernel coverage feedback) ───────────────────
    129 # kcov_shim runs INSIDE the QEMU VM. Cross-compile or build on the guest.
    130 # Here we build a host-native version for testing; deploy to VM initramfs manually.
    131 if [[ ! -f "kcov_shim" ]] || [[ "kcov_shim.c" -nt "kcov_shim" ]]; then
    132     log "Building kcov_shim (KCOV coverage shim — deploy inside QEMU VM)..."
    133     gcc -O2 -static -o kcov_shim kcov_shim.c 2>/dev/null || \
    134         gcc -O2 -o kcov_shim kcov_shim.c && \
    135         ok "  kcov_shim (dynamic — static build failed, ensure libc is in VM)" || \
    136         echo "[!] kcov_shim build failed (needs kernel KCOV headers) — skip for now"
    137 fi
    138 
    139 # ── Done ─────────────────────────────────────────────────────────────────────
    140 echo ""
    141 ok "All harnesses built:"
    142 ls -lh fuzz_protocol fuzz_devlist fuzz_urb fuzz_vhci_server fuzz_stub_client 2>/dev/null
    143 echo ""
    144 echo "  Quick smoke test:"
    145 echo "    ./fuzz_protocol corpus/op_common_req_devlist"
    146 echo "    ./fuzz_urb      corpus/urb_submit_64b"
    147 echo ""
    148 echo "  In-process (no VM):    bash run-fuzzers.sh"
    149 echo "  QEMU vhci (two-sided): afl-fuzz -S vhci  -i corpus/vhci -o output -t 5000 -- ./fuzz_vhci_server @@ 0.0.0.0 13241"
    150 echo "  QEMU stub (client):    afl-fuzz -S stub  -i corpus/stub -o output -t 5000 -- ./fuzz_stub_client @@ <vm-ip> 3240"