etc.git


etc

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

run-fuzzers.sh (5699B)

      1 #!/bin/bash
      2 # Run all TTYD fuzzers in tmux
      3 # Two visible panes (one main per target), cmplog + secondaries run headless
      4 # Safe to detach from SSH - everything persists in background
      5 
      6 set -e
      7 
      8 SESSION="ttyd-fuzz"
      9 SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
     10 
     11 # Check dependencies
     12 if ! command -v tmux &> /dev/null; then
     13     echo "[!] tmux not found. Install with: sudo apt-get install tmux"
     14     exit 1
     15 fi
     16 
     17 if ! command -v afl-fuzz &> /dev/null; then
     18     echo "[!] afl-fuzz not found. Install AFL++ first."
     19     exit 1
     20 fi
     21 
     22 # Check that harnesses are built
     23 for harness in fuzz_websocket_auth fuzz_http_parsing; do
     24     if [ ! -x "$SCRIPT_DIR/$harness" ]; then
     25         echo "[!] $harness not found. Run ./build_fuzzers.sh first."
     26         exit 1
     27     fi
     28 done
     29 
     30 # Generate corpus if missing
     31 for dir in websocket_auth http_parsing; do
     32     if [ ! -d "$SCRIPT_DIR/corpus/$dir" ] || [ -z "$(ls -A "$SCRIPT_DIR/corpus/$dir" 2>/dev/null)" ]; then
     33         echo "[*] Corpus missing. Run ./build_fuzzers.sh first to generate it."
     34         exit 1
     35     fi
     36 done
     37 
     38 # Find dictionaries
     39 DICT_DIR=""
     40 for candidate in /usr/share/afl++/dictionaries /usr/local/share/afl++/dictionaries "$SCRIPT_DIR/dictionaries"; do
     41     if [ -d "$candidate" ]; then
     42         DICT_DIR="$candidate"
     43         break
     44     fi
     45 done
     46 
     47 if [ -z "$DICT_DIR" ]; then
     48     echo "[!] Warning: No AFL++ dictionaries directory found."
     49 fi
     50 
     51 # Calculate core allocation
     52 TOTAL_CORES=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)
     53 CORES_PER_TARGET=$((TOTAL_CORES / 2))
     54 [ "$CORES_PER_TARGET" -lt 1 ] && CORES_PER_TARGET=1
     55 
     56 echo "[*] System: $TOTAL_CORES cores, $CORES_PER_TARGET per target"
     57 
     58 # Create output directories
     59 mkdir -p "$SCRIPT_DIR/output/websocket_auth" "$SCRIPT_DIR/output/http_parsing"
     60 
     61 # Kill existing session if running
     62 tmux kill-session -t "$SESSION" 2>/dev/null || true
     63 
     64 echo "[*] Starting fuzzing in tmux session: $SESSION"
     65 echo
     66 
     67 # Build afl-fuzz command
     68 build_afl_cmd() {
     69     local harness=$1 corpus=$2 output=$3 dict=$4 node_flag=$5
     70     shift 5
     71     local extra="$*"
     72     local cmd="afl-fuzz -i $corpus -o $output $node_flag"
     73     [ -n "$DICT_DIR" ] && [ -f "$DICT_DIR/$dict" ] && cmd="$cmd -x $DICT_DIR/$dict"
     74     [ -n "$extra" ] && cmd="$cmd $extra"
     75     cmd="$cmd -- ./$harness"
     76     echo "$cmd"
     77 }
     78 
     79 # Custom mutator for http_parsing
     80 HTTP_ENV=""
     81 if [ -f "$SCRIPT_DIR/http_mutator.so" ]; then
     82     HTTP_ENV="AFL_CUSTOM_MUTATOR_LIBRARY=$SCRIPT_DIR/http_mutator.so"
     83     echo "[+] Using custom HTTP mutator for http_parsing"
     84 fi
     85 
     86 # ── Launch headless background nodes ──────────────────────────────────────────
     87 # These run without a UI pane — they sync via the shared output dir
     88 BG_PIDS=()
     89 
     90 launch_bg() {
     91     local env_prefix="$1"
     92     local cmd="$2"
     93     local logfile="$3"
     94     (cd "$SCRIPT_DIR" && AFL_NO_UI=1 $env_prefix $cmd > "$logfile" 2>&1) &
     95     BG_PIDS+=($!)
     96 }
     97 
     98 bg_count=0
     99 
    100 for target_info in "fuzz_websocket_auth|websocket_auth|json.dict|" "fuzz_http_parsing|http_parsing|http.dict|$HTTP_ENV"; do
    101     IFS='|' read -r harness corpus_dir dict env_prefix <<< "$target_info"
    102     output="output/$corpus_dir"
    103     corpus="corpus/$corpus_dir"
    104     logdir="$SCRIPT_DIR/output/$corpus_dir"
    105 
    106     # CmpLog secondary (if binary exists and we have cores)
    107     if [ -x "$SCRIPT_DIR/${harness}_cmplog" ] && [ "$CORES_PER_TARGET" -ge 2 ]; then
    108         cmd=$(build_afl_cmd "$harness" "$corpus" "$output" "$dict" "-S cmplog" "-c ./${harness}_cmplog")
    109         launch_bg "$env_prefix" "$cmd" "$logdir/cmplog.log"
    110         bg_count=$((bg_count + 1))
    111     fi
    112 
    113     # Extra secondaries
    114     used=2  # main + cmplog
    115     remaining=$((CORES_PER_TARGET - used))
    116     for i in $(seq 1 $remaining); do
    117         cmd=$(build_afl_cmd "$harness" "$corpus" "$output" "$dict" "-S sec_$i")
    118         launch_bg "$env_prefix" "$cmd" "$logdir/sec_$i.log"
    119         bg_count=$((bg_count + 1))
    120     done
    121 done
    122 
    123 echo "[*] Launched $bg_count headless secondary nodes"
    124 
    125 # ── Create tmux: 2 panes (main nodes with UI) ────────────────────────────────
    126 ws_main=$(build_afl_cmd "fuzz_websocket_auth" "corpus/websocket_auth" "output/websocket_auth" "json.dict" "-M main")
    127 http_main=$(build_afl_cmd "fuzz_http_parsing" "corpus/http_parsing" "output/http_parsing" "http.dict" "-M main")
    128 
    129 tmux new-session -d -s "$SESSION" -n "fuzzers" \
    130     "cd '$SCRIPT_DIR' && $ws_main; echo '[!] Fuzzer exited'; read"
    131 tmux split-window -h -t "$SESSION:fuzzers" \
    132     "cd '$SCRIPT_DIR' && $HTTP_ENV $http_main; echo '[!] Fuzzer exited'; read"
    133 
    134 # ── Status window ─────────────────────────────────────────────────────────────
    135 tmux new-window -t "$SESSION" -n "status" \
    136     "cd '$SCRIPT_DIR' && watch -n 10 'echo \"=== WebSocket Auth ===\"; echo; afl-whatsup -s output/websocket_auth 2>&1; echo; echo \"=== HTTP Parsing ===\"; echo; afl-whatsup -s output/http_parsing 2>&1'"
    137 
    138 # Select fuzzers window
    139 tmux select-window -t "$SESSION:fuzzers"
    140 
    141 # Save background PIDs so clean.sh can kill them
    142 printf '%s\n' "${BG_PIDS[@]}" > "$SCRIPT_DIR/.bg_fuzz_pids"
    143 
    144 echo
    145 echo "[+] All fuzzers started in tmux session: $SESSION"
    146 echo "    2 main nodes (visible) + $bg_count headless secondaries"
    147 echo
    148 echo "Commands:"
    149 echo "  tmux attach -t $SESSION          # Attach to session"
    150 echo "  Ctrl-b d                         # Detach (fuzzers keep running)"
    151 echo "  tmux kill-session -t $SESSION    # Stop all fuzzers"
    152 echo
    153 echo "[*] You can safely disconnect from SSH. Fuzzers will keep running."
    154 echo "[*] Crashes will be saved in output/*/main/crashes/"