Phrozen Timeline

Tiny snippet to know whether or not target process id is running under 32bit or 64bit architecture.

If result is True, target process is running under 64bit architecture.

If result is False, target process is running under 32bit architecture.

// ...

uses Windows, SysUtils;

// ...
type
  TArchitecture = (x86, x64, xUnknown);
// ...

function IsProcessX64(AProcessId : Cardinal) : TArchitecture;
var AProcHandle   : THandle;
    AWow64Process : bool;
begin
  result := xUnknown;
  ///

  {
    If we are not in a 64Bit system then we are for sure in a 32Bit system
  }
  if (TOSVersion.Architecture = arIntelX86) then
    Exit();
  ///

  AProcHandle := OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, False, AProcessId);
  if AProcHandle = 0 then
    Exit;
  try
    isWow64Process(AProcHandle, AWow64Process);
    ///

    if AWow64Process then
      result := x86
    else
      result := x64;
  finally
    CloseHandle(AProcHandle);
  end;
end;
Read more...

Tiny delphi unit to get and update debug flag from PEB (Process Environment Block).

This unit was created while working on a friend project called Unprotect (@fr0gger_), https://github.com/fr0gger/unprotect

Indeed, some Malware often check the value of Debug flag to know whether or not they are getting debugged and apply anti debug techniques if this is the case.

Example of implementation can be found there

(*******************************************************************************


  Author:
    ->  Jean-Pierre LESUEUR (@DarkCoderSc)
        https://github.com/DarkCoderSc
        https://gist.github.com/DarkCoderSc
        https://www.phrozen.io/

  License:
    -> MIT


*******************************************************************************)

unit UntPEBDebug;

interface

uses Windows;

const PROCESS_QUERY_LIMITED_INFORMATION = $1000;
      PROCESS_BASIC_INFORMATION         = 0;

// https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationprocess
var _NtQueryInformationProcess : function(
                                            ProcessHandle : THandle;
                                            ProcessInformationClass : DWORD;
                                            ProcessInformation : Pointer;
                                            ProcessInformationLength :
                                            ULONG; ReturnLength : PULONG) : LongInt; stdcall;

    hNTDLL : THandle;


{$IFDEF WIN64}
type
  PProcessBasicInformation = ^TProcessBasicInformation;
  TProcessBasicInformation = record
    ExitStatus         : Int64;
    PebBaseAddress     : Pointer;
    AffinityMask       : Int64;
    BasePriority       : Int64;
    UniqueProcessId    : Int64;
    InheritedUniquePID : Int64;
  end;
{$ELSE}
type
  PProcessBasicInformation = ^TProcessBasicInformation;
  TProcessBasicInformation = record
    ExitStatus         : DWORD;
    PebBaseAddress     : Pointer;
    AffinityMask       : DWORD;
    BasePriority       : DWORD;
    UniqueProcessId    : DWORD;
    InheritedUniquePID : DWORD;
  end;
{$ENDIF}

function GetProcessDebugStatus(AProcessID : Cardinal; var ADebugStatus : boolean) : Boolean;
function SetProcessDebugStatus(AProcessID : Cardinal; ADebugStatus : Boolean) : Boolean;

implementation

{-------------------------------------------------------------------------------
  Open a process and retrieve the point of debug flag from PEB.

  If function succeed, don't forget to call close process handle.
-------------------------------------------------------------------------------}
function GetDebugFlagPointer(AProcessID : Cardinal; var AProcessHandle : THandle) : Pointer;
var PBI     : TProcessBasicInformation;
    ARetLen : Cardinal;
begin
  result := nil;
  ///

  AProcessHandle := 0;

  if NOT Assigned(_NtQueryInformationProcess) then
    Exit();
  ///

  AProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_WRITE or PROCESS_VM_READ, false, AProcessID);
  if (AProcessHandle = 0) then
    Exit;

  if _NtQueryInformationProcess(AProcessHandle, PROCESS_BASIC_INFORMATION, @PBI, sizeOf(TProcessBasicInformation), @ARetLen) = ERROR_SUCCESS then
    result := Pointer(NativeUInt(PBI.PebBaseAddress) + (SizeOf(Byte) * 2))
  else
    CloseHandle(AProcessHandle);
end;

{-------------------------------------------------------------------------------
  Retrieve the target process debug status from PEB.

  ADebugStatus = True  : Target process debug flag is set.
  ADebugStatus = False : Target process debug flag is not set.
-------------------------------------------------------------------------------}
function GetProcessDebugStatus(AProcessID : Cardinal; var ADebugStatus : boolean) : Boolean;
var hProcess         : THandle;

    pDebugFlagOffset : Pointer;
    pDebugFlag       : pByte;
    ABytesRead       : SIZE_T;
begin
  result := false;
  ///

  pDebugFlagOffset := GetDebugFlagPointer(AProcessID, hProcess);

  if not Assigned(pDebugFlagOffset) then
    Exit();
  ///
  try
    getMem(pDebugFlag, sizeOf(Byte));
    try
      if NOT ReadProcessMemory(hProcess, pDebugFlagOffset, pDebugFlag, sizeOf(Byte), ABytesRead) then
        Exit;

      ///
      ADebugStatus := (pDebugFlag^ = 1);
    finally
      FreeMem(pDebugFlag);
    end;

    ///
    result := (ABytesRead = SizeOf(Byte));
  finally
    CloseHandle(hProcess);
  end;
end;

{-------------------------------------------------------------------------------
  Update target process debug flag.

  ADebugStatus = True  : Set target process debug flag.
  ADebugStatus = False : Unset target process debug flag.
-------------------------------------------------------------------------------}
function SetProcessDebugStatus(AProcessID : Cardinal; ADebugStatus : Boolean) : Boolean;
var hProcess         : THandle;

    pDebugFlagOffset : Pointer;
    ADebugFlag       : Byte;
    ABytesWritten    : SIZE_T;
begin
  result := false;
  ///

  pDebugFlagOffset := GetDebugFlagPointer(AProcessID, hProcess);

  if not Assigned(pDebugFlagOffset) then
    Exit();
  ///
  try
    if ADebugStatus then
      ADebugFlag := 1
    else
      ADebugFlag := 0;

    if NOT WriteProcessMemory(hProcess, pDebugFlagOffset, @ADebugFlag, SizeOf(Byte), ABytesWritten) then
      Exit;

    ///
    result := (ABytesWritten = SizeOf(Byte));
  finally
    CloseHandle(hProcess);
  end;
end;

initialization
  {
    Load NtQueryInformationProcess from NTDLL.dll
  }
  _NtQueryInformationProcess := nil;

  hNTDLL := LoadLibrary('ntdll.dll');

  if (hNTDLL <> 0) then
    @_NtQueryInformationProcess := GetProcAddress(hNTDLL, 'NtQueryInformationProcess');

finalization
  _NtQueryInformationProcess := nil;

  if (hNTDLL <> 0) then
    FreeLibrary(hNTDLL);


end.
Read more...