{*******************************************************} { } { Tocsg.NTDLL.Decompress } { } { Copyright (C) 2022 kku } { } {*******************************************************} unit Tocsg.NTDLL.Decompress; interface uses SysUtils, Winapi.Windows; const COMPRESSION_FORMAT_NONE = 0; COMPRESSION_FORMAT_DEFAULT = 1; COMPRESSION_FORMAT_LZNT1 = 2; COMPRESSION_FORMAT_XPRESS = 3; COMPRESSION_FORMAT_XPRESS_HUFF = 4; STATUS_SUCCESS = 0; STATUS_ACCESS_DENIED = $C0000022; type TRtlHeader = record arrSig: array[0..3] of AnsiChar; dwSize: DWORD; end; NTSTATUS = DWORD; ULONG = DWORD; PULONG = ^ULONG; PVOID = Pointer; USHORT = WORD; UCHAR = Byte; PUCHAR = ^UCHAR; PWSTR = PWideChar; TRtlGetCompressionWorkSpaceSize = function(CompressionFormatAndEngine: USHORT; CompressBufferWorkSpaceSize: PULONG; CompressFragmentWorkSpaceSize: PULONG): NTSTATUS; stdcall; TRtlDecompressBufferEx = function(CompressionFormat: USHORT; UncompressedBuffer: PUCHAR; UncompressedBufferSize: ULONG; CompressedBuffer: PUCHAR; CompressedBufferSize: ULONG; FinalUncompressedSize: PULONG; WorkSpace: PVOID): NTSTATUS; stdcall; function RtlGetCompressionWorkSpaceSize(CompressionFormatAndEngine: USHORT; CompressBufferWorkSpaceSize: PULONG; CompressFragmentWorkSpaceSize: PULONG): NTSTATUS; // stdcall external 'ntdll.dll'; function RtlDecompressBufferEx(CompressionFormat: USHORT; UncompressedBuffer: PUCHAR; UncompressedBufferSize: ULONG; CompressedBuffer: PUCHAR; CompressedBufferSize: ULONG; FinalUncompressedSize: PULONG; WorkSpace: PVOID): NTSTATUS; // stdcall external 'ntdll.dll'; function RtlDecompress(pSrc, pDest: Pointer; dwSrcSize, dwDecompSize, dwCompFormat: DWORD): DWORD; implementation var _hNtdll: THandle = 0; _fnRtlGetCompressionWorkSpaceSize: TRtlGetCompressionWorkSpaceSize = nil; _fnRtlDecompressBufferEx: TRtlDecompressBufferEx = nil; function InitNtdllDecompProcedure: Boolean; begin if _hNtdll = 0 then begin _hNtdll := GetModuleHandle('ntdll.dll'); if _hNtdll <> 0 then begin @_fnRtlGetCompressionWorkSpaceSize := GetProcAddress(_hNtdll, 'RtlGetCompressionWorkSpaceSize'); @_fnRtlDecompressBufferEx := GetProcAddress(_hNtdll, 'RtlDecompressBufferEx'); end; end; Result := _hNtdll <> 0; end; function RtlGetCompressionWorkSpaceSize(CompressionFormatAndEngine: USHORT; CompressBufferWorkSpaceSize: PULONG; CompressFragmentWorkSpaceSize: PULONG): NTSTATUS; begin if InitNtdllDecompProcedure and Assigned(_fnRtlGetCompressionWorkSpaceSize) then Result := _fnRtlGetCompressionWorkSpaceSize(CompressionFormatAndEngine, CompressBufferWorkSpaceSize, CompressFragmentWorkSpaceSize) else Result := STATUS_ACCESS_DENIED; end; function RtlDecompressBufferEx(CompressionFormat: USHORT; UncompressedBuffer: PUCHAR; UncompressedBufferSize: ULONG; CompressedBuffer: PUCHAR; CompressedBufferSize: ULONG; FinalUncompressedSize: PULONG; WorkSpace: PVOID): NTSTATUS; begin if InitNtdllDecompProcedure and Assigned(_fnRtlDecompressBufferEx) then Result := _fnRtlDecompressBufferEx(CompressionFormat, UncompressedBuffer, UncompressedBufferSize, CompressedBuffer, CompressedBufferSize, FinalUncompressedSize, WorkSpace) else Result := STATUS_ACCESS_DENIED; end; function RtlDecompress(pSrc, pDest: Pointer; dwSrcSize, dwDecompSize, dwCompFormat: DWORD): DWORD; var dwOutSize, dwResult, dwCompBufWorkSpaceSize, dwCompFragWorkSpaceSize: DWORD; pWorkSpace: array of AnsiChar; begin Result := 0; dwResult := RtlGetCompressionWorkSpaceSize(dwCompFormat, @dwCompBufWorkSpaceSize, @dwCompFragWorkSpaceSize); if dwResult <> STATUS_SUCCESS then exit; dwOutSize := 0; SetLength(pWorkSpace, dwCompBufWorkSpaceSize); dwResult := RtlDecompressBufferEx(dwCompFormat, pDest, dwDecompSize, pSrc, dwSrcSize, @dwOutSize, pWorkSpace); if dwResult = STATUS_SUCCESS then Result := dwOutSize; end; end.