Easycrypter

  • Mich hat es immer gewundert, warum RunPE basierende Crypter fast immer so viele "unnötige" Funktionen verwenden (z.B ZwUnmapViewOfSection und natürlich das Reservieren des Speichers in "einzelschritten" - für jede Section einzeln).
    Denn in vielen Fällen braucht man nur die "Stub" beim Cryptvorgang etwas anzupassen und spart sich dann 5-6 "verdächtige" API Aufrufe.


    Kurzum - RunPE war imho eher ein PoC. Und der wurde in 90% aller Fälle einfach stumpf kopiert. Ich hab damit ein bisschen rumgespielt und ein "Crypter"+Binder in einem ist fast fertig ;). Da das eigentlich anschmei�?en der Exe ziemlich einfach ist, konnte ich meine Aufmerksamkeit viel interessanteren Dingen widmen.


    1. Es gibt keine "feste" Stub.
    Eine "Wirt" Anwendung wird ausgewählt. Sofern diese mit dem "Ziel" kompatibel ist (ImageBase + Vorhanden sein von LoadLibarary oder GetModuleHandle API) werden beide zusammengebunden.
    Der Wirt wird so modifiziert, dass er die "Zielanwendung" startet - allerdings selber weiterhin vollständig funktionsfähig bleibt (man braucht also keine Fake-Meldungen).
    Um das als Bsp auf die üblichen 90% der Crypter anzuwenden: jedesmal, wenn man einen neuen "Wirt" auswählt, hat man praktisch eine neue Stub ;).


    PE-mä�?ig wird ein "richtiger" Rebuild vorgenommen - die letze Section wird zwar vergrö�?ert, allerdings werden einige Codeteile in Codecaves geschrieben, so dass heuristikmä�?ig die Modifikation bei allen AVs als unverdächtig durchgeht.


    2. Es werden soviele Parameter wie möglich im vornherein ausgelsen und ausgewertet. Denn so gut wie immer kann man sich z.B das Einlesen der Exe von der Platte sparen, wenn man den Anhang einfach richtig an die letze Section dranhängt und ImageSize erhöht - dann kann man den ganzen Anhängsel direkt im Speicher lesen. Dasselbe gilt für ImageSize &Co. Dadurch bleibt der eigentliche "Launchcode" sehr übersichtlich und klein.


    3. Natürlich ist der "Launchcode" nicht nur klein, sondern auch komplett adressunabhängig ;) (erst dadurch ist das verzichten auf die "klassische" Exe-Stub möglich. Wie gesagt - Exen sind nur Wirt/Ziel vorhanden+etwas hinzugefügten Code für den Launch)
    Dadurch eignet sich dieser auch besonders gut, mit Junkcode vermengt zu werden :D.Und damit meine ich nicht

    Code
    1. jmp weiterrandombytes, randombytesweiter:

    Sondern:

    Klar, die Qualität ist nicht sooo toll, aber um diesen Code wirklich programmiertechnisch als Junk zu klassifizieren, muss man sich imho ziemlich anstrengen ;).
    Als Bonus: wer das genauer betrachtet, sieht "eingebaute" Schleifen:
    z.B 004047E8 bis 00404855 (ist ja nur ein ausschnitt). Es werden mehere Schleifen generiert, die dann eine "Mindestlaufzeit" haben. Da der Code imho schon eine gewisse Qualität hat, wird er von einem AV Code-Emulator eventuell nicht direkt als Junk/Junkschleife erkannt ;).


    Im moment bin ich dabei, die richtige decryptroutine in den Junkcode einzubeziehen. Dann generiert jeder Cryptvorgang wirklich eine "unique" Anwendung ;)


    Zum Release: es wird erstmal eine Demo geben. Ich überlege es mir noch, das ganze nur für Secondleveluser zugänglich zu machen (einfach weil man von denen nicht per PM mit blöden Fragen ala "mein BIFI wird zerstört!!!" zugepostet wird ;) ).

  • Hey EBFE, nette Arbeit, die du hier vorstellst. :)


    Ich erlaube mir dennoch ein paar (hoffentlich konstruktive!) Kommentare.


    Natürlich lässt sich das Stub-Konzept rapide vereinfachen, wenn es sich um dieselbe ImageBase handelt. So spart man sich das Erstellen eines zweiten Prozesses und alles, was damit zusammenhängt (Kopieren/Anpassen der Sections und �hnliches).


    Jedoch funktioniert das nicht immer, weshalb eine Kombination mehrerer Methoden wohl das effizienteste wäre. :)


    Das Kriterium bezüglich LoadLibraryA/GetModuleHandleA kann man noch umgehen (Export Table Traversal würde ich hier verwenden, wie schon von diversen Protections bekannt).


    Das Erweitern der letzten Section kann problematisch werden, wenn die PE Bound Imports enthält (bei XP war Notepad an sich eine solche PE, wenn ich mich richtig erinnere). Mit etwas Glück kann man das Bound Import Directory einfach löschen udn die Sache ist erledigt.


    Ein richtiger Rebuild ist natürlich die bessere Methode, ein solches Projekt anzugehen, aber hey, das ist doch zu kompliziert für die Kinder, da müssen sie ja doch noch das PE-Format lernen (genaugenommen müssten sie es für RunPE auch, aber C&P wins again...)! ;)

  • Zitat von f0Gx;16074

    Hey EBFE, nette Arbeit, die du hier vorstellst. :)


    Natürlich lässt sich das Stub-Konzept rapide vereinfachen, wenn es sich um dieselbe ImageBase handelt. So spart man sich das Erstellen eines zweiten Prozesses und alles, was damit zusammenhängt (Kopieren/Anpassen der Sections und �?hnliches).


    Jedoch funktioniert das nicht immer, weshalb eine Kombination mehrerer Methoden wohl das effizienteste wäre. :)


    Ich nutze CreateProcess schon ;). Kann mir sonst nicht vorstellen, wie ich die Wirtanwendung lauffähig erhalte. Allerdings ist ja die "Wirt"Anwendung immer grö�?er als die Zielanwendung (weil diese drangehängt wird) - daher reicht bei gleichen ImageBasen imho das simple überschreiben mit dem Ziel"dump". D.h ich bereite die Zielanwendung natürlich vorher auf (starten mit SUSPENDED und dumpen), hänge ihn an und beim Launch wird dieser Dump anstatt des Wirts geschrieben.


    Zitat


    Das Kriterium bezüglich LoadLibraryA/GetModuleHandleA kann man noch umgehen (Export Table Traversal würde ich hier verwenden, wie schon von diversen Protections bekannt).

    Ich denke, du meinst das manuelle abklappern der Exports? Die Routine habe ich schon (sogar hier vorgestellt) - allerdings gibts irgendwie keine (auch unter vista64 ) zuverlässige Methode, an die Kernel32 ImageBase zu kommen. Hab auch kein Vista64 um sich das wirklich genau anzuschauen.
    Daher kombiniere ich im Moment die "zuverlässige" Export-Abklappermethode mit einem GetModuleHandle/LoadLibrary Aufruf (in grö�?eren non VB Exen eher zu 90% vorhanden).


    Zitat


    Das Erweitern der letzten Section kann problematisch werden, wenn die PE Bound Imports enthält (bei XP war Notepad an sich eine solche PE, wenn ich mich richtig erinnere). Mit etwas Glück kann man das Bound Import Directory einfach löschen udn die Sache ist erledigt.

    Da stehe im Moment auf dem Schlauch (die offizielle PE Doku gibt dazu auch nicht viel her :( ). Soweit ich das Konzept vertanden habe, werden einfach die OriginalFirstThunks schon "vorher" mit Adressen vollgepackt und nur bei Bedarf angepasst (da ich immer mit "calc" teste, bin ich bei Import-Parsing und ermittlung der LoadLibrary VA darüber auf die Fre.. geflo... ähm gestolpert). Dabei wird die Bound Imports als "Datenbasis" genutzt. Die Tabelle an sich ist alledings ja in irgendeiner Section an einem "validen" Platz. Mir ist also nicht ganz klar, warum es da Probleme geben soll :) ? Hab auch gerade mit calc/notepad auf meinem sowie VM XP getestet.


    d1s2: k.A. Im Prinzip bleibt eigentlich nur noch das Austesten. Allerdings gefällt mir im Moment die Spielerei mit Junk-Code Generierung :D. Da steckt noch einiges an Potential drin. Und ein paar von F0GX erwähnten Kompatibilitätsoptionen sollten wohl auch noch rein, damit das nicht nur mit Calc/Notepad&Co funktioniert.

  • Zitat

    allerdings gibts irgendwie keine (auch unter vista64 ) zuverlässige Methode, an die Kernel32 ImageBase zu kommen. Hab auch kein Vista64 um sich das wirklich genau anzuschauen.


    Doch, gibt es. ;) Schau' dir mal den PEB an, über diesen kommst du leicht an die Base des Kernels.


    Das Problem an der Stack-Methode ist, dass der Zugriff bei einem Block in der .dll nicht ausreicht (Protection Flags, DEP, x64 Exception Handling, whatever) und dann entsprechend eine Exception geworfen wird.


    Ich habe Vista x64, wenn ich also mal etwas testen soll, kann ich das tun.

  • Jap hatte es mal getestet und das Problem war wirklich ein geschützer Bereich kurz hinter dem Beginn der ImageBase. Mit try .. except bzw einem SEH Handler konnte ich das Problem umgehen, aber schön ist das natürlich nicht ..

  • Zitat von Serverspy;16474

    Gibts es schon wo eine Demo zum saugen?



    Denk mal scharf nach, les den ersten Post nochmal, dreh dich 3x im Kreis und beantworte dir die Frage dann selbst. :censored:

  • Zitat von f0Gx;16364

    Doch, gibt es. ;) Schau' dir mal den PEB an, über diesen kommst du leicht an die Base des Kernels.
    Ich habe Vista x64, wenn ich also mal etwas testen soll, kann ich das tun.


    Ich hatte PEB immer als OS Spezifisch in Erinnerung ;).


    Aber:
    PEB_LDR_DATA Struktur
    http://msdn.microsoft.com/en-us/library/aa813708(VS.85).aspx

    Zitat


    Windows Server 2003 and Windows XP/2000:
    The Reserved3 member is defined as Reserved3[2].

    gegenüber PVOID reserved3 Definition.
    komme ich da unter Vista an den Pfad?


    Besser wäre es natürlich, wenn man davon ausgehen könnte, dass kernel32.dll immer an zweiter Stelle in der Liste kommt - dann funktioniert sowas (zumindest unter XP/Vista 32 Bit):

    Code
    1. 00401163 > 64:A1 3000000>MOV EAX,DWORD PTR FS:[30]00401169 8B40 0C MOV EAX,DWORD PTR DS:[EAX+C]0040116C 8B40 1C MOV EAX,DWORD PTR DS:[EAX+1C]0040116F 8B00 MOV EAX,DWORD PTR DS:[EAX]00401171 8B40 08 MOV EAX,DWORD PTR DS:[EAX+8]

    bzw. Bytes

    Code
    1. 64 A1 30 00 00 00 8B 40 0C 8B 40 1C 8B 00 8B 40 08

    und man spart sich den UNICODE Vergleich :)

  • Nee, im PEB_LDR_DATA_TABLE_ENTRY
    http://msdn.microsoft.com/en-us/library/aa813708(VS.85).aspx
    (unter DLLBase)
    DWORD PTR FS:[30] <- PEB
    MOV EAX,DWORD PTR DS:[EAX+C] <--- Zeiger auf PPEB_LDR_DATA
    MOV EAX,DWORD PTR DS:[EAX+1C] <--- LIST_ENTRY
    MOV EAX,DWORD PTR DS:[EAX] <--- nächster Listeneintrag
    MOV EAX,DWORD PTR DS:[EAX+8] <--- ImageBase

  • Die PEB-Adresse befindet sich bei fs:[0x30], bei fs:[0x0] ist die (x86) SEH-Chain beheimatet, ansonsten stimmen deine weiteren Ausführungen.


    Der PEB ist in der Tat "OS-spezifisch" - seine Struktur ist unter 9x (obsolete *hust*) eine andere als bei NT-basierenden Systemen (womit XP/Vista x64 logischerweise eingeschlossen ist).


    Das Auslesen der zweiten Stelle ist in der Tat zuverlässig. :)


    Grü�e

  • Nun gut, dann hab ich mir das Importparsing wohl umsonst angetan :)


    Ein kleines Update bezüglich JunkCode:
    Bsp:

    Code
    1. 0040495E 21F3 AND EBX,ESI00404960 83EF 1E SUB EDI,1E00404963 83D2 38 ADC EDX,3800404966 014D C0 ADD DWORD PTR SS:[EBP-40],ECX00404969 6A 02 PUSH 20040496B 85F2 TEST EDX,ESI0040496D 58 POP EAX0040496E 83E8 02 SUB EAX,200404971 73 14 JNB SHORT EBFEsRun.0040498700404973 55 PUSH EBP00404974 53 PUSH EBX00404975 51 PUSH ECX00404976 56 PUSH ESI00404977 52 PUSH EDX00404978 6A D4 PUSH -2C0040497A 54 PUSH ESP0040497B 6A 1A PUSH 1A0040497D 6A 79 PUSH 790040497F FF15 8C304000 CALL DWORD PTR DS:[<&user32.GetDlgItemT>; user32.GetDlgItemTextA00404985 C9 LEAVE00404986 C3 RETN00404987 83EE F7 SUB ESI,-90040498A 215D D0 AND DWORD PTR SS:[EBP-30],EBX0040498D 81C7 A009D3CD ADD EDI,CDD309A000404993 83CF D4 OR EDI,FFFFFFD400404996 033D 41214000 ADD EDI,DWORD PTR DS:[402141]0040499C 894D 9C MOV DWORD PTR SS:[EBP-64],ECX0040499F 094D BC OR DWORD PTR SS:[EBP-44],ECX004049A2 83F7 CA XOR EDI,FFFFFFCA004049A5 83C0 E9 ADD EAX,-17004049A8 294D 8C SUB DWORD PTR SS:[EBP-74],ECX004049AB 6A 0C PUSH 0C004049AD 85CF TEST EDI,ECX004049AF 83EB 87 SUB EBX,-79004049B2 83C1 32 ADD ECX,32004049B5 297D 98 SUB DWORD PTR SS:[EBP-68],EDI004049B8 58 POP EAX004049B9 83C0 0C ADD EAX,0C004049BC 75 0C JNZ SHORT EBFEsRun.004049CA004049BE 6A 18 PUSH 18004049C0 52 PUSH EDX004049C1 50 PUSH EAX004049C2 6A E7 PUSH -19004049C4 FF15 44304000 CALL DWORD PTR DS:[<&kernel32.GetFileSi>; kernel32.GetFileSize004049CA 2975 9C SUB DWORD PTR SS:[EBP-64],ESI

    einige zufällig generierte Decryption-Loops (im Loop ist sowohl code zum "XOR-entschlüsseln" wie auch Junk enthalten):
    Eine Version

    Code
    1. 00404DF7 83CE CF OR ESI,FFFFFFCF00404DFA 85D7 TEST EDI,EDX00404DFC 854D A8 TEST DWORD PTR SS:[EBP-58],ECX00404DFF 8BCA MOV ECX,EDX00404E01 BE B0040000 MOV ESI,4B000404E06 56 PUSH ESI00404E07 83C3 8E ADD EBX,-7200404E0A 214D A4 AND DWORD PTR SS:[EBP-5C],ECX00404E0D 6A 74 PUSH 7400404E0F 1975 98 SBB DWORD PTR SS:[EBP-68],ESI00404E12 1B1D 9B214000 SBB EBX,DWORD PTR DS:[40219B]00404E18 21C1 AND ECX,EAX00404E1A 5F POP EDI00404E1B 83E7 74 AND EDI,7400404E1E 7F 08 JG SHORT EBFEsRun.00404E2800404E20 6A D9 PUSH -2700404E22 FF15 9C304000 CALL DWORD PTR DS:[<&user32.DialogBoxIn>; user32.DialogBoxIndirectParamA00404E28 83C3 F2 ADD EBX,-0E00404E2B 83E3 D8 AND EBX,FFFFFFD800404E2E 09C6 OR ESI,EAX00404E30 2BF4 SUB ESI,ESP00404E32 83E2 DA AND EDX,FFFFFFDA00404E35 5F POP EDI00404E36 83EF 03 SUB EDI,300404E39 57 PUSH EDI00404E3A 294D A4 SUB DWORD PTR SS:[EBP-5C],ECX00404E3D 83F3 39 XOR EBX,3900404E40 83EB 9A SUB EBX,-6600404E43 83E8 B1 SUB EAX,-4F00404E46 81E1 4359EE4F AND ECX,4FEE594300404E4C 85FF TEST EDI,EDI00404E4E 2B35 85214000 SUB ESI,DWORD PTR DS:[402185]00404E54 5E POP ESI00404E55 56 PUSH ESI00404E56 BA 37133713 MOV EDX,1337133700404E5B 3196 082E0600 XOR DWORD PTR DS:[ESI+62E08],EDX00404E61 83C7 BF ADD EDI,-4100404E64 09F7 OR EDI,ESI00404E66 85C3 TEST EBX,EAX00404E68 5E POP ESI00404E69 4E DEC ESI00404E6A ^ 75 9A JNZ SHORT EBFEsRun.00404E0600404E6C C9 LEAVE00404E6D C3 RETN

    oder

    Code
    1. 00404DFA 11E1 ADC ECX,ESP00404DFC 2BC8 SUB ECX,EAX00404DFE 83DA 27 SBB EDX,2700404E01 BE B0040000 MOV ESI,4B000404E06 56 PUSH ESI00404E07 83EA 12 SUB EDX,1200404E0A 85DD TEST EBP,EBX00404E0C 83EA 8B SUB EDX,-7500404E0F 854D B0 TEST DWORD PTR SS:[EBP-50],ECX00404E12 03C2 ADD EAX,EDX00404E14 83C0 B8 ADD EAX,-4800404E17 03D0 ADD EDX,EAX00404E19 81F2 774D203C XOR EDX,3C204D7700404E1F 83EE 8A SUB ESI,-7600404E22 81EB 70DCDB99 SUB EBX,99DBDC7000404E28 5A POP EDX00404E29 83EA 03 SUB EDX,300404E2C 52 PUSH EDX00404E2D 8535 72204000 TEST DWORD PTR DS:[402072],ESI00404E33 855D B0 TEST DWORD PTR SS:[EBP-50],EBX00404E36 1B15 6F234000 SBB EDX,DWORD PTR DS:[40236F]00404E3C 83C2 B3 ADD EDX,-4D00404E3F 33F6 XOR ESI,ESI00404E41 83E2 C8 AND EDX,FFFFFFC800404E44 2BC9 SUB ECX,ECX00404E46 5E POP ESI00404E47 56 PUSH ESI00404E48 BB 37133713 MOV EBX,1337133700404E4D 319E 082E0600 XOR DWORD PTR DS:[ESI+62E08],EBX00404E53 81E1 6927F373 AND ECX,73F3276900404E59 8BD9 MOV EBX,ECX00404E5B 5E POP ESI00404E5C 4E DEC ESI00404E5D ^ 75 A7 JNZ SHORT EBFEsRun.00404E0600404E5F C9 LEAVE00404E60 C3 RETN

    oder

    Wie man vielleicht sieht, löst Olly API Calls auf. Ist auch kein Zufall - für JunkCALL Generierung wird unter anderem IAT Base+Size des Wirtes genutzt :). Für Junk-Operationen Database/Datasize. Für relative Calls Codebase/Codesize. D.h die Calls gehen immer zu "realen" Speicherbereichen.
    Weiterhing gibts jetzt auch 5 Byte Opcode-Operationen (MOV/OR/AND/ADD/SUB Register,Wert/Speicher) und es werden LEAVE/RET eingestreut. Mir fällt nun auch nichts mehr gro�artiges zum generieren ein, was sich noch "easy" umsetzen lie�e.




    Zum Release: nach reifer �berlegung ("neue beiträge" und "private Nachrichten" waren dabei sehr Hilfreich :censored: ) wirds wohl im Secondlevel releast.

  • Krasse Sache! Werde ich wohl nie so hinbekommen =/ Mit Junkcode tu ich mich ziemlich schwer. Wie machst du es, dass der wahllos in deinen Decrypter reingestreute Junkcode nicht die Register verändert oder sonstwie Einfluss auf den echten Code nimmt? Soweit ich das sehe sind das ja keine trivialen Opcodes.