AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Dynamische Memory Adressen - Startpunkt herausfinden

Dynamische Memory Adressen - Startpunkt herausfinden

Ein Thema von milos · begonnen am 19. Jul 2015 · letzter Beitrag vom 24. Jul 2015
Antwort Antwort
Seite 1 von 2  1 2   
Benutzerbild von milos
milos

Registriert seit: 14. Jul 2008
Ort: Bern (CH)
494 Beiträge
 
Delphi 10.4 Sydney
 
#1

Dynamische Memory Adressen - Startpunkt herausfinden

  Alt 19. Jul 2015, 05:31
Hey,

ich möchte einen Status in einem Spiel über ReadProcessMemory auslesen. Das würde auch soweit klappen, jedoch sind die Adressen nach jedem Neustart des Spiels anders.

Ich weiss, dass man nach einem "Eintrittspunkt" suchen muss, der dynamisch ist und ich dann einem festen wert addieren kann um zu meinem Ziel zu kommen, jedoch weiss ich nicht wie ich diesen "Eintrittspunkt" finden soll. Müsste halt bei jedem Start neu gesucht werden oder?

Hoffe einer kann mir hier helfen ^^

Freundliche Grüsse

Edit: Mir geht es primär um einen Weg wie man das in Delphi lösen kann. Wie das mit Memory Searchern geht weiss ich, bringt mir aber leider nicht viel :/
Milos

