Write/Read ProcessMemory() - Multilevel pointer

04/07/2013 16:35 H4rtzer#1
Hallo!

Ich habe für ein Spiel den BasePointer gefunden.
Sein Adresse ist: FF96AFA8, das erste Offset ist:14, das Zweite ist 50!
PHP Code:
DWORD BasePointer 0xFF96AFA8
WORD offset 0x0014;
WORD offset2 0x0050;
ReadProcessMemory(solHandle,(LPCVOID)(BasePointer+offset2+offset),&pointed4NULL); 
Wie muss es richtig sein. Die Funk. Readp... gibt eine NULL aus. Alles andere bis auf die Pointer - Offset Geschichte ist in Ordnung.
04/07/2013 17:19 snow#2
Das ist nicht zufällig ein Spiel mit der CryEngine, oder?

Hier ein Beispiel für die Position mit Multi-Level-Pointern: (extra für dich kommentiert und der Code geht bestimmt besser, aber egal)

Code:
	DWORD *baseAddress = (DWORD *)((DWORD)hCryAction + baseCoordOffset); // äquivalent zum BasePointer
	DWORD *offset1	   = (DWORD *)(*baseAddress  + COORD_1); // Adresse, die in baseAddress ist + 1. Offset
	DWORD *offset2     = (DWORD *)(*offset1 + COORD_2); // Adresse, die in offset1 ist + 2. Offset
	DWORD *content= (DWORD *)(*offset2 + COORD_3); // Adresse, die in offset2 ist + 3. Offset

        struct coordinates *st = (coordinates *)(*content + COORD_X); // und hier die Verwendung: Einen Struct-Pointer auf den Inhalt von content + COORD_X (das ist bei mir 0x0 und ist nur zur Übersichtlichkeit da)
Genauso musst du es auch mit ReadProcessMemory machen. BasePointer auslesen und den Wert + offset auslesen usw. :)
04/07/2013 17:39 H4rtzer#3
Danke für deine Antwort. Ist nur Solitär. Aber das hilft mir nur bedingt weiter. Es wäre nett, wenn du dich direkt aus Solität beziehen könntest. ...Ich bin nämlich gerade am Verzweifeln!
04/07/2013 17:46 snow#4
Bei Solitär ist das der selbe Weg, mal auf meinen Code umgeschrieben (ich habe eine DLL, weshalb ich kein ReadProcessMemory() benötige, du musst natürlich immer den Weg über ReadProcessMemory() gehen)

Code:
DWORD *baseAddress = (DWORD)*0xFF96AFA8; // nicht sicher, ob man auch die Base Address des Programms braucht 
	DWORD *offset1	   = (DWORD *)(*baseAddress  + 0x14); // Adresse, die in baseAddress ist + 1. Offset
	DWORD *content     = (DWORD *)(*offset1 + 0x50); // Adresse, die in offset1 ist + 2. Offset -> da drinnen ist der Content.
Das Prinzip von Multilevelpointern ist halt, dass in einer Adresse & einem Offset eine neue Adresse hinterlegt ist, die + ein weiteres Offset ergibt eine Adresse, in der eine Adresse ist (= ein Pointer) usw.
04/07/2013 17:52 H4rtzer#5
Danke, das erscheint mir schon logischer.
(DWORD)*0xFF96AFA8 ...Hier gibt es die Fehlermeldung: Der Operand muss ein Zeiger sein.

Ich meine, wenn ich auf meine statische Basisadresse die Offsets addiere, dann müsste ich auf die (dynamische)Adresse kommen in der der gewünschte bzw. der auszulesende Wert steht. Oder?
04/07/2013 18:01 snow#6
Hoppla, Tippfehler. Natürlich muss der Pointer-Cast das Asteriks-Dings (*) beinhalten. (DWORD*) statt (DWORD)* löst das ganze.

Ne, du hast in der statischen Basisadresse eine (wahrscheinlich) variable Basisadresse. Diese + das Offset ergibt wieder eine variable Adresse (die über die variable Adresse in der statischen Adresse + das immer gleich bleibende Offset bekommt), mit der + dem 2. Offset kommt man wieder auf eine variable Adresse, in der der Wert liegt.
Bisschen kompliziert, aber wenn man mal das Prinzip der Pointer verstanden hat, ist es eigentlich relativ leicht. :)
04/07/2013 18:20 H4rtzer#7
PHP Code:
#include <iostream>
#include <windows.h>

using namespace std;
int a;
int main ()
{
DWORD *baseAddress = (DWORD*) 0xFF96AFA8// nicht sicher, ob man auch die Base Address des Programms braucht 
DWORD *offset1       = (DWORD *)(*baseAddress  0x14); // Adresse, die in baseAddress ist + 1. Offset
DWORD *content     = (DWORD *)(*offset1 0x50); // Adresse, die in offset1 ist + 2. Offset -> da drinnen ist der Content.

cout << *content << content << endl;
cin >> a;

return 
0;

Ich habe das mal kompiliert und erhalte nun einen neuen seltsamen Fehler.:(

"Unbehandelte Ausnahme bei 0x76f815de in test5.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0xff96afa8."
04/07/2013 18:27 MrSm!th#8
Beschäftige dich nochmal mit der Sprache und lerne, wie Pointer funktionieren.
Kleiner Tipp nebenbei: Dein Programm und Solitair teilen sich nicht denselben Adressraum, du kannst Pointer nicht direkt dereferenzieren.
04/07/2013 18:36 H4rtzer#9
Quote:
Originally Posted by MrSm!th View Post
Beschäftige dich nochmal mit der Sprache und lerne, wie Pointer funktionieren.
Kleiner Tipp nebenbei: Dein Programm und Solitair teilen sich nicht denselben Adressraum, du kannst Pointer nicht direkt dereferenzieren.
Danke für den Tipp. Wie kann ich also in den anderen Adressraum "übergreifen"? Bei der Funktion:
PHP Code:
OpenProcess (PROCESS_ALL_ACCESS PROCESS_VM_READ PROCESS_VM_WRITEfalseProcessID); 
muss ich die ja die Rechte in den Parametern übergeben. Muss ich bei diesem Problem ähnlich heran gehen?
04/07/2013 18:38 MrSm!th#10
ReadProcessMemory
04/07/2013 18:58 snow#11
"du musst natürlich immer den Weg über ReadProcessMemory() gehen"

und lass das mit "4" bei der size & nutze sizeof(type), sonst hast du ein Problem, wenn das Programm auf einem System läuft, das eine andere Größe für DWORD hat.
04/07/2013 19:19 Nightblizard#12
Quote:
Originally Posted by snow911 View Post
"du musst natürlich immer den Weg über ReadProcessMemory() gehen"

und lass das mit "4" bei der size & nutze sizeof(type), sonst hast du ein Problem, wenn das Programm auf einem System läuft, das eine andere Größe für DWORD hat.
Da er hier mit Windows arbeitet, ist das egal ob er "4" nimmt oder "sizeof(DWORD)", da DWORD auf allen Windows Systemen eine größe von 4 Bytes hat. Und sobald er auf einen Unixoiden wechselt kann er ReadProcessMemory eh nicht mehr verwenden.
Problematisch ist eher, dass er DWORD zum Auslesen von Pointern benutzt. Das geht nur so lange gut, wie er sich in einer 32 bit Umgebung befindet. Erstellt er sein Programm für x64, sind die Pointer plätzlich 8 Bytes groß und er ließt dann Müll aus, weshalb er lieber DWORD_PTR nehmen sollte. Dann greift auch wieder das Argument, dass er nicht sizeof(4) sondern sizeof(DWORD_PTR) machen soll, weil das hier einen wirklichen Unterschied macht.

Siehe:
[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]
04/08/2013 18:06 H4rtzer#13
In meinem BasePointer (solitaire.exe+BAFA8) steht solitaire.exe. Wie komme ich an die Adresse für solitaire.exe! Ich dachte gehört zu haben, dass solitaire.exe dem Prozesshandle entspricht. Ist das richtig?
04/08/2013 18:17 Master674b#14
Quote:
Originally Posted by H4rtzer View Post
In meinem BasePointer (solitaire.exe+BAFA8) steht solitaire.exe. Wie komme ich an die Adresse für solitaire.exe! Ich dachte gehört zu haben, dass solitaire.exe dem Prozesshandle entspricht. Ist das richtig?
Nö ists nicht. Schau dir mal [Only registered and activated users can see links. Click Here To Register...] an.
04/08/2013 18:22 H4rtzer#15
Das hilft mir leider nicht weiter, aber trotzdem Danke!