Szukanie adresu znając wartość

Odpowiedz Nowy wątek
2013-03-07 18:16
Maciej22
0

Witam, mam pewne zagadanienie z którym nie mogę sobie poradzić,
Korzystając z delphi potrzebuję znaleść adres mająć wartość tego adresu

wartość jest tekstowa nie zmienna, natomiast adress jest zmienny, nie wiem jak do tego sie zabrac z racji że

ReadProcessMemory(tProc, Ptr(Address), @value, 4, NBR);

Funkcją readprocessmemory mozna pobrać wartość z adresu, a jak to się ma w drugą stronę?

taka funkcja jest w cheatengine, szukałem w kodach źrodłowych aczkolwiek nie mogę ogarnąć.

edytowany 1x, ostatnio: furious programming, 2016-12-13 18:26

Pozostało 580 znaków

2013-03-07 19:43
0

O ile dobrze zorzumialem, bo napisałeś tak, że się motam się czytając powyższe. Musisz przeszukać pamięć procesu i wylistować wyniki. Niech strace, przykładowy kod poniżej. Mam nadzieję, że nie będzie dodatkowych pytań, bo poniższe jest w miarę oczywiste i proste jak się da, a także jak konstrukcja cepa :) I zaraz mnie za pewne "IngliszNazi" @Patryk27 zjedzie, że coś nie tak po angielsku, bo raz to przy okazji tego kodu robił. Ale dodam, że ignlisza to ja się uczyłem tylko cztery lata dawno temu w podstawówce, więc operuje nim jak potrafię. Ważne, że kod działa i wedle mnie taka metoda jest przejrzysta.

W oryginale kod pochodził z Google i zostal dopasowany przeze mnie na moje potrzeby. A co do kodu źródlowego Cheat Engine to przynajmniej ten pisany jeszcze pod Delphi 7 do wersji 5.6 da się ogarnąc. Wyciągałem sobie stamtąd i dostosowałem do WinAPI sposób obslugi HotKeyów we własnych trainerach, także jest to do okiełznania. Ok, oto mój kod. Jak widać jest funkcje do szukania zarówno tablicy bajtów jak i procedura do wyszukania stringów. Ale nie problem to sobie przerobić po swojemu i dopasować do swoich potrzeb aby szukało też wartości liczbowych tak, jak w Cheat Engine.

Ważne, że testowałem to nie raz oraz używałem i oczywiście działa dobrze, tak jak chciałem. Na Google znajdziesz funkcje do pobrania zarówno tak zwanego BaseAddress jak i rozmiaru exeka, coś jak to pokazywane przez LordPE. A co jest przydane kiedy niekoniecznie chcesz szukać w takim zakresie, jak robi to CE.

type
  TOnFindProc = procedure(FindedAddress : Cardinal);

function FindBytesInMemory(APid : DWORD; RangeFrom, RangeTo : Cardinal;
  ArrayOfBytes : array of Byte; OnFindProc : TOnFindProc;
  StopAfterFirstFinding : boolean) : Cardinal;
const
  BufferSize = 65535;
var
  Found : boolean;
  SizeOfArr : Byte;
  HProcess : THandle;
  X, Y, Addr : Cardinal;
  BytesRead, BytesToRead : DWORD;
  Buffer : array[0..BufferSize - 1] of Byte;
