Speicher lesen C++
lima-city → Forum → Programmiersprachen → C/C++ und D
ahnung
auslese
auto
bereich
break
code
falle
funktionieren
http
not
pointer
programmieren
sagen
sinn
sparen
speichern
spiel
sternchen
type
windows
-
Hallo Community,
Ich möchte den Speicher, eines Programmes, an einer bestimmten Stelle lesen.
Um das ganze nachvollziehbarer zu machen, nehme ich mal ein funktionierendes und echtes Beispiel.
Jeder der das Spiel Guild Wars 2 besitzt kann es testen. Ohne dem Spiel ist es eben die Theorie.
#include <windows.h> #include <TlHelp32.h> #include <iostream> #include <tchar.h> using namespace std; DWORD dwGetModuleBaseAddress(DWORD dwProcessIdentifier, TCHAR *lpszModuleName) { HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessIdentifier); DWORD dwModuleBaseAddress = 0; if (hSnapshot != INVALID_HANDLE_VALUE) { MODULEENTRY32 ModuleEntry32 = { 0 }; ModuleEntry32.dwSize = sizeof(MODULEENTRY32); if (Module32First(hSnapshot, &ModuleEntry32)) { do { if (_tcscmp(ModuleEntry32.szModule, lpszModuleName) == 0) { dwModuleBaseAddress = (DWORD)ModuleEntry32.modBaseAddr; break; } } while (Module32Next(hSnapshot, &ModuleEntry32)); } CloseHandle(hSnapshot); } return dwModuleBaseAddress; } int main() { HWND window = FindWindow(0, _T("Guild Wars 2")); if (window == 0){ printf("Window not found!\n"); char f; cin >> f; return 0; } DWORD pID = 0; GetWindowThreadProcessId(window, &pID); DWORD baseAddr = dwGetModuleBaseAddress(pID, _T("Gw2.exe")); DWORD staticOffset = 0x1430654; HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID); DWORD value; DWORD numBytesRead; ReadProcessMemory(handle, (LPCVOID)(baseAddr + staticOffset), &value, sizeof(DWORD), &numBytesRead); value += 0x16c; ReadProcessMemory(handle, (LPCVOID)value, &value, sizeof(DWORD), &numBytesRead); value += 0x54c; ReadProcessMemory(handle, (LPCVOID)value, &value, sizeof(DWORD), &numBytesRead); value += 0x0; ReadProcessMemory(handle, (LPCVOID)value, &value, sizeof(DWORD), &numBytesRead); value += 0x48; ReadProcessMemory(handle, (LPCVOID)value, &value, sizeof(DWORD), &numBytesRead); value += 8; ReadProcessMemory(handle, (LPCVOID)value, &value, sizeof(DWORD), &numBytesRead); CloseHandle(handle); cout << value << endl; cin.get(); }
Mein Code funktioniert und ließt das Ergebnis im 4 Byte Typ aus, der Typ sollte aber Float sein.
Gibt es in C++ eine Funktion, mit der ich das Ergebnis in Float wandeln kann oder kann mir kurz wer sagen wie ich es eben gleich in Float wandle bzw. lese?
Um ehrlich zu sein bin ich grade einfach nur zufrieden, dass es jetzt endlich geht aber leider eben im 4 Byte Format... . Wenn innerhalb einer Woche keinem hier ne Lösung einfällt schau ich mir des nochmals an, daweil geht´s jetzt morgen erstmal wieder mit der Webentwicklung weiter :D.
Ich freue mich auf eine richtige Antwort
Übrigens, C++ Syntax highlighting ist hier im Forum anscheinen nicht möglich. Ich habe deswegen C genommen. Wer meinen Code mit C++ Syntax highlighting ansehen möchte nimmt einfach diese Version. Der Link führt zu pastebin, die Programmierer hier kennen die Seite wohl sowieso schon - finde es ne super Sache.
Beitrag zuletzt geändert: 25.5.2014 23:06:18 von master4860 -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
5 Pointern folgen … interessant. Du willst deine 4 Bytes also als
interpretieren? Wie wäre es so?float
DWORD value = 0x12345678; float* f = (float*)&value; printf("float = %1.2f\n", *f);
-
Muss ich heute mal testen,
Inwiefern ist es interessant 5 Pointern zu folgen?
Wie hättest du es gelöst?
Wenn ich nicht nach jedem Neustart des Programms wieder einen neuen Pointer finden will muss ich doch mit offsets arbeiten. Mit einem 5er Pointer ist es doch schon recht sicher, dass man noch die richtige Adresse bei einem Programm-Neustart erhält.
Eventuell geht es einfacher?
Kannst gerne etwas sinnvolles vorschlagen
Was bedeutet eigentlich die Kombination von Datentyp mit anschließendem Sternchen?
In diesem Fall,
float*
?
Außerdem fällt mir gerade ein, wenn ich den Datentyp einfach umcaste in float - gehen mir dann nicht Nachkommastellen flöten?
Eventuell wäre das auslesen im float-Format die beste Lösung, oder irre ich mich gerade?
Beitrag zuletzt geändert: 26.5.2014 10:29:39 von master4860 -
master4860 schrieb:
Es ist interessant, weil du eben 5x Pointern folgst, um dein finales Ergebnis zu erzielen. Falls das Programm tatsächlich Daten so speichert lässt sich das natürlich auch nur so lösen.
Inwiefern ist es interessant 5 Pointern zu folgen?
Wie hättest du es gelöst?
master4860 schrieb:
Ich hoffe mal du weißt was du schreibst und willst.
Wenn ich nicht nach jedem Neustart des Programms wieder einen neuen Pointer finden will muss ich doch mit offsets arbeiten. Mit einem 5er Pointer ist es doch schon recht sicher, dass man noch die richtige Adresse bei einem Programm-Neustart erhält.
master4860 schrieb:
Und dabei machst du dir Sorgen wegen C/C++, während dir die Grundlagen fehlen?
Was bedeutet eigentlich die Kombination von Datentyp mit anschließendem Sternchen?
In diesem Fall,
float*
?
Es handelt sich hierbei um einen Pointer. Das ist eine Variable, die auf einen Speicherbereich zeigt, selbst die Daten aber nicht beinhaltet. Mit dem
-Operator (wie in meinem Beispiel) bekommst du die Adresse einer Variablen. Wenn nun folgendes dortsteht:&
DWORT x; float* y = (float*)&x;
dann zeigt y auf den Speicher der Variablen x. Wenn man nun auf den Wert, auf den y zeigt, zugreift (mit
), dann tut man so, als ob x ein float wäre:*
printf("float: %1.2f\n", *y);
master4860 schrieb:
Wenn du von
Außerdem fällt mir gerade ein, wenn ich den Datentyp einfach umcaste in float - gehen mir dann nicht Nachkommastellen flöten?
nachDWORD
castest hast du sowieso keine Nachkommastellen, dafloat
ein ganzzahliger Datentyp ist.DWORD
-
Dann lese ich falsch aus, hatte ich bereits befürchtet. Ich brauche die Nachkommastellen und ein einfaches umcasten, danach, ist nicht der Sinn der Sache. Ich muss gleich alles in dem Datentyp float auslesen.
Übrigens ich habe keine Kenntnisse über C oder C++, ich habe bisher nur im Webbereich ein wenig Erfahrung gesammelt. Habe mich gestern zum ersten mal mit C++ beschäftigt. Ich weiß nicht wieso du denkst das ich so erfahren wäre, bzw. es behaupte. Habe ich das gesagt? Falls ja entschuldige ich mich dafür.
Den Operator & hatte ich bereits gekannt sprich & vor einer Variable stellt eine Referenz da. Nur das Sternchen hat mir nichts gesagt, danke dir.
Beitrag zuletzt geändert: 26.5.2014 17:34:18 von master4860 -
Ich versteh zwar nicht wirklich, was Du mit dem Programm willst, aber soweit ich dir folgen kann, sollte der letzte Aufruf an ReadProcessMemory ein float auslesen.
Dazu solltest Du einfach folgendes machen können:
... value += 8; float result; ReadProcessMemory(handle, (LPCVOID)value, &result, sizeof(float), &numBytesRead); ... cout << result << endl;
Denn wie Du hier siehst: http://msdn.microsoft.com/en-us/library/windows/desktop/ms680553(v=vs.85).aspx
Will ReadProcessMemoty als 3. Parameter einfach nur den Pointer auf irgendwas, da einfach der Speicher von dem anderen Prozess in dem von deinem kopiert wird. Da ist es windows egal, ob Du das jetzt als float, DWORD oder sonst was interpretierst.
Wenn Du schon anfängst im Speicher von anderen Prozessen herumzufuhrwerken, setzt man normalerweise ein gewisses Grundverständnis der benutzten Sprache voraus, denn das ist nicht gerade das simpelste Thema. Ich denke deswegen hat hackyourlife sich auch über die fehlenden Sprachkenntnisse gewundert. -
#include <windows.h> #include <TlHelp32.h> #include <iostream> #include <tchar.h> using namespace std; DWORD dwGetModuleBaseAddress(DWORD dwProcessIdentifier, TCHAR *lpszModuleName) { HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessIdentifier); DWORD dwModuleBaseAddress = 0; if (hSnapshot != INVALID_HANDLE_VALUE) { MODULEENTRY32 ModuleEntry32 = { 0 }; ModuleEntry32.dwSize = sizeof(MODULEENTRY32); if (Module32First(hSnapshot, &ModuleEntry32)) { do { if (_tcscmp(ModuleEntry32.szModule, lpszModuleName) == 0) { dwModuleBaseAddress = (DWORD)ModuleEntry32.modBaseAddr; break; } } while (Module32Next(hSnapshot, &ModuleEntry32)); } CloseHandle(hSnapshot); } return dwModuleBaseAddress; } int main() { HWND window = FindWindow(0, _T("Guild Wars 2")); if (window == 0){ printf("Window not found!\n"); char f; cin >> f; return 0; } DWORD pID = 0; GetWindowThreadProcessId(window, &pID); DWORD baseAddr = dwGetModuleBaseAddress(pID, _T("Gw2.exe")); DWORD staticOffset = 0x1430654; HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID); while (true){ DWORD value = baseAddr + staticOffset; DWORD numBytesRead; ReadProcessMemory(handle, (LPCVOID)value, &value, sizeof(DWORD), &numBytesRead); value += 0x16c; ReadProcessMemory(handle, (LPCVOID)value, &value, sizeof(DWORD), &numBytesRead); value += 0x54c; ReadProcessMemory(handle, (LPCVOID)value, &value, sizeof(DWORD), &numBytesRead); value += 0x0; ReadProcessMemory(handle, (LPCVOID)value, &value, sizeof(DWORD), &numBytesRead); value += 0x48; ReadProcessMemory(handle, (LPCVOID)value, &value, sizeof(DWORD), &numBytesRead); value += 8; float result; ReadProcessMemory(handle, (LPCVOID)value, &result, sizeof(float), &numBytesRead); cout << result << endl; Sleep(1000); } CloseHandle(handle); // Mit der Endlosschleife wird das Handle natürlich nicht mehr geschlossen... }
Funktioniert einwandfrei. Jeder fängt mal bei 0 an orange.
Wo wir gleich beim Thema sind was bedeutet,
Datentyp* und was bedeutet,
*Datentyp ?
Sprich ein Sternchen vor einer Variable und ein Sternchen vor einer Variable.
Ein Sternchen nach einer Variable ist ein Zeiger/Pointer auf den Datentyp der Variablen, nennen wir se mal x.
Gibt es die Sternchen auch in Verbindung mit einer Variable? -
Freut mich, dass es funktioniert.
Ein Sternchen vor einer Variable ist das Gegenteil von einem & vor einer Variable:
int i = 3; int *p = &i; //p ist nun ein Pointer auf i int j = *p; //j wird hier der Wert von p zugewiesen
Da p ein Pointer ist, können wir j nicht einfach so p zuweisen (OK, wir können schon, aber es ergibt meistens keinen Sinn). Wenn man den Wert haben will, auf den ein Pointer zeigt, verwendet man den dereferenzieroperator, also das * vor der Variable. Les Dir am besten mal sowas durch: http://www.cplusplus.com/doc/tutorial/pointers/
etwas wie *Datentyp hab ich noch nicht gesehen, gibts so weit ich weiß auch nicht. -
ich habe ja mehrere rpm`s
ReadProcessMemory(handle, (LPCVOID)value, &value, sizeof(DWORD), &numBytesRead);
hierbei wird der zweite Parameter(in meinem Falle value) ja mit einem expliziten typecast zu LPCVOID gecastet.
Statt LPCVOID würde jetzt aber auch 100% void* funktionieren.
Ich weiß nur nicht wieso, ich will damit nur darauf anspielen das auch nach einem Datentyp ein Sternchen kommen kann.
Wenn jemand alle "Sternchen-Fälle" mal verständlich erklären könnte, oder zumindest versuchen, wäre ich so dankbar! Ich weiß man kann auch 100te Seiten lesen nur wenn es wär kurz und knapp erklären könnte, sodass man es versteht wäre es einfach klasse! -
Schau mal hier, LPCVOID ist als void* definiert: http://msdn.microsoft.com/en-us/library/windows/desktop/aa383751%28v=vs.85%29.aspx
Ich sagte ja auch nur, dass es ein * vor einem Datentyp nicht gibt.
type*: Pointer auf type
*variable: dereferenzieren einer Variable (darf nur auf der rechten Seite einer Zuweisung stehen, da der
Rückgabewert konstant ist).
Das sind schon die 2 Sternchen Fälle. Beide abgedeckt in dem von mir geposteten Code Beispiel.
Es mag ja sein, dass Du links nicht magst, aber meist sind solche Tutorials doch wesentlich besser durchdacht als alles, was ich dir hier jetzt sage. -
Ein Variable* gibts schon, aber dann im Sinn von multipliziere variable mit dem, was dahinter steht.
Ansonsten würde mich allerdings tatsächlich interessieren, woher Du den Code hast, wie Du die Offsets bekommen hast und was für eine Zahl Du da eigentlich ausließt. Ich kann das hier nicht ausprobieren, da ich kein Windows mehr verwende.
Das value += 0x0; kannst Du dir dabei übrigens sparen, x+0 ist immer x. -
Ob hex oder nicht 0 ist 0, natürlich kann ich mir das in diesem Falle sparen. Als ich des geschrieben habe hatte ich da an der Stelle nicht so wirklich nachgedacht. Da war erstmal der Teil mit der Baseadresse... Dann hatte ich zuerst die Adresse zusammengerechnet und wollte dann n read process memory machen - was aber ja nicht funktionieren kann... Ich muss ja nach und nach auslesen bei mehreren offsets sprich ne Art Adressverfolgung bzw. halt den Pointern folgen... .
Wie ich so ein Basepointer kriege ist nicht das Problem. Das ist ein Bereich, für den du im Grunde noch gar nicht programmieren können musst. Natürlich will man es später verwenden und dafür musste natürlich programmieren können! Aber meine Hauptfrage war eigentlich ja das Sternchen Zeug, was ich mir aber jetzt mal durch gelesen habe und mittlerweile habe ich es verstanden! So kann ich genauso gut (int*) p = &b; schreiben als int *p = &b; . Naja wie gesagt das habe ich jetzt verstanden. Das Speicher schreiben und auslesen habe ich damals schon einmal selbst in auto it geschrieben. Aber auto it is performance mäßig schlecht. Ich glaube auto it basiert teils auf c++ ? Keine Ahnung aufjedenfall ist es ne Klasse Sprache, wenn man mal schnell n Klick bot oda derartiges möchte! Auch Farbbereiche oder Mustererkennungen sind damit ganz leicht umzusetzen.Wie gesagt, Assembler und so Pointer Angelegenheiten sind mit ollydbg oder vergleichbarem möglich(cheat engine etc.). Die Verwendung von C++ im Bereich Reverse Engineering ist einfach klasse. Da sich mit einer derart Hardware nahen Sprache solche Dinge leichter und vor allem besser umsetzen lassen.
Das auslesen des Lebens in Gw2 habe ich jetzt nur kurz gemacht, um einfach mal C++ kurz anzutesten. Normalerweise entwickel ich mehr fürs Web daher ist eine native Sprache schon eher ein Fremdbereich. Zudem muss man sagen das ich noch sehr wenig Ahnung vom Programmieren habe, da ich insgesamt weniger als 1 Jahr programmiere. Letztes Jahr im September erst, eben mit Anfang meiner fachinfo Ausbildung.
Ich habe mich und auch noch heute immer viel zu sehr von guten Games ablenken lassen :-). Da wären wir schon beim nächsten guten Game, Watchdogs ist ja jetzt seit kurzem draußen .
Ich sehe das reine programmieren nicht wirklich als Lebenserfüllung, damit meine ich das ich auf gute Games und Filme in der Freizeit nicht verzichten möchte und werde. Manche Leute sind dazu ja tatsächlich im Stande, ich definitiv nicht :D.
Beitrag zuletzt geändert: 27.5.2014 18:08:24 von master4860 -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage