I'm trying make a translation of this C++ code that was suggested as possible solution to verify if TESTSIGNING is enabled.
My code almost worked fine, but in this part:
while (status = STATUS_BUFFER_OVERFLOW) or (status = STATUS_INFO_LENGTH_MISMATCH) do
begin
n := Max(br, n * 2);
ReallocMem(Buffer, n * SizeOf(TSystemCodeIntegrityInformation));
Status := NtQuerySystemInformation({SystemCodeIntegrityInformation}103, Buffer, n * SizeOf(TSystemCodeIntegrityInformation), @br);
Writeln('0x'+IntToHex(Status));
end;
where i'm receiving an error:
out of memory
How this can be solved?
Full code:
program test;
{$APPTYPE CONSOLE}
{$R *.res}
uses
Windows,
SysUtils,
Math;
type
NTSTATUS = DWORD;
TSystemInformationClass = SYSTEM_INFORMATION_CLASS;
TNativeQuerySystemInformation = function(SystemInformationClass: TSystemInformationClass; SystemInformation: Pointer; SystemInformationLength: ULONG; ReturnLength: PULONG): NTSTATUS; stdcall;
SYSTEM_CODEINTEGRITY_INFORMATION = record
Length: ULONG;
CodeIntegrityOptions: ULONG;
end;
TSystemCodeIntegrityInformation = SYSTEM_CODEINTEGRITY_INFORMATION;
PSystemCodeIntegrityInformation = ^TSystemCodeIntegrityInformation;
const
NTDLL_DLL = 'NTDLL.DLL';
STATUS_SUCCESS = $00000000;
STATUS_BUFFER_OVERFLOW = $80000005;
STATUS_INFO_LENGTH_MISMATCH = $C0000004;
var
NtQuerySystemInformation: TNativeQuerySystemInformation = nil;
NTDLLHandle: THandle = 0;
UnloadNTDLL: Boolean;
Buffer: Pointer;
Status: Cardinal;
psci: PSystemCodeIntegrityInformation;
n, br: Cardinal;
function InitNativeAPI: Boolean;
begin
NTDLLHandle := GetModuleHandle(NTDLL_DLL);
UnloadNTDLL := NTDLLHandle = 0;
if NTDLLHandle = 0 then
NTDLLHandle := LoadLibrary(NTDLL_DLL);
if NTDLLHandle <> 0 then
begin
@NtQuerySystemInformation := GetProcAddress(NTDLLHandle, 'NtQuerySystemInformation');
end;
Result := (NTDLLHandle <> 0) and Assigned(NtQuerySystemInformation);
end;
procedure FreeNativeAPI;
begin
if (NTDLLHandle <> 0) and UnloadNTDLL then
begin
if not FreeLibrary(NTDLLHandle) then
raise Exception.Create(Format('Unload Error: %s - 0x%x', [NTDLL_DLL, GetModuleHandle(NTDLL_DLL)]))
else
NTDLLHandle := 0;
end;
end;
begin
try
Writeln(InitNativeAPI);
Buffer := nil;
n := $100;
Buffer := AllocMem(n * SizeOf(TSystemCodeIntegrityInformation));
Status := NtQuerySystemInformation(SystemCodeIntegrityInformation, Buffer, n * SizeOf(TSystemCodeIntegrityInformation), @br);
while (status = STATUS_BUFFER_OVERFLOW) or (status = STATUS_INFO_LENGTH_MISMATCH) do
begin
n := Max(br, n * 2);
ReallocMem(Buffer, n * SizeOf(TSystemCodeIntegrityInformation));
Status := NtQuerySystemInformation(SystemCodeIntegrityInformation, Buffer, n * SizeOf(TSystemCodeIntegrityInformation), @br);
Writeln('0x'+IntToHex(Status));
end;
try
if Status = STATUS_SUCCESS then
begin
psci := PSystemCodeIntegrityInformation(Buffer);
Writeln(IntToHex(psci.CodeIntegrityOptions));
end;
finally
Reallocmem(Buffer, 0);
Buffer := nil;
end;
FreeNativeAPI;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
You are allocating way more memory than you need. The C++ code allocates only 1 SYSTEM_CODEINTEGRITY_INFORMATION
but you are allocating a huge array of them. That is not necessary.
But, more importantly, you are not initializing the SYSTEM_CODEINTEGRITY_INFORMATION.Length
field before calling NtQuerySystemInformation()
, like the C++ code is doing.
Try this instead:
program test;
{$APPTYPE CONSOLE}
{$R *.res}
uses
Windows,
SysUtils,
Math;
type
NTSTATUS = DWORD;
TSystemInformationClass = SYSTEM_INFORMATION_CLASS;
TNativeQuerySystemInformation = function(SystemInformationClass: TSystemInformationClass; SystemInformation: Pointer; SystemInformationLength: ULONG; ReturnLength: PULONG): NTSTATUS; stdcall;
SYSTEM_CODEINTEGRITY_INFORMATION = record
Length: ULONG;
CodeIntegrityOptions: ULONG;
end;
TSystemCodeIntegrityInformation = SYSTEM_CODEINTEGRITY_INFORMATION;
PSystemCodeIntegrityInformation = ^TSystemCodeIntegrityInformation;
const
NTDLL_DLL = 'NTDLL.DLL';
STATUS_SUCCESS = $00000000;
var
NtQuerySystemInformation: TNativeQuerySystemInformation = nil;
NTDLLHandle: THandle = 0;
UnloadNTDLL: Boolean = False;
Status: DWORD;
sci: TSystemCodeIntegrityInformation;
br: ULONG;
function InitNativeAPI: Boolean;
begin
Result := False;
NTDLLHandle := GetModuleHandle(NTDLL_DLL);
if NTDLLHandle = 0 then
begin
NTDLLHandle := LoadLibrary(NTDLL_DLL);
UnloadNTDLL := (NTDLLHandle <> 0);
end;
if NTDLLHandle <> 0 then
begin
@NtQuerySystemInformation := GetProcAddress(NTDLLHandle, 'NtQuerySystemInformation');
Result := Assigned(NtQuerySystemInformation);
end;
end;
procedure FreeNativeAPI;
begin
if (NTDLLHandle <> 0) and UnloadNTDLL then
begin
if not FreeLibrary(NTDLLHandle) then
raise Exception.Create(Format('Unload Error: %s - 0x%x', [NTDLL_DLL, GetModuleHandle(NTDLL_DLL)]);
NTDLLHandle := 0;
end;
end;
begin
try
Writeln(InitNativeAPI);
try
sci.Length := sizeof(sci);
Status := NtQuerySystemInformation(SystemCodeIntegrityInformation, @sci, SizeOf(sci), @br);
Writeln('0x'+IntToHex(Status));
if Status = STATUS_SUCCESS then
begin
Writeln(IntToHex(sci.CodeIntegrityOptions));
end;
finally
FreeNativeAPI;
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.