Geändert von milos (19. Jul 2015 um 06:07 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.197 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#2

AW: Dynamische Memory Adressen - Startpunkt herausfinden

  Alt 19. Jul 2015, 10:45
Man sucht sich vorher die "Signatur" der Funktion heraus die man finden will. (Per Disassembler o.ä.)
Die Signatur ist eine eindeutige Bytefolge innerhalb der exe die am Anfang der gewünschten Funktion beginnt.

Wenn du die Funktion dann zur Laufzeit ermitteln willst musst du den Speicher des fremden Prozesses nach der Signatur durchsuchen. Die Startadresse der Signatur ist die Adresse der Funktion.
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."
  Mit Zitat antworten Zitat
Benutzerbild von milos
milos

Registriert seit: 14. Jul 2008
Ort: Bern (CH)
494 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: Dynamische Memory Adressen - Startpunkt herausfinden

  Alt 19. Jul 2015, 11:32
Man sucht sich vorher die "Signatur" der Funktion heraus die man finden will. (Per Disassembler o.ä.)
Die Signatur ist eine eindeutige Bytefolge innerhalb der exe die am Anfang der gewünschten Funktion beginnt.

Wenn du die Funktion dann zur Laufzeit ermitteln willst musst du den Speicher des fremden Prozesses nach der Signatur durchsuchen. Die Startadresse der Signatur ist die Adresse der Funktion.
Danke für die Antwort!
Ich bin mir gerade nicht sicher ob ich dich richtig verstanden habe, aber wenn doch, dann hab ich das alles bisher so gemacht, jedoch ändert sich die Adresse nach jedem Neustart des Spiels wieder, aber nur um den "Einstiegspunkt", siehe anhang. Den müsste ich irgendwie über Delphi rausbekommen also wenns geht ohne externes Programm wie Cheat Engine oä.

Falls ich dich komplett falsch verstanden haben sollte, und die Lösung eigentlich schon geschrieben wurde, tut es mir sehr leid. Bin ziemlich frisch in dem Bereich ^^

Freundliche Grüsse
Miniaturansicht angehängter Grafiken
i5ks.jpg  
Milos
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.197 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#4

AW: Dynamische Memory Adressen - Startpunkt herausfinden

  Alt 19. Jul 2015, 16:36
Die Signatur ist ja gerade ist ja gerade dafür da die Funktion wiederzufinden OBWOHL die Adresse sich geändert hat.

Im Anhang ist ein Bild von einer Exe in einem Disassembler. Links siehst du rot Umrandet die ersten paar Befehle der Funktion die du finden willst (deren Signatur du willst). Auf der rechten Seite in der Hex-Ansicht siehst du die binäre Darstellung (als Hexwerte) dieser Befehle. Du kopierst dir die ersten x Bytes und schaust ob diese Bytereihenfolge mehr als einmal (also noch an anderen Stellen) vorkommt. Falls ja, musst du die Signatur solange vergrößern bis sie eindeutig ist.

In deinem Programm suchst du nun nach genau dieser Bytefolge (das ist jetzt die aus dem Beispiel, du musst natürlich deine Signatur benutzen):

Zitat:
56 33 F6 57 8B 3D 24 C2 5B 00 C7 05 48 86 5F 00 74 C6 5D 00 39 35 50 86 5F 00 76 1B
Da sich zumindest für far-jumps/calls/etc die Adressen ändern können musst du diese Bytes ignorieren.
Dadurch ergibt sich in meinem Fall folgendes Muster:

Zitat:
56 33 F6 57 8B 3D ** ** ** ** C7 05 ** ** ** ** ** ** ** ** 39 35 ** ** ** ** 76 1B
** bedeutet in dem Fall dass diese Bytes bei der Suche nach der Signatur ignoriert werden.
Du solltest jetzt nochmal sichergehen dass die Signatur trotz der "Don't care"-Bytes immernoch eindeutig ist!


Edit: Ich glaube ich hab dich ein bisschen falsch verstanden. Du suchst keine Funktion sondern einen einzelnen Variablenwert. Du kannst mit GetModuleHandle(nil) die Startadresse deines Prozesses herausfinden. Ggf. musst du dann die Basisadresse des Spiels per DLL-Injection herausfinden.
Miniaturansicht angehängter Grafiken
signatur.jpg  
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."

Geändert von Neutral General (19. Jul 2015 um 16:45 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#5

AW: Dynamische Memory Adressen - Startpunkt herausfinden

  Alt 19. Jul 2015, 22:00
Mein Wissen über die Win-API ist etwas rostig, aber an sich sollte es nicht so schwer sein.

Ich verstehe dein Problem so:
Du hast beispielsweise die Speicheradresse 15 wo sich die Variable befindet und die Basisadresse bei des Spiels bei 9. Beim nächsten Start ist die Speicheradresse bei 33 und die Basisadresse des Spiels bei 27.
Dh. die Adresse der Variable ist relativ zur Basisadresse + 6.

Die Basisadresse ist meistens konstant, kann sich aber ändern oder wenn es eine Maßnahme gegen cheating ist, wird es sich ändern.
Um die Basisadresse rauszufinden, muss im Speicherbereich des Spiels laut GetModuleHandle
Zitat:
If this parameter is NULL, GetModuleHandle returns a handle to the file used to create the calling process (.exe file).
folgender Code ausgeführt werden:
Delphi-Quellcode:
  //
  GetModuleHandle(NIL)
"handle to the file" ist die Startadresse / Basisadresse / "Eintrittspunkt" so wie du das fälschlicherweise nennst.

Weiters bieten sich zwei Methoden an, um Code in einem fremden Speicherbereich / Prozess auszuführen:
- Dll Injection: du injizierst eine Dll die den Code oben ausführt
- Code Injection: du injizierst direkt Code in den fremden Process, führst in aus und liest das Result aus

Dll Injection ist einfach - vorallem weil es sehr viele Quellen gibt, wo das genau beschrieben wird.

Code Injection ist angenehmer, aber dafür etwas komplizierter.
Für die Codeinjection musst Speicher im fremden Process allozieren, den Speicherbereich per MSDN-Library durchsuchenVirtualProtect() auf PAGE_READWRITE_EXECUTE setzen (also ausführbar machen), deinen Code dort reinschreiben, dann einen weiteren Speicherbereich allozieren, wo du deine Daten festhältst (Variablen, Rückgabewerte usw - in diesem Fall genau 4 Bytes).
Weiters musst du in der Bytefolge deines Codes die Adresse des Speicherbereichs, denn du gerade alloziert hast, reinschreiben.
Anschließend kannst du dein Code ausführen, da er nun alle Daten enthält.
Nachdem dein Code fertig ist (WaitForSingleEvent() mit dem Handle von CreateRemoteThread oder so ähnlich - recherchieren!), kannst du den Rückgabewert anschließend wieder auslesen.

Warnung: VAC.
Sobald du im Spielprozess rumpfuscht, wird VAC sich ein Profil von dir machen. Bei nem offiziellen Server wirst du direkt geebannt, offline tricksen die auch rum - die merken sich, wer gerade an Blödsinn Interesse hat bzw. nen "cheat" entwickelt. Ich würd das einfach sein lassen. Sofern du es nicht gepirated hast, ist es nicht Wert, die ~15€, die du für das Spiel investiert hast, zu verlieren.
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG
  Mit Zitat antworten Zitat
Benutzerbild von milos
milos

Registriert seit: 14. Jul 2008
Ort: Bern (CH)
494 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Dynamische Memory Adressen - Startpunkt herausfinden

  Alt 21. Jul 2015, 12:30
Vielen dank für eure antworten

Aphton hat es erfasst. Ich würde gerne die Basisadresse () eines Prozesses finden. Über den Weg mit dem Injecten und GetModuleHandle bin ich über Google schon gestossen, jedoch ist das Injecten genau das welches ich eigentlich vermeiden will, da das ganze Extern laufen soll ohne wirklich in den Prozess eingreifen zu müssen ausser das ich ein paar Daten auslesen will. Im Internet bin ich über eine Interessante Funktion gestossen:

Delphi-Quellcode:
function GetBasePointerOfModule(ProcessId: dword; Modulename: string): Integer;
var
  FSnapshotHandle: THandle;
  FModulEntry32: MODULEENTRY32;
  s: string;
begin
  Result := 0;
  FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ProcessId);
  try
    if FSnapshotHandle <> INVALID_HANDLE_VALUE then
    begin
      FModulEntry32.dwSize := SizeOf(FModulEntry32);
      if Module32First(FSnapshotHandle, FModulEntry32) then
      begin
        repeat
          s := FModulEntry32.szModule;
          if s = Modulename then
          begin
            Result := Integer(FModulEntry32.modBaseAddr);
            break;
          end;
        until (not Module32Next(FSnapshotHandle, FModulEntry32));
      end;
    end;
  finally
    closeHandle(FSnapshotHandle);
  end;
end;
Diese gibt mir immer eine Adresse zurück die immer gleich ist, bis man das Spiel neu startet. Jedoch scheint es nicht die gesuchte Basisadresse zu sein. Die Funktion benutze ich so:

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
var
  GameHandle : Cardinal;
  BaseAddress : int64;

  Address : Int64;
  Bytesread: SIZE_T ;
  puffer : DWORD;

  Window : cardinal;
  PID : cardinal;
begin

  Window := FindWindow(nil,'Counter-Strike: Global Offensive');
  GetWindowThreadProcessId(Window,PID);
  GameHandle := OpenProcess(PROCESS_VM_READ,false,PID);

  if GameHandle > 0 then
  begin
    BaseAddress := GetBasePointerOfModule(PID, 'csgo.exe');

    showmessage('Base: ' + IntToHex(BaseAddress,8));

    Address :=BaseAddress + $0;

    ReadProcessMemory(GameHandle, ptr(Address), @puffer, sizeof(puffer), Bytesread);

    showmessage(puffer.ToString());
  end;
end;
Im Anhang gibts ein Bild, welches im Dialogfenster die zurückgegebene Adresse und unter dem Fenster die Baseadresse von Cheat Engine zeigt. Ist das ein Fehler der Funktion oder ist "csgo.exe" wahrscheinlich das falsche Modul?

Ich hoffe es gibt einen der weiter weiss ^^

Freundliche Grüsse

Wegen VAC: Danke für die Warnung Ich habe nicht vor einen "echten Hack" mit Aimbot, Wallhack usw. zu schreiben. Das ganze dient eher als kleine Übung und da es mich in den letzten Tagen sehr Interessiert hat würde ich da auch gerne weiter machen. Nun ist es nur noch die Basisadresse die mich daran hindert :/ Alles natürlich auf meinem Smurf, offline gegen Bots und ohne aktiviertem VAC

Und auch wenn man es mir nach dem Thread wahrscheinlich nicht glauben mag: Ich hacke nicht, dafür spiele ich schon zu lange Teambasierte Competetive Spiele mit Leidenschaft, als dass ich mein Spielerlebniss mit Hacken zerstöre
Miniaturansicht angehängter Grafiken
0uqb.jpeg  
Milos
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.197 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#7

AW: Dynamische Memory Adressen - Startpunkt herausfinden

  Alt 21. Jul 2015, 12:36
Warum denkst du, dass es nicht die richtige Basisadresse ist?
Vllt. sind deine Nachfolgenden Berechnungen einfach nicht ganz korrekt?

(PS: Ich denke "Eintrittspunkt" ist durchaus ein nutzbarer Begriff in dem Zusammenhang wenn man bedenkt, dass es im Englischen "entry point" genannt wird.)
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."
  Mit Zitat antworten Zitat
Benutzerbild von milos
milos

Registriert seit: 14. Jul 2008
Ort: Bern (CH)
494 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: Dynamische Memory Adressen - Startpunkt herausfinden

  Alt 21. Jul 2015, 13:40
Warum denkst du, dass es nicht die richtige Basisadresse ist?
Vllt. sind deine Nachfolgenden Berechnungen einfach nicht ganz korrekt?

(PS: Ich denke "Eintrittspunkt" ist durchaus ein nutzbarer Begriff in dem Zusammenhang wenn man bedenkt, dass es im Englischen "entry point" genannt wird.)
Weil ich es so probiert habe:
  1. Spiel gestartet.
  2. Basisadresse der Methode abgefragt und 008D0000 bekommen.
  3. Danach habe ich über Cheat Engine den Wert gesucht den ich haben wollte: 047AEC0C
  4. Wenn ich nicht falsch liege bekomme ich die Speicheradresse indem ich die Basisadresse von der in Cheat Engine gefundene Speicheradresse subtrahiere: 047AEC0C - 008D0000 = 3EDEC0C
  5. Nun lese ich in Delphi die Adresse (Basisadresse + Speicheradresse) aus und das klappt natürlich.
  6. Um ganz sicher zu sein teste ich dies natürlich indem ich das Spiel neustarte.
  7. Also versuche ich nochmal die errechnete Speicheradresse (03D1AE4C) mit der neuen Basisadresse (00FB0000) zu addieren und diese Adresse auszulesen, was nun nicht mehr klappt. (00FB0000 + 3EDEC0C = 4E8EC0C)
  8. Habe also Cheat Engine wieder angeschmissen, die Adresse manuel gesucht und siehe da: Die neue Adresse ist 0456E30C, also anders als ich es einen Schritt vorher versucht habe...
Habe ich hier was falsch gemacht?

Könnte es sein das csgo.exe nicht das richtige Modul ist?
BaseAddress := GetBasePointerOfModule(PID, 'csgo.exe'); Hab das ganze gerade 3 mal getestet um sicher sein zu können keinen Fehler gemacht zu haben.

Freundliche Grüsse
Milos

Geändert von milos (21. Jul 2015 um 13:43 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.197 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#9

AW: Dynamische Memory Adressen - Startpunkt herausfinden

  Alt 21. Jul 2015, 14:05
Hast du in Cheatengine mal geschaut ob es einen Pointer auf deinen Wert gibt? Wahrscheinlich wird für deinen Wert dynamisch Speicher reserviert und der Speichermanager hat dann aufgrund von unterschiedlichen Speicherreservierungen/Freigaben zum letzten Start (man tut ja nicht jedes mal exakt das gleiche, d.h. für unterschiedliche (oder unterschiedlich viele) Daten wurden ggf. in unterschiedlicher Reihenfolge Speicher reserviert).

Die Speicheradresse zum Pointer auf diesen Wert könnte aber statisch sein (zumindest so statisch, dass er im Verhältnis zur Basisadresse immer am selben Ort im Speicher zu finden ist). Über den Pointer kriegst du dann natürlich dann auch den Wert an den du wirklich ranwillst (bzw. die Adresse des Werts).

Wenn du Pech hast musst du auf den Pointer auf den Pointer auf den Wert zurückgehen, falls der Pointer auf den Wert auch dynamisch ist.

(Okay das war z.T. etwas anstrengend zu lesen - ich hoffe man kann es trotzdem verstehen^^)
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#10

AW: Dynamische Memory Adressen - Startpunkt herausfinden

  Alt 24. Jul 2015, 15:37
(PS: Ich denke "Eintrittspunkt" ist durchaus ein nutzbarer Begriff in dem Zusammenhang wenn man bedenkt, dass es im Englischen "entry point" genannt wird.)
Nein.
Mit der "Basisadresse" meint er "ImageBase", nicht EntryPoint.. Das sind zwei verschiedene Dinge.
Die ImageBase ist üblicherweise die Startadresse des Images (Exe / DLL) im Speicher (meist 0x00400000) und EntryPoint ist eine RVA (relative virtual address) zum ersten Code im ".code" oder ".text" Segment einer exe/dll.
Code:
ImageBase = 0x00400000
EntryPoint = 0x00000400

Address of First Asm Code (entry point) = ImageBase + EntryPoint = ... usw
Edit: Zum eigentlichen Thema - zum Beitraag #8
Wie Neutral General erwähnt hat, muss es nicht so sein, dass die Variable, die du auslesen willst, sich immer an derselben Adresse befindet. Das kann spieltechnisch realisiert sein, oder vlt funkt dir auch ASLR (oder ähnliches) rein. Ist jedoch alles umgehbar, man muss halt nur vorher rausfinde, was für ein Fall vorliegt.

Führ z.B. das hier 2x mal aus:
Delphi-Quellcode:
var
  myVar: ^Integer;
begin
  new(myVar);
  showMessage(IntToHex(myVar, 8));
end;
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG

Geändert von Aphton (24. Jul 2015 um 15:48 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:33 Uhr.
Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf