char array vom pointer mit srcpy changen

04/07/2015 17:12 Slade100#1
Hey zusammen,
also habe ein kleines problem das grad unnormal nervt:rtfm:

Habe in einem game ein pointer der auf ein char array zeigt
der pointer ist
DWORD* F = (DWORD*)0x0076BBD8; // hier der pointer

auf dem pointer ist jetzt ein char array drauf, nehmen wir einfach als beispiel
"hey"

so jetzt wollte ich mit strcpy z.b "bye" drauf speichern
strcpy((char*)F, "bye");


naja habe das schonmal so gemacht bei nem anderen server und da hatte das so funktioniert :S aber wenn ich das jetzt mache crasht mein game..
jemand vielleicht eine ahnung woran das liegt?
04/07/2015 17:44 snow#2
Das kann viele Gründe haben, z.B. könnte der char-Zeiger auf eine schreibgeschützte Region zeigen oder der Zeiger ist nicht konstant.

Warum castest du die Adresse erst gewaltsam zu einem DWORD-Zeiger und dann zu einem char-Zeiger? Warum nicht char *F = reinterpret_cast<char *>(0x00...);?
04/07/2015 20:06 Slade100#3
Quote:
Originally Posted by snow View Post
Das kann viele Gründe haben, z.B. könnte der char-Zeiger auf eine schreibgeschützte Region zeigen oder der Zeiger ist nicht konstant.

Warum castest du die Adresse erst gewaltsam zu einem DWORD-Zeiger und dann zu einem char-Zeiger? Warum nicht char *F = reinterpret_cast<char *>(0x00...);?
danke erstmal auf die antwort, naja mache das mit dem dword weil ich das immer so mache^^ ich werde gleich mal deine methode probieren :D
also schreibgeschützt ist die nicht, weil ich die value mit der cheat engine auch verändere und alles klappt :D
naja probiere mal kurz das mit char *F = reinterpret_cast<char *>(0x00...);

Edit: ach ich verzweifel xD crasht genau im selben moment, iwie liegts am strcpy :/ kennst du vielleicht eine gute alternative dazu? :D
04/07/2015 20:50 Jeoni#4
Bist du überhaupt im selben Adressraum, wie der Zielprozess, also wird dein Code im Zielprozess ausgeführt? Wenn du von extern arbeitest, kannste das so eh vergessen und musst auf [Only registered and activated users can see links. Click Here To Register...] (WPM) zurückgreifen.
Davon abgesehen arbeitet CheatEngine auch von extern (oder wahlweise mit einem Treiber, soweit ich weiß), wodurch es ebenfalls WPM nutzt.
Bei WPM ist es egal, ob die Speicherregion, auf die man schreiben will, schreibgeschützt ist. Will man den Schreibschutz intern abschalten, nutzt man in der Regel [Only registered and activated users can see links. Click Here To Register...].
Mit freundlichen Grüßen
Jeoni
04/07/2015 21:53 Slade100#5
Quote:
Originally Posted by Jeoni View Post
Bist du überhaupt im selben Adressraum, wie der Zielprozess, also wird dein Code im Zielprozess ausgeführt? Wenn du von extern arbeitest, kannste das so eh vergessen und musst auf [Only registered and activated users can see links. Click Here To Register...] (WPM) zurückgreifen.
Davon abgesehen arbeitet CheatEngine auch von extern (oder wahlweise mit einem Treiber, soweit ich weiß), wodurch es ebenfalls WPM nutzt.
Bei WPM ist es egal, ob die Speicherregion, auf die man schreiben will, schreibgeschützt ist. Will man den Schreibschutz intern abschalten, nutzt man in der Regel [Only registered and activated users can see links. Click Here To Register...].
Mit freundlichen Grüßen
Jeoni
erstmal danke, aber da ich mit einer dll injection arbeite kann ich doch soweit ich weiß auf virtualprotect und wpm verzichten oder nicht?
04/07/2015 22:18 Jeoni#6
Auf WriteProcessMemory, ja.
Wenn die Region, in der sich besagter String befindet aber tatsächlich schreibgeschützt ist, darfst du nicht auf VirtualProtect verzichten. Sobald auf schreibgeschützten Speicher geschrieben wird (hier durch strcpy), wird eben eine Exception geworfen wird ("Access Violation", Code 0xC0000005), die sich, da sie nicht abgefangen wird, als Crash äußert.
Du musst also VirtualProtect nutzen, um die Berechtigungen der Speicherregion so zu ändern, dass du drauf schreiben darfst. Anschließend bestenfalls die Berechtigungen mit VirtualProtect wieder zurücksetzen.
Mit freundlichen Grüßen
Jeoni
04/08/2015 21:07 Slade100#7
danke dir habs gemacht und hat auch geklappt :D nur eine kleine frage habe ich + etwas das mir merkwürdig vorkommt^^
also meine frage erstmal, also habe das hier

VirtualProtect((LPVOID)(F), 7, PAGE_EXECUTE_READWRITE, &OldProtection);

strcpy((char*)F, "7654321");

VirtualProtect((LPVOID)(F), 7, OldProtection, NULL);

habe für dwsize 7 genommen da es 7 chars hat, bin mir aber nicht ganz sicher ob das so richtig durchdacht ist^^, ich dachte mir halt ein char hat 1 byte und da das 7 sind, nehm ich 7.. klappen tuts auch nur ka obs so optimal ist, oder ich gerade scheiße gebaut habe :D

