Jak w temacie. Zapisać w pliku tak, żeby dało się potem załadować (chodzi o pamięć innego procesu).
0
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