etc.git


etc

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

run-fuzzers.sh (9119B)

      1 #!/bin/bash
      2 # run-fuzzers.sh — launch USB/IP fuzzing in tmux with a 2-fuzzer budget.
      3 #
      4 # Default profile (max-impact):
      5 #   Pane 1: in-process fuzz_urb (fast, high exec/sec, CmpLog-enabled)
      6 #   Pane 2: vhci kernel fuzzer (fuzz_vhci_server) against QEMU VM
      7 #
      8 # Optional profile:
      9 #   --inproc  : protocol + urb only (no QEMU)
     10 #   --stub    : fuzz_urb + stub kernel fuzzer (fuzz_stub_client) against QEMU VM
     11 #
     12 # This script intentionally keeps only two AFL++ instances active.
     13 # For vhci mode it also launches a helper QEMU window in the same tmux session.
     14 
     15 set -euo pipefail
     16 
     17 SCRIPT_DIR="$(cd "$(dirname "${0}")" && pwd)"
     18 cd "${SCRIPT_DIR}"
     19 
     20 AFL_BIN="${SCRIPT_DIR}/afl-build/usr/local/bin"
     21 [[ -d "${AFL_BIN}" ]] && export PATH="${AFL_BIN}:${PATH}"
     22 
     23 SESSION="usbip-fuzz"
     24 OUTPUT_DIR="${SCRIPT_DIR}/output"
     25 CORPUS_DIR="${SCRIPT_DIR}/corpus"
     26 CORPUS_PROTOCOL="${CORPUS_DIR}/protocol"
     27 CORPUS_URB="${CORPUS_DIR}/urb"
     28 CORPUS_VHCI="${CORPUS_DIR}/vhci"
     29 CORPUS_STUB="${CORPUS_DIR}/stub"
     30 DICT="${SCRIPT_DIR}/dictionaries/usbip.dict"
     31 TIMEOUT=1000
     32 VHCI_TIMEOUT=5000
     33 STUB_TIMEOUT=5000
     34 NICE=10
     35 PROFILE="max-impact"
     36 VMLINUX="${SCRIPT_DIR}/bzImage"
     37 VMLINUX_QEMU="${SCRIPT_DIR}/qemu/bzImage"
     38 INITRD_VHCI="${SCRIPT_DIR}/initramfs-vhci.cpio.gz"
     39 INITRD_VHCI_QEMU="${SCRIPT_DIR}/qemu/initramfs-vhci.cpio.gz"
     40 INITRD_SERVER="${SCRIPT_DIR}/initramfs.cpio.gz"
     41 INITRD_SERVER_QEMU="${SCRIPT_DIR}/qemu/initramfs.cpio.gz"
     42 
     43 log()  { echo "[*] $*"; }
     44 ok()   { echo "[+] $*"; }
     45 die()  { echo "[!] $*" >&2; exit 1; }
     46 
     47 case "${1:-}" in
     48     --status)
     49         command -v afl-whatsup > /dev/null 2>&1 && \
     50             afl-whatsup "${OUTPUT_DIR}" 2>/dev/null || \
     51             echo "Output dir: ${OUTPUT_DIR}"
     52         exit 0 ;;
     53     --rerun)
     54         tmux kill-session -t "${SESSION}" 2>/dev/null || true
     55         ;;
     56     --inproc)
     57         PROFILE="inproc"
     58         ;;
     59     --stub)
     60         PROFILE="stub"
     61         ;;
     62     --max-impact|"")
     63         ;;
     64     *) die "Unknown option: ${1}. Use --rerun, --status, --inproc, --stub, --max-impact." ;;
     65 esac
     66 
     67 command -v afl-fuzz > /dev/null 2>&1 || die "afl-fuzz not found."
     68 [[ -f "fuzz_urb" ]] || die "fuzz_urb not found. Run build_fuzzers.sh first."
     69 [[ -f "fuzz_urb.cmplog" ]] || die "fuzz_urb.cmplog not found."
     70 [[ -d "${CORPUS_URB}" ]] || die "corpus/urb/ not found. Re-run gen_corpus.py first."
     71 tmux list-sessions 2>/dev/null | grep -q "${SESSION}" && \
     72     die "Session '${SESSION}' already running. Use --rerun to restart."
     73 
     74 sudo sysctl -w kernel.core_pattern=core > /dev/null 2>&1 || true
     75 echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor > /dev/null 2>&1 || true
     76 
     77 mkdir -p "${OUTPUT_DIR}"
     78 
     79 if [[ "${PROFILE}" == "max-impact" || "${PROFILE}" == "stub" ]]; then
     80     if [[ -f "${VMLINUX}" ]]; then
     81         KERNEL_PATH="${VMLINUX}"
     82     elif [[ -f "${VMLINUX_QEMU}" ]]; then
     83         KERNEL_PATH="${VMLINUX_QEMU}"
     84     else
     85         die "Kernel image not found (expected bzImage or qemu/bzImage)."
     86     fi
     87 fi
     88 
     89 if [[ "${PROFILE}" == "max-impact" ]]; then
     90     [[ -f "fuzz_vhci_server" ]] || die "fuzz_vhci_server not found. Run build_fuzzers.sh first."
     91     [[ -d "${CORPUS_VHCI}" ]] || die "corpus/vhci/ not found. Re-run gen_corpus.py first."
     92 
     93     if [[ -f "${INITRD_VHCI}" ]]; then
     94         INITRD_PATH="${INITRD_VHCI}"
     95     elif [[ -f "${INITRD_VHCI_QEMU}" ]]; then
     96         INITRD_PATH="${INITRD_VHCI_QEMU}"
     97     else
     98         die "initramfs-vhci.cpio.gz not found. Re-run setup.sh."
     99     fi
    100 fi
    101 
    102 if [[ "${PROFILE}" == "stub" ]]; then
    103     [[ -f "fuzz_stub_client" ]] || die "fuzz_stub_client not found. Run build_fuzzers.sh first."
    104     [[ -d "${CORPUS_STUB}" ]] || die "corpus/stub/ not found. Re-run gen_corpus.py first."
    105 
    106     if [[ -f "${INITRD_SERVER}" ]]; then
    107         INITRD_PATH="${INITRD_SERVER}"
    108     elif [[ -f "${INITRD_SERVER_QEMU}" ]]; then
    109         INITRD_PATH="${INITRD_SERVER_QEMU}"
    110     else
    111         die "initramfs.cpio.gz not found. Re-run setup.sh."
    112     fi
    113 fi
    114 
    115 log "Creating tmux session '${SESSION}'..."
    116 tmux new-session -d -s "${SESSION}" -x 220 -y 50
    117 tmux split-window -h -t "${SESSION}:0"
    118 
    119 if [[ "${PROFILE}" == "inproc" ]]; then
    120     [[ -f "fuzz_protocol" ]] || die "fuzz_protocol not found. Run build_fuzzers.sh first."
    121     [[ -f "fuzz_protocol.cmplog" ]] || die "fuzz_protocol.cmplog not found."
    122     [[ -d "${CORPUS_PROTOCOL}" ]] || die "corpus/protocol/ not found. Re-run gen_corpus.py first."
    123 
    124     log "Launching AFL++ master (fuzz_protocol)..."
    125     tmux send-keys -t "${SESSION}:0.0" \
    126         "AFL_SKIP_CPUFREQ=1 AFL_AUTORESUME=1 AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 \
    127         ASAN_OPTIONS=abort_on_error=1:symbolize=0:detect_leaks=0 \
    128         nice -n ${NICE} afl-fuzz \
    129         -M master \
    130         -i ${CORPUS_PROTOCOL} \
    131         -o ${OUTPUT_DIR} \
    132         -x ${DICT} \
    133         -c ./fuzz_protocol.cmplog \
    134         -t ${TIMEOUT} \
    135         -p fast \
    136         -m none \
    137         -- ./fuzz_protocol" \
    138         Enter
    139 
    140     log "Launching AFL++ secondary (fuzz_urb)..."
    141     tmux send-keys -t "${SESSION}:0.1" \
    142         "AFL_SKIP_CPUFREQ=1 AFL_AUTORESUME=1 AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 \
    143         ASAN_OPTIONS=abort_on_error=1:symbolize=0:detect_leaks=0 \
    144         nice -n ${NICE} afl-fuzz \
    145         -S urb \
    146         -i ${CORPUS_URB} \
    147         -o ${OUTPUT_DIR} \
    148         -x ${DICT} \
    149         -t ${TIMEOUT} \
    150         -p fast \
    151         -m none \
    152         -- ./fuzz_urb" \
    153         Enter
    154 elif [[ "${PROFILE}" == "max-impact" ]]; then
    155     log "Launching AFL++ master (fuzz_urb, in-process lane)..."
    156     tmux send-keys -t "${SESSION}:0.0" \
    157         "AFL_SKIP_CPUFREQ=1 AFL_AUTORESUME=1 AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 \
    158         ASAN_OPTIONS=abort_on_error=1:symbolize=0:detect_leaks=0 \
    159         nice -n ${NICE} afl-fuzz \
    160         -M master \
    161         -i ${CORPUS_URB} \
    162         -o ${OUTPUT_DIR} \
    163         -x ${DICT} \
    164         -c ./fuzz_urb.cmplog \
    165         -t ${TIMEOUT} \
    166         -p fast \
    167         -m none \
    168         -- ./fuzz_urb" \
    169         Enter
    170 
    171     log "Launching AFL++ secondary (fuzz_vhci_server, kernel lane)..."
    172     tmux send-keys -t "${SESSION}:0.1" \
    173         "AFL_SKIP_CPUFREQ=1 AFL_AUTORESUME=1 AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 \
    174         nice -n ${NICE} afl-fuzz \
    175         -S vhci \
    176         -i ${CORPUS_VHCI} \
    177         -o ${OUTPUT_DIR} \
    178         -x ${DICT} \
    179         -t ${VHCI_TIMEOUT} \
    180         -m none \
    181         -- ./fuzz_vhci_server @@ 0.0.0.0 13241" \
    182         Enter
    183 
    184     log "Starting vhci QEMU VM window..."
    185     tmux new-window -t "${SESSION}" -n vm-vhci
    186     tmux send-keys -t "${SESSION}:vm-vhci" \
    187         "qemu-system-x86_64 \
    188         -kernel ${KERNEL_PATH} \
    189         -initrd ${INITRD_PATH} \
    190         -nographic \
    191         -append 'console=ttyS0 quiet panic=-1 oops=panic kasan_multi_shot' \
    192         -m 512M \
    193         -net nic,model=e1000 -net user" \
    194         Enter
    195 else
    196     log "Launching AFL++ master (fuzz_urb, in-process lane)..."
    197     tmux send-keys -t "${SESSION}:0.0" \
    198         "AFL_SKIP_CPUFREQ=1 AFL_AUTORESUME=1 AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 \
    199         ASAN_OPTIONS=abort_on_error=1:symbolize=0:detect_leaks=0 \
    200         nice -n ${NICE} afl-fuzz \
    201         -M master \
    202         -i ${CORPUS_URB} \
    203         -o ${OUTPUT_DIR} \
    204         -x ${DICT} \
    205         -c ./fuzz_urb.cmplog \
    206         -t ${TIMEOUT} \
    207         -p fast \
    208         -m none \
    209         -- ./fuzz_urb" \
    210         Enter
    211 
    212     log "Launching AFL++ secondary (fuzz_stub_client, kernel lane)..."
    213     tmux send-keys -t "${SESSION}:0.1" \
    214         "AFL_SKIP_CPUFREQ=1 AFL_AUTORESUME=1 AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 \
    215         nice -n ${NICE} afl-fuzz \
    216         -S stub \
    217         -i ${CORPUS_STUB} \
    218         -o ${OUTPUT_DIR} \
    219         -x ${DICT} \
    220         -t ${STUB_TIMEOUT} \
    221         -m none \
    222         -- ./fuzz_stub_client @@ 127.0.0.1 13240" \
    223         Enter
    224 
    225     log "Starting stub QEMU VM window..."
    226     tmux new-window -t "${SESSION}" -n vm-stub
    227     tmux send-keys -t "${SESSION}:vm-stub" \
    228         "qemu-system-x86_64 \
    229         -kernel ${KERNEL_PATH} \
    230         -initrd ${INITRD_PATH} \
    231         -nographic \
    232         -append 'console=ttyS0 quiet panic=-1 oops=panic kasan_multi_shot' \
    233         -m 512M \
    234         -net nic,model=e1000 -net user,hostfwd=tcp:127.0.0.1:13240-:3240" \
    235         Enter
    236 fi
    237 
    238 log "Adding status window..."
    239 tmux new-window -t "${SESSION}" -n status
    240 tmux send-keys -t "${SESSION}:status" \
    241     "watch -n 10 '$(command -v afl-whatsup) ${OUTPUT_DIR} 2>/dev/null || echo \"output dir: ${OUTPUT_DIR}\"'" \
    242     Enter
    243 
    244 tmux select-window -t "${SESSION}:0"
    245 
    246 ok "Fuzzing session started."
    247 echo ""
    248 echo "  Attach:       tmux attach -t ${SESSION}"
    249 echo "  Status:       ${0} --status"
    250 echo "  Profile:      ${PROFILE}"
    251 echo "  Crashes:      ${OUTPUT_DIR}/master/crashes/"
    252 [[ "${PROFILE}" == "inproc" ]] && echo "                ${OUTPUT_DIR}/urb/crashes/"
    253 [[ "${PROFILE}" == "max-impact" ]] && echo "                ${OUTPUT_DIR}/vhci/crashes/"
    254 [[ "${PROFILE}" == "max-impact" ]] && echo "  QEMU console: tmux window 'vm-vhci'"
    255 [[ "${PROFILE}" == "stub" ]] && echo "                ${OUTPUT_DIR}/stub/crashes/"
    256 [[ "${PROFILE}" == "stub" ]] && echo "  QEMU console: tmux window 'vm-stub'"
    257 echo "  Stop:         bash cleanup.sh"
    258 echo ""
    259 
    260 tmux attach -t "${SESSION}"