
Reproduziert den Integer-Überlauf CVE-2026-70638 in llama.cpp Android JNI mit einer sicheren Arithmetik-Demo, einem schädlichen GGUF-Generator und einem Frida-Hook für autorisierte Sicherheitsforschung.
Begleitender PoC zum Hunt-Benito-Artikel „Eine Multiplikation zu viel: CVE-2026-70638 — Integer Overflow in der Android-JNI-Heap-Zuweisung von llama.cpp" → https://www.hunt-benito.com/blog/one-multiply-too-many-cve-2026-70638-llama-cpp-android-jni-integer-overflow/
Java_android_llama_cpp_LLamaAndroid_new_1batch() in
examples/llama.android/llama/src/main/cpp/llama-android.cpp (llama.cpp-Builds
b1886–b7445) ist eine manuelle Kopie von llama_batch_init(), die mehrere
ungeprüfte malloc(sizeof(T) * count)-Berechnungen durchführt. Wenn ein
angreiferkontrollierter Multiplikator (n_seq_max, n_tokens oder embd)
verwendet wird, läuft die Größenberechnung über, der Heap-Block ist zu klein,
und die anschließenden Schreibvorgänge des Aufrufers lassen ihn überlaufen
(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).
Der verwundbare Kern der Funktion:
batch->seq_id[i] = (llama_seq_id *) malloc(sizeof(llama_seq_id) * n_seq_max);
# 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 <package> --no-pause
[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)
armeabi-v7a, nach wie vor ausgeliefert) direkt erreichbar. Auf 64-Bit
(arm64-v8a) fordert derselbe ungeprüfte Ausdruck stattdessen einen
Multi-GiB-Block an, bei dem malloc fehlschlägt (NULL → späterer Absturz /
DoS); Heap-Korruption erfordert den 32-Bit-Pfad.overflow_demo.c führt keinen Out-of-Bounds-Schreibzugriff aus — es
beweist nur, dass die Arithmetik überläuft. craft_gguf.py erzeugt ein
nicht ausführbares Modell (keine Tensoren) und lässt sich daher nicht
direkt als Waffe einsetzen; es demonstriert, dass der
angreiferkontrollierte Multiplikator aus nicht vertrauenswürdigen Metadaten
stammt.Aktualisieren Sie llama.cpp auf b7446 oder neuer (der new_1batch-JNI-Pfad
wurde durch die Neufassung der Android-Anbindungen entfernt). Falls Sie auf
einem betroffenen Build oder einem Downstream-Fork bleiben müssen, wenden Sie
Cyeras Validierungs-Patch von
https://github.com/Vladimir-tokarev-cyera/llama-cpp-security-patches an
(die CVE-2026-43627-Batch-Init-Absicherung ist der kanonische Fix für diese
Bug-Klasse).
NUR FÜR AUTORISIERTE SICHERHEITSFORSCHUNG UND BILDUNGSZWECKE.
| Datei | Zweck |
|---|
overflow_demo.c | Eigenständiger Reproduktor der überlaufenden Größenarithmetik unter 32-Bit (armeabi-v7a) im Vergleich zu 64-Bit (arm64-v8a) size_t. Kein korrupter Schreibvorgang — überall sicher ausführbar. |
craft_gguf.py | Erstellt ein minimales, strukturell gültiges GGUF, bei dem llama.embedding_length auf einen Angreiferwert gesetzt ist, und zeigt damit den Zustellungsvektor über die Modelldatei (embd wird direkt aus nicht vertrauenswürdigen Metadaten gelesen). |
hook_new_batch.js | Frida-Hook, der die drei Multiplikanden an der Live-JNI-Grenze auf einem Forschungsgerät protokolliert/überschreibt. |