naja was ich merkwürdig finde ist das ich nachdem ich das einmal gemacht habe, dannach direkt strcpy((char*)F, "1234567"); aufrufen kann ohne wieder virtualprotect aufzurufen, ich sollte doch mit
VirtualProtect((LPVOID)(F), 7, OldProtection, NULL);

die adresse wie zu beginn schreibgeschützt haben, aber wieso ist das nicht der fall? wäre das der fall müsste es doch wieder crashen so wie vorher .. :S
04/08/2015 21:46 Jeoni#8
1.) Du (bzw. dein strcpy Aufruf) schreibst 8 byte / chars. Die 7, die du siehst und dann noch den Nullterminator.
VirtualProtect arbeitet aber generell pageweise. Protection existiert halt nicht pro Byte, sondern pro Page, was 0x1000 Bytes sind.
2.) Dein 2. VirtualProtect-Aufruf schlägt fehl, was du auch am Rückgabewert sehen würdest, würdest du ihn auswerten / ausgeben.
Der Grund dafür ist, dass der letzte Parameter nicht NULL / nullptr sein darf.
[Only registered and activated users can see links. Click Here To Register...] dazu:
Quote:
If this parameter is NULL or does not point to a valid variable, the function fails.
Selbst wenn du also die alte Protection im 2. Aufruf nicht brauchst (weil sie ja aller Wahrscheinlichkeit nach eh PAGE_EXECUTE_READWRITE ist), musst den Parameter dennoch entsprechend füllen, damit die Funktion nicht fehlschlägt.
Mit freundlichen Grüßen
Jeoni
04/09/2015 00:26 Slade100#9
Quote:
Originally Posted by Jeoni View Post
1.) Du (bzw. dein strcpy Aufruf) schreibst 8 byte / chars. Die 7, die du siehst und dann noch den Nullterminator.
VirtualProtect arbeitet aber generell pageweise. Protection existiert halt nicht pro Byte, sondern pro Page, was 0x1000 Bytes sind.
2.) Dein 2. VirtualProtect-Aufruf schlägt fehl, was du auch am Rückgabewert sehen würdest, würdest du ihn auswerten / ausgeben.
Der Grund dafür ist, dass der letzte Parameter nicht NULL / nullptr sein darf.
[Only registered and activated users can see links. Click Here To Register...] dazu:
Selbst wenn du also die alte Protection im 2. Aufruf nicht brauchst (weil sie ja aller Wahrscheinlichkeit nach eh PAGE_EXECUTE_READWRITE ist), musst den Parameter dennoch entsprechend füllen, damit die Funktion nicht fehlschlägt.
Mit freundlichen Grüßen
Jeoni
daran das das fehlschlägt hätte ich garnicht gedacht, ich wunder mich gerade nur wie viele leute das im internet falsch machen ^^ das mit dem NULL wird so oft am ende genutzt :mad:, naja danke dir sehr für die hilfe :D werde das dann mal so probieren
DWORD OldProtection;
DWORD NewProtection;

if(VirtualProtect((LPVOID)(F), 0x1000, PAGE_EXECUTE_READWRITE, &OldProtection))
strcpy((char*)F, "7654321");
else
cout << "Virtualprotect failed" << endl;
if(VirtualProtect((LPVOID)(F), 0x1000, OldProtection, &NewProtection))
cout << " successfully adding back oldprotection to Virtualprotect" << endl;
else
cout << " Virtualprotect failed on puting oldprotection back " << endl;

und bin fest davon überzeugt das es klappen wird :D mal schauen

edit: funzt perfekt, bin dir sehr dankbar für deine geleistete hilfe :D kann von mir aus geclosed werden :D
04/09/2015 09:43 Jeoni#10
Du brauchst nicht unbedingt 2 Variablen. Kannst ja beim zweiten Aufruf auch wieder einen Pointer auf OldProtection übergeben, wenn du die Variable danach nicht mehr brauchst.
Das mit dem pageweise schrieb ich nur als Nebeninformationen. Wenn du hier 0x1000 übergibst, und die Region, deren Protection du ändern willst, nicht gerade am Anfang einer Page anfängt, änderst du so (unnötigerweise) mehr als eine Page, weil VirtualProtect "merkt", dass die Region, deren Protection du verändern willst, sich über mehr als eine Page zieht.
Als Größe 8 zu nehmen war schon richtig. War, wie gesagt, nur als Nebeninformation gedacht ;)
Mit freundlichen Grüßen
Jeoni
04/09/2015 11:57 Slade100#11
Quote:
Originally Posted by Jeoni View Post
Du brauchst nicht unbedingt 2 Variablen. Kannst ja beim zweiten Aufruf auch wieder einen Pointer auf OldProtection übergeben, wenn du die Variable danach nicht mehr brauchst.
Das mit dem pageweise schrieb ich nur als Nebeninformationen. Wenn du hier 0x1000 übergibst, und die Region, deren Protection du ändern willst, nicht gerade am Anfang einer Page anfängt, änderst du so (unnötigerweise) mehr als eine Page, weil VirtualProtect "merkt", dass die Region, deren Protection du verändern willst, sich über mehr als eine Page zieht.
Als Größe 8 zu nehmen war schon richtig. War, wie gesagt, nur als Nebeninformation gedacht ;)
Mit freundlichen Grüßen
Jeoni
aso ok dann sollte das jetzt gelungen sein :D danke