[X] Reverse Engineering: Patching



  • Reverse Engineering: Patchen Teil 1

    Inhalt

    1. Benötigtes
    1.1 OllyDbg
    1.2 Peid
    2. Introduction
    3. Materie
    4. Der Patch
    5. Kurzreferenz: Hexbefehle

    1 Benötigtes

    In diesem Artikel verwende ich Disassembler/Debugger, um Programme zu analysieren. Diese sind hier erhältlich:

    -OllyDBG http://www.ollydbg.de/
    -Peid http://peid.has.it/

    1.1 OllyDbg

    OllyDbg ist ein von Oleh Yuschuk entwickelter 32-Bit Debugger für Windows Betriebssysteme. Hauptsächlich wird OllyDbg zur binären Codeanalyse verwendet werden.

    OllyDbg bietet folgende Features:

    -Debugging von Multithread Programmen
    -Anhängen an laufende Prozesse
    -Konfigurierbarer Disassembler mit Unterstützung der Formate MASM und IDEAL
    -MMX, 3DNow, SSE, ASCII und UNICODE Unterstützung
    -Hardware- und Software-Breakpoints
    -Suchen über Speicherbereiche
    -Modifikation von Speicherbereichen on-the-fly

    1.2 Peid

    Peid erkennt die meisten bekannten Packers, Cryptors und Compiler.

    Peid bietet diese Features:

    -EInfach zu handhabende GUI.
    -Shell Eingliederung, Kommandozeilenunterstützung.
    -Task viewer und controller.
    -Hex Viever

    2 Introduction

    Patches sind Programme, die andere Programme in der Struktur ändern. Sie "patchen" mit Hilfe von dem hexadezimalen Zahlensystem bestimmte Bytes in der [ich nehme an] Executable.

    Es sei gesagt, dass Sie sich hiermit auf dem Gebiet des Reverse Engineering bewegen.

    Mehr dazu hier: http://en.wikipedia.org/wiki/Reverse_engineering

    Patchen ist nicht immer das erweitern, sondern auch das reduzieren bzw. ausbessern von Code.

    Man springt relativ vom Anfang der Datei die Entfernung zu den gesuchten Variablen/Codestücken. Daher benötigen wir den Offset. Der Patch selber ist schnell hergestellt, solange es nur kleine Ausbesserungen sind; die Suche nach dem richtigen Stück Code aber, welches wir bearbeiten wollen oft nicht.

    //Tip: Protokollieren Sie alle Daten. Sie werden diese im Patch benötigen.

    Ich möchte nicht zuviel Theorie in diesem Artikel einbringen. Den meisten von Ihnen ist die praxisnahe Arbeit wohl viel lieber.

    3 Materie

    Wir brauchen erst einmal ein Programm, welches wir patchen möchten.

    Ich schreibe noch eine kleine Story, damit Sie wissen, was jemanden zum Patchen bewegen kann.

    Dazu nehmen Siw dies als Beispiel:

    //prim.c
    //---------
    #include <stdio.h>
    
    int main(){
    
        printf("Primzahlen unterstehen diesen Regeln: \n\n");
        printf("Primzahlen lassen sich nicht als Produkt zweier natuerlicher Zahlen,"
                     "die beide groesser als eins sind, darstellen.\n");
        printf("Ist ein Produkt zweier natuerlicher Zahlen durch eine Primzahl teilbar,"
                     "so ist bereits einer der Faktoren durch sie teilbar.\n");
        printf("Jede natuerliche Zahl laesst sich als Produkt von Primzahlen schreiben."
                     "Diese Produktdarstellung ist bis auf die Reihenfolge der Faktoren eindeutig.\n");
    
        printf("\nkleine Primzahlen: \n\n");
        char *primzahlen[15] = {"2", "3", "5", "7", "11", "12", "13", "17", "19", "23", "29", "31", "37", "41", "43"}; // 12 ist keine Primzahl
        for(int i = 0; i < 15; i++){
            printf("%s ",primzahlen[i]);
        }
    }
    

    Nehmen wir an, eine Array gefüllt mit Primzahlen wäre in einer Funktion, die
    zu einem Programm gehört, dass wir für eine Firma geschrieben haben.

    Nun braucht dieses Programm eine Berechnung der Primzahlen. Denken wir uns einfach es ist eine Datenbank und ein Angestellter, der einigermaßen aufmerksam ist, sieht nun dort eine 12: Er ist entsetzt.

    Nun läuft er schnell zum Chef und dieser ruft uns gleich, mit leicht zorniger Stimme, an. Er verlangt das wir das Problem auf der Stelle beheben sonst...

    Wir brauchten eine Hintergrundgeschichte. Nun haben wir sie.

    Also haben wir und noch einmal den Quellcode angeguckt. Und da war diese 12.
    Es war die Einzige falsche Primzahl in diesem Array[Eigentlich kann man diese auch berechnen, aber mir ist kein besseres Problem eingefallen].

    Nun patchen wir diese 12, die niemand haben möchte.

    Kompilieren wir den Quelltext oben und schmeißen das Programm erst in OllyDBG.

    Nun müssten wir das Programm in hexadezimaler Form und in Assemblercode sehen.

    Mit den Schritten:

    -rechte Maustaste im Hauptfenster
    -Search For
    -All Referenced Text Strings

    ,bekommen wir alle Strings im Programm aufgelistet.

    wir klicken auf unsere ASCII "%s", womit ja unsere 12 auch ausgegeben wird.

    Nun werden wir zur Stelle im Programm geleitet, wo wir auf den Stack zugreifen.

    Wir sehen, dass unsere Variable auf dem Stack bei der Adresse[Compilerabhängig;mit CodeBlocks compiliert] prim.004031F5 ist.

    Dies ist die .rdata-Sektion.

    Nun beenden wir OllyDBG und benutzen PEID. Mit PEID kann man sehr leicht den benötigten Offset einsehen.

    Mit Peid öffnen wir also nocheinmal das Programm und gehen wie folgt vor:

    Der Pfeil bei EP Sektion führt uns zu der Sektionsübersicht. Unser Code ist in .rdata und dort wollen wir hin.

    Rechtsklick -> Hexviewer zeigt uns nun die hexadezimale Ansicht unserer Sektion.

    Wir sehen schon gleich unsere nette 12 dastehen[gekennzeichnet als 31 32 hex],
    was die hexadezimalen Werte der ASCII-Werte sind, die eine Taste kennzeichnen.

    Wir klicken mit der schönen Maus darauf und unten links wird unser Offset auch schon angegeben.

    Da hätten wir 0x000011D7 und 0x000011D8

    Für weitere Informationen über Hexeditoren siehe: http://en.wikipedia.org/wiki/Hex_editor

    4 Der Patch

    Nun schreiben wir unser Programm, um diese eckelhafte 12 wegzubekommen.

    //patch.c
    //---------
    #include <fstream>
    
    class PYTE{
        public:
        long oSet;
        int hexV;
    };
    
    static const PYTE pytes[2] = {
                                    {0x000011D7,0x08},      //offsets und hexacode values;
                                    {0x000011D8,0x00},      //0x08 für backspace->löscht letztes Nullbyte
                                                            //0x00 für das Setzen von einem Nullbyte.
                                                            //Sinn: Schönheitmackel der 2 Leerzeichen
                                                            //entfernen
    };
    
    int main(){
        FILE *patchFile = fopen("prim.exe","r+");
        for(int i = 0; i < 2; i++){
            fseek(patchFile, pytes[i].oSet, SEEK_SET);
            fwrite(&pytes[i].hexV, 1, 1, patchFile);
        }
        fclose(patchFile);
    }
    

    Somit haben wir unsere 12 los.

    Eine komplette Rekonstruktion des Programmes hätte einen nicht unermesslichen Zeitwand gekostet. Durch das Patchen wird der Betrieb nur eine kurze Zeitspanne unterbrochen, um das System zu updaten. Der Chef der Firma nimmt uns den Fehler doch nicht so dermaßen übel und wir sind glücklich, dass das so ist.

    Man kann auch Patchen, um Sicherheitsmechanismen zu umgehen, aber das ist sicherlich mit diesem Artikel nicht gewollt.

    5 Kurzreferenz: Hexbefehle

    Zum Abschluss noch eine kleine Hexadezimale Befehlstabelle:

    74          JE          Springe wenn gleich
    75          JNE         Springe wenn nicht gleich
    77          JA          Springe wenn größer
    0F86        JNA         Springe wenn nicht größer
    0F8C        JL          Springe wenn kleiner
    0F87        JNL         Springe wenn nicht kleiner
    0F83        JGE         Springe wenn größer oder gleich				
    0F8E        JLE         Springe wenn kleiner oder gleich
    EB          JMP         Unbedingter Sprung
    90          NOP         Keine Operation
    

    Für den Asciizeichensatz in Hexadezimal könnt ihr euch diesen Link anschauen: http://en.wikipedia.org/wiki/Ascii

    Ich könnte schon bald einen weiteren Artikel über das Teile des Reverse Engineering schreiben, aber mir fällt nichts ein, was man noch praktisch erklären könnte. Ich bin für Vorschläge offen.

    MFG winexec*



  • Äußerst interessant, aber für meinen Geschmack fast etwas zu knapp.

    Wie wäre es noch mit einem zweiten Beispiel? z.B. wie man eine if(-else)-Anweisung aushebeln kann, oder eine falsche Schleifenbedingung korrigiert?

    Ansonsten gut, ich hatte keinerlei Verständnisprobleme, auch wenn ich es nicht nachprobiert habe 😉



  • Hallo,

    Ja, habe ich mir auch gedacht, aber ich das nötig? Ich dachte nach dem Beispiel schaffen die Anfänger in dem Gebiet auch das.

    Aber ich überlege einmal, was ich noch als zweites Beispiel zeigen könnte.

    MFG winexec*



  • Ja Zusatz Artikel wären wirklich erwünscht!
    Weil es ein interessantes Thema ist!



  • Hallo,

    Ja, Ok :). Ich schreibe nochmal über die nächste Woche etwas zusammen, aber nicht das es dann illegal wird ;).

    Wie gesagt: Es wäre nett, wenn ihr sagen würdet, was euch genau noch interessierten würde, dann kann ich das reinbringen.

    Ich arbeite zurzeit noch an einem anderen Artikel, siehe Allegro.

    MFG winexec*



  • Und dabei schliesse ich mich Reyx voll an!

    Du könntest daraus ja Kurzbeiträge machen wie in einer Grundlageneinführung!

    1. IF manipulieren
    2. IF ELSE manipulieren
    3. FOR manipulieren
    4. DO/WHILE manipulieren

    Wobei das dann sicherlich bei Schleife sehr auf Manipulation
    von Marken (Addressen) hinausläuft.
    Die Schleifen sind ja auch bedingte Sprüng zu anderen Programmaddressen.
    Dabei würde dem Anfänger auch noch nützen wie er bestimmte Programmstellen findet.

    Wie gesagt ich würde für jeden Punkt einen eigenen Beitrag machen.

    mfg sclearscreen



  • Hallo,

    Das würde dann aber zu lang werden für einen Artikel.

    Wie wäre es, wenn ich einen ersten Artikel für die Einführung nutze und einen weiteren für Problemfälle, wie du es gesagt hast?

    MFG winexec*



  • winexec* schrieb:

    Hallo,

    Ja, Ok :). Ich schreibe nochmal über die nächste Woche etwas zusammen, aber nicht das es dann illegal wird ;).

    Wie gesagt: Es wäre nett, wenn ihr sagen würdet, was euch genau noch interessierten würde, dann kann ich das reinbringen.

    Ich arbeite zurzeit noch an einem anderen Artikel, siehe Allegro.

    MFG winexec*

    Illegal so ein Quatsch man muss ja nicht direkt sagen das es legal ist!
    Als Entwickler steht man doch immer mit einem Bein in der Legalität und mit dem anderen in der Illegalität.

    Können Wir was dfür das man jede Datei mit Dateibearbeitung auch Byte für Byte
    manipulieren kann?



  • winexec's Enzyklopedie/Grundlagen der Rückwärtsentwicklung von Software



  • winexec* schrieb:

    Hallo,

    Das würde dann aber zu lang werden für einen Artikel.

    Wie wäre es, wenn ich einen ersten Artikel für die Einführung nutze und einen weiteren für Problemfälle, wie du es gesagt hast?

    MFG winexec*

    ja kannst den ja für Teilbeiträge als Grundlage nehmen.
    Und das Probeprogramm immer entsprechend ändern!



  • Hallo,

    Klingt etwas zu dick aufgetragen.

    Wir können uns auch einmal über IRC über die Themenwahl unterhalten.

    MFG winexec*



  • Was mich dabei wie geasgt am meisten interessiert
    wie kann man sicher bestimmt Prommsignaturen im HEX-Code verifizieren?

    Beispiel:

    for(int i=;i<len;i++){...}
    

    schliesslich rutscht ja ein Instructionpoiter drüber über den "quasi Hex-Code" bei der konkreten Ausführung.
    Davon hat ja bestimmt so manch einer was gehört aber für mich ist das z.B. auch nichts alltägliches. Hatte mich vor langer Zeit mal etwas in Assembler probiert
    auch ein paar kleinerer Sachen gemacht aber über die Grundlagen komme ich damit nicht.



  • Was heisst zu Dick aufgetragen?

    Aber nee hast Du auch ICQ?



  • Hallo,

    Ja, sicher: 283-311-769

    Ich leg mich aber für heute aufs Ohr. Ich bin übernächtigt.

    Für die Nachtwandler: Weiteres Feedback erwünscht.

    MFG winexec*



  • Hmm fürs IRC werde ich mir mal eine Client saugen müssen...
    mal suchenn im Netzt...



  • Hallo,

    mIrc vielleicht. Ist mgw. aber zu aufdringlich.

    MFG winexec*



  • XChat http://www.silverex.org/download/

    ^^

    BR
    Vinzenz



  • sclearscreen schrieb:

    Hmm fürs IRC werde ich mir mal eine Client saugen müssen...
    mal suchenn im Netzt...

    Oder ihr nehmt das Applet, was ich extra für Euch umgebastelt habe. 🙂
    Der Link ist nochmal im Forenkopf: http://www.c-plusplus.net/magazin/orga/cppmag.html

    Ich finds klasse, dass das Thema hier so gut ankommt. 👍



  • Hallo,

    estartu.. ich hatte vor die Executable zum downloaden anzubieten, da wegen der Compilerunterschiede die Begrifflichkeit zu leiden hat. Kann ich[falls erlaubt] eine Rar-Datei auf den Server laden?

    MFG winexec*



  • winexec* schrieb:

    Hallo,

    estartu.. ich hatte vor die Executable zum downloaden anzubieten, da wegen der Compilerunterschiede die Begrifflichkeit zu leiden hat. Kann ich[falls erlaubt] eine Rar-Datei auf den Server laden?

    MFG winexec*

    Ja, ist kein Problem. Aber mach ein zip anstatt ein rar.

    Dein zweites Listing ist etwas "unüblich" für C, v.a. da du Klassen verwendest, mach's besser so, dann frisst's auch ein C Compiler:

    //patch.c
    //---------
    #include <stdio.h>
    
    typedef struct { 
        long oSet;
        int hexV;
    } PYTE;
    
    static PYTE pytes[2] = {
                                    {0x000011D7,0x08},      //offsets und hexacode values;
                                    {0x000011D8,0x00},      //0x08 für backspace->löscht letztes Nullbyte
                                                            //0x00 für das Setzen von einem Nullbyte.
                                                            //Sinn: Schönheitmackel der 2 Leerzeichen
                                                            //entfernen
    };
    
    int main(void){
        FILE *patchFile = fopen("prim.exe","r+");
        for(int i = 0; i < 2; i++){
            fseek(patchFile, pytes[i].oSet, SEEK_SET);
            fwrite(&pytes[i].hexV, 1, 1, patchFile);
        }
        fclose(patchFile);
    }
    

    Und im ersten Listing würde ich die ganzen printfs, die nur strings ausgegeben, durch puts ersetzen. Erspart einige '\n' und ist flotter.

    MfG

    GPC



  • Hallo,

    Ja sicher, habe nur nicht alles in einem Ordner gehabt und daher ist is es alles bisschen chaotisch geworden.

    MFG winexec*


Anmelden zum Antworten