[C/C++] PE Crypter

Dieses Thema im Forum "Projekte / Codes" wurde erstellt von terraNova, 30. Juli 2010 .

Schlagworte:
  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen
  1. terraNova
    terraNova hooman hurr durr
    VIP
    #1 30. Juli 2010
    Zuletzt von einem Moderator bearbeitet: 14. April 2017
    PE Crypter

    Hey.

    Zum Blogeintrag gibt es natürlich auch einen kleinen Test Crypter zum Nachschauen.
    Es ist natürlich nicht einfach das ganze zu verstehen und soll auch nicht als Leitfaden, jedoch als Hilfe
    verstanden werden.

    Der Crypter fügt einen Stub in einer seperaten Sektion in die Ausgabedatei "crypted_Originalname.exe" hinzu
    welche die Importtable-Addresse herausfindet, den Code entschlüsselt und die Addressen anpasst.

    Der Crypter hat jedoch einen Addresslimit und funktioniert somit nicht bei großen Anwendungen, dass müsst ihr
    dann selber erweitern. ;-)

    Ein Beispielprogramm liegt direkt im Projekt bei.

    Das Projekt ist ein 'Visual C++ 2010 Express'-Projekt und wird daher auch die selbe IDE brauchen.

    Artikel: PE Crypter
    Projekt: Download: tnCrypter.rar | www.xup.in

    Viel Spaß damit
     

  2. Anzeige
  3. N0S
    N0S Malware Schreck
    VIP
    #2 30. Juli 2010
    AW: PE Crypter

    Das ist echt ein super PE Crypter Beispiel. Hab wirklich noch nie einen so guten Open-Source C++ XOR Crypter gesehen, wo sogar die Stub in C++ programmiert wurde und nicht in Assembler, wie es bei den meisten anderen Cryptern ist. :thumbsup:
     
  4. aRiGaT0
    aRiGaT0 Neu
    Stammnutzer
    #3 29. März 2014
    AW: PE Crypter

    Hallo terraNova,

    vielen Dank für den Source, habe ihn mir im Detail angeschaut.

    Bezüglich dem Thema "Crypter" Allgemein und der .stub habe ich Fragen an Dich:

    Crypter Allgemein:

    1) Crypter werden u.a. dazu verwendet um Scanengines von AVs auszutricksen. Auf einer Signatur basierende Engines nutzen z.B. Pattern-Matcher um Malware zu erkennen. Doch an dieser Stelle ist doch der springende Punkt: die .stub bietet doch auch ein Pattern, welches die AV-Hersteller in ihre Engine implementieren können bzw. bei einem Signaturupdate aufnehmen können. Somit muss wieder die .stub wieder angepasst werden, um nicht erkannt zu werden. Der Cryper ermöglicht es zwar den eigentlichen Source vor den AVs zu verschleiern, jedoch kann die .stub immer noch per Signatur erkennt werden. Ist meine Sichtweise richtig?

    2) Kannst Du mir Veränderungspotential aufzeigen? Damit gemeint sind andere Implementierungsansätze: deinen Source habe ich (fast) verstanden, jedoch wäre es mir nicht möglich selbst eine andere Implementierung zu schreiben.

    Zur .stub:

    3)
    Code:
     __asm mov ib.l_base, edx 
    Warum steht in EDX der Anfang der .stub Section? Ich meine, dass es funktioniert sehe ich. Jedoch sehe ich nicht warum dies funktionert. Google konnte mir hierzu auch nicht helfen. Bestimmt gibt es eine einfache Antwort.

    4)
    Code:
    if( *(data+(i-2)) == 0x89 // 
    && *(data+(i-1)) == 0x35)
    
    Wenn dieses Muster in der .text-Section vorhanden ist wird j=i gesetzt. Ist j vorhanden, dann wird 8B70F durch 909090 ersetzt. Beispiel aus IDA (noch nicht alles vollständig ersetzt):
    Code:
    .text:00151640 dd 8108B70Fh --> .text:00151640 dd 8108B790h 
    Kannst Du mir bitte erklären warum dieser Schritt getätigt wird?

    5)

    Meine letzte Frage betrifft das Patchen der Adressen. Kannst Du hier bitte nochmal genauer darauf eingehen warum dies getätigt wird bzw. es funktioniert? Diese Frage betrifft vorallem die den letzten Abschnitt im Code.
    Spoiler
    Code:
     /* PATCHING ADDRESSES */
     if(j) // Wenn es 0x89 und 0x35 gibt, dann Adresse patchen
     {
     for(i=2; i<code_size; i++)
     {
     // 0F B7 08
     if(*(data+(i+0)) == 0x0F // .text:00151640 dd 8108B70Fh --> .text:00151640 dd 8108B790h
     && *(data+(i+1)) == 0xB7
     && *(data+(i+2)) == 0x08)
     {
     *(data+(i+0)) = 0x90; // 
     *(data+(i+1)) = 0x90;
     *(data+(i+2)) = 0x90;
    
     i+=2;
     }
    
     if( *(short*)(data+i) == *(short*)(data+(j+2)) )
     {
     __asm nop
     __asm nop
     *(data+(i+0)) = ib.ch_base[2]; // Was passiert hier?
     *(data+(i+1)) = ib.ch_base[3];
     __asm nop
     __asm nop
     }
     }
     
     *(data+(j+0)) = ib.ch_base[2]; // Warum?
     *(data+(j+1)) = ib.ch_base[3];
     }
    

    Vielen Dank für deinen Source und die Beantwortung meiner Fragen!

    Gruß
     
  5. terraNova
    terraNova hooman hurr durr
    VIP
    #4 30. März 2014
    AW: PE Crypter

    Hallo, aRiGaTo,

    es freut und überrascht mich, dass es noch jemanden gibt, den der Source etwas bringt und gerne beantworte ich dir die Fragen, so gut ich kann.

    Zu 1) Ja, das ist so korrekt. Deswegen nutzen die meisten Crypter auch Routinen um, zwischen dem richtigen Code, Belanglosen hinzuzufügen (NOPs, Nullen, Code ohne Sinn oder einfache Puffer die übersprungen werden, etc.). Das generiert einen, zumeist, einzigartigen Stub.

    Zu 2) Ich bin mir nicht sicher, was ich dir hier schreiben soll, wenn ich ehrlich bin. Du solltest dir die grundlegende Vorgehensweise veranschaulichen und entsprechend deinen Code entwerfen. Im Endeffekt besteht ein Crypter ja aus dem Verschlüsselungsteil und seinem Gegenpart. Ersteres ist ohne weiteres zu bewältigen, während Letzteres schon etwas knifflicher ist, wie du oben ja schon klargestellt hast, jedoch immer von einer, in das Ziel implementierte, Dekodierungsroutine, sowie idR. Code um sich vor Debugger zu schützen.

    Zu 3) EDX enthält, soweit ich mich erinnere, die ImageBase.

    Zu 4) Gehört zu 4., und dient als Flag für die Sprungtabelle (Nicht wirklich sicher, deshalb folgenden Punkt beachten und direkt vermeiden).

    Zu 5) Das würde ich heute ganz auslassen, denn hätte ich an dem Punkt vorher einmal den Kopf eingeschaltet wäre mir eingefallen, dass ich die Adressen nicht zu patchen brauche, hätte ich das Ziel vorher gestartet mit den bereits übersetzten Adressen, oder in dem man den Crypter direkt intelligenter gestaltet und gewisse Dinge selber übernimmt, wie eben die Tatsache, die Importe vorher zu übersetzen, was im Regelfall der PE-Loader übernimmt (Weswegen es auch klüger gewesen wäre, das Zielprogramm aus dem Speicher zu laden, wo dieser Schritt schon getan wurde).

    Ich hoffe, ich konnte dir helfen. Vielleicht schreibe ich demnächst ja mal eine Version die etwas .. ästhetischer ist. :p
     
  6. aRiGaT0
    aRiGaT0 Neu
    Stammnutzer
    #5 30. März 2014
    AW: PE Crypter

    Danke für deine schnelle Rückmeldung, die Antworten bringen mich schon wieder ein bisschen weiter. Das Schwierige an der ganzen Theatik ist, dass es relativ wenig gute Beispiele dazu gibt (zumindest Beispiele zu denen ich Zugang habe bzw. die Öffentlich sind).

    Ich wurde es sehr begrüßen und mich freuen wenn Du Zeit findest um eine überarbeitete Version zu erstellen. Mitunter ist dann der Lerneffekt noch größer, da ein Vorher/Nachher-Vergleich möglich wird.
     
  7. terraNova
    terraNova hooman hurr durr
    VIP
    #6 31. März 2014
    AW: [C/C++] PE Crypter

    Wichtig ist es sich um Informationen zu bemühen. Was Du schon weißt, ist, dass du mit dem PE-Format arbeitest, also würde ich mich da schonmal dran hängen und mir die Informationen von MS besorgen.

    Dort wird geschildert wie die Struktur dieses Formats aussieht und wie du damit umzugehen hast, bzw. wie der PE-Loader damit umgeht. Jetzt hast du schonmal das nötige Wissen um eine PE zu laden, auszulesen und ggf. zu modifizieren.

    Was dir noch fehlt ist der Stub. Am einfachsten, jedenfalls meiner Meinung nach, ist es, einfach den Code direkt in eine seperate Section deines Crypters zu schreiben und dann, angepasst, in das Ziel zu pflanzen. Natürlich solltest Du die Einsprungsaddresse entsprechend setzen, die Alte aber nicht vergessen, denn nach der Entschlüsselung wird diese ja zum Sprung dorthin benötigt, damit das ursprüngliche Programm ausgeführt werden kann.
     

  8. Videos zum Thema