Wolfteam - LithTech und Engine Draw Hook

Manchmal hat man keine Lust auf Anti-Cheats, welche permanent (und aus manch unerfindlichem Grund) Kicks verteilen. Daher beginnen wir mit dem spassigen Teil: Die LithTech Engine und der Draw Hook.

Zunächst ein paar Worte zu der Engine: Die LithTech Engine ist das Herzstück von Spielen wie FEAR, ein paar Medal of Honor Titeln, Combat Arms und Crossfire. Inzwischen ist ein SDK veröffentlicht, das für uns sowohl ein Segen als auch ein Fluch ist. Denn so lässt sich zwar die Basis-Struktur von Klassen nachvollziehen, aber es gibt keine Garantie dass diese Klassen nicht geändert wurden. So kann man sich ein SDK als grobe Orientierung vorstellen, aber nicht als Basis der Programmierung.

Am Anfang war der DirectX Hook. Man hooked dazu (wie schon von Siedler bekannt) die Funktionen EndScene und Reset, um eigene Sachen zu zeichnen. Funktioniert hat das überraschend gut, aber nur bis das Device Resettet wurde. Ein Reset passiert z.B, wenn das Fenster in den Hintergrund geschoben wird und dann wieder Fokus erlangt. Oder auch, wenn man vom der Ingame-GUI ein Match Startet. Aus unerfindlichen Gründen wurde die Font, die ich zum Zeichnen erzeuge, nicht freigegeben. Eigentlich sollte das mit Aufrufen von OnLostDevice() und OnResetDevice() die Font Freigeben bzw wieder neu allokieren. Irgendwas lief schief, so dass ich diesen Ansatz nach ein paar Stunden des Debuggens wieder aufgab.

WolfteamColor

Lassen wir also die Engine das ganze Font verwalten und Strings zeichnen übernehmen. Dazu hooken wir uns in End2DOptimized, was dank diverser Strings in der Binary leicht möglich ist. Interessanter wird es, das Rendern vorzubereiten und wieder zu beenden. Dazu bedienen wir uns das Klasse ILTDrawPrim, welche ebenfalls über Strings schnell gefunden wird. Ein Blick in das SDK liefert auch schöne Klassenmember und virtuelle Funktionen, die wir uns zu nutze machen können.

The ILTDrawPrim is a low level polygon
based drawing/rendering interface
class ILTDrawPrim : public IBase
{
    public :
    /* Called to begin a draw primitive block. This is for optimizing draw primitive calls.
Calls to have the engine render anything not through the draw primitive cannot be made inside this block. */
	virtual LTRESULT BeginDrawPrim() = 0;
/* Called to end a draw primitive block. 
    Used for: Rendering. */
	virtual LTRESULT EndDrawPrim() = 0;

Diese Funktionen aus den VTables dürfen wir auf jeden Fall aufrufen bevor wir zeichnen!

Weiter geht es mit dem eigentlichen Zeichnen. Dazu schreibt uns das SDK vor, eine CFontInfo zu erzeugen, aus der wir wiederrum ein CTextureString-Klasse bekommen. Beim Registrieren müssen wir alle Characters übergeben, die wir in dem String nutzen wollen. Wolfteam registriert für jeden String eine eigene CTextureString und beschränkt daher den Zeichensatz auf den String. Wir registrieren alle Buchstaben von a-Z und ein paar Sonderzeichen. Mit diesem CTextureString können wir über RenderSubString() ein gewünschten String an der Position XY Zeichnen. Was in dem SDK so schön beschrieben ist, stellt sich als intensive Debugsession herraus. Denn die VTables von der CTextureString stimmen nicht mit denen aus dem SDK überein. Nachdem die richtigen Funktionen gefunden waren, wurde einfach kein String gezeichnet. Ziemlich frustrierend das ganze!

Der Übeltäter war eine modifizierte CFontInfo Klasse. Daher wurde die Funktion zum Erzeugen von Fonts gehookt, welche uns wiederrum eine ausgefüllte CFontInfo im Parameter mitliefert. Dort ändern wir nun den Fontnamen und die Fontgröße nach belieben und registrieren sie.

Auf der Suche nach der richtigen DrawString Funktion modifzierte ich auch die Zeichenfarbe, um sicherzustellen dass wirklicher jeder String über diese Funktion läuft. Inzwischen gefällt mir das türkisene Layout, was ihr oben auf dem Screenshot geht ganz gut.

Doch waren es diese vielen Stunden Aufwand für “nur” einen Draw-Hook Wert? JA! Denn nun haben wir Debugausgaben auf dem Screen! Ein Draw-Hook ist immer der erste Schritt zu einem Hack. Desweitern lernt man die Engine immer besser kennen und für das später behandelte Auffinden der WorldToScreen-Funktion wird uns der Draw-Hook das Leben um einiges leichterer machen.

Bis dann!

5 people like this post.
  1. Noch keine Kommentare vorhanden.

  1. Noch keine TrackBacks.