CSAW CTF Qualifiers 2012 –
Exploitation 200

Diese Challenge (Exploitation 200) stellt ein Binary bereit und verlangt von uns:

“Read the key out of ./key in the current working directory.”

Zusätzlich wird der Server “128.238.66.218” mit dem Port “54321” genannt.

Es geht also darum, die bereitgestellte ausführbare Datei, die auch auf dem genannten Server an Port 54321 betrieben wird, so durch das Senden von Daten auszunutzen, dass wir an den Inhalt der “key”-Datei gelangen, die auf dem Server abgelegt ist.

Wir sehen uns das Binary wie üblicherweise mit dem Tool “file” genauer an, um die zum Bearbeiten erforderliche Virtuelle Machine bestimmen zu können.

rup0rt@lambda:~/CSAW2012$ file exploitation1-release
exploitation1-release: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x94e984380a61d713c1a614f40eeee92c533593d4, not stripped

Es handelt sich um ein normales 32-bit Linux-Programm. Ich starte daher eine entsprechende Machine, hier ein Debian GNU Linux 6.0 über VirtualBox.

Auf der Virtuellen Machine legen wir zunächst eine “key”-Datei mit beliebigem Inhalt an. Diese soll die Datei auf dem Server nachstellen und beim späteren Testen des Exploits unterstützen, den Erfolg des Auslesens feststellen zu können. Danach starten wir die Datei machen uns mit der Funktionsweise des Binarys vertraut.

user@linux:~$ ./exploitation1-release 
Got a connection from 127.0.0.1 on port 50047

user@linux:~$ nc localhost 54321
Wecome to my first CS project.
Please type your name:  rup0rt
user@linux:~$

Genau wie auf dem Zielserver lauscht das Binary auf Port 54321. Nach dem Verbindungsaufbau mit “netcat” werden wir begrüßt und zur Eingabe unseres Namens aufgefordert. Nachdem dieser Abgesendet wurde, passiert nichts weiter.

Dem Anschein nach wird die Lösung dieser Challenge also darin bestehen, eine geeignete Zeichenkette zu wählen, so dass die interne Bearbeitung des Namens zu einem (ungewollten) Programmverhalten führt, durch das wir an den Inhalt der “key”-Datei gelangen können.

Um einen solchen String erstellen zu können, sehen wir uns als Erstes die disassemblierte Darstellung der Datei mit dem Tool “objdump” an. Hier ein Auszug des Codes aus der Funktion “<handle>” an der Stelle, wo die Zeichenkette des Namens verarbeitet wird:

 804896a:    c7 44 24 0c 00 00 00     movl   $0x0,0xc(%esp)
 8048971:    00 
 8048972:    c7 44 24 08 04 02 00     movl   $0x204,0x8(%esp)
 8048979:    00 
 804897a:    8d 85 f4 fd ff ff        lea    -0x20c(%ebp),%eax
 8048980:    89 44 24 04              mov    %eax,0x4(%esp)
 8048984:    8b 45 08                 mov    0x8(%ebp),%eax
 8048987:    89 04 24                 mov    %eax,(%esp)
 804898a:    e8 81 fe ff ff           call   8048810 <recv@plt>

 804898f:    c6 45 f3 00              movb   $0x0,-0xd(%ebp)
 8048993:    c7 44 24 04 78 b0 04     movl   $0x804b078,0x4(%esp)
 804899a:    08 
 804899b:    8d 85 f4 fd ff ff        lea    -0x20c(%ebp),%eax
 80489a1:    89 04 24                 mov    %eax,(%esp)
 80489a4:    e8 e7 fc ff ff           call   8048690 <strcmp@plt>

 80489a9:    85 c0                    test   %eax,%eax
 80489ab:    75 07                    jne    80489b4 <handle+0x97>
 80489ad:    c7 45 f4 01 00 00 00     movl   $0x1,-0xc(%ebp)
 80489b4:    83 7d f4 00              cmpl   $0x0,-0xc(%ebp)
 80489b8:    0f 84 83 00 00 00        je     8048a41 <handle+0x124>

 80489be:    ba c8 8e 04 08           mov    $0x8048ec8,%edx
 80489c3:    b8 ca 8e 04 08           mov    $0x8048eca,%eax
 80489c8:    89 54 24 04              mov    %edx,0x4(%esp)
 80489cc:    89 04 24                 mov    %eax,(%esp)
 80489cf:    e8 ac fd ff ff           call   8048780 <fopen@plt>

