Delphi ReadProcessMemory来自记事本

时间:2013-12-12 21:00:44

标签: string delphi notepad readprocessmemory

我想提取记事本进程的完整进程内存并将其写入文本文件。 问题是我在文本文件中找不到我在记事本中键入的内容。 例如,如果我在记事本中键入“test123”,我找不到程序创建的文本文件中的字符串。 这是代码:

{$APPTYPE CONSOLE}

uses
  Windows,
  TLHelp32,
  SysUtils;

var
  Snap, err: dword;
  sysinfo: TSystemInfo;
  Process: TPROCESSENTRY32;
  Handle: THandle;
  Mbi: TMemoryBasicInformation;
  Addr, BytesRead: dword;
  Buf: PChar;
  f: TextFile;
begin
  GetSystemInfo(sysinfo);
        Handle := OpenProcess(PROCESS_ALL_ACCESS, false, 2928);
        if Handle <> 0 then
        begin
          writeln(Process.szExeFile);
          Addr := dword(sysinfo.lpMinimumApplicationAddress);
          while (Addr < $80000000) do
          begin
            if VirtualQueryEx(Handle, Ptr(Addr), Mbi, SizeOf(Mbi)) = 0 then
            begin
              err := GetLastError;
              inc(Addr, sysinfo.dwPageSize);
              continue;
            end;
             Buf := AllocMem(Mbi.RegionSize);
             ReadProcessMemory(Handle, Mbi.BaseAddress, Buf, Mbi.RegionSize, BytesRead);
             AssignFile(f, 'Test.txt');
             Append(f);
             WriteLn(f, Buf);
             CloseFile(f);
             FreeMem(Buf);
            if Addr + Mbi.RegionSize < Addr then
              break;
            Addr := Addr + Mbi.RegionSize;
          end;
          CloseHandle(Handle)
        end;
  Readln;
end.

2 个答案:

答案 0 :(得分:1)

检索记事本文本内容的正确方法是使用HWNDFindWindowEx()或类似内容找到记事本编辑字段的EnumChildWindows(),然后发送它是WM_GETTEXT消息。

但是如果你必须转储Notepad的已分配内存,那么你需要修复你的代码。它忽略了错误,并没有正确地将检索到的数据写入文件。尝试更像这样的东西:

uses
  Windows,
  TLHelp32,
  SysUtils;

var
  err: DWORD;
  sysinfo: TSystemInfo;
  Handle: THandle;
  Mbi: TMemoryBasicInformation;
  Addr: DWORD_PTR;
  BytesRead: DWORD;
  Buf: array of Byte;
  f: TFileStream;
begin
  GetSystemInfo(sysinfo);
  Handle := OpenProcess(PROCESS_ALL_ACCESS, FALSE, 2928);
  if Handle = 0 then
  begin
    err := GetLastError;
    // do something...
  end else
  try
    f := TFileStream.Create('Test.txt', fmCreate);
    try
      Addr := DWORD_PTR(SysInfo.lpMinimumApplicationAddress);
      while (Addr < $80000000) do
      begin
        if VirtualQueryEx(Handle, Pointer(Addr), Mbi, SizeOf(Mbi)) = 0 then
        begin
          err := GetLastError;
          Inc(Addr, sysinfo.dwPageSize);
          Continue;
        end;
        if Mbi.RegionSize > Length(Buf) then
          SetLength(Buf, Mbi.RegionSize);
        if not ReadProcessMemory(Handle, Mbi.BaseAddress, @Buf[0], Mbi.RegionSize, BytesRead) then
        begin
            err := GetLastError;
            // do something...
        end else
          f.WriteBuffer(Buf[0], BytesRead);
        if Addr + Mbi.RegionSize < Addr then
          break;
        Addr := Addr + Mbi.RegionSize;
      end;
    finally
      f.Free;
    end;
  finally
    CloseHandle(Handle);
  end;
  Readln;
end.

答案 1 :(得分:0)

记事本可能会将其文本存储在Windows原生UTF-16中。因此,将该文本视为一个宽字符串。

我猜另一个问题是您正在将二进制数据写入文本文件。内存块中的任何空字符都将终止输出。您真的想停止使用Pascal I / O并将此内存转储到文件流中。或者,如果你必须至少以二进制模式使用Pascal I / O.

使用自动化API或发送WM_GETTEXT会不会更容易?