22.07.2012, 20:21
Irgendwie scheint mir das Du dich zu sehr auf Pointer fixiert hast?!?
Von diesem Gedanken solltest Du dich ganz schnell trennen, denn nicht immer ist ein Spiel nur mit Pointern zu bescheißen...
In erster Linie solltest Du Dir auch das Codecave Tutorial von Acubra zu Gemüte führen... Das findest Du HIER
Bei diesem Code gibts nichts auseinanderzupflücken...
[code=ASM]JustCause2.exe+4103F0 - F3 0F11 46 40 - movss [esi+40],xmm0[/code]
Der erste Teil beschreibt die Position wo diese Anweisung zu finden ist. Und da sehen wir das diese Anweisung in der "JustCause2.exe" an Adresse "JustCause2.exe+4103F0" zu finden ist. Und da die Basisadresse der EXE Datei im Speicher immer diesselbe ist, nämlich 0x400000h, so könnte ich auch statt "JustCause2.exe+4103F0" auch einfach nur "008103F0" schreiben. Weil, wenn ich zur Basisadresse von 0x400000h den Wert 0x4203F0h addiere ich eben den HEX Wert 008103F0 erhalte.
Die darauffolgenden Bytes sind die sogenannten Opcodes. Laienhaft ausgedrückt, das was der Computer versteht. Und da sich solche Bytefolgen schlecht merken lassen hat Gott den Dissassembler erfunden der diese Bytefolgen in verständliche Befehle umwandelt und wir bzw. ein Programmierer oder auch Cracker weiß was hier für Anweisungen über den Bildschirm flimmern.
Nur mal so am Rande und rein zur Info... Eine relativ Bekannte ASM Library ist die BEA Engine. Diese gibts z.B. hier.
Die XMM Register wurden damals von Intel eingeführt. Allen bekannt dürfte ja wohl das Kürzel SSE sein. Welches damals erstmals beim Pentium III eingeführt wurde. Insgesamt standen nun 8 128-Bit Register zur Verfügung, also die Register von XMM0 bis hin zum Register XMM7. Später wurden diese nochmals erweitert.
Mit der Anweisung "movss [esi+40], xmm0" wird also eine Gleitkommazahl aus dem XMM0 Register in den Speicher an Adresse [ESI+40] kopiert. Wenn jetzt z.B. ESI den Wert 0x400400h enthält dann wird also der Wert des Registers in den Speicher an Adresse 0x400400h + 0x40h = 0x400440h kopiert.
Der zusammengerechnete Wert von [ESI+40] ist in diesem Falle die Adresse die den Wert des Timers enthält. Also quasi wieviel Zeit wir noch haben bevor das Minigame als gescheitert gilt. Wenn also diese Adresse z.B. die "16BF06A2" ist, dann kann man auch zurückrechnen welcher Wert in ESI stehen muss. Wir ziehen also von dieser Timeradresse den Wert 0x40h ab. Also muss im ESI Register der Hexadezimale Wert "16BF0662" stehen.
Nun ist aber auch erstmal viel interessanter die Frage was wir eigentlich mit einer Codecave erreichen wollen? Oder anders gesagt, was bringt uns eine Codecave für Vorteile, zu welchem Zweck dient sie und bzw. oder warum sind wir darauf angewiesen???
In erster Linie muss amn sich vor Augen halten das dass was wir mit einer Codecave versuchen zu bezwecken vom Spiel so nicht vorgesehen ist. Und mit einer Codecave wollen wir ja auf gut Deutsch bescheißen und das erfordert meist eine Reihe von Befehlen die wir so im herkömmlichen Programmcode an besagten Stellen nicht unterbringen weil ganz einfach der Platz dazu nicht ausreicht.
Die Anweisung die unsere Timer Adresse beschreibt ist genau 5 Bytes groß bzw. lang. Und unser reiner Cheatcode ist im Endeffekt 10 Bytes lang...
[code=ASM]F3 0F 10 46 44 - movss xmm0,[esi+44]
F3 0F 11 46 40 - movss [esi+40],xmm0[/code]
Also muss eben eine Codecave her. Und da wir durch den Sprung zu dieser Codecave den Originalcode "movss [esi+40],xmm0" überschreiben da können wir uns diesen auch gleich zu unseren Zwecken ausnutzen. Und da wir vom normalen Programmablauf zu unserer Codecave springen müssen wir natürlich von dieser Codecave auch wieder in den normalen Programmablauf wieder zurückspringen.
Die Codecave musst Du dir folgendermaßen vor Augen halten. Wenn das Spiel in seinem Ablauf, also die Spielfigur z.B. grade ne Bombe entschärft, an Adresse 008103F0 kommt dann führen wir nicht den normalen Code aus (also das die Zeit abläuft), sondern wir springen zur Codecave. Und das wird durch den Sprungbefehl "jmp JustCause2.exe+5593ED" erreicht. Das heißt wiederrum das dass Spiel dann unsere Codecave durchläuft.
Und wie ich da bereits sagte wird in [ESI+40], was unsere Timer Adresse ist, immer wieder der Wert des XMM0 Registers kopiert. Die Zeit nimmt also ab. Aber direkt neben der Adresse des tatsächlichen Zeitwertes befindet sich auch die Adresse mit dem maximalen Zeitwert bzw. dem Zeitwert bei vollem Balken.
Also...
[ESI+40] = Tatsächlicher Zeitwert
Timer Adresse + 4 Bytes = Maximaler Zeitwert
Man könnte das auch so schreiben
[ESI+40+4] aber [ESI+44] ist ja dasselbe
Und mit dem Befehl "movss xmm0,[esi+44]" kopieren wir immer den maximal möglichen Zeitwert in das XMM0 Register. Und dort alleine nützt der uns nix also müssen wir das Spiel dazu bringen das es immer nur diesen Wert an der Adresse für den tatsächlichen Zeitwert hat. Das realisieren wir dann mit dem Befehl, welches auch der Originalcode ist, "movss [esi+40],xmm0".
Vereinfacht ausgedrückt sieht das im Spiel dann so aus wenn die Spielfigur eine Bombe entschärft der Balken, der der zur Verfügung stehenden Zeit entspricht, nicht mehr abnimmt.
Das wichtigste aber ist noch der Rücksprung, aus der Codecave zum weiteren Spielablauf. Das heißt wir müssen eine Zeile weiter im Code springen wo wir den Sprung zu unserer Codecave gemacht haben. Der Sprung zur Codecave war an Adresse "JustCause2.exe+4103F0", oder anders geschrieben an Adresse "008103F0". Da der Sprung, genauso wie der Originalcode, 5 Bytes lang/groß ist addieren wir zu dieser Adresse 5 Bytes hinzu. Also müssen wir zu Adresse "JustCause2.exe+4103F5", oder anders geschrieben zu Adresse "008103F5" zurückspringen.
Noch etwas zum Abschluss... Eine Codecave ist kein vordefinierter Bereich innerhalb des Speichers. Eine Codecave befindet sich immer innerhalb des Spiels zur Verfügung stehenden Speichers. Dies kann feststehender Speicher innerhalb des Moduls sein, also der EXE. Oder man stellt dem Spiel Speicher zur Verfügung so das es diesen nutzen kann. Und genau das macht Cheat Engine mit dem Befehl oder der Option "Allocate Memory". Weiterhin darf sich aber die Codecave nicht innerhalb eines Bereiches befinden der vom Spiel explizit gebraucht wird.
Bestes Beispiel z.B. da wo sich der Originalcode befindet. Würde man da wild eine Codeinjection schreiben stürzt das Spiel unweigerlich ab weil es Daten bekommt die es nicht erwartet. Die Register kriegen falsche Werte, der Stack wird durcheinander gewürfelt. Letzenendes stimmt der komplette Programmablauf nicht mehr.
Aber eines muss man auch dazu sagen... Die oben gezeigte Codecave ist noch die einfachste Form. Sowas gibts noch viel komplexer und umfangreicher...
Von diesem Gedanken solltest Du dich ganz schnell trennen, denn nicht immer ist ein Spiel nur mit Pointern zu bescheißen...
In erster Linie solltest Du Dir auch das Codecave Tutorial von Acubra zu Gemüte führen... Das findest Du HIER
Bei diesem Code gibts nichts auseinanderzupflücken...
[code=ASM]JustCause2.exe+4103F0 - F3 0F11 46 40 - movss [esi+40],xmm0[/code]
Der erste Teil beschreibt die Position wo diese Anweisung zu finden ist. Und da sehen wir das diese Anweisung in der "JustCause2.exe" an Adresse "JustCause2.exe+4103F0" zu finden ist. Und da die Basisadresse der EXE Datei im Speicher immer diesselbe ist, nämlich 0x400000h, so könnte ich auch statt "JustCause2.exe+4103F0" auch einfach nur "008103F0" schreiben. Weil, wenn ich zur Basisadresse von 0x400000h den Wert 0x4203F0h addiere ich eben den HEX Wert 008103F0 erhalte.
Die darauffolgenden Bytes sind die sogenannten Opcodes. Laienhaft ausgedrückt, das was der Computer versteht. Und da sich solche Bytefolgen schlecht merken lassen hat Gott den Dissassembler erfunden der diese Bytefolgen in verständliche Befehle umwandelt und wir bzw. ein Programmierer oder auch Cracker weiß was hier für Anweisungen über den Bildschirm flimmern.
Nur mal so am Rande und rein zur Info... Eine relativ Bekannte ASM Library ist die BEA Engine. Diese gibts z.B. hier.
Die XMM Register wurden damals von Intel eingeführt. Allen bekannt dürfte ja wohl das Kürzel SSE sein. Welches damals erstmals beim Pentium III eingeführt wurde. Insgesamt standen nun 8 128-Bit Register zur Verfügung, also die Register von XMM0 bis hin zum Register XMM7. Später wurden diese nochmals erweitert.
Mit der Anweisung "movss [esi+40], xmm0" wird also eine Gleitkommazahl aus dem XMM0 Register in den Speicher an Adresse [ESI+40] kopiert. Wenn jetzt z.B. ESI den Wert 0x400400h enthält dann wird also der Wert des Registers in den Speicher an Adresse 0x400400h + 0x40h = 0x400440h kopiert.
Der zusammengerechnete Wert von [ESI+40] ist in diesem Falle die Adresse die den Wert des Timers enthält. Also quasi wieviel Zeit wir noch haben bevor das Minigame als gescheitert gilt. Wenn also diese Adresse z.B. die "16BF06A2" ist, dann kann man auch zurückrechnen welcher Wert in ESI stehen muss. Wir ziehen also von dieser Timeradresse den Wert 0x40h ab. Also muss im ESI Register der Hexadezimale Wert "16BF0662" stehen.
Nun ist aber auch erstmal viel interessanter die Frage was wir eigentlich mit einer Codecave erreichen wollen? Oder anders gesagt, was bringt uns eine Codecave für Vorteile, zu welchem Zweck dient sie und bzw. oder warum sind wir darauf angewiesen???
In erster Linie muss amn sich vor Augen halten das dass was wir mit einer Codecave versuchen zu bezwecken vom Spiel so nicht vorgesehen ist. Und mit einer Codecave wollen wir ja auf gut Deutsch bescheißen und das erfordert meist eine Reihe von Befehlen die wir so im herkömmlichen Programmcode an besagten Stellen nicht unterbringen weil ganz einfach der Platz dazu nicht ausreicht.
Die Anweisung die unsere Timer Adresse beschreibt ist genau 5 Bytes groß bzw. lang. Und unser reiner Cheatcode ist im Endeffekt 10 Bytes lang...
[code=ASM]F3 0F 10 46 44 - movss xmm0,[esi+44]
F3 0F 11 46 40 - movss [esi+40],xmm0[/code]
Also muss eben eine Codecave her. Und da wir durch den Sprung zu dieser Codecave den Originalcode "movss [esi+40],xmm0" überschreiben da können wir uns diesen auch gleich zu unseren Zwecken ausnutzen. Und da wir vom normalen Programmablauf zu unserer Codecave springen müssen wir natürlich von dieser Codecave auch wieder in den normalen Programmablauf wieder zurückspringen.
Die Codecave musst Du dir folgendermaßen vor Augen halten. Wenn das Spiel in seinem Ablauf, also die Spielfigur z.B. grade ne Bombe entschärft, an Adresse 008103F0 kommt dann führen wir nicht den normalen Code aus (also das die Zeit abläuft), sondern wir springen zur Codecave. Und das wird durch den Sprungbefehl "jmp JustCause2.exe+5593ED" erreicht. Das heißt wiederrum das dass Spiel dann unsere Codecave durchläuft.
Und wie ich da bereits sagte wird in [ESI+40], was unsere Timer Adresse ist, immer wieder der Wert des XMM0 Registers kopiert. Die Zeit nimmt also ab. Aber direkt neben der Adresse des tatsächlichen Zeitwertes befindet sich auch die Adresse mit dem maximalen Zeitwert bzw. dem Zeitwert bei vollem Balken.
Also...
[ESI+40] = Tatsächlicher Zeitwert
Timer Adresse + 4 Bytes = Maximaler Zeitwert
Man könnte das auch so schreiben
[ESI+40+4] aber [ESI+44] ist ja dasselbe
Und mit dem Befehl "movss xmm0,[esi+44]" kopieren wir immer den maximal möglichen Zeitwert in das XMM0 Register. Und dort alleine nützt der uns nix also müssen wir das Spiel dazu bringen das es immer nur diesen Wert an der Adresse für den tatsächlichen Zeitwert hat. Das realisieren wir dann mit dem Befehl, welches auch der Originalcode ist, "movss [esi+40],xmm0".
Vereinfacht ausgedrückt sieht das im Spiel dann so aus wenn die Spielfigur eine Bombe entschärft der Balken, der der zur Verfügung stehenden Zeit entspricht, nicht mehr abnimmt.
Das wichtigste aber ist noch der Rücksprung, aus der Codecave zum weiteren Spielablauf. Das heißt wir müssen eine Zeile weiter im Code springen wo wir den Sprung zu unserer Codecave gemacht haben. Der Sprung zur Codecave war an Adresse "JustCause2.exe+4103F0", oder anders geschrieben an Adresse "008103F0". Da der Sprung, genauso wie der Originalcode, 5 Bytes lang/groß ist addieren wir zu dieser Adresse 5 Bytes hinzu. Also müssen wir zu Adresse "JustCause2.exe+4103F5", oder anders geschrieben zu Adresse "008103F5" zurückspringen.
Noch etwas zum Abschluss... Eine Codecave ist kein vordefinierter Bereich innerhalb des Speichers. Eine Codecave befindet sich immer innerhalb des Spiels zur Verfügung stehenden Speichers. Dies kann feststehender Speicher innerhalb des Moduls sein, also der EXE. Oder man stellt dem Spiel Speicher zur Verfügung so das es diesen nutzen kann. Und genau das macht Cheat Engine mit dem Befehl oder der Option "Allocate Memory". Weiterhin darf sich aber die Codecave nicht innerhalb eines Bereiches befinden der vom Spiel explizit gebraucht wird.
Bestes Beispiel z.B. da wo sich der Originalcode befindet. Würde man da wild eine Codeinjection schreiben stürzt das Spiel unweigerlich ab weil es Daten bekommt die es nicht erwartet. Die Register kriegen falsche Werte, der Stack wird durcheinander gewürfelt. Letzenendes stimmt der komplette Programmablauf nicht mehr.
Aber eines muss man auch dazu sagen... Die oben gezeigte Codecave ist noch die einfachste Form. Sowas gibts noch viel komplexer und umfangreicher...
Irren ist menschlich. Aber wer richtigen Mist bauen will, braucht einen Computer !!!
Traineranfragen per PM werden prinzipiell gelöscht...
Traineranfragen per PM werden prinzipiell gelöscht...