Archive for the ‘ Sielder 3 RE ’ Category

Siedler 3 - Die GUI

Die GUI! Wofür interssierten wir uns überhaupt für die GUI? Die GUI mag zwar ein Randaspekt sein, aber 3 Gründe sind genug, dass wir eine Analyse vornehmen:

  • Wir wollen später eine eigene Lobby schreiben, und dabei wenn möglich diese GUI Elemente wie Buttons verwenden
  • Viele Werte, wie z.B. der nachher besprochene Mapname, tauchen zunächst nur in der GUI auf.
  • Die GUI ist die Brücke zwischen Benutzer und Programm. Wenn wir wissen wollen, welche Funktion aufgerufen wird wenn ein bestimmter Button gedrückt wird, müssen wir wissen wie die Eventhandler für diesen Button aussehen. Und danach landen wir genau in der gesuchten Funktion (Beispiel: Neues Spiel Button -> Direkt beim Game-Konstruktor)

Anhand der GUI kann man schön sehen, wie OOP verwendet wurde. Alle Menüs erben von einem “Grundmenü”. Die Menüs implementierren die Funktionen wie zeichnen und handeln von Benutzereingaben, so dass eine schöne Kapselung entsteht. Und zum Wechseln des Menus wird einfach der Zeiger des aktuellen Menus aktualisiert, schon wird das nächste Menu angezeigt.

Beginnen wir mit etwas Code, der das Menu wechselt:

v4 = (int)this; // v4 ist das Register EBX
this->CurrentMenuIndex = a2; // Im Argument 2 wird übergeben, welche ID das neue Menu hat
v5 = v4->lpActualScreen; // Zeiger auf das aktuelle Menu Element
if ( v5 ) if (lpActualScreen != null)
{
    v7 = (int)((char *)&v5->dword4 + *(_DWORD *)(v5->dword4 + 4)); // dynamsichen Funktionszeiger holen
    (**(void (__thiscall ***)(_DWORD, _DWORD))v7)(v7, 1); // und aufrufen
}

Auch wenn der von IDA Pro erzeugte Code schrecklich aussieht, so kann man daraus einiges rauslesen. Fangen wir mit der ersten komischen Zeile an. Wieso speichert das Programm den this-Pointer in einer lokalen Variable (bzw genauer gesagt einem Register?). Da der This-Pointer in ECX übergeben wird, aber weitere Funktionen mit einem vielleicht anderen This-Pointer aufgerufen werden, wird der This-Pointer in EBX gespeichert. Das ist für die Funktionsscope nun der gesicherte This-Pointer. Nun wird das aktuelle Menu überprüft (lpActualScreen != null). Wenn ein Menu gesetzt ist, so wird in v7 ein Funktionszeiger geladen, der sich aus Werten des aktuellen Menus zusammensetzt. Im Anschluss wird die Funktion aufgerufen, und dies passiert dynamisch. Per IDA Pro kann man solche Calls nicht zurückverfolgen, per Debugger allerdings schon. In diesem Falle wird eine “Uninitialize”-Methode aufgerufen, die ein paar Aufräumarbeiten erledigt. Da jedes Menu andere Aufräumarbeiten zu leisten hat, ist auch die Funktion jeweils anders.

Weiterlesen

4 people like this post.

Siedler 3 - 2 lustige Bilder für Zwischendurch

Manchmal kann man es einfach nicht lassen: Man findet eine nette Funktion und muss sie irgendwie Ausnutzen. Aber keine Sorge, die hier gezeigte Funktion zum Items Spawnen sorgt im Multiplayer für eine Desynchronisation ;)

Zunächst war da die Funktion, um das GoldItem zu spawnen.

S3_Hack2

Auf der Suche nach weiteren ItemIDs habe ich mal in einer Loop alle Items erstellen lassen. Da ich die Taste etwas zu lange gedrückt habe ist dieses Bild entstanden :D

S3_Hack1

Und nunja, damit bliebt mir nur noch zu Sagen:

Math_XMas

Greez

17 people like this post.

Siedler 3 - Draw Hook und GDI

Mit dem Wissen über COM Objekte aus dem letzen Beitrag gerüstet, sind wir nun in der Lage, Code vor bzw hinter die jeweiligen DirectX Funktionsaufrufe zu packen. DirectX 8 nutzt zum Zeichnen sog. Surfaces, also eine Fläche, auf die gezeichnet wird. Im normalfall wird jeweils das Backbuffer Surface beschrieben und im Anschluss mit dem primären Surface ausgetauscht (Flip). Das macht Siedler 3 im Hintergrund für uns, daher müssen wir uns nicht darum kümmern.

Wir könnten einerseits über die Funktion “Lock” und “Unlock” direkten Zugriff auf das Surface bekommen, um dort einzelne Pixel zu setzen. Da dieses aber nicht so effektiv ist, gibt es andere Wege. Man könnte die sog. “Blit” (bit block transfer) Funktion aufrufen, um Teile aus einer Grafik in das Surface zu schreiben. So wird das zum Beispiel mit den Menuelementen, oder auch mit Sprite-Grafiken gemacht. Da wir aber zunächst nur Text ausgeben wollen, bietet uns DirectX 8 ein nettes Feature: GDI.

S3_GDI

GDI steht für Graphics Device Interface und bietet uns Funktionen zum Zeichnen, wie wir es z.B. von dem .NET Graphics Namespace gewöhnt sind. Über die Funktion “GetDC” erhalten wir einen sog. “Device Context”, welcher einem Zeichenhandle entspricht. Mit diesem können wir nun alle Funktionen aufrufen, die ein solches Handle entgegen nehmen, z.B. FillRect oder auch TextOutA/W. Zum simplen Zeichnen nehmen wir also folgenden Code:

// In einer Init Methode
LPLOGFONT fontArial = new LOGFONT();
 
ZeroMemory(this->fontArial, sizeof(this->fontArial)); // Wir setzen lieber nochmal den Speicher auf 0
wcscpy(this->fontArial->lfFaceName, L"Arial"); // Wir kopieren den Fontnamen den wir haben wollen rein
this->fontArial->lfQuality = ANTIALIASED_QUALITY; // Und setzen noch ein bisschen Anti Analising
 
// In der Methode zum Textzeichen
HFONT hFont = CreateFontIndirect(font);		// Eine "richtige" Font aus unserer LOGFONT
SelectObject(this->currentHdc, hFont);		// GDIHandle, nutze für das nächste diese Font
SetBkMode(this->currentHdc, TRANSPARENT);	// Mach den Background Transparent, sonst gibts Rahmen
SetTextColor(this->currentHdc, color);		// Setze die Color (color ist eine COLORREF struct)
TextOutA(this->currentHdc, x,y, pText, strlen(pText));	// Und schreibe den Spass in unser Surface

Weiterlesen

9 people like this post.

Siedler 3 - COM Objekte, DirectDraw und Fenstermodus

Grau, teurer Freund, ist alle Theorie, und Grün des Lebens goldner Baum. (Mephisto)

Diese Thorie wird, so leid es mir auch tut, den gesammten folgenden Artikel durchziehen. Man braucht ein paar Grundlagen, auf die man später zurückgreifen kann, wenn es richtig spassig wird. Diese Grundlagen sind zu vergleichen mit einem Bauplan: Woher sollten wir wissen, an welchen Schrauben wir drehen müssen und wie diese Aussehen, um ein bestimmtes Ziel zu erreichen?

Fangen wir mit den COM-Objekten, bzw genauer mit Interfaces und ihren “Virtual Tables” (VTables) an. Ein Objekt das von einem Interface erbt, ist gezwungen, die im Interface definierten Methoden zu implementieren (die Methoden zu “überladen”). Dabei kommen sog. Funktionszeiger zum Einsatz, die auf eine Funktionsaddresse zeigen. Von dieser Funktion ist der Prototype bekannt, also wird diese Adresse angesprungen, nachdem die bekannten Argumente auf den Stack gepushed wurden. COM-Interfaces sind spezielle Interfaces, die alle von IUnknown erben. Konkret bedeutet das, dass jedes COM-Objekt die 3 in IUnknown deklarierten Methoden “QueryInterface”, “AddRef” und “Release” implementiert. QueryInterface erstellt ein Interface, das einer IID entspricht. Im Post CLRHosting Reloaded wurde z.B. ein Interface vom Typ “IID_CLRRuntimeHost” erstellt, das uns wiederrum bestimmte Funktionen bereitgestellt hat. AddRef erhöht den Referenzcount, Release erniedrigt den Referenzcount und löscht das Objekt, falls dieser Null wird. Wichtig ist hier zu erwähnen, dass die VTable eines Interfaces, wenn es erstellt und gelöscht wurde, sich noch immer an der selben Stelle im Speicher befindet. In OllyDbg sieht ein solches Interface folgendermaßen aus:

S3_Interface1

Hier haben ein direkten Call eines Interfaces. Es handelt sich dabei (wie bei allen Interface Calls) um die sog. Thiscall-Convention, heißt im Register ECX wird ein THIS_POINTER übergeben, sonst werden die anderen Argumente normal auf den Stack gepushed. Nun wird CALL [ECX+80h] aufgerufen, was einem Funktionsaufruf in der VTable entspricht. Genauer gesagt die Funktion (80h / 4), also 20h oder 32. Im Dump-Window habe ich hier ECX geladen, was direkt der VTable entspricht. Die ersten 3 markierten Funktionen Funktionen ensprechen den Funktionen aus IUnknown (QueryInterface, AddRef, Release), in Orange ist die aufgerufene Funktion “Unlock” markiert. Schauen wir doch mal in die ddraw.h, in welcher alle unsere Interfaces deklariert sind.

Weiterlesen

11 people like this post.

Neue Reverse Engineering Serie - Siedler 3

Wer kennt es nicht? Das Kultspiel Siedler 3, das sogar noch heutzutage mein und so manch anderes Spielerherz höher schlagen lässt. Aber keine Sorge, in dieser Serie wird kein Hack entwickelt, dafür wäre das Spiel zu schade. Es geht also um etwas anderers:

Der Publisher Ubisoft, welcher Blue Byte im Jahre 2001 aufkaufte, hat vor einiger Zeit die öffentliche Lobby (siedler3svr.bluebyte.de:3344) abgeschaltet. So ist ein Online Matchmaking umständlich nur noch über den LAN Modus und diverser Tricks zu erreichen. Über das Back2Hack Board bekam ich Kontakt zu einem Programmierer, welcher das Matchmaking wieder leichter und komfortabler machen will. Das optimale Ziel wäre es, die Lobby wiederherzustellen, aber die Matchmaking Logik über seine Server laufen zu lassen.

Nach ein wenig Kontakt beschlossen wir, ein solches Projekt in Angriff zu nehmen. Dabei geht es im ersten Schritt darum, das Matchmaking über die Spielesuche im LAN-Menu zu entwickeln. Der selbst programmierte Server empfängt alle neu gehosteten Spiele und sendet diese an andere Clients, die gerade Spiele suchen. Dabei sendet der Server Packete, wie sie der Siedler 3 Client/Host im LAN schicken würde.

S3_Lobby

Das alles klingt leichter gesagt als getan, denn Siedler 3 legt einem einige Stolpersteine, wenn nicht sogar ziemlich große Felsbrocken in den Weg. So ist das Spiel ohne Fenstermodus erschienen, was dank Auflösung von max. 800 x 600 Debugging unmöglich macht. Des weiteren wird das alte DirectDraw verwendet, was ein Segen und Fluch zugleich ist. Der DirectPlay Support ist in Windows Vista nahezu vollständig entfernt worden, was Probleme beim Erzeugen von gewrappen Interfaces gibt. Und als ob das nicht alles schon schwer genug wäre, so ist der Programmierstil der 2000der Jahre auch nicht der strukturierteste.

In der folgenden Serie wird es also darum gehen, Siedler 3 unter die Lupe zu nehmen und geschickt ein paar Hooks zu platzieren, die uns im Ende eine funktionierende Lobby ermöglichen. Ob es funktioniert weiß ich noch nicht, allerdings bin ich durch die bisherigen Ergebnisse ziemlich zuversichtlich. Zudem bekommt ihr einen Eindruck, wie Gruppen wie z.B Techogods arbeiteten, wenn sie Spiele Analysieren und Modifizieren. Des weiteren werden ein Informationen zu DirectDraw, GDI und natürlich Netzwerktechnik vermittelt.

Der nächste Artikel wird sich mit COM Objekten, Direct Draw und dem Fenstermodus befassen. Je nach Länge des Posts wird noch der DircetDraw Hook vorgestellt. Und bis dahin fröhliches Siedeln!

Greez

 

8 people like this post.