[Tutorial] Reverse Engineering

  • Hallo Liebe NosHack Community ,


    Zu später Stunde möchte ich euch noch ein kleines Tutorial im Bereich "Reverse Engineering" vorstellen dies hat mir am Anfang sehr geholfen.
    Dies Tutorial ist nicht von mir geschrieben sondern von Krusty doch wo ich gerade mir mal den ReverseEngineering-Bereich anschauen wollte
    habe ich eig. nichts großes gefunden deswegen dachte ich mir schreibe ich das Tutorial mal hier für NosHacks ab in diesen Tutorial geht es nicht um NosTale oder allgemein um ein Spiel sondern um den Windows Life Messenger, ich kann euch das Tutorial nur ans Herz legen weil die Sachen die man in diesen Tutorial lernt auch auf NosTale oder allgemein Spiele übertragen kann dies Tutorial habe ich 1:1 abgeschrieben weil es dies eig. nur als PDF Datei gibt die Bilder haben ich Hochgeladen najagenug geschrieben fangen wir an viel Spaß beim lernen


    Reverse Engineering am Beispiel vom Windows Life Messenger



    Gliederung

    • Einleitung
    • Werkzeuge/Programme
    • Assembler
    • Der Multiclient
    • Der Ringpatch
    • Abschluss


    1.Einleitung


    Hallo, ich bin der Krusty und ich möchte euch heute einige Dinge im Bereich Reverse Engineering
    näher bringen.
    Wir werden uns den Windows Life Messenger vorknöpfen und den ein klein wenig verändern,
    sodass wir den Messenger mehrmals starten, uns mehrmals einloggen können (Multiclient) und
    unsere Freunde unendlich an ringen können (Ringpatch). Auch wenn diese Funktionen bereits durch
    MSN Plus zur Verfügung stehen, kann es nicht schaden, wenn wir uns mal anschauen, wie so was
    funktioniert.


    2. Werkzeuge/Programme
    Als aller erstes brauchen wir unser Opferprogramm, den Windows Life Messenger in einer
    aktuellen Version. Wir installieren diesen. Dann brauchen wir natürlich Programme, mit denen wir
    unser Opferprogramm bearbeiten können; Wir werden uns mit dem Debugger OllyDBG anfreunden
    und uns gegebenenfalls mit dem Programm Cheat Engine relevante Programmstellen suchen. Alle
    Programme lassen sich leicht bei Google finden.


    Windows Life Messenger:
    Naja, den sollte eigentlich jeder kennen, es handelt sich um einen Messenger von Microsoft, den
    Nachfolger des MSN Messengers. Ohne die MSN Plus Addons hat man leider nicht die Möglichkeit
    unendlich zu ringen und den Client mehrmals zu starten. Der Messenger muss natürlich installiert
    werden.


    OllyDBG:
    Der Olly Debugger ist sehr verbreitet und ein beliebtes Arbeitswerkzeug im Reverse Engineering.
    Mit diesem Programm werden wir uns den Messenger in Assemblerquellcode (kurtz ASM)
    anschauen und diesen so umschreiben, dass wir die oben genannten Ziele erreichen. Der OllyDBG
    muss nicht installiert werden, nach dem Download kann er sofort gestartet werden. Es gibt ne
    menge nützliche PlugIns, die man nachträglich hinzufügen kann, ich kann euch das PlugIn
    „Analyse This“ empfehlen... wir werden als Anfänger aber kein einziges PlugIn brauchen.


    Cheat Engine:
    Wie der Name schon sagt, handelt es sich um ein Programm, das ursprünglich zum Cheaten gedacht
    war und durchaus fähig ist als solches verwendet zu werden... Sprich; Man verwendet das
    Programm eher in der Cheatingszene, um z.B, Speicheradresse von Geld, Lebenspunkten oder
    Munition zu finden und diese zu verändern. Cheat Engine besitzt ebenfalls einen guten Debugger.
    Wir brauchen dieses Programm nicht unbedingt, es hilft jedoch die richtigen Stellen im
    Opferprogramm zu finden und erspart uns, vor allem als Anfänger, eine Menge Zeit.


    3. Assembler
    Jetzt wird es etwas unangenehm. Unser Computer kennt nur 2 Zustände, Strom an (1) und Strom
    aus (0)... Programme bestehen also aus sehr vielen Nullen und Einsen, die aneinandergereiht sind,
    man spricht vom sogenannten Opcode. Für einen Menschen ist es fast unmöglich ein Programm in
    dieser Form zu analysieren, deshalb übersetzt man diesen Opcode in sogenannten
    Assemblerquellcode, der für uns leichter zu lesen ist. Im Debugger haben können wir diesen
    Assemblercode betrachten und bei bedarf auch ändern. Es gibt eine Reihe von wichtigen
    Operatoren und Funktionen in Assembler, ich werde einige im Laufe erklären. Bei unserer Arbeit
    begleitet uns eine nette Situation, wir müssen selber kein Assembler schreiben, sondern es nur lesen
    und abändern.
    4. Der Multiclient
    Viele Programmiere schützen ihre Programme gegen doppeltes Ausführen, umgeht man diesen
    Schutz, erstellt man einen Multiclient. Viele Programme verwenden die CreateMutex Funktion
    oder die CreateEvent Funktion, um sich vor doppeltem Ausführen zu schützen. Das sind
    Windows API Funktionen aus der Kernel32 DLL. Mit der GetLastError Funktion wird
    anschließend überprüft, ob das Programm bereits ausgeführt ist, oder gestartet werden darf.
    Unsere Aufgabe ist es also die Stelle im Windows Life Messenger Client zu finden, an der diese
    Abfrage abläuft und den Speicher so zu manipulieren, dass sich der Client mehrmals starten lässt.
    Okay, wir haben den Windows Life Messenger erfolgreich installiert. Die Verknüpfung führt uns, je
    nach Installation, zur C:\Programme\Windows Live\Messenger\msnmsgr.exe, das sollte in etwa so
    aussehen:


    [Blocked Image: http://i.epvpimg.com/siYPf.png]


    Das ist also das Programm, welches wir bearbeiten müssen. Die restlichen Dateien im Ordner sind




    DLLs, Sounds usw. und sind für uns nicht interessant. Starten wir also unseren Debugger Ollydbg
    und laden unser Opferprogramm, indem wir oben links auf „File“, dann „Open“ klicken und
    msnmsgr.exe anwählen. Das ganze sollte so aussehen:


    [Blocked Image: http://i.epvpimg.com/TXXab.png]



    Ollydbg analysiert automatisch das Programm und gibt uns Hilfestellung, das kann ein wenig
    dauern, da das geladene Programm sehr umfangreich ist.
    Wir sehen hier im Hintergrund des „Open 32-bit executable“ ein großes Fenster, das in 4 Abschnitte
    eingeteilt ist. Der größere, obere linke Abschnitt beinhaltet den Assemblercode das ist der
    Disassembler. Rechts daneben sehen wir die Register, sie dienen als Zeiger bzw Speicher, wir
    werden uns kaum mit ihnen beschäftigen. Der untere linke Abschnitt zeigt uns den Hexdump, ein
    einfacher Hexeditor, für uns auch nicht so wichtig. Rechts daneben sehen wir den sogenannten
    Stack. Das ist ein Stapel an Informationen. Bevor eine Funktion aufgerufen wird, werden ihr
    Informationen (Parameter) auf den Stack gepackt. Der Stack ist für uns auch nicht so wichtig.
    Solltet ihr euch mit Assembler und Reverse Engineering über dieses Tutorial hinaus befassen
    wollen, dann müsst ihr euch trotzdem mit dem Stack und den Registern auseinandersetzen!
    Wir haben unseren Messenger in den Debugger geladen, unten Rechts sehen wir „Paused“, unser
    Opferprogramm ist also eingefroren. Mit einem Druck auf F8 können wir jede Zeile durchgehen,
    jeden Assemblerbefehl von den Millionen aneinandergereihten Befehlen ausführen lassen. Mit
    einem Klick auf den Play Button lässt sich das Programm im Debugger starten.


    [Blocked Image: http://i.epvpimg.com/Wvfxf.png]



    Der Stopp Button neben dem Play Button friert das Programm nach dem es gestartet wurde wieder
    ein (das Programm wird pausiert).
    Mit dem X Button kann man das Programm aus dem Debugger entfernen.
    Mit dem << Button lädt man das Programm erneut in den Debugger. Es ist eine Art Reload
    Funktion. Sollte etwas schief gegangen sein, dann lädt man das Programm einfach neu und versucht
    sein Glück erneut. Der Debugger bietet noch viel, viel mehr Funktionen, weitere Erklärungen
    würden die weite des Tutorials sprengen.



    Wie oben bereits angesprochen müssen wir die CreateEvent Funktion finden, das geht auch ganz
    einfach. Wir machen einen Rechtsklick auf das Fenster mit dem Assemblercode und wählen Search
    for an und klicken anschließend auf All intermodular Calls, das heißt so viel wie: Zeige alle
    intermodularen Funktionen an, die aufgerufen werden. Das ganze sollte so aussehen:


    [Blocked Image: http://i.epvpimg.com/Xo1ub.png]



    Anschließend öffnet sich ein großes Fenster. Uns ist das zu unleserlich, also machen wir einen
    Rechtsklick und wählen bei Sort by Destination an. Nun begeben wir uns auf die Suche nach der
    Funktion CreateEvent. Es gibt gleich mehrere Funktionen, wir nehmen einfach mal die erste:


    [Blocked Image: http://i.epvpimg.com/lwCEc.png]



    Wir klicken auf Follow in Disassembler oder doppelklicken die Funktion einfach. Wir gelangen nun
    zu dem Assemblercodeabschnitt, indem geregelt wird, ob der Messenger gestartet werden darf, oder
    nicht.



    Folgender Code lädt die Parameter mit dem Push Befehl für die CreateEvent Funktion auf den
    Stack:



    0049796F |> 68 B0594000 /PUSH msnmsgr.004059B0 ; /EventName = "MSNMSGR"
    00497974 |. 53 |PUSH EBX ; |InitiallySignaled
    00497975 |. 6A 01 |PUSH 1 ; |ManualReset = TRUE
    00497977 |. 53 |PUSH EBX ; |pSecurity


    mit dem Call Befehl wird die CreateEvent Funktion dann schließlich aufgerufen:


    00497978 |. FF15 78134000 |CALL DWORD PTR DS:[<&KERNEL32.CreateEv>; \CreateEventA


    Ein paar Zeilen darunter wird die GetLastError Funktion aufgerufen:


    00497989 |. FF15 B4134000 |CALL DWORD PTR DS:[<&KERNEL32.GetLastE>; [GetLastError




    Diese Funktion überprüft, ob ein Fehler aufgetrefen ist. Eine Zeile tiefer sehen wir, wie das
    Programm mit dem CMP Befehl einen Vergleich anstellt und eine weitere Zeile tiefer mit dem JNZ
    Befehl entscheidet, ob das Programm gestartet werden darf oder nicht:
    00497994 |. 0F85 88010000 |JNZ msnmsgr.00497B22




    Dieser Punkt ist sehr entscheidend. JNZ steht für Jump if Not Zero, zu Deutsch: Springe, wenn
    nicht Null. Hinter dem JNZ steht die Adresse zu der gesprungen werden soll. Das JNZ wertet den
    Vergleich CMP in der Zeile davor aus und entscheidet dann, ob das Programm gestartet werden darf
    oder nicht. Wir müssen nun das Programm zwingen zu Springen und damit die Möglichkeit des
    Nichtspringens auslöschen. Wir doppelklicken die JNZ Zeile und ersetzen das JNZ durch JMP. JMP
    steht für Jump (=springen). Das Programm ist damit also gezwungen zu springen, egal, ob die
    GetLastError Funktion einen Fehler geliefert hat, oder nicht.


    [Blocked Image: http://i.epvpimg.com/8YvRf.png]


    So, wir müssen unseren Multiclient nun noch abspeichern, das geht ganz einfach. Rechtsklick auf
    unseren Disassembler, Copy To Executable es sollte sich ein weiteres Fenster öffnen... Rechtsklick,
    Backup und anschließend Save Data To Fil. Wir speichern unseren Multiclient mit einem Namen
    wie patchedMSN o.ä. Ab und probieren, ob alles soweit funktioniert.


    [Blocked Image: http://i.epvpimg.com/KDhTg.png]


    Herzlichen Glückwunsch zu deinem, wahrscheinlich, ersten Multiclient.


    5. Der Ringpatch


    So, kommen wir nun zum Ringpatch. Ich gehe davon aus, dass ihr alles, was ich oben erklärt hatte,
    auch verstanden habt. Wir beschäftigen uns nun mit Cheat Engine. Wie bereits gesagt, erstellt man
    damit normalerweise Cheats für Spiele, wir nutzen das ganze um einen vorübergehenden
    Ringpatch zu erstellen und die relevanten Stellen für einen festen Ringpatch zu finden. Wir starten
    Cheat Engine (Abkürzung CE) und starten unseren Windows Life Messenger. Cheat Engine wird
    uns fragen, ob wir das Tutorial machen wollen... könnt ihr erst mal mit nein beantworten. Wir
    klicken in oben links auf den kleinen Bildschirm mit der Lupe, es öffnet sich ein Fenster und wir
    wählen den Prozess vom Opferprogramm aus und klicken auf open:


    [Blocked Image: http://i.epvpimg.com/wPYDc.png]


    Wir loggen uns beim Messenger ein und wählen uns einen jemanden aus, den wir gleich ein wenigstressen werden. Bereit ? Wir öffnen also das Chatfenster und begeben uns zurück in Cheat Engine.


    Kurze ErklärungBei dem Messenger kann man alle 10 oder 20 Sekunden jemandem einen Ring senden. Wirmöchten diese 10 oder 20 Sekundensperre umgehen, damit wir unsere Freunde so richtig nervenkönnen. Irgendwo im Speicher steht momentan also „Ja, du darfst einen Ring senden“. Wenn wirnun einen Ring senden steht dort dann „Nein du darfst momentan keinen Ring senden“ wir gehendavon aus, dass der erste Fall im Programm durch eine 1 und der zweite Fall durch eine 0dargestellt wird. In dem Programm wird es sicherlich mehrere tausend, wenn nicht sogar millionenEinsen und Nullen geben und hier hilft uns Cheat Engine. Mit CE können wir unsere relevanteSpeicheradresse aus den millionen von Speicheradressen filtern.Okay, ich habe mir jemanden ausgesucht, den ich ärgern möchte, sein Chatfenster geöffnet undmöchte nun die erste Suche nach unser Adresse starten. Ich gehe davon aus, dass die Adresse denWert 1 hat, ich darf also einen Ring senden. Dazu gebe ich in das Textfeld von Cheat Engine,überdem Value steht also eine 1 ein und klicke auf first scann:


    [Blocked Image: http://i.epvpimg.com/QVyJc.png]


    Cheat Engine durchsucht jetzt das Programm nach allen Speicheradressen, die den Wert 1 haben.
    Sobald ich einen Ring senden müsste der Wert der gesuchten Adresse auf 0 springen... Ich gebe in
    das Textfeld in Cheat Engine also schonmal eine 0 ein, sende einen Ring in dem Chatfenster und
    klicke ganz schnell danach in Cheat Engine auf Next Scann. Cheat Engine sucht nun aus allen
    gerade gefundenen Adressen nach allen Speicheradressen, die den Wert 0 haben. Wie wir sehen sind
    es nun weniger Adressen, anfangs 195878 sind es nun nur noch 836 (bei euch können diese Werte
    abweichen). Wir warten 20 Sekunden ab und Scannen erneut nach der 1: geben also wieder in das
    Textfeld 1 ein und klicken auf Next Scann. Bei mir sind es jetzt nur noch 14 Adressen und eine
    davon ist unsere gesucht Adresse. Ein letzter Scann soll unsere gesuchte Adresse enttarnen:


    [Blocked Image: http://i.epvpimg.com/QUpgf.png]


    (Die Adresse kann bei euch anders sein!)




    Wir doppelklicken die letzte Adresse, damit sie (wie im Bild) nach unten geladen wird und setzen
    einen Haken bei Frozen, damit frieren wir die Adresse ein. Wir haben jetzt bereits den
    vorübergehenden Ringpatch erstellt, mit dem Einfrieren der Adressen wird deren Wert
    durchgehend auf 1 gesetzt, das heißt wir haben durchgehend die Erlaubnis zu ringen, versucht es
    mal aus. So ein vorübergehender Ringpatch ist leider nicht das wahre, nach jedem Neustart des
    Messengers verändert sich die Adresse und wir müssen diese erneut raus suchen. Um die relevante
    Stelle im Programm zu finden machen wir einen Rechtsklick auf die unten geladene Adresse und
    klicken auf Find out what writs to this Address und bestätigen die kommende Frage mit Ja. Es
    sollten sich 2 Fenster öffnen. Wir gehen zurück ins Chatfenster unseres Freundes/din, den/die wir
    nerven wollen und ringen nochmal, das sollte so aussehen:


    [Blocked Image: http://i.epvpimg.com/GZ7Nc.png]



    (Adresse können bei euch abweichen!)
    Wir klicken auf More Information und es öffnet sich noch ein Fenster ^^. Wir sollten eine rote Zeile
    sehen, die ist wichtig!


    00568CE8 - mov [esi+0000035c],eax




    Wir sehen wieder Assemblerquellcode. Uns interessiert erst mal aber nur die Adresse, die da am
    Anfang der Zeile steht. Wir können Cheat Engine nun schließen, wenn wir uns die Adresse gemerkt
    oder notiert haben.Wir öffnen unseren Debugger (OllyDBG) und laden unseren Messenger erneut in
    den Disassembler. Wir wollen nun unsere gefundene Adresse ansteuern, machen also einen
    Rechtsklick und klicken auf Goto und dann auf Expression und geben dort unsere Adresse ein und
    klicken OK:


    [Blocked Image: http://i.epvpimg.com/FCkKf.png]


    Unser Disassembler springt automatisch zu dieser Adresse und wir schauen uns die Umgebung mal



    an. Uns fallen die Timerfunktionen ins Auge Time = Zeit, wir müssen ja nach jedem Ring eine
    bestimmte Zeit warten, also haut das irgendwie hin. Wir scrollen nach oben und finden folgenden
    Assemblercode, indem die Parameter für einen Timer geladen werden:



    00568C79 |. 53 PUSH EBX ; /Timerproc
    00568C7A |. 68 F82A0000 PUSH 2AF8 ; |Timeout = 11000. ms
    00568C7F |. 68 90010000 PUSH 190 ; |TimerID = 190 (400.)
    00568C84 |. 50 PUSH EAX ; |hWnd


    Der zweite Parameter sagt uns übrigens, wie lange wir warten müssen, 11000 Millisekunden sind 11
    Sekunden.
    Direkt darunter wird natürlich der Timer gestartet:


    00568C85 |. FFD7 CALL EDI ; \SetTimer




    Zum Timer : Ein Timer wird gestartet und führt in einem bestimmten Abstand einen bestimmten
    Programmabschnitt aus, bis man den Timer beendet (killt).
    Der Timer wird immer dann gestartet, wenn wir einen Ring gesendet haben.
    Für uns ist dieser Teil interessant:



    00568CBA 74 22 JE SHORT msnmsgr5.00568CDE
    00568CBC |. 8B3D 081B4000 MOV EDI,DWORD PTR DS:[<&USER32.KillTimer>]
    00568CC2 |. 53 PUSH EBX ; /TimerID
    00568CC3 |. FF76 28 PUSH DWORD PTR DS:[ESI+28] ; |hWnd
    00568CC6 |. FFD7 CALL EDI ; \KillTimer
    00568CC8 |. 68 90010000 PUSH 190 ; /TimerID = 190 (400.)
    00568CCD |. FF76 28 PUSH DWORD PTR DS:[ESI+28] ; |hWnd
    00568CD0 |. FFD7 CALL EDI ; \KillTimer


    Die KillTimer Funktion beendet einen Timer... unseren Timer. Der JE Befehl überprüft, ob der
    Timer gekillt werden soll, oder nicht:



    00568CBA 74 22 JE SHORT msnmsgr5.00568CDE


    Wir überschreiben die Abfrage einfach mit NOPs, damit der Timer sofort gekillt wird und wirweiter ringen können, wir doppelklicken also die Zeile, schreiben NOP in das Textfeld und setzeneinen Haken bei Fill with NOPs. Nun müssen wir alles noch abspeichern:
    [Blocked Image: http://i.epvpimg.com/2W4Mc.png]



    7. Abschluss
    Okay, ihr habt es geschafft. Wir haben die CreatEven Funktion abgefangen und den Timer gekillt.Ich hoffe das kleine Tutorial hat euch geholfen.
    ----------------------------------------------------------------------------------
    So ich hoffe das Tutorial hat in gefallen mir hat es auf jeden fall geholfen :) und sehr viel Zeit gekostet :awe:
    Lg.Memory