检测是否启用了 TESTSIGNING

Detect whether or not TESTSIGNING is enabled

我正在尝试翻译 this C++ code,建议将其作为可能的解决方案来验证是否启用了 TESTSIGNING

我的代码几乎可以正常工作,但在这部分:

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;

我在哪里收到错误:

out of memory

如何解决?

完整代码:

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 = [=11=]000000;
  STATUS_BUFFER_OVERFLOW = 000005;
  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 := 0;
    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.

您分配的内存超出了您的需要。 C++ 代码仅分配 1 SYSTEM_CODEINTEGRITY_INFORMATION,但您正在分配大量数组。那是没有必要的。

但是,更重要的是,您没有像 C++ 代码那样在调用 NtQuerySystemInformation() 之前初始化 SYSTEM_CODEINTEGRITY_INFORMATION.Length 字段。

试试这个:

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 = [=10=]000000;

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.