Dump Process Memory via ReadProcessMemory - Delphi

DarkCoderSc personal avatar
DarkCoderSc

Jean-Pierre LESUEUR

uses
 System.SysUtils, Winapi.Windows, System.Math;

// ...

function DumpProcessMemory(const ATargetProcessId : Cardinal; const AOutputPath : String) : SIZE_T;
begin
  result := 0;
  ///

  var hFile := CreateFileW(PWideChar(AOutputPath), GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  if hFile = INVALID_HANDLE_VALUE then
    raise EWindowsException.Create('CreateFileW');
  try
    var hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, ATargetProcessId);
    if hProcess = 0 then
      raise EWindowsException.Create('OpenProcess');
    try
      var AMemoryBasicInformation : TMemoryBasicInformation;
      var ASize := SizeOf(TMemoryBasicInformation);

      ZeroMemory(@AMemoryBasicInformation, ASize);

      const CHUNK_SIZE = 8192; // 8KiB

      var pBuffer : Pointer;
      GetMem(pBuffer, CHUNK_SIZE);
      try
        while VirtualQueryEx(hProcess, AMemoryBasicInformation.BaseAddress, AMemoryBasicInformation, ASize) = ASize do begin
          if AMemoryBasicInformation.RegionSize = 0 then
            continue;
          ///

          var ATotalBytesRead : SIZE_T;

          if (AMemoryBasicInformation.State = MEM_COMMIT) and
             (AMemoryBasicInformation.Protect and PAGE_GUARD = 0) and
             (AMemoryBasicInformation.Protect and PAGE_NOACCESS = 0) then
          begin
            ATotalBytesRead := 0;
            repeat
              var ABytesRead : SIZE_T;
              var ABytesToRead : SIZE_T := Min(CHUNK_SIZE, AMemoryBasicInformation.RegionSize - ATotalBytesRead);

              if not ReadProcessMemory(hProcess, AMemoryBasicInformation.BaseAddress, pBuffer, ABytesToRead, ABytesRead) then
                break;

              var ABytesWritten : DWORD;
              if not WriteFile(hFile, PByte(pBuffer)^, ABytesRead, ABytesWritten, nil) then
                raise EWindowsException.Create('WriteFile');

              Inc(ATotalBytesRead, ABytesRead);
            until ATotalBytesRead = AMemoryBasicInformation.RegionSize;

            ///
            Inc(result, ATotalBytesRead);
          end;

          ///
          AMemoryBasicInformation.BaseAddress := Pointer(
            NativeUInt(AMemoryBasicInformation.BaseAddress) + AMemoryBasicInformation.RegionSize
          );
        end;
      finally
        FreeMem(pBuffer, CHUNK_SIZE);
      end;
    finally
      CloseHandle(hProcess);
    end;
  finally
    CloseHandle(hFile);
  end;
end;

// ...

begin
  try
    var AOutputFile := 'C:\Temp\process.dmp';

    var ATotalMemoryDumped := DumpProcessMemory(<target_process_id>, AOutputFile);

    if ATotalMemoryDumped > 0 then
      WriteLn(Format('%d bytes have been successfully dumped to "%s".', [
        ATotalMemoryDumped,
        AOutputFile
      ]))
    else
      WriteLn('Nothing dumped so far!');
  except
    on e : Exception do
      WriteLn(e.Message);
  end;
// ...

Creating and researching code snippets takes time and effort. You’re welcome to share them through your own platforms, but please don’t forget to credit the original author, here: Jean-Pierre LESUEUR.

Depends On


Created

June 9, 2025

Last Revised

June 9, 2025