Age of Empires 2 - External Entity Hack
Ich glaube annährend jeder Besucher dieses Blogs hat früher, oder sogar in letzter Zeit als HD Remake, Age of Empires 2 gespielt. Dieses Kultspiel wird hier exemplarisch herrangezogen, um die Schritte beim Programmieren eines Hacks nachvollziehbarer zu machen. Genaue Offsets und Klassen gibt es nicht, wohl aber die Möglichkeit die Schritte nachzumachen. Damit stösst man unweigerlich auch auf die Offsets und lernt den Umgang mit IDA Pro und dem Debugger. Es ist definitiv nicht meine Intention, die Grundlage für einen Hack zu schaffen. Vielmehr hab ich gemerkt, wie schön man das Finden der Entites als Beispiel nutzen und abstrahieren kann.
Am Ende des Blogposts werden wir die Positionen aller Entites und aller Spieler auf eine Grafik plotten können. Natürlich wären weitere Features möglich, aber es geht nur um den Weg bis zu diesem Punkt
Fangen wir mit etwas allgemeinen Informationen an. AoE2 ist wie eigentlich jedes ältere Spiel in C++ geschrieben. Konkret heißt das für uns, dass wir eine Entity-Basisklasse haben, von denen alle Einheiten und Gebäude erben. Im Speicher befindet sich also immer die Basisklasse, gefolgt von den speziellen Attributen je nach Klassentyp. Damit wissen wir auch, dass der erste Eintrag in diesen Entity-Klassen die VTable ist. Das Konzept dahinter wurde schon bei Siedler3 und Interfaces erklärt: Um bei einem Aufruf von “Building->Update()” und “Unit->Update()” bei unterschiedlichen Funktionen zu landen, wird der Update()-Funktionszeiger überschrieben, der sich an einer fixen Stelle innerhalb der VTable befindet. Das hat den Vorteil, das wenn wir ein riesiges Array von Entites haben, einfach alle durchlaufen und die Update()-Funktion aufrufen können. Die VTable sorgt dann schon dafür, dass die richtige spezielle Methode aufgerufen wird und wir müssen uns nicht darum kümmern.
Soviel zur gleich gebrauchten Theorie, los gehts in der Praxis mit Memory Scanning. Wie brauchen nämlich eine Variable, die sicher in der Entity-Klasse steht. Optional sollte sie noch leicht zu verändern und eindeutig sein. Was gibt es da passenderes wie das Leben der Entity? Starten wir Cheat Engine und stellen den Typ auf Float. Wir markieren eine Einheit, lesen das Leben ab und verändern es, indem wir die Einheit einen Gegner angreifen lassen. Zum Glück können wir über F3 das Spiel pausieren, so ist entspanntes Suchen nach der richtigen Variable möglich ohne in die Trickkiste greifen zu müssen. Übrig bleiben sollten zwei Variablen die jeweils das aktuelle Leben anzeigen. Mit der Adresse der Variable selbst fangen wir nichts an, denn spätenstens beim nächsten Spielstart sieht diese ganz anders ist. Spannender ist aber die Funktion von Cheat Engine, über den Debugger herraus zu finden welche Instruktionen auf die Variable zugreifen. Das ist natürlich auch im normalen Debugger über einen Memory-Breakpoint möglich, allerdings bekommen wir bei den doch vielen Zugriffen eine schöne Liste von CheatEngine.