PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [PE] Problem bei einfachem Crypter



Cardano
24.07.2010, 21:48
Guten Abend allerseits.

Ich habe mal versucht mein bisheriges Wissen über das PE Dateiformat an einem kleinen Crypter umzusetzen. Es wird alles genau so durch mein Programm erstellt wie ich es will. In CFF Explorer sieht alles 1a aus. Aber wenn ich das ganze dann starten will.... nichts. Windows 7 x86 weigert sich komplett. Ich habe es in Ollydbg versucht zu untersuchen. Nachdem ich es in Olly geladen hatte sah noch alles in Ordnung aus. Olly sprang zu dem von mir gewählten EP und es stand auch der richtige Code dort. Ich drückte F7 aber nichts. F8 und F9 lieferten auch keinen Erfolg. Im Hintergrund sah ich wie Windows bereits eine Fehlermeldung erzeugte. Danach hatte ich mein Programm so umgebaut, dass gerade einmal der minimalste Part erledigt wird und verwendete statt einer eigens implementierten RC4 Encryption eine XOR Encryption.

Nun wurde NURNOCH folgendes gemacht:

1. Es wird eine Section hinzugefügt (Header usw werden entsprechend angepasst)
2. Der OEP wird auf die erste Instruktion der neuen Section gesetzt
3. Die checksum wird auf 0 gesetzt, BaseOfCode wird auf die neue Section gesetzt
4. Die Characteristics der .text Section wird auf C0000040 geändert.
5. In die neue Section wird eine XOR Encryption eingebaut in welcher alle wichtigen Daten wie Anfang und Größe der .text Section automatisch eingetragen werden.
6. Es wird ein Relocationeintrag für die neue Section angelegt indem alle in der XOR Encryption vorkommenden RVA's an denen VA's addressiert werden eingetragen werden. (Somit ist das ganze unabhängig von der Imagebase)

Wie man sieht eine sehr einfache Implementierung des Crypters, vorher wurden zb Checksum ermittelt, eventuelle Codecaves genutzt usw.

Nun probiere ich die fertig 'gecryptete' Datei erneut aus. DASSELBE Risultat!
Der reinen Neugier halber, probiere ich es unter XP... ES FUNKTIONIERT. Ich testete meine vorherige eigentliche Version... SIE FUNKTIONIERTE. Beide Version funktionierten 1a unter XP und Ollydbg funktionierte ebenfalls gut mit den Datein.

Nun frage ich mich natürlich weswegen es nicht unter 7 funktioniert, wohlmöglich auch nicht unter Vista??

