Przeszukiwanie pamięci (FindBytesInMemory by Olesio)

0

Mam funkcję Olesia:

 
function FindBytesInMemory(APID : WORD; RangeFrom, RangeTo: Cardinal; ArrayOfBytes: array of Byte): Cardinal;
const
  BufferSize = 65535;
var
  FOund : boolean;
  SizeOfArr : Byte;
  X, Y, Addr : Cardinal;
  HProcess, BytesRead, BytesToRead : DWORD;
  Buffer : array[0..BufferSize - 1] of Byte;
begin
  Result := 0;
  SizeOfArr := Length(ArrayOfBytes);
  HProcess := OpenProcess(PROCESS_VM_READ, False, APID);
  if (HProcess > 0) and (RangeFrom < RangeTo) then
  begin
    Addr := RangeFrom;
    while Addr < RangeTo do
    begin
      BytesToRead := BufferSize;
      if (RangeTo - Addr) < BytesToRead then
      begin
        BytesToRead := RangeTo - Addr;
      end;
      ReadProcessMemory(HProcess, Pointer(Addr), @Buffer[0], BytesToRead, BytesRead);
      if BytesRead > 0 then
      begin
        for X := 0 to BytesRead - 1 do
        begin
          Found := True;
          for Y := Low(ArrayOfBytes) to High(ArrayOfBytes) do
            if Buffer[X + Y] <> ArrayOfBytes[Y] then
            begin
              Found := False;
              Break;
            end;
          if Found then
          begin
            Result := Addr + X + Y - SizeOfArr;
            Break;
          end;
        end;
      end;
      Addr := Addr + BytesToRead;
    end;
  end;
  CloseHandle(HProcess);
end;

Pamięć przeszukiwana jest od końca zakresu do jego początku, dlaczego? Z tego co widzę, powinno być od początku do końca.

Ustawiam zakres od $0000000 do $FFFFFFFF i szukam w pamięci ciągu bajtów "7B226163". Według Cheat Engine istnieją dwa takie ciągi. Mnie interesuje ten pierwszy począwszy od $0000000. Mimo to zczytuje mi ten drugi (czyli pierwszy od końca). Dlaczego?

0

A sprawdzałeś czy w ogóle wyszukuje oba adresy? Pamięć podzielona jest na obszary o różnych prawach dostępu - może to jest przyczyną.

0

Jak dam mniejszy zakres to łapie bez problemu odczytuje pierwszą wartość. Jak dam cały zakres to czyta pierwsze od końca, a nie od początku. Jak to naprawić?

0

Złoty Szczur. Nie wydaje się mi że jest tak jak piszesz. Nie raz używałem tę funkcję i mam w zdaje się nie raz tutaj publikowych kodach tę funkcję jako wyszukującą więcej niż jeden adresów z bajtami. I ten pierwszy zawsze zgadzał się mi z pierwszym w Cheat Engine. Może być tak jak pisze poprzednik. Kod nie jest idealny, znalazłem go kiedyś nie pamiętam gdzie i już sobie po drobnych przeróbkach zostawiłem. Linia z Addr := RangeFrom; po pierwszym if'ie "mówi", że początek szukania to adres początkowy.

Warunek unila oraz zwiększanie miejsca o ilośc bajtów również wskazują że wyszukiwanie jest od - do. Ale więcej poradzić Tobie nie potrafię. Jak wiecie z powodów, o których nie chce pisać po raz 1000czy bo ktoś uważa, że mam taki obowiązek. I nieważne że forum jest darmowe i zajmujemy się nim hobbystycznie. Pojawiam się rzadko. Nie moderuje aktywnie ani nie czytuje praktycznie nic tutaj. Bo się mi po prostu nie chce. Teraz jestem w pracy na nocce. Miałem chwilę to zajrzałem na pocztę i zobaczyłem że mnie przywołano, to spojrzałem o co chodzi. A o więcej zapytaj bardziej doświadczonych i mających czas na odpisywanie bez zbędnych opóźniej forumowiczów.

0

user image

W Cheat Engine znajduję 3 adresy z interesującym mnie ciągiem bajtów.

Twoja funkcja zwraca mi cały ciąg na adresie:

F12083A

a nie na:

83DE442

mimo, że "F" jest dalej w pamięci.

0
          if Found then
          begin
            Result := Addr + X + Y - SizeOfArr;
            Break;
          end;

Wywal tego break'a i wypisz wartość zwróconą. Pewnie po znalezieniu wart. przerywa tylko pętlę szukania wzorca w danej "porcji" i mieli dalej. W rezultacie masz ost. adres

0

@szopenfx - nie tyle wywalić Break, co zamienić go na Exit, bo po znalezieniu danych funkcja powinna całkowicie przerwać działanie; Obecnie Break znajduje się w zagnieżdżonej pętli, więc przerywa tylko pętlę For, a pętla While działa dalej, czyli szuka kolejnego wystąpienia;

Funkcja ta będzie prawidłowo działać (czyli zwracać pierwsze wystąpienie danych), jeśli w całej badanej pamięci szukane dane wystąpią raz; W przeciwnym razie zawsze będzie zwracany adres ostatniego wystąpienia;

Pozostaje też kwestia podziału szukanych danych na dwa niezależne bufory; Funkcja nie znajdzie danych, jeśli ich początkowy fragment znajduje się w buforze Buffer, a końcowy jeszcze nie został pobrany; Tu trzeba by zastosować mechanizm podobny do metody parsowania wejściowego strumienia przez klasę TStrings, którego wynikiem jest podział strumienia na linie tekstu; Ta metoda nie zna długości poszczególnych linii, a jednak potrafi po kawałku wczytywać dane ze strumienia i odpowiednio dodawać linie do listy;

Ostatnią rzeczą, o której należy wspomnieć, to pętla porównująca bufory; Nie jest ona w ogóle potrzebna, dlatego że szuka idealnego dopasowania, więc należy ją zamienić np. na CompareMem.

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