Szukanie array of bytes w innym procesie

2

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;
0

Kurde powiem że klasa :D Rewelacyjnie śmiga poza jedną rzeczą.

007B9000
007BE000
007C2000
0097E000
00988000
00BB2000
00BC0000
00C90000
00CD8000
00D50000
00D60000
00D70000
00E70000
00E80000
00E90000
00EA0000
0173C000
0174D000
01750000
0303F000
0304F000
03050000
03098000
030D8000
030EF000
03100000
03130000
0333F000
03C80000
03E80000
05F80000
05FEB000
07F80000
0800A000
0804C000
080B8000
080F8000
08138000
08140000
08198000
...
77079000
77127000
77182000
77224000
77242000
77365000

Dlaczego mi to dodaje tak dużo adresów do memo zamiast tylko te z napisem "found at"?

1

Bo chciałem aby logowało jakie obszary pamięci są sprawdzane (te do których jest dostęp). Aby logowało tylko gdzie znalazło trzeba usunąć:

Memo1.Lines.Add(Format('%0:.8x', [Int64(Mbi.BaseAddress)]));
0

Ok. Wystarczyło usunąć Memo1.Lines.Add(Format('%0:.8x', [Int64(Mbi.BaseAddress)]));

Dzięki za gotowca w sumie :)
Miłego wieczoru.

0
kAzek napisał(a):

bezpieczniej:

          for i := 0 to Length(Buff)  - Length(Target) do
          if CompareMem(@Buff[i], @Target[1], Length(Target)) then
          begin
            ShowMessage('Found');
          end;

I nadal jedziesz o 1 bajt za daleko. Length(Buff) - Length(Target)-1 być powinno. Rzadko się wykrzaczy, ale jednak jak wejdziesz na kolejną stronę pamięci będzie lipa.

0
Błękitny Krawiec napisał(a):

I nadal jedziesz o 1 bajt za daleko. Length(Buff) - Length(Target)-1 być powinno.

Racja

Błękitny Krawiec napisał(a):

Rzadko się wykrzaczy, ale jednak jak wejdziesz na kolejną stronę pamięci będzie lipa.

W ostatecznym kodzie było

for i := 0 to BytesRead - Length(Target) do

Co także jest źle (ciągle ten 1 bajt) ale w tym kodzie niemożliwe jest wjechać na kolejną stronę pamięci ze względu na działanie funkcji VirtualQueryEx i założenie że szukana ilość bajtów wynosi co najmniej 1. Niemniej dzięki za uwagę już poprawiam.

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