xpress-huffman¶
Decompress Microsoft Xpress-Huffman (MS-XCA §2.2.4) anywhere — the codec behind Win10+ prefetch, hiberfil.sys, SMB3 and registry-hive compression — in pure, panic-free Rust with no Windows API.
// `compressed` is an LZXPRESS_HUFFMAN stream (e.g. a prefetch MAM payload after
// the 8-byte header); `size` is the decompressed length the container records.
let plain = xpress_huffman::decompress(compressed, size)?;
That's the whole surface: one function, no setup, #![no_std]-compatible.
Why this crate¶
Modern Windows compresses a lot with Xpress-Huffman (COMPRESSION_FORMAT_XPRESS_HUFF, value 4): Win8.1+ Prefetch (the MAM wrapper), hiberfil.sys, SMB3 transport compression, registry hive compression, and Windows Update payloads. Decoding it off-Windows usually means shelling out to RtlDecompressBufferEx — which only exists on Windows.
| Algorithm | Xpress-Huffman support? | Decodes off-Windows? | |
|---|---|---|---|
xpress-huffman (this crate) |
Xpress-Huffman (MS-XCA §2.2.4) | ✅ | ✅ pure Rust, any platform |
rust-lzxpress, xpress_rs |
plain LZXpress (COMPRESSION_FORMAT_XPRESS = 3) |
❌ format 3 only | ✅ |
RtlDecompressBufferEx (Windows API) |
both | ✅ | ❌ Windows only |
The existing Rust crates implement plain LZXpress (the LZNT-style LZ77 format, value 3). This crate implements the Huffman-coded variant (value 4) that the artifacts above actually use.
Trust, but verify¶
#![forbid(unsafe_code)], nounwrap/expect/panic in production paths — every length and offset read from the (untrusted) input is bounds-checked. A corrupt stream yields anErr, never a panic or out-of-bounds read.#; enable thestdfeature for astd::error::Errorimpl.- Validated against an independent decompressor. The decoder is a clean-room implementation of the MS-XCA algorithm; its output is confirmed byte-for-byte against Fox-IT's independent
dissect.utildecompressor on real Windows artifacts. Seedocs/validation.md.
Install¶
Decoding a Windows prefetch payload¶
// A Win8.1+ prefetch file: `MAM\x04` + u32 decompressed size + the stream.
let size = u32::from_le_bytes(mam[4..8].try_into().unwrap()) as usize;
let scca = xpress_huffman::decompress(&mam[8..], size)?;
assert_eq!(&scca[4..8], b"SCCA");
(For full prefetch parsing — run counts, last-run times, loaded files — see the
prefetch-forensic crate, which builds on this one.)
Privacy Policy · Terms of Service · © 2026 Security Ronin Ltd