Определить, включен ли ТЕСТСИЙНГ

Aug 19 2020

Я пытаюсь сделать перевод этого кода C ++, который был предложен в качестве возможного решения, чтобы проверить , включен ли 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;

где я получаю сообщение об ошибке:

недостаточно памяти

Как это можно решить?

Полный код:

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.

Ответы

1 RemyLebeau Aug 19 2020 at 11:45

Вы выделяете намного больше памяти, чем вам нужно. Код C ++ выделяет только 1, SYSTEM_CODEINTEGRITY_INFORMATIONно вы выделяете их огромный массив. В этом нет необходимости.

Но, что более важно, вы не инициализируете SYSTEM_CODEINTEGRITY_INFORMATION.Lengthполе перед вызовом NtQuerySystemInformation(), как это делает код C ++.

Попробуйте вместо этого:

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.