我想提取记事本进程的完整进程内存并将其写入文本文件。 问题是我在文本文件中找不到我在记事本中键入的内容。 例如,如果我在记事本中键入“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.
答案 0 :(得分:1)
检索记事本文本内容的正确方法是使用HWND
或FindWindowEx()
或类似内容找到记事本编辑字段的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会不会更容易?