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"