Closed vGimly closed 2 years ago
$REPARSE_POINT attribute for IO_REPARSE_TAG_WOF: length is always 16 bytes (4 dwords): 1,2,1,PACK_TYPE
PACK_TYPE = AlgName (BLOCK_SIZE) 0 = XPRESS4K 1 = LZX (32k) 2 = XPRESS8K 3 = XPRESS16K
eg $REPARSE_POINT data: 01 00 00 00 02 00 00 00 01 00 00 00 02 00 00 00 = XPRESS8K 01 00 00 00 02 00 00 00 01 00 00 00 01 00 00 00 = LZX
WofCompressedData stream consists in two parts:
Compression logic:
Compression/decompression with ntdll (only XPRESS, no LZX):
DWORD64 comp_block, comp_frag;
RtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_XPRESS_HUFF, &comp_block, &comp_frag);
LPVOID workspace = LocalAlloc(LMEM_FIXED, comp_block);
RtlCompressBuffer(COMPRESSION_FORMAT_XPRESS_HUFF, uncomp, uncomp_len, comp, comp_buf_len, block_size, &packed, workspace);
RtlDecompressBufferEx(COMPRESSION_FORMAT_XPRESS_HUFF, uncomp, uncomp_buf_len, comp,comp_len, &unpacked, workspace);
LocalFree(workspace);
eg for XPRESS16K, source file 32k of 00 bytes:
0000: 07 01 00 00 *02 00 00 00 │ 00 00 00 00 00 00 00 00
0010: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
0020: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
0030: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
0040: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
0050: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
0060: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
0070: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
0080: 00 00 00 00 02 00 00 00 │ 00 00 00 10 00 00 00 00
0090: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
00A0: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
00B0: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
00C0: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
00D0: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
00E0: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
00F0: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
0100: 00 00 00 00 00 98 00 00 │ FF FC 3F *02 00 00 00 00
0110: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
0120: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
0130: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
0140: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
0150: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
0160: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
0170: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
0180: 00 00 00 00 00 00 00 00 │ 00 00 00 02 00 00 00 00
0190: 00 00 10 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
01A0: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
01B0: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
01C0: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
01D0: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
01E0: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
01F0: 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00
0200: 00 00 00 00 00 00 00 00 │ 00 00 00 00 98 00 00 FF
0210: FC 3F
Two fragments (32K/16K), so offsets table have 1 element (0x107). First fragment offset 0x04, length 0x107 (due to offsets table), Second fragment offset 0x107+0x04 = 0x10B, length till the end of the stream.
Thanks for the details! I have a working PoC for xpress, need to clean the code a bit and I will push it
With ed083d4ff63164069cdf74f75a960740a3fdc8ca, you should be able to extract wof (xpress) files using:
ntfstool extract disk=1 volume=2 from="c:\windows\splwow64.exe:WofCompressedData" output="c:\splwow64.exe"
I also added description for $REPARSE_POINT & wof Ex:
+----------------------------------------------------------------------------------------------------------+
| 5 | $REPARSE_POINT | False | 24 | Type : Windows Overlay |
| | Raw address: 014516e7f1d8h | | | ------ |
| | | | | Version : 1 |
| | | | | Provider : 2 |
| | | | | File Version : 1 |
| | | | | Compression Algorithm : LZX 32k |
+----------------------------------------------------------------------------------------------------------+
Windows 10 introduces Windows Overlay Filtering compression for NTFS. And there even Windows 10 "Compact Edition", where that compression is turned on by default.
To check it just run in windows 10/11:
Note sparse/reparse flags are set, new ADS $DATA:WofCompressedData, $REPARSE_POINT with Type "Windows Overlay" IO_REPARSE_TAG_WOF .
There is XPRESS4K/XPRES8K/XPRESS16K/LZX compression algo. And also this tag should support for WIM files (reparse point can reference to WIM archive) - but I have no proof for it. https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/compact-os?view=windows-11 RtlDecompressBufferEx have support for COMPRESSION_FORMAT_XPRESS_HUFF - for WIM-LZX decompressor can be found on github...