Wir sehen hier drei wichtige Funktionen:

  • recv: es werden 0x204 (516) Bytes vom Netzwerksocket empfangen; das ist die Zeichenkette, die wir als Namen übergeben
  • strcmp: der von uns übergebene String wird mit dem String bei Speicheradresse 0x804b078 verglichen und bei Übereinstimmung die Bearbeitung mit der nächsten Funktion (fopen) fortgesetzt
  • fopen: die Datei, deren Namen bei Speicheradresse 0x8048eca hinterlegt ist, wird geöffnen und im weiteren Verlauf ausgegeben

Wenn wir nun mit dem GDB prüfen, welcher Dateiname bei Speicheradresse 0x8048eca gespeichert ist, erhalten wir:

(gdb) x/s 0x8048eca
0x8048eca:       "./key"

Zu unserem Erstauen stellen wir fest, dass das Programm selbst bereits alle Instruktionen zum Öffen (fopen) und im weiteren Programmfluss auch zum Ausgeben (fscanf) der Datei “key” umsetzt. Wir können also davon ausgehen, dass wir keinen eigenen Shellcode übermitteln und zur Ausführung bringen müssen, sondern den Programmfluss nur in Richtung der fopen-Routine leiten müssen.

Wie wir bereits erkannt haben, hängt die Ausgabe der “key”-Datei maßgeblich von der “strcmp”-Funktion ab, die den von uns übergebenen Namen mit der an Speicheradresse 0x804b078 hinterlegten Zeichenkette vergleicht. Stimmt der Namen mit dieser Zeichkette überein, wird die “key”-Datei geöffnet und ausgegeben.

Wir prüfen daher als nächsten mit dem GDB, welcher String bei der Speicherstelle 0x804b078 abgelegt ist.

(gdb) x/s 0x804b078
0x804b078 <secret>:      'A' <repeats 26 times>, "\n"

Es handelt sich um die Zeichenkette “AAAAAAAAAAAAAAAAAAAAAAAAAA”, gefolgt von einem Zeilenumbruch. Zusätzlich erkennen wir auf Grund der Debugging-Symbole, dass diese Speicheradresse mit dem Namen “secret” versehen ist, was noch mehr darauf hindeutet, die richtige Stelle im Binary gefunden zu haben.

Nun wird es Zeit, diese Erkenntnis zu testen und zunächst an unser lokales Binary diesen String zu übertragen.

user@linux:~$ nc localhost 54321
Wecome to my first CS project.
Please type your name:  AAAAAAAAAAAAAAAAAAAAAAAAAA
Rup0rtIsHereAAAAAAAAAAAAA

Wir erhalten tatsächlich den Inhalt unserer lokalen “key”-Datei ausgeben, die ich zuvor mit der Zeichenkette “Rup0rtIsHere” versehen hatte. Demnach konnten wir das Binary korrekt reverse engineeren und die Funktionsweise in Erfahrung bringen.

Sofern das Programm auf dem Server “128.238.66.218” nicht verändert worden ist, sollte also bei der gleichen Zeichenkette auch die “key”-Datei des Systems ausgegeben werden. Dies probieren wir aus:

rup0rt@lambda:~$ perl -e 'print "A"x26 . "\n"' | nc 128.238.66.218 54321
Wecome to my first CS project.
Please type your name:  b3ee1f0fff06f0945d7bb018a8e85127

Erfreulicherweise reagiert auch der Server wie erwartet und liefert uns die Lösung zur Challenge.

Das Ergebnis lautet: “b3ee1f0fff06f0945d7bb018a8e85127“.

Leave a Reply

Your email address will not be published.