begin
  Result := 0;
  Found := False;
  SizeOfArr := Length(ArrayOfBytes);
  HProcess := OpenProcess(PROCESS_ALL_ACCESS, 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
          begin
            if Buffer[X + Y] <> ArrayOfBytes[Y] then
            begin
              Found := False;
              Break;
            end;
          end;
          if Found then
          begin
            Result := Addr + X + Y - SizeOfArr;
            if @OnFindProc <> nil then
            begin
              OnFindProc(Result);
            end;
            Break;
          end;
        end;
      end;
      Addr := Addr + BytesToRead;
      if (Found) and (StopAfterFirstFinding) then
      begin
        Break;
      end;
    end;
    CloseHandle(HProcess);
  end;
end;

procedure FindStringInMemory(APID : WORD; RangeFrom, RangeTo : Cardinal;
  StringToFind : string; IgnoreCase : boolean; OnFindProc : TOnFindProc);
const
  BufferSize = 65535;
var
  FOund : boolean;
  S1, S2 : string;
  SizeOfArr : Word;
  X, Y, Addr : Cardinal;
  ArrayOfBytes : array of Byte;
  HProcess, BytesRead, BytesToRead : DWORD;
  Buffer : array[0..BufferSize - 1] of Byte;
begin
  if StringToFind <> '' then
  begin
    SetLength(ArrayOfBytes, Length(StringToFind));
    for X := Low(ArrayOfBytes) to High(ArrayOfBytes) do
    begin
      ArrayOfBytes[X] := Ord(StringToFind[X + 1]);
    end;
    SizeOfArr := Length(ArrayOfBytes);
    HProcess := OpenProcess(PROCESS_ALL_ACCESS, 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
            begin
              if IgnoreCase then
              begin
                S1 := AnsiLowerCase(Chr(Buffer[X + Y]));
                S2 := AnsiLowerCase(Chr(ArrayOfBytes[Y]));
                if S1 <> S2 then
                begin
                  Found := False;
                  Break;
                end;
              end
              else
              begin
                if Buffer[X + Y] <> ArrayOfBytes[Y] then
                begin
                  Found := False;
                  Break;
                end;
              end;
            end;
            if Found then
            begin
              if @OnFindProc <> nil then
              begin
                OnFindProc(Addr + X + Y - SizeOfArr);
              end;
            end;
          end;
        end;
        Addr := Addr + BytesToRead;
      end;
    end;
    CloseHandle(HProcess);
  end;
end;

EDIT: a co do samego CheatEngine i jego źródla, to w tym którym ja dysponuje, o ile dobrze patrzę to wszystko co potrzeba jest zawarre w module o nazwie memscan. Zaś więcej można dowiedzieć się analizując formatkę i kod głównego modułu, czyli MainUnit.


edytowany 3x, ostatnio: olesio, 2013-03-07 19:55
Masz tę piątkę za angielski, my work here is done :P - Patryk27 2013-03-07 20:02
Dzięki :P Najważniejsze, że w nazwach funkcji API nie ma błędów ;) Chociaż pewnie wtedy by się nie kompilowało ;P A jak ktoś ma jakieś zastrzeżenia, to niech odpisuje przede mną, bo - jeśli dobrze "pacze" - przez około półtorej godziny post pozostawał bez odpowiedzi. Fakt, że ciężko od razu domysleć się, o co na pewno chodzi pytającemu. Ale ponieważ powołał się On na CheatEngine - to wszystko staje się jasniejsze :) - olesio 2013-03-07 20:10

Pozostało 580 znaków

2013-03-07 22:30
Maciej22
0

Serdeczne dzięki, o to chodziło, i wszystko działa jak należy. Co do Cheat Engine to fakt ja dobierałem sie do najnowszej wersji, troche bałan jak dlamnie w plikach źrodłowych CE.

Proszę bardzo. Nie patrzyłem na najnowsze źródła CE, całkiem możłiwe że ze względu iż projekt jest spory, to autor trochę nie utrzymał tam porządku. A i całkiem możliwe, że nauczył się częściowo języka polskiego i trafił na 4p, gdzie poczytał posty @-321oho i przesiadł się na Lazarusa, widząc peany nad tym IDE ;) A tak poważnie zakładal to już kiedyś i pisał o tym na forum. No coż, każdy używa to czego mu wygodnie, wedle mnie źródło w Delphi 7 było jeszcze do ogarnięcia, a po tej przesiadce wolę się nie zagłębiać. Co mi było potrzebne w CE sobie dodałem (reverse bytes). - olesio 2013-03-07 23:12

Pozostało 580 znaków

2013-03-07 23:22
Maciej22
0

Pojawił sie inny problem, a dokładniej z wpisaniem string'u do odcztanego adresu, a mianowicie.

procedure MemWriteString(Address : Integer; Value : String; Bytes : Byte = 0);
VAR
  NB : LongWord;
  Temp : ARRAY [1..255] OF Byte;
  I : Byte;
  Empty:Integer;
  N:DWord;
