● Zion Boggan
repos/Cyclops V2/targets/hunt_gguf.sh
zionboggan.com ↗
64 lines · bash
History for this file →
1
set -e
2
export CYCLOPS_HOME=/opt/cyclops-v2
3
PY=/opt/cyclops-venv/bin/python
4
T=/opt/cyclops-v2/targets/src/gguf-tools
5
H=/opt/cyclops-v2/oracle/harnesses
6
W=/opt/cyclops-v2/oracle/work/gguf
7
mkdir -p "$H" "$W" "$W/seeds"
8
 
9
echo "=== [1/4] BRAIN: joern memory-corruption dataflow on gguflib.c ==="
10
$PY /opt/cyclops-v2/brain/brain.py "github.com/antirez/gguf-tools" "ml-model-loaders" "$T" "c" "fdfafbe" || true
11
 
12
echo "=== [2/4] generate a valid seed GGUF (gets the harness past the magic/header) ==="
13
$PY - <<'PYEOF'
14
import struct
15
buf = b"GGUF"
16
buf += struct.pack("<I", 3)
17
buf += struct.pack("<Q", 0)
18
buf += struct.pack("<Q", 1)
19
buf += struct.pack("<Q", 1) + b"a"
20
buf += struct.pack("<I", 8)
21
buf += struct.pack("<Q", 1) + b"b"
22
open("/opt/cyclops-v2/oracle/work/gguf/seeds/seed1.gguf","wb").write(buf)
23
print("seed bytes:", len(buf))
24
PYEOF
25
 
26
echo "=== [3/4] write libFuzzer harness for the full parse path ==="
27
cat > "$H/gguf_harness.c" <<'EOF'
28
// Drive the real parse path: gguf_open() mmaps + parses header, then we walk
29
// every key and tensor (attacker-controlled offsets/lengths/type enums).
30
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
31
    char path[] = "/dev/shm/gguffzXXXXXX";
32
    int fd = mkstemp(path);
33
    if (fd < 0) return 0;
34
    if (write(fd, data, size) != (ssize_t)size) { close(fd); unlink(path); return 0; }
35
    close(fd);
36
    gguf_ctx *ctx = gguf_open(path);
37
    if (ctx) {
38
        gguf_key key;
39
        while (gguf_get_key(ctx, &key)) {
40
            // touch the value (exercises type dispatch / value parsing)
41
            gguf_print_value(ctx, key.type, key.val, 0);
42
        }
43
        gguf_tensor tensor;
44
        while (gguf_get_tensor(ctx, &tensor)) { /* walks tensor info offsets */ }
45
        gguf_close(ctx);
46
    }
47
    unlink(path);
48
    return 0;
49
}
50
EOF
51
 
52
echo "=== [4/4] compile (ASan+UBSan+fuzzer) and launch background fuzz ==="
53
cd "$W"
54
clang -g -O1 -fsanitize=fuzzer,address,undefined -fno-omit-frame-pointer \
55
    "$H/gguf_harness.c" "$T/gguflib.c" "$T/fp16.c" "$T/sds.c" \
56
    -I"$T" -lm -o "$W/fuzz_gguf" 2>&1 | tail -5
57
echo "compiled: $(ls -la $W/fuzz_gguf 2>/dev/null | awk '{print $5}') bytes"
58
mkdir -p "$W/corpus" && cp "$W/seeds/"* "$W/corpus/" 2>/dev/null || true
59
nohup "$W/fuzz_gguf" -max_total_time=1800 -print_final_stats=1 \
60
    -artifact_prefix="$W/crash-" "$W/corpus" "$W/seeds" \
61
    > "$W/fuzz.log" 2>&1 &
62
echo "FUZZ_PID=$!"
63
sleep 8
64
echo "=== early fuzz log ==="; tail -8 "$W/fuzz.log" 2>/dev/null