Ich habe euch hier eine .rar gemacht in der ihr eine hallowelt App findet und eine Datei mit dem Namen hallowelt_mod, welche die mit der XOR-Version gecryptete Datei ist. Solltet ihr sie unter XP starten, werdet ihr merken dass alles funktioniert. Unter Windows 7 sieht das Ganze aber anders aus.
RapidShare: 1-CLICK Web hosting - Easy Filehosting (http://rapidshare.com/files/408850974/hallowelt.rar)


Hat einer von euch eine Idee was hier angepasst werden muss damit Windows 7 die Datei ebenfalls starten kann ?

Vielen Dank für eure Hilfe, Cardano

ocz
24.07.2010, 22:22
lol, fuck this.

Cardano
24.07.2010, 22:56
Oh danke :D
Ich seh aber gerade dadurch, dass du mich darauf hinweist, weswegen die RelocTable alles zerstört. Ich habe diese XOR-Version auf die schnell implementiert und wie es aussieht eben den XOR Key selber mit auf die RelocTable gesetzt :lol (dieser kleiner Patzer ist mir bei der eigentlichen Version nicht passiert:P )
Jetzt ist dieser runter von der RelocTable und in Olly siehts auch richtig aus:
http://img3.imagebanana.com/img/l8oia3w3/thumb/Unbenannt.png (http://www.imagebanana.com/view/l8oia3w3/Unbenannt.png)

Hier die aktulle Datei(wieder selbes Problem unter Win 7):
RapidShare: 1-CLICK Web hosting - Easy Filehosting (http://rapidshare.com/files/408862262/hallowelt_mod1.exe)

Danke schonmal für deine Antwort;)

ocz
24.07.2010, 23:03
lol, fuck this.

DizzY_D
24.07.2010, 23:04
Dein Problem ist nicht, wie fälschlicherweise von OpCodez (<3) behauptet, der reloc table, sondern das allseits gemochte DEP.
MSVC exen haben im OptionalHeader -> DllCharacteristics den Wert "Image is NX compatible" gesetzt. Das bedeutet eben, dass DEP hier "verschärft zugreift".
Nimm diesen Wert einfach mal raus, dann kann dein Code auch ohne Probleme ausgeführt werden.
Ein zweiter Feheler ist, dass du im reloc Table an der RVA 1009 einen Eintrag hinzugefügt hast für die Schleifendurchläufe.
Siehe:


01296008 B9 5408E900 MOV ECX,0E90854
0129600D 807431 FF 3F XOR BYTE PTR DS:[ESI+ECX-1],3F
01296012 E2 E2 LOOP SHORT 01295FF6


Das ist ein einfacher Brainerror, wie wir ihn sicherlich alle kennen.
Denn die Size der Codesection hat ja wenig mit relocation/imagebase issues zu tun.

Nach diesen änderungen hat alles fehlerfrei bei mir auf W7 funktioniert.

BTW: Sehr nettes Projekt, weiter so!

Cardano
24.07.2010, 23:57
Danke DizzY_D, von der DEP hatte ich bisher noch nichts gehört (werde mich gleich mal drüber schlau lesen :P). Aber leider muss ich sagen, dass es bei mir immernoch nicht funktioniert. Dank deines Tipps läuft es auch inzwischen unter Windows 7 in Olly. Ich kann erstmal die Stub durchlaufen lassen und am Ende ist die .text Section wieder richtig encryptet und es wird dorthin gesprungen. Nur wird gleich der erste Call in der .text Section, der nach hallowelt.__security_init_cookie dem Ganzen zum Verhängnis. Genauergesagt ist es dort die 5. Instruktion (makiert im Screenshot[rechts: hallowelt_mod, links: hallowelt]):
http://img3.imagebanana.com/img/gujs2r87/thumb/Unbenannt.png (http://www.imagebanana.com/view/gujs2r87/Unbenannt.png)


012E1791 A1 0030527F MOV EAX,DWORD PTR DS:[7F523000]wobei an der Addresse 0x00000000 steht
Sobald diese ausgeführt wird in *_mod passiert eine Accessviolation. Anders hingegen in der hallowelt, dort wird folgendes gemacht:

00141791 |. A1 00301400 MOV EAX,DWORD PTR DS:[__security_cookie]und hier bei der Addresse: DS:[00143000]=BB40E64E steht.

Hier die Version (ich hoffe alles berücksichtigt zu haben, was euch aufgefallen ist): RapidShare: 1-CLICK Web hosting - Easy Filehosting (http://rapidshare.com/files/408869549/hallowelt_mod.exe)

BTW: Es ist schonwieder nur mein Win 7 :D, Windows XP schluckt alles ohne zu meckern :P

Danke schonmal an OpCodez und DissY_D :)
MfG Cardano

ocz
25.07.2010, 00:07
lol, fuck this.

DizzY_D
25.07.2010, 00:16
Nach etwas Nachdenken kam mir gerade der Geistesblitz:
Ist doch klar, dass das nicht funktioniert (für OpCodez(<3) anscheinend nicht):
Die Relocations werden vom Loader ja BEVOR der EP ausgeführt wird, angewandt.
Wenn du da dann natürlich "drüberxorst", stimmen die Adressen natürlich nicht mehr.

Das heißt, du musst die Relocs nach deiner Cryptroutine "per Hand" fixen.

Und nochmal an OpCodez(<3):
Probleme schafft man nicht aus der Welt, indem man sie ignoriert!!

Cardano
25.07.2010, 01:19
DANKE Dizzy =)
Aber nicht nur das :D
Eigentlich muss ich doch folgendes machen:
Ich muss die eigentlichen Relocs irgendwo zwischenspeichern, löschen und erst nach dem XOR'ren wiederherstellen und selber fixen.
Denn würden die Relocs zur Zeit des Loaders existieren, würde ein an einer RVA innerhalb der .text Sektion stehender und zum Relocieren bestimmter Pointer doch zur Zeit des Loaders um += des Deltas, von dem Aktuellen zur bevorzugten ImageBase verändert werden.
Also sagen wir an 1000h wäre ein Pointer welcher innerhalb der RelocTable steht und der Bereich von 1000h bis 2000h bildet die .text Section:
So würde an 1000h ein verxor'xter Pointer stehen, welcher sagen wir den Wert 30000h hat, also in reverse Byteorder: 00 00 03 00. Nach dem xor'xen hat er bei einem Key von 3F den Wert: 3F 3F 3C 3F. Wenn die Imagebase sich um 40h unterscheidet, dann sieht der Relocierte Pointer wie folgt aus:
3F3C3EFF = FF 3E 3C 3F. Wenn dann meine XOR Routine dadrüber wandert siehts so aus:
C0 01 03 00 = 000301C0, also liegt die Addresse nun um 180h = 384 Bytes daneben.

