Ech dopiero po odpaleni zauważyłem byki takie jak próby odczytu z pamięci do której nie mamy dostępu (można by próbować uzyskać dostęp funkcja VirtualProtect
ale co gorsze CloseHandle
odpowiedzialne za zamknięcie uchwytu procesu było po nie tym end
więc zamykało go zbyt wcześnie. Masz działającą chyba poprawnie (na tyle na ile zdążyłem przetestować) funkcję. Zawiera ona proste logowanie do Memo
dla testu to możesz usunąć te linie.
procedure TForm2.Button1Click(Sender: TObject);
const
Target: array[0..3] of byte = ($6E, $69, $63, $6F);
var
Mbi: TMemoryBasicInformation;
Handle: THandle;
buff: array of byte;
hWin, ProcID, BuffSize: Cardinal;
Addr: DWORD_PTR;
BytesRead: NativeUInt;
i: integer;
begin
Addr:= $400000; //tak dla testu initcjalizacja adresu szukania
Memo1.Lines.Clear;
hWin := FindWindow(nil, 'TestSft');
if hWin > 0 then
GetWindowThreadProcessID(hWin, @ProcId);
if ProcId > 0 then
begin
Handle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, ProcId);
if Handle <> 0 then
begin
while (VirtualQueryEx(Handle, Ptr(Addr), Mbi, SizeOf(Mbi)) <> 0) do
begin
if ((Mbi.State = MEM_COMMIT) and (not (Mbi.Protect = PAGE_GUARD)
or (Mbi.Protect = PAGE_NOACCESS)) and (Mbi.Protect = PAGE_READWRITE)) then
begin
Memo1.Lines.Add(Format('%0:.8x', [Int64(Mbi.BaseAddress)]));
SetLength(buff, Mbi.RegionSize);
if ReadProcessMemory(Handle, Mbi.BaseAddress, Buff, Mbi.RegionSize, BytesRead) then
begin
for i := 0 to BytesRead - Length(Target) -1 do
if CompareMem(@Buff[i], @Target[0], Length(Target)) then
begin
Memo1.Lines.Add(Format('Found at %0:.8x', [Int64(Mbi.BaseAddress) + i]));
//ShowMessage('Found');
end;
end;
end;
Addr := Addr + Mbi.RegionSize;
end;
end;
SetLength(buff, 0);
CloseHandle(Handle);
end;
end;