BEGIN
  Empty := $00;
  if (Length(Value) < 1) then Exit;
  FOR I := 1 TO 255 DO
    BEGIN
      Temp[I] := Ord(Value[I]);
    END;
  IF Bytes = 0 THEN
    I := Length(Value)
  ELSE
    I := Bytes;
    WriteProcessMemory(APID, Ptr(Address), @Temp[1], I, NB);
    WriteProcessMemory(APID, Ptr(Address + Length(Value)), @Empty, 1, N);
end;

i wywoływana przez

  Memwritestring(Address,'testowy_tekst',255);

Aczkolwiek nic nie jest wpisywane do tego adresu

Pozostało 580 znaków

2013-03-08 00:27
0

Zależy czy masz prawa do zapisu w dany obszar procesu. Nie wiem jaki podałeś PID. Można też nie znaleźć stringów we własnym Pidzie. Najlepiej przeanalizuj sobie mój kod dołaczony do tego posta. Uruchom najpierw ___test.exe i później Project1.exe, a następnie kliknij na przycisk i po pokazaniu się komunikatów zobacz jaki jest efekt w oknie procesu ___test.exe. Jak widzisz wszystko działa. Kod dołączonych modułów process_op, a także useful_winapi może Ci się kiedyś przydać. Szczególnie kiedy będziesz chciał jak ja pisać pod WinAPI ;) A podany przez Ciebie kod jest nie jest do konca ok. Ja bym tak zapisu na pewno nie przeprowadzał. Może się tak zdarzyć, że zapiszesz żądany tekst plus 255 - DlugoscTekstuDoWpisania jakimiś losowymi znakami, przez co możesz uszkodzić pamięc tego procesu i go "wyłożyć" albo też wywołać jakieś błedy av. Lepiej zapisywać Length(TekstDoWpisania) i w ogóle zobacz sobie jak u mnie wygląda MemWriteString. Na pewno - według mnie - poprawniej.

EDIT: wyedytowałem swój post, bo na początku nie spojrzałem czy Twój kod jest do końca ok. Poza tym zapomniałem dołaczyć prawidłowe archiwum z kodem ode mnie. A już zdążył machnąc komentarz Pan @_13th_Dragon, co to na PW mi nie odpisze i czekać musze jak @MSM coś wykombinuje z moim DOS Trainerem żeby działał. W ogóle, tak to czas reakcji jest u Was ogromny, a w nocy to tak nagle wszyscy intensywnie tutaj piszą i reagują ;) Ale to dobrze. Byle merytorycznie i z sensem.

EDIT2: Ok - Pan Dragon usprawiedliwiony, już wiem dlaczego pisał na forum, a moje PW ignorował :)


edytowany 5x, ostatnio: olesio, 2013-03-08 00:49

Pozostało 580 znaków

2013-03-08 00:29
0

W moim mikro arcie podawałem uwagi nt używania writeprocessmemory, możesz zajrzeć w -> kompedium wiedzy -> delphi -> artykuly jak źle użyjesz zmiennych efektem będzie nie wpisanie niczego do pamięci albo jakieś błędy

Pozostało 580 znaków

2013-03-08 00:42
0

@tweety: fajnie, artykułow nigdy dość. Ale na Boga/Allaha/Trygława/Whatever! Co za pr0 poziom! Cytuję:

O co chodzi? Przecież wszystko wpisaliśmy zgodnie z nagłówkiem procedury? Wydawało by się że wszystko dobrze...

Widziałeś kiedyś deklaracje funkcji WriteProcessMemory z modułu Windows? Nawet pod starszymi Delphi wygląda ona tak, jak ponizej:

function WriteProcessMemory(hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer;
  nSize: DWORD; var lpNumberOfBytesWritten: DWORD): BOOL; stdcall;

Jakim cudem więc uważasz, że deklarowanie 5 jako ostatniego parametru miało by być ok, skoro jak byk stoi tam magiczne słowo var. Weż to popraw. To już zjadacze crackersów lepsze arty pisali po pijaku do starych zinów i nawet po latach jest to ciekawsze do czytania, bo człowiek może zrobić TSR trainer pod dosową grę (no chyba, że trzeba użyć rejestrów do przechowania DWORD, to się "gupi" TASM mnie czepia i trzeba czekać, aż Dragon wyzdrowieje albo @MSM znajdzie czas na pomoc;)) A nie taki troszkę "z pupki" nawet mikro "artykuł". Ok. Fajnie, że chcesz wzbogacić artykuły swoim wpisem, ale niech to będzie na jakimś merytorycznym poziomie i ogólnie przydatne, a nie takie jak teraz. Imo trochę nie za bardzo.


edytowany 5x, ostatnio: olesio, 2013-03-08 00:53

Pozostało 580 znaków

2013-03-08 04:08
0

Olesio... czep sie prądu jak nie masz czego. napisz coś swojego i zobaczymy na jakim jesteś poziomie... powodzenia..... jaki copyrighter się znalazł....

edytowany 1x, ostatnio: tweety, 2013-03-08 04:09
Wszedł byś chociaż na jego blog do którego link jest podany w stopce każdego jego posta a nie pieprzysz głupoty. - babubabu 2013-03-08 15:05

Pozostało 580 znaków

2013-03-08 12:33
1

No nie ma to jak pr0 zachowane i reakcja na poziomie. Sorry, ale ile Ty masz lat? Bo pyskujesz tutaj jak jakiś dzieciak, zamiast się zastosować. Albo napisać to w sposób kultularny. Nikt nie jest idealny. Ale można napisać, że nie mam racji, bo...? No właśnie. Owszem pisałem tutaj czasami arty. Jeżeli mamy się już porównywać, to na przykład osobiście uważam swój art o HTTP i Synapse (chociaż wiadomo tematyka nieco inna) dostępny pod adresem: Obsługa protokołu HTTP przy użyciu pakietu Synapse za o wiele lepszy, bo zawarlem przykłady kodu i wyczerpująco opisałem temat, aby ktoś początkujący, a może i nie tylko taki, mógl zostać tam skierowany i uzyskał konkretną pomoc. Co do samych operacji na pamięci to odsyłam na swojego bloga (link w synaturze). Wprawdzie nie miałem weny by go od jakiegoś czasu aktualizowac, ale jest tam uważam długi i konkretny wpis dotyczący robienia trainera dla gry "Max Payne". Dołączyłem do niego, uwazam dobrze napisany i przydatny kod trainera w WinAPI, co pozwoli się łatwo komuś nauczyć jak można pisać takie rzeczy. Sam artykuł omawia po kolei jak doszedłem do ustalenia odpowiednich wartości w pamięci i je analizowałem. Na przyszłość radzę ochłonąć, a nie pyskowoć kiedy ktoś wytknie Ci błedy. Napisałeś arta? Fajnie, ale ciskasz się kiedy ktoś zwraca Tobie uwagę, że jest on na słabym poziomie merytorycznym. Można było poprawić to, o czym wspomniałem, a nie pyszczyć. Nie jestem copyrighterem, nie jestem też żadnym guru. Jednak mogę wyrazić swoją opinię o czymś co polecasz sam w tym temacie, a co wiele zarówno do tematu nie wniosło, a poziom tego tekstu - wybacz - jest słaby i . Mam swoje zdanie i po tym co przeczytałem w Twoim wykonaniu go nie zmienię. Krytyka była również - według mnie - konstruktywna, bo pokazałem co najbardziej mnie raziło jak to przeczytałem. Kiedy już coś publikujemy jako pomoc dla innych, fajnie żeby to miało ręce i nogi. Wiadomo, że Internet tak, jak papier - niemal wszystko przyjmie. Ale później sieć zalana jest wątpliwej jakości materiałami, które swoim otagowaniem, treścią, poziomiem i tak dalej - tylko powodują zamęt i po prostu go zaśmiecają, zamiast służyć ludziom. Ty w opowiedzi jednak umiesz się tylko ciskać. Także opinie również o Twoim poziomie ostatecznie sobie wyrobiłem :/


edytowany 2x, ostatnio: olesio, 2013-03-08 12:37
średnio mnie obchodzi co Pan o tym sądzi;] - tweety 2013-03-08 15:29
Ok, Twoje prawo. Tylko wystawiając artykul na widok publiczny i podając do niego link, musisz się liczyć z pewnymi faktami. Poza tym, że ktoś to oczywiście będzie mógł przeczytać. To również będzie mógl wyrazić o tym swoją opinię. Niekoniecznie pozytywną. A w swojej napisałem to, co mi nie odpowiada w tym artykule. I tyle. - olesio 2013-03-09 21:39

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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