154 lines
5.5 KiB
Plaintext
154 lines
5.5 KiB
Plaintext
{*******************************************************}
|
|
{ }
|
|
{ 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.
|