Zapisać pamięć procesu

0

Jak w temacie. Zapisać w pliku tak, żeby dało się potem załadować (chodzi o pamięć innego procesu).

0

To wcale nie jest taka prosta sprawa !

Poniżej masz przykład zapisania pamięci Notatnika do pliku "_dump.exe".
Ale to jeszcze nie rozwiązuje całego problemu. Teraz trzeba odbudować tabelę importów. Info: <url>http://www.smola.pac.pl/exepackfaq.htm#Odbudowa tabeli importów w plikach PE</url>

uses
  Windows, ShellAPI .......;
...............
type
  PImageDosHeader = ^TImageDosHeader;
  PIMAGE_DOS_HEADER = ^TImageDosHeader;
  _IMAGE_DOS_HEADER = packed record 
    e_magic: Word;
    e_cblp: Word;
    e_cp: Word;
    e_crlc: Word;
    e_cparhdr: Word;
    e_minalloc: Word;
    e_maxalloc: Word;
    e_ss: Word;
    e_sp: Word;
    e_csum: Word;
    e_ip: Word;
    e_cs: Word;
    e_lfarlc: Word;
    e_ovno: Word;
    e_res: array[0..3] of Word;
    e_oemid: Word;
    e_oeminfo: Word;
    e_res2: array[0..9] of Word;
    e_lfanew: LongInt;
  end;
  TImageDosHeader = _IMAGE_DOS_HEADER;
  IMAGE_DOS_HEADER = _IMAGE_DOS_HEADER;

  PIMAGE_NT_HEADERS = ^IMAGE_NT_HEADERS;
  IMAGE_NT_HEADERS = packed record
    Signature: DWORD;
    FileHeader: IMAGE_FILE_HEADER;
    OptionalHeader: IMAGE_OPTIONAL_HEADER;
  end;

............
function GetImageBase(const FileName: string): DWORD;
var
  fh, fm: THandle;
  fb: Pointer;
  DosHeader: PIMAGE_DOS_HEADER;
  NTHeader: PIMAGE_NT_HEADERS;
begin
  Result := 0;

  fh := CreateFile(
    PChar(FileName),
    GENERIC_READ,
    FILE_SHARE_READ,
    nil,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    0
    );

  if fh = INVALID_HANDLE_VALUE then
  begin
    CloseHandle(fh);
    MessageBox(0, PChar('Could not open: "' + FileName + '"'), 'Error', MB_OK);
    Exit;
  end;

  fm := CreateFileMapping(fh, nil, PAGE_READONLY, 0, 0, nil);
  if fm = 0 then
  begin
    CloseHandle(fm);
    CloseHandle(fh);
    MessageBox(0, 'CreateFileMapping Failed !', 'Error', MB_OK);
    Exit;
  end;

  fb := MapViewOfFile(fm, FILE_MAP_READ, 0, 0, 0);
  if fb = nil then
  begin
    UnMapViewOfFile(fb);
    CloseHandle(fm);
    CloseHandle(fh);
    MessageBox(0, 'MapViewOfFile Failed !', 'Error', MB_OK);
    Exit;
  end;

  DosHeader := PIMAGE_DOS_HEADER(fb);
  if not DosHeader.e_magic = IMAGE_DOS_SIGNATURE then
  begin
    UnMapViewOfFile(fb);
    CloseHandle(fm);
    CloseHandle(fh);
    MessageBox(0, 'Unrecognized file format !', 'Error', MB_OK);
    Exit;
  end;

  NTHeader := PIMAGE_NT_HEADERS(Longint(DosHeader) + DosHeader.e_lfanew);
  if IsBadReadPtr(NTHeader, SizeOf(IMAGE_NT_HEADERS)) or
    (NTHeader.Signature <> IMAGE_NT_SIGNATURE) then
  begin
    UnMapViewOfFile(fb);
    CloseHandle(fm);
    CloseHandle(fh);
    MessageBox(0, 'NOT a PE-32 executable file !', 'Error', MB_OK);
    Exit;
  end;

  Result := NTHeader.OptionalHeader.ImageBase;
  UnMapViewOfFile(fb);
  CloseHandle(fm);
  CloseHandle(fh);
end;

................

procedure TFormMain.Button1Click(Sender: TObject);

  function WInDir: string;
  var
    buffer: array[0..MAX_PATH - 1] of Char;
  begin
    FillChar(buffer, SizeOf(buffer), 0);
    GetWindowsDirectory(buffer, SizeOf(buffer));
    Result := buffer;
  end;

var
  dwX, base: DWORD;
  buffer: array[0..15] of byte;
  fs: TFileStream;
  b: BOOL;
  sei: TShellExecuteInfo;
  Exe: string;
begin
  Exe := WinDir + '\notepad.exe';
  base := GetImageBase(Exe);

  if base = 0 then
  begin
    MessageBox(Handle, 'ImageBase = 0 ???', 'Error', MB_OK);
    Exit;
  end;

  FillChar(sei, SizeOf(sei), 0);

  with sei do
  begin
    cbSize := SizeOf(sei);
    lpFile := PChar(Exe);
    nShow := SW_SHOW;
    fMask := SEE_MASK_NOCLOSEPROCESS;
  end;

  if not ShellExecuteEx(@sei) then
  begin
    MessageBox(Handle, 'ShellExecuteEx Failed !', 'Error', MB_OK);
    Exit;
  end;

  WaitForInputIdle(sei.hProcess, INFINITE);

  //Jeśli proces jest już uruchomiony, do pobrania hProcess użyj OpenProcess(PROCESS_VM_READ....

  try
    fs := TFileStream.Create('_dump.exe', fmCreate);
    try
      repeat
        b := ReadProcessMemory(sei.hProcess, Pointer(base), @buffer, SizeOf(buffer), dwX);
        if b then fs.Write(buffer, dwX);
        base := base + dwX;
      until not b;
    finally
      fs.Free;
    end;
  finally
    CloseHandle(sei.hProcess);
  end;

end;  //ButtonClick

1 użytkowników online, w tym zalogowanych: 0, gości: 1