[X] Reverse Engineering: Patching



  • 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*



  • Hier eine neuere Version: Ist mir hier lieber, habe alles in einer Textdatei, da sieht das so hingeschmissen aus:

    Reverse Engineering: Patchen

    Inhalt

    1. Benötigtes
    1.1 OllyDbg
    1.2 Peid
    2. Introduction
    3. Materie
    3.1 Beispiel: Fehlerkorrektur
    3.2 If-else-Bedingung aushebeln
    3.3 Schleifenbedingung korrigieren
    3.4 Programmstellen indizieren
    4. Kurzreferenz: Hexbefehle
    5. Nachwort

    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/

    Ich informiere Sie kurz über diese Produkte.

    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 und bietet diese Features:

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

    2 Introduction

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

    Es sei gesagt, dass Sie sich hiermit auf dem Gebiet des Reverse Engineering bewegen. In der Internetkultur hat sich Reverse Engineering zu einer Sportart entwickelt. Siehe Hackits/Crackits.

    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.

    3 Materie

    In diesem Artikel zeige ich drei Anwendungsmöglichkeiten. Das erste Problem dient als Einführung.

    Info:

    Ich drücke hier ausdrücklich aus, dass sich Offsets und Programmadressen je nach dem Compiler, mit dem das Programm kompiliert wurde, richten. Ich verwende hier CodeBlocks v1.0.

    Außerdem sollte sich jeder im klaren sein, dass der Herausgeber des Programmes das Reverse Engineering erlaubt haben muss. Ich muss nicht sagen, dass es strafbar ist fremde Software durch RE zu "klauen".

    3.1 Beispiel: Fehlerkorrektur

    Als Einführung in das Thema soll eine Fehlerkorrektur mit einer kleinen Story dienen.

    Dazu nehmen Sie bitte diesen Sourcecode als Beispiel:

    //prim.c
    //---------
    #include <stdio.h>
    
    int main(){
        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 uns 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.

    004012C0  |> C70424 2930400>MOV DWORD PTR SS:[ESP],prim.00403029     ; |ASCII "%s "
    

    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 prim.00403029 ist.

    Dies ist die .rdata-Sektion, wie man sich mit den entsprechenden Zahlen unter View -> Memory bewusst machen kann.

    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 0x0000100B und 0x0000100C

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

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

    //prim_patch.c 
    //--------- 
    #include <stdio.h> 
    
    typedef struct { 
        long oSet; 
        int hexV; 
    } PYTE; 
    
    static PYTE pytes[2] = { 
                                    {0x0000100B,0x08},      //offsets und hexacode values; 
                                    {0x0000100C,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); 
    }
    

    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.

    3.2 If-else-Bedingung aushebeln

    Nun, da wir uns reichlich mit den Grundlagen beschäftigt und drumherumgeredet haben, kommen wir zum nächsten Punkt.

    Zuerst: Wie wird in Assembly eine If-else-Bedingung ausgedrückt //mir fällt kein anderer Ausdruck ein

    Es gibt zwei Möglichkeiten:

    Springe zum else-Zweig

    oder

    Springe zum if-Zweig

    Nehmen Sie bitte dieses Programm als Beispiel:

    //if_else.cpp
    //---------
    #include <stdio.h>
    
    int cp(char passw[]){
        const char p[]=  "www.c-plusplus.net";
        int n = sizeof(p) / sizeof(char);
        for(int i = 0; i < n; i++){
            if(passw[i] != p[i]){
                return 0;
            }
        }
        return 1;
    }
    int main(){
        char pw[17];
        printf("pw_ ");
        fgets(pw, 18, stdin);
        if(cp(pw) == 1){
            puts("Zugriff gewaehrt");
        }
        else{
            puts("Zugriff verweigert");
        }
    }
    

    Zur Erklärung, mit dem "Es gibt nur einen Zweig", hier eine Programmablaufbeschreibung:

    schreibe "pw_ "
    lese pw
    lade passwortstring
    vergleiche passwortstring mit pw
    wenn gleich bzw. wenn nicht gleich, dann springe
    weiterer codeablauf

    Da wir dies hätten, suchen wir unsere Programmstelle und haben dann diesen oder ähnlichen Code vorliegen:

    004012F0  /$ 55             PUSH EBP
    004012F1  |. B8 10000000    MOV EAX,10
    004012F6  |. 89E5           MOV EBP,ESP
    004012F8  |. 53             PUSH EBX
    004012F9  |. 83EC 54        SUB ESP,54
    004012FC  |. 83E4 F0        AND ESP,FFFFFFF0
    004012FF  |. E8 EC040000    CALL if_else.004017F0
    00401304  |. E8 87010000    CALL if_else.00401490
    00401309  |. C70424 1230400>MOV DWORD PTR SS:[ESP],if_else.00403012  ; ||ASCII "pw_ "
    00401310  |. BB 12000000    MOV EBX,12                               ; ||
    00401315  |. E8 96050000    CALL <JMP.&msvcrt.printf>                ; |\printf
    0040131A  |. 8B0D DC504000  MOV ECX,DWORD PTR DS:[<&msvcrt._iob>]    ; |msvcrt._iob
    00401320  |. 895C24 04      MOV DWORD PTR SS:[ESP+4],EBX             ; |
    00401324  |. 8D5D D8        LEA EBX,DWORD PTR SS:[EBP-28]            ; |
    00401327  |. 894C24 08      MOV DWORD PTR SS:[ESP+8],ECX             ; |
    0040132B  |. 891C24         MOV DWORD PTR SS:[ESP],EBX               ; |
    0040132E  |. E8 6D050000    CALL <JMP.&msvcrt.fgets>                 ; \fgets
    00401333  |. 8B15 00304000  MOV EDX,DWORD PTR DS:[403000]
    00401339  |. 8955 B8        MOV DWORD PTR SS:[EBP-48],EDX
    0040133C  |. A1 04304000    MOV EAX,DWORD PTR DS:[403004]
    00401341  |. 8945 BC        MOV DWORD PTR SS:[EBP-44],EAX
    00401344  |. 8B0D 08304000  MOV ECX,DWORD PTR DS:[403008]
    0040134A  |. 894D C0        MOV DWORD PTR SS:[EBP-40],ECX
    0040134D  |. 8B15 0C304000  MOV EDX,DWORD PTR DS:[40300C]
    00401353  |. 8955 C4        MOV DWORD PTR SS:[EBP-3C],EDX
    00401356  |. 31D2           XOR EDX,EDX
    00401358  |. 0FB705 1030400>MOVZX EAX,WORD PTR DS:[403010]
    0040135F  |. 66:8945 C8     MOV WORD PTR SS:[EBP-38],AX
    00401363  |. 8DB6 00000000  LEA ESI,DWORD PTR DS:[ESI]
    00401369  |. 8DBC27 0000000>LEA EDI,DWORD PTR DS:[EDI]
    00401370  |> 0FB64C2A B8    /MOVZX ECX,BYTE PTR DS:[EDX+EBP-48]      ; |
    00401375  |. 3A0C1A         |CMP CL,BYTE PTR DS:[EDX+EBX]            ; |
    00401378  |. 75 19          |JNZ SHORT if_else.00401393              ; |
    0040137A  |. 42             |INC EDX                                 ; |
    0040137B  |. 83FA 12        |CMP EDX,12                              ; |
    0040137E  |.^7C F0          \JL SHORT if_else.00401370               ; |
    00401380  |. C70424 1730400>MOV DWORD PTR SS:[ESP],if_else.00403017  ; |ASCII "Zugriff gewaehrt"
    00401387  |. E8 04050000    CALL <JMP.&msvcrt.puts>                  ; \puts
    0040138C  |. 8B5D FC        MOV EBX,DWORD PTR SS:[EBP-4]
    0040138F  |. 31C0           XOR EAX,EAX
    00401391  |. C9             LEAVE
    00401392  |. C3             RETN
    00401393  |> C70424 2830400>MOV DWORD PTR SS:[ESP],if_else.00403028  ; |ASCII "Zugriff verweigert"
    0040139A  |. E8 F1040000    CALL <JMP.&msvcrt.puts>                  ; \puts
    0040139F  |. 8B5D FC        MOV EBX,DWORD PTR SS:[EBP-4]
    004013A2  |. 31C0           XOR EAX,EAX
    004013A4  |. C9             LEAVE
    004013A5  \. C3             RETN
    

    Bedingter Sprung: 00401378 |. 75 19 |JNZ SHORT if_else.00401393 ;

    Zur Erklärung:

    0040132E  |. E8 6D050000    CALL <JMP.&msvcrt.fgets>                 ; \fgets
    00401333  |. 8B15 00304000  MOV EDX,DWORD PTR DS:[403000]
    00401339  |. 8955 B8        MOV DWORD PTR SS:[EBP-48],EDX
    0040133C  |. A1 04304000    MOV EAX,DWORD PTR DS:[403004]
    00401341  |. 8945 BC        MOV DWORD PTR SS:[EBP-44],EAX
    00401344  |. 8B0D 08304000  MOV ECX,DWORD PTR DS:[403008]
    0040134A  |. 894D C0        MOV DWORD PTR SS:[EBP-40],ECX
    0040134D  |. 8B15 0C304000  MOV EDX,DWORD PTR DS:[40300C]
    00401353  |. 8955 C4        MOV DWORD PTR SS:[EBP-3C],EDX
    00401356  |. 31D2           XOR EDX,EDX
    00401358  |. 0FB705 1030400>MOVZX EAX,WORD PTR DS:[403010]
    0040135F  |. 66:8945 C8     MOV WORD PTR SS:[EBP-38],AX
    00401363  |. 8DB6 00000000  LEA ESI,DWORD PTR DS:[ESI]
    00401369  |. 8DBC27 0000000>LEA EDI,DWORD PTR DS:[EDI]
    

    Hier schreiben wir den String "www.c-plusplus.net" in den Speicher und lesen pw ein.

    00401370  |> 0FB64C2A B8    /MOVZX ECX,BYTE PTR DS:[EDX+EBP-48]      ; |
    00401375  |. 3A0C1A         |CMP CL,BYTE PTR DS:[EDX+EBX]            ; |
    00401378  |. 75 19          |JNZ SHORT if_else.00401393              ; |
    

    Hier ist der Test auf Null, welcher unserer Sprung ist.

    In diesem Fall müssen wir unseren Sprung nur noppen[No Operation; Hexcode 90]

    Wie man sieht haben wir 2 hexadezimale Befehle[75 und 19].

    Diesesmal befindet sich alles in der Text-sektion, außer unserem Passwort-String.

    Diese fängt bei mir bei 00401000 an und endet bei 00402000.

    Falls unser Stück in der Text-Sektion ist, können wir den Offset auch Ausrechnen:

    -----
    Absolute Adresse des Befehles

    Absolute Adresse der .text-Sektion
    +
    400
    -----

    Daher:

    00401378 - 00401000 = 0x00000378

    0x0000038C + 400 = 0x00000778

    Unsere Matrix für den Patch sieht also nun so aus:

    static PYTE pytes[2] = {
                                    {0x00000778,0x90},
                                    {0x00000779,0x90},
    };
    

    Wie Sie den Passwortstring ändern, können Sie 4.1 entnehmen.

    3.3 Schleifenbedingung korrigieren

    Nun widmen wir uns den Schleifenbedingungen. Als Beispiel nehme ich hier eine For-Schleife.

    Dieses Programm:

    //condition.c
    //---------
    #include <stdio.h>
    
    int main(){
        for(int i = 0; i < 10; i++){
            putc(i+65,stdout);
        }
    }
    

    Ist an dieser Stelle beachtenswert:

    00401290  /$ 55             PUSH EBP
    00401291  |. B8 10000000    MOV EAX,10
    00401296  |. 89E5           MOV EBP,ESP
    00401298  |. 56             PUSH ESI
    00401299  |. 53             PUSH EBX
    0040129A  |. 83EC 10        SUB ESP,10
    0040129D  |. 83E4 F0        AND ESP,FFFFFFF0
    004012A0  |. E8 9B040000    CALL conditio.00401740
    004012A5  |. E8 36010000    CALL conditio.004013E0
    004012AA  |. 31DB           XOR EBX,EBX
    004012AC  |. EB 12          JMP SHORT conditio.004012C0
    004012AE  |  89F6           MOV ESI,ESI
    004012B0  |> 8B42 20        MOV EAX,DWORD PTR DS:[EDX+20]
    004012B3  |. 89F1           MOV ECX,ESI
    004012B5  |. 43             INC EBX
    004012B6  |. 8808           MOV BYTE PTR DS:[EAX],CL
    004012B8  |. FF42 20        INC DWORD PTR DS:[EDX+20]
    004012BB  |. 83FB 09        CMP EBX,9
    004012BE  |. 7F 29          JG SHORT conditio.004012E9
    004012C0  |> 8B15 D8504000  /MOV EDX,DWORD PTR DS:[<&msvcrt._iob>]   ;  msvcrt._iob
    004012C6  |. 8D73 41        |LEA ESI,DWORD PTR DS:[EBX+41]
    004012C9  |. 8D4A 20        |LEA ECX,DWORD PTR DS:[EDX+20]
    004012CC  |. 8B41 04        |MOV EAX,DWORD PTR DS:[ECX+4]
    004012CF  |. 48             |DEC EAX
    004012D0  |. 85C0           |TEST EAX,EAX
    004012D2  |. 8941 04        |MOV DWORD PTR DS:[ECX+4],EAX
    004012D5  |.^79 D9          |JNS SHORT conditio.004012B0
    004012D7  |. 894C24 04      |MOV DWORD PTR SS:[ESP+4],ECX
    004012DB  |. 43             |INC EBX
    004012DC  |. 893424         |MOV DWORD PTR SS:[ESP],ESI
    004012DF  |. E8 FC040000    |CALL <JMP.&msvcrt._flsbuf>
    004012E4  |. 83FB 09        |CMP EBX,9
    004012E7  |.^7E D7          \JLE SHORT conditio.004012C0
    004012E9  |> 8D65 F8        LEA ESP,DWORD PTR SS:[EBP-8]
    004012EC  |. 31C0           XOR EAX,EAX
    004012EE  |. 5B             POP EBX
    004012EF  |. 5E             POP ESI
    004012F0  |. 5D             POP EBP
    004012F1  \. C3             RETN
    

    Hier nun die Erklärung:

    00401290  /$ 55             PUSH EBP
    00401291  |. B8 10000000    MOV EAX,10
    00401296  |. 89E5           MOV EBP,ESP
    00401298  |. 56             PUSH ESI
    00401299  |. 53             PUSH EBX
    0040129A  |. 83EC 10        SUB ESP,10
    0040129D  |. 83E4 F0        AND ESP,FFFFFFF0
    004012A0  |. E8 9B040000    CALL conditio.00401740
    004012A5  |. E8 36010000    CALL conditio.004013E0
    

    Nicht beachtenswert.

    004012AA |. 31DB XOR EBX,EBX

    EBX wird auf 0 gesetzt.

    004012AC  |. EB 12          JMP SHORT conditio.004012C0
    004012AE  |  89F6           MOV ESI,ESI
    004012B0  |> 8B42 20        MOV EAX,DWORD PTR DS:[EDX+20]
    004012B3  |. 89F1           MOV ECX,ESI
    004012B5  |. 43             INC EBX
    004012B6  |. 8808           MOV BYTE PTR DS:[EAX],CL
    004012B8  |. FF42 20        INC DWORD PTR DS:[EDX+20]
    

    Nicht beachtenswert

    004012BB  |. 83FB 09        CMP EBX,9
    004012BE  |. 7F 29          JG SHORT conditio.004012E9
    

    Prüfe das erste mal, ob EBX größer als 9 ist[10].

    Nun kommen wir in eine Schleife.

    004012C0  |> 8B15 D8504000  /MOV EDX,DWORD PTR DS:[<&msvcrt._iob>]   ;  msvcrt._iob
    004012C6  |. 8D73 41        |LEA ESI,DWORD PTR DS:[EBX+41]
    

    41 Hexedezimal ist 65 Dezimal..

    004012C9  |. 8D4A 20        |LEA ECX,DWORD PTR DS:[EDX+20]
    004012CC  |. 8B41 04        |MOV EAX,DWORD PTR DS:[ECX+4]
    004012CF  |. 48             |DEC EAX
    004012D0  |. 85C0           |TEST EAX,EAX
    004012D2  |. 8941 04        |MOV DWORD PTR DS:[ECX+4],EAX
    004012D5  |.^79 D9          |JNS SHORT conditio.004012B0
    004012D7  |. 894C24 04      |MOV DWORD PTR SS:[ESP+4],ECX
    004012DB  |. 43             |INC EBX
    

    EBX += 1

    004012DC  |. 893424         |MOV DWORD PTR SS:[ESP],ESI
    004012DF  |. E8 FC040000    |CALL <JMP.&msvcrt._flsbuf>
    004012E4  |. 83FB 09        |CMP EBX,9
    004012E7  |.^7E D7          \JLE SHORT conditio.004012C0
    

    Prüfe, ob EBX größer als 9 ist.

    Dieser Teil ist unsere Bedingung.

    Wir müssen nur den Wert 9 ändern, damit wir eine andere Bedingung haben.

    Eine Endlosschleife würden wir herbeirufen, wenn wir

    004012DB  |. 43             |INC EBX
    

    Noppen würden.

    3.4 Programmstellen indizieren

    Dies ist nun etwas kniffelig. Es gibt mehrere Probleme:

    -Wie muss ich die Register handhaben
    -Wo genau muss etwas indiziert werden
    -Wie kriege ich dazu den Hexcode?

    /*

    */

    4 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

    5 Nachwort

    Alles Sources und Executables finden Sie hier zum download: www.nochnichtvorhanden.de

    MFG winexec*



  • Ich habe den Artikel nur kurz überflogen. Mir sind aber ein paar Kleinigkeiten aufgefallen.

    Die Kapitelüberschriften finde ich teilweise nicht so schön. "Benötigtes" klingt imho etwas unbeholfen. Wie wäre es mit "Voraussetzungen"?
    Die zweite Kapitelüberschrift: "Introduction" da stört mich ehrlich gesagt das englisch. Warum nicht einfach "Einführung" oder "Einleitung"?

    Einige Formulierungen rufen in mir das Bedürfnis zu antworten hervor:

    "Es sei gesagt, dass ..." - Dann sag's doch einfach!
    "Ich drücke hier ausdrücklich aus, dass ..." - auch da denke ich wieder, dann mach's und red nicht drüber.

    Aber das ist mit Sicherheit auch Geschmacksache, sieh's einfach als Anregung. Nur das ausdrückliche ausdrücken würde ich auf jeden Fall überarbeiten.

    MfG Jester



  • @winexec* Kann der Artikel bei der nächsten Runde mit raus? Der sieht schon relativ fertig aus...



  • Hallo,

    Ich hatte bis jetzt noch keine Zeit nocheinmal drüberzuschauen. Ich wollte vielleicht noch unmittelbare Injektionen mit einbringen. Ich werde einmal schauen, aber es sollte möglich sein(90%).

    MFG winexec*



  • Okay, das klingt gut... außerdem sind ja noch zwei Wochen Zeit.


Anmelden zum Antworten