Sploitus

Exploit for CVE-2026-70638

githubexploit Β· 2026-08-07

Exploit Code

README84 lines
## https://sploitus.com/exploit?id=1EE31CF2-51B3-5C44-B696-818B1B1D1244
# CVE-2026-70638 - llama.cpp LLaMA-Android JNI Integer Overflow

Companion PoC for the Hunt-Benito article
**"One Multiply Too Many: CVE-2026-70638 β€” Integer Overflow in llama.cpp's Android JNI Heap Allocation"**
β†’ https://www.hunt-benito.com/blog/one-multiply-too-many-cve-2026-70638-llama-cpp-android-jni-integer-overflow/

## The bug

`Java_android_llama_cpp_LLamaAndroid_new_1batch()` in
`examples/llama.android/llama/src/main/cpp/llama-android.cpp` (llama.cpp builds
**b1886–b7445**) is a hand-copy of `llama_batch_init()` that performs several
unchecked `malloc(sizeof(T) * count)` computations. With an attacker-controlled
multiplier (`n_seq_max`, `n_tokens`, or `embd`), the size wraps, the heap block
is undersized, and the caller's subsequent writes overflow it
(**CWE-190 β†’ CWE-122**). NVD CVSS 3.1 **7.8 High**
(`AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H`).

The vulnerable core of the function:

```cpp
batch->seq_id[i] = (llama_seq_id *) malloc(sizeof(llama_seq_id) * n_seq_max);
```

## Files

| File | Purpose |
|------|---------|
| `overflow_demo.c` | Standalone reproducer of the wrapping size arithmetic under 32-bit (`armeabi-v7a`) vs 64-bit (`arm64-v8a`) `size_t`. No corrupted write β€” safe to run anywhere. |
| `craft_gguf.py` | Builds a minimal, structurally-valid GGUF with `llama.embedding_length` set to an attacker value, showing the model-file delivery vector (`embd` is read straight from untrusted metadata). |
| `hook_new_batch.js` | Frida hook that logs/overrides the three multiplicands at the live JNI boundary on a research device. |

## Run

```bash
# 1. Arithmetic demonstrator (the core of the article's PoC)
cc -O2 -o overflow_demo overflow_demo.c
./overflow_demo

# 2. Malicious model file
python3 craft_gguf.py 0x40000001 malicious.gguf   # -> 416-byte GGUF
xxd malicious.gguf | head                           # verify magic 'GGUF' + key

# 3. Live hook (rooted/emulator device with frida-server, authorized target only)
frida -U -l hook_new_batch.js -f  --no-pause
```

### Expected demo output (excerpt)

```
[2] Malicious: n_seq_max = 0x40000000 (2^30). 4 * 2^30 = 2^32 -> wraps:
  n_seq_max (attacker)   = 1073741824 (0x40000000)
  malloc size, arm64     = 4294967296 bytes (4.00 GiB)
  malloc size, armeabi-v7a = 0 bytes
  caller believes it got = 4294967296 bytes
  >>> 32-bit WRAP: 4294967296-byte write into 0-byte heap block (CWE-122)
```

## Scope & accuracy notes

- The wrap-to-undersized-allocation is directly reachable on **32-bit ABIs**
  (`armeabi-v7a`, still shipped). On **64-bit** (`arm64-v8a`) the same
  unchecked expression instead requests a multi-GiB block that `malloc` fails
  (`NULL` β†’ later crash / DoS); heap corruption requires the 32-bit path.
- `overflow_demo.c` performs **no** out-of-bounds write β€” it only proves the
  arithmetic wraps. `craft_gguf.py` produces a **non-runnable** model (no
  tensors) so it cannot be weaponized as-is; it demonstrates that the
  attacker-controlled multiplier is sourced from untrusted metadata.

## Remediation

Upgrade llama.cpp to **b7446 or later** (the `new_1batch` JNI path was removed
by the Android-binding rewrite). If you must stay on an affected build or a
downstream fork, apply Cyera's validation patch from
https://github.com/Vladimir-tokarev-cyera/llama-cpp-security-patches
(the `CVE-2026-43627` batch-init guard is the canonical fix for this bug class).

## Sources

- NVD β€” https://nvd.nist.gov/vuln/detail/CVE-2026-70638
- Fix (rewrite) β€” https://github.com/ggml-org/llama.cpp/commit/5c0d18881e0e9794c96b2602736b758bac9d9388
- Affected source β€” https://github.com/ggml-org/llama.cpp/blob/b7445/examples/llama.android/llama/src/main/cpp/llama-android.cpp

FOR AUTHORIZED SECURITY RESEARCH AND EDUCATIONAL USE ONLY.