MW2 Bot in C# - Teil 1

Willkommen zum ersten “richtigen” Teil des MW2 Bots. Hier wird vorallem auf das CLR-Hosting eingegangen und am Ende die Basis-Funktionen und der Hook der zu injectenden DLL erklärt.

Widmen wir uns zu erst dem CLR-Hosting. Die in Teil 0 angesprochene Problematik, managed Code in einem unmanaged Programm auszuführen wird durch das sog. Hosting eines CLR-Interfaces umgangen. Auf Wikipedia gibt es zu dem Thema einen schönen Beitrag und eine noch schönere Grafik:



Doch was ist jetzt dieses ominöse CLR-Hosting? Im Grunde genommen lädt das Programm dazu ein paar .NET DLLs nach, welche uns das Ausführen von managed Code ermöglicht. Und dazu gibt es eine tolle Klasse, welche wir verwenden werden: ICLRRuntimeHost!

Ich persönlich habe mir einen CLRHelper geschrieben, welcher die einzelnen Abläufe vereinfacht. Hier mal die Header-Datei des CLRHelpers. Denkt daran “MSCorEE.h” einzubinden und “MSCorEE.lib” mitzulinken.

class CLRHelper
{
   public:
      static void InitCLR(); // Initialisiert das ganze CLRHosting
      static int ExecuteMethod(char* sName, char* sParam); // Ruft eine Methode aus einer (noch) hardcoded DLL auf
      static ICLRRuntimeHost* pCLR; // Unsere eigentliche Hostingklasse
      static DWORD LastResult; // Hier wird der letze Rückgabewert von dem managed Code gespeichert
      static LPCWSTR CharToWideChar(char* txt); // Da wir WideChar in der Funktion "ExecuteMethod" verwenden müssen, ist hier eine Converterfunktion
};

 

Ich denke die einzelnen Objekte und Methoden brauchen keine weitere Erklärung, daher gleich weiter zur CPP Datei:

void CLRHelper::InitCLR()
{
   CorBindToRuntimeEx(NULL, L"wks", NULL, CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&pCLR);
 
   pCLR->Start();
}

 

Diese Funktion initialisiert unser Hostingobjekt. Im Grunde bindet diese Funktion die .NET Runtime an den aktuellen Prozess und läd die entspechenden DLLs, wenn nicht schon gesehen. Die genaue Paramter kann man in der Linkliste weiter unten in dem Post finden. Wichtig ist dass die Adresse unsereres Hostingobjekts übergeben wird und dieses somit initialisiert ist.

Im Anschluss wird dann pCLR->Start() aufgerufen, um das Hosting zu starten.

int CLRHelper::ExecuteMethod(char* sName, char* sParam)
{
   pCLR->ExecuteInDefaultAppDomain(L"Z:\GAMEZ\Call Of Duty Modern Warfare 2\MW2_ModLoader_Bots\MW2BotDLLManaged.dll", L"MW2_Bot_DLL_Managed.Main", CLRHelper::CharToWideChar(sName), CLRHelper::CharToWideChar(sParam), &CLRHelper::LastResult);
return CLRHelper::LastResult;
}

Die Methode “ExecuteInDefaultAppDomain” ruft eine statische Funktion aus einer managed DLL auf, der Rückgabewert wird in LastResult gespeichert.

Die Parameter sehen wie folgt aus:

  1. Pfad und Dateiname zu der DLL aus der gelesen werden soll
  2. Der Namespace und die statische Klasse aus der eine Funktion aufgerufen werde. Es MUSS eine statische Klasse sein!
  3. Der Name der Funktion die aufgerufen werden soll. Diese muss ebenfalls statisch sein, ein Int32 zurückliefern und als einzigen Parameter einen String erwarten.
  4. Ein Parameter in Form eines Strings, welcher an die Funktion übergeben wird.

Wie ihr seht ist der Pfad z.Z. noch hardcoded, ist z.Z. zu Debugzwecken so eingerichtet.

LPCWSTR CLRHelper::CharToWideChar(char* txt)
{
   size_t newsize = strlen(txt) + 1;
   wchar_t * wcstring = new wchar_t[newsize];
 
   size_t convertedChars = 0;
   mbstowcs_s(&convertedChars, wcstring, newsize, txt, _TRUNCATE);
 
   return wcstring;
}

Hier noch schließlich die Funktion zum Umwandeln eines char-Pointers in ein WideCharString. Die Funktion ist aus dem Internet und u.a. hier zu finden.

Das war schon der ganze CLRHosting Teil. Jetzt möchte ich noch schnell den restlichen Source der zu injectenden DLL erklären. Ich gehe dabei davon aus, dass ihr wisst wie Detours funktionieren ;-) Wenn nicht -> Google.

BOOL APIENTRY DllMain( HMODULE hModule, DWORD  dwReason, LPVOID lpReserved)
{
   if(dwReason == DLL_PROCESS_ATTACH)
   {
      CreateThread(0, 0, HooK, 0, 0, 0);
   }
   return TRUE;
}

Was ihr hier seht ist der EntryPoint der DLL. Sobald sie attached ist, wird ein neuer Thread mit unserer Hook-Funktion gestartet. Der Grund, warum dieses in einen Thread geschieht, ist folgender: Wenn kein Thread verwendet wird, so kann dieses in einem Deadlock enden.

Für die folgende Funktion fehlt uns noch die Typedefinierung der die EndScene Funktion. Diese erwartet, wie man sehen kann, keine Parameter.

typedef void ( _cdecl* tRenderShit )();
tRenderShit oRenderShit=0; // Dieses ist unsere originale EndScene Funktion
 
DWORD WINAPI HooK( LPVOID )
{
   CLRHelper::InitCLR(); // Initialisiert unser CLRHosting
   CLRHelper::ExecuteMethod("Init","Init"); // Ruft die statische Init-Funktion mit dem Parameter "Init" auf.
 
   oRenderShit = (tRenderShit)DetourFunction( ( PBYTE )0x586E00, ( PBYTE )&hRenderShit ); //Diese Funktion hooked schließlich die EndFrame Funktion. Dabei wird die originale Funktion in oRenderShit gespeichert und zu hRenderShit detoured.
   return 0;
}

0x586E00 ist die Adresse, an der die orginale EndFrame-Funktion zu finden ist. Ich verwende die AlterIWNet Version (1.3.3.7++), das entspricht der 1.0.184 der SteamVersion. Zu Detours einfach mal nach “Microsoft Detours” suchen. Ansonsten sollten die Kommentare soweit alles andere beschreiben, daher gleich weiter mit hRenderShit.

void hRenderShit( )  // Die gedetourte Funktion
{
   _asm pushad; // wir sichern alle Register
 
   CLRHelper::ExecuteMethod("Run","Test"); // Der CLRHelper ruft die Run-Methode unseres Bots auf
 
   __asm popad; // wir stellen alle Register wieder auf den Orginalzustand zurück
 
   oRenderShit();  // und schließlich wird die originale EndFrame-Funktion aufgerufen
}

Das wars auch schon von dieser relativ “kleinen” DLL. Natürlich wird diese später noch wachsen, aber das ist soweit das Grundgerüst. Damit ist es möglich, dass bei jedem Ende vom einem Spiel-Frame die Run-Methode, welche managed Code ist, aufgerufen wird!

Sollte es Fragen zu diesem Thema geben, so hinterlasst doch einfach ein Kommentar!

Linklist zu managed DLL Injection und Hosting:

Greez Easysurfer

4 people like this post.

Andere Artikel zu dieser Serie

  1. MW2 Bot in C# – Teil 9
  2. MW2 Bot in C# – Teil 8
  3. MW2 Bot in C# – Teil 7
  4. MW2 Bot in C# - Teil 6
  5. MW2 Bot in C# - Teil 5
  6. MW2 Bot in C# - Teil 4
  7. MW2 Bot in C# - Teil 3
  8. MW2 Bot in C# - Was will er eigentlich?
  9. MW2 Bot in C# - Teil 2
  10. MW2 Bot in C# - Teil 1 (This post)
  11. MW2 Bot in C# - Teil 0
  1. Noch keine Kommentare vorhanden.

  1. 7. Jun. 2011
    TrackBack von: MW2 Bot in C# – Teil 1


drei × 7 =