Will heißen: Ich müsste alle relocs (bis auf die der neuen Section) zwischenspeichern und später eigenhändig ablaufen, oder ?

Vielen Dank für alle Antworten bisher =)

BTW: Ich benutze wie gesagt statt der XOR Encryption eigentlich eine RC4 Encryption. Ich hab die (mit meinen spärlichen ASM Künsten) soweit optimiert wie ich nur konnte, sind 103 Byte für eine RC4 Encryptionstub angemessen?

MfG Cardano

jojoomgasd
25.07.2010, 11:48
Nimm lieber XOR und mach das so: (Dann ist es auch FUD)


for(int i = 0; i < size; i++)
{
if(byte[i] == xorKey || byte[i] == 0x00)
continue;
byte[i] = byte[i] ^ xorKey;
}

Cardano
25.07.2010, 11:58
Was hat das denn damit zutun ? Du scheinst nicht ganz aufmerksam gelesen zu haben. Es geht gerade um das Problem der Relocs ;)
Eigentlich verwende ich RC4 und im Mom. zum Testen XORing
In C++ auf Seiten den Crypters siehts so aus:



BYTE *Addr = pefile->getPointerToDataByRO(pefile->getSectionHeaderById(pefile->getSectionIdByName(".text"))->PointerToRawData);
for(DWORD i = 0; i < pefile->getSectionHeaderById(pefile->getSectionIdByName(".text"))->Misc.VirtualSize; i++)
Addr[i] ^= 0x3F;
Und in der ASM Stub siehts so aus


pushad
pushf
mov esi, 11111111h
mov ecx, 22222222h
@@:
xor byte ptr [esi + ecx - 1], 33h
loop @b
popf
popad
push FFFFFFFFh
ret
Was als OpCodepattern wie folgt aussieht:


BYTE xorcode[] = { '\x60', '\x66', '\x9C', '\xBE', '\x11', '\x11', '\x11', '\x11',
'\xB9', '\x22', '\x22', '\x22', '\x22', '\x80', '\x74', '\x31',
'\xFF', '\x33', '\xE2', '\xF9', '\x66', '\x9D', '\x61', '\x68',
'\xFF', '\xFF', '\xFF', '\xFF', '\xC3'};
Wobei 11111111h, 22222222h, 33h, FFFFFFFFh Platzhalter für Werte die durch mein C++ Programm gefüllt werden mit den Addressen der .text Section, der Addresse des OEP's, dem XOR Key usw.

Das entxoren, bzw entRC4en funktioniert 1a, nur werden alle verschlüsselten und zum Relocieren vorgemerkten Addresse wie in meinem vorherigen Post beschrieben, durch den Windows Loader 'kaputtgerechnet'. Danke also schonmal für eine Antwort auf meinen vorherigen Post

DizzY_D
25.07.2010, 12:29
So würde an 1000h ein verxor'xter Pointer stehen, welcher sagen wir den Wert 30000h hat, also in reverse Byteorder: 00 00 03 00. Nach dem xor'xen hat er bei einem Key von 3F den Wert: 3F 3F 3C 3F. Wenn die Imagebase sich um 40h unterscheidet, dann sieht der Relocierte Pointer wie folgt aus:
3F3C3EFF = FF 3E 3C 3F. Wenn dann meine XOR Routine dadrüber wandert siehts so aus:
C0 01 03 00 = 000301C0, also liegt die Addresse nun um 180h = 384 Bytes daneben.


Das verstehe ich jetzt nicht so ganz.
Aber ich denke du meinst das, was ich in meinem vorherigen Post schon gesagt habe.
Ich würde das nun vorerst so lösen, dass ich den reloc Eintrag aus dem DataDirectory entferne und die Position+Size davon der Stub übergebe.
Dann werden die Relocs vom Loader ja schonmal garnicht mehr angewandt.
Deine Stub muss dann eben durch den reloc-Table per Schleife durchgehen und auf alle dort eingetragenen RVAs die Imagebase addieren.
Die Imagebase musst du dann natürlich nicht aus dem PE Header auslesen, sondern aus dem PEB:


mov esi,dword ptr fs:[030h] ;Get IMGBASE
mov esi,dword ptr[esi+8]


Ein Problem wird sein, dass du für jede Section, in der Relos vorhanden sind, Schreibrechte brauchst.
Im Fall von "hallowelt.exe" gibt es ja auch Relocs außerhalb der .text Section. Das heißt auch in der Section müsstest du die Characteristics auf writable setzen.

Wenn der Crypter wirklich eine positive Auswirkung auf die Detectionrate haben soll, würde ich versuchen auf Schreibrechte in den Sectioncharacteristics komplett zu verzichten.
Das kannst du z.B. per Export Walk umgehen, indem du die API VirtualProtect lädest und dann eben über diese API Schreibrechte zur Laufzeit anforderst.

Ich hoffe das hat dir ein bisschen geholfen.

MfG
DizzY_D

Cardano
25.07.2010, 13:12
Danke schon einmal wieder für die Antwort.

Aber anstatt, dass ich die ganze RelocTable, bis auf die Einträge meiner neuen Section, entferne, könnte ich doch besser so machen, dass meine Relocs den einzigen RelocEntry bilden und die anderen dahinter kopiert werden. Dann nurnoch DataDirectory[IBR].Size anpassen und schon lädt der Loader nurnoch meine Relocs. Ich versuchs mal das gerade beschriebene darzustellen:

RelocTable:

-------------
| rva:1000h |
| bytes: xy |
-------------
-------------
| rva:2000h |
| bytes: xy |
-------------
....
....
....
-------------
| rva:6000h |
| bytes: xy |
-------------

Sagen wir meine Relocs sind in dem RelocTable Entry, welcher alles von rva 6000h bis 6fffh relociert. Dann könnte ich doch am besten folgendes machen:

-------------
| rva:6000h |
| bytes: xy |
-------------
-------------
| rva:1000h |
| bytes: xy |
-------------
-------------
| rva:2000h |
| bytes: xy |
-------------
....
....
....

Somit wäre mein Entry in der RelocTable nun an erster Stelle. Was jetzt noch zutun wäre, ist dass man im DataDirectory Eintrag im NTHeader die Größe der RelocTable auf die Größe meines RelocTable Entrys ändert.
Dann würde der Loader ja sowieso nur die Relocs für meine Section ablaufen, aber nicht die für die anderen. Dann kann ich in meiner Stub einfach selber die anderen RelocTable Entrys ablaufen, denn durch diese Verschiebung weiß ich dass die echten Relocs sich an der Stelle:

ImageBase + DataDict[IBR].VirtualAddress + DataDict[IBR].Sizebefinden.

Zu deinen Vorschlägen:
Könntest du mir sagen was du mit PEB meinst ?

BTW: Da wir langsam diesen Thread echt zuspammen würde ich vorschlagen, dass wir das auch über ICQ besprechen könnten oder per PN. Ich schick dir gleich mal eine PN mit meiner ICQ#.

Vielen Dank für eure vielen nützlichen Antworten =)

ocz
25.07.2010, 14:21
lol, fuck this.