Buffer Overflow Angriffe, Teil 2 - Ruhr
Transcription
Buffer Overflow Angriffe, Teil 2 - Ruhr
Grundpraktikum Netz- und Datensicherheit Thema: Buffer Overflow Angriffe, Teil 2 Lehrstuhl für Netz- und Datensicherheit Ruhr-Universität Bochum Versuchdurchführung: Raum ID 2/168 Betreuung: Florian Feldmann Zusammengestellt von: Stefan Hoffmann & Hannes Oberender & Florian Bache & Patrick Meier Stand: 8. Januar 2014 Version: 1.0 Inhaltsverzeichnis Inhaltsverzeichnis 1 Vorwort 2 2 Hinweise 3 3 Einleitung 3 4 Grundlagen zum Shellcode-Programmieren 3 5 Start des Shellcodes 5.1 Parameter an Funktionen übergeben . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 4 6 Durchführung 6 7 Aufgabe 1 7.1 Aufgabe 1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.2 Aufgabe 1.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.3 Aufgabe 1.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 7 7 7 8 Aufgabe 2 8.1 Aufgabe 8.2 Aufgabe 8.3 Aufgabe 8.4 Aufgabe 8.5 Aufgabe 7 7 8 8 8 9 2.1 2.2 2.3 2.4 2.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Fragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1 Vorwort Ziel des Praktikums soll sein, ihnen grundlegendes Wissen der Netz- und Datensicherheit praktisch darzustellen. Neben dem didaktischen Erfolg soll der Spaß an Kryptographie, Internetsicherheit und Programmierung im Vordergrund stehen. Trotzdem sollten sie den Aufwand dieser Veranstaltung nicht unterschätzen! Sie werden in diesem Praktikum einer Auswahl an Themen begegnen, die in solch einem Umfang den Rahmen einer einzigen Vorlesung überschreiten würden. Viel mehr wird ihnen Wissen vermittelt, das Bestandteil einiger Grundlagenvorlesungen ist, oder Basis für vertiefende Vorlesungen sein wird. Aus diesem Grund ist ihre Vorbereitung entscheidend für den Erfolg des Praktikums. Das Studium der angegebenen Literaturreferenzen ist Voraussetzung für einen erfolgreichen Praktikumsversuch. Durch das Studium der Referenzen eignen sie sich theoretisches Wissen an, das Grundlage für die Durchführung eines Versuchs ist und welches anschließend in einem Versuch praktisch untermauert werden soll. Die Aufgabe eines Betreuers ist somit nicht die Vermittlung des Grundlagenwissens, sondern die Unterstützung bei der Durchführung ihres Versuchs. Vor Beginn eines Versuchs wird in einem Vortestat überprüft, ob sie die Referenzen ausreichend studiert haben. Damit wird sichergestellt, dass sie in der vorgegeben Zeit die gestellten Aufgaben lösen können. Sollte vom Betreuer festgestellt werden, dass sie nachweislich nicht vorbereitet sind, werden sie von dem Versuch ausgeschlossen und müssen zu einem Nachholtermin erscheinen. Ihr Ziel sollte es demnach sein, das Testat auf den direkten Weg zu erhalten. Grundpraktikum NDS - Buffer Overflows 2 2 8. Januar 2014 2 Hinweise 2 Hinweise Lesen sie sich zuerst das Grundlagenkapitel durch. Recherchieren sie bei Unklarheiten im Internet, diskutieren sie mit Kommilitonen oder kontaktieren sie bei schwerwiegenden Problemen ihren Betreuer. Nehmen sie bei ihrer Recherche die angegebenen Quellen zur Hilfe, und versuchen sie sich an den Hilfsfragen zu orientieren. Sie sollten unter allen Umständen auch Versuchen die Aufgaben so weit wie möglich zu bearbeiten. Es ist ebenfalls möglich die Aufgaben vollständig in Heimarbeit zu lösen, sofern ihnen alle Materialien zur Verfügung stehen. Ihre Lösungen werden vom Betreuer während des Praktikums kontrolliert und bei nachweislich selbstständiger Erarbeitung erhalten sie vorab das Testat. Nach einem Versuch muss jede Gruppe ein Protokoll anfertigen, in dem die Herleitung, die Lösung der Aufgaben, und vor allem deren Begründung unter Ausnutzung des gesammelten Wissens erörtert werden. Bei der Begründung können Zeichnungen helfen! Das Protokoll kann wahlweise in deutscher oder englischer Sprache erstellt werden. Es sollte den orthographischen und grammatischen Anforderungen der Sprache genügen. Sie haben bis zu einer Woche Zeit, um ihr computergefertigtes Protokoll in ausgedruckter Form beim Betreuer abzugeben, ansonsten erhalten sie ihr Endtestat nicht. Sollte ihre schriftliche Ausarbeitung nicht den Hinweisen in [1] genügen, so ist dies ein Grund ihnen kein Testat zu erteilen. Bei offenen Fragen richten sie sich immer an den jeweiligen Betreuer! Viel Spaß! Grundpraktikum 3 Einleitung Der Versuch Buffer-Overflow 2 baut auf das erlernte Wissen aus Buffer-Overflow 1 auf. Alle Informationen aus Teil 1 sollten verstanden worden sein, sonst ist ein nochmaliges durchgehen Dieser empfehlenswert. In diesem Versuch beschäftigen wir uns zum einen mit Shellcode Programmierung, sowie des praktischen Einsatzes eines Exploits in einer realen Anwendung namens WinAmp. 4 Grundlagen zum Shellcode-Programmieren Linux bietet, im Gegensatz zu Windows, eine direkte Verbindung zum Kernel über das int 0x80 Interface. Bei Windows hingegen gibt es dieses Interface nicht. Um hier mit dem System zu kommunizieren muss die Adresse der Funktion ,die wir ausführen wollen, aus einer DLL geladen werden. Das heißt jedoch das die Adresse unserer gesuchten Funktion von Windows Version zu Windows Version verschieden ist. Wohingegen die int 0x80 Systemaufrufe bei Linux konstant bleiben. Es gibt 2 Möglichkeiten wie man Funktionen in einer DLL ausführen kann. • Statischer Ansatz: Hierbei werden die Adressen der Funktionen die man benötigt Hardcoded in den Shellcode eingetragen. Der Vorteil ist die geringere Größe des Shellcodes und die Einfachheit beim Programmieren. Der Nachteil ist das diese Art Shellcode nur für ein bestimmtes Betriebssystem mit jeweiligen Servicepack funktioniert, da man erwartet das die Funktionen auch an der Stelle liegen. • Dynamischer Ansatz: Bei diesem werden die Adressen der Funktionen durch den Shellcode ermittelt und dann ausgeführt. Vorteil dabei ist natürlich das man den Shellcode für mehrere Betriebssysteme nutzen kann. Der Nachteil ist, dass hierbei die Größe des Codes deutlich zu nimmt. Grundpraktikum NDS - Buffer Overflows 2 3 8. Januar 2014 5 Start des Shellcodes In diesem Versuch benutzen wir einen Dynamisch-Statischen Ansatz. Das heißt wir werden dynamisch DLLs und ihre Funktionen laden, aber die Funktionen um dies zu tun werden statisch sein (die sei an dieser Stelle erst mal so hinzunehmen, im weiteren Verlauf folgt ein Beispiel). Der Grund liegt an der Komplexität des Versuchs, sollte es zu einem rein dynamischen Verhalten kommen. 5 Start des Shellcodes Um etwas in Windows auszuführen müssen wir Funktionen in DLLs nutzen. Dazu müssen diese DLLs als Module geladen sein. Die einzige DLL von der wir von vornherein sicher sein können das sie geladen ist, ist Kernel32.dll . Diese liefert den größten Teil der Win32 Grund-API-Funktionen, wie Speichermanagement oder Prozess- und Thread-Erstellung usw.[8]. Die für uns wichtigen Funktionen darin sind: • LoadLibraryA zum laden von anderen DLLs • GetProcAddress um die Adresse von anderen Funktionen zu finden • ExitProcess um Prozesse sauber zu beenden und keinen Absturz herbei zu führen • WinExec um ein Programm zu starten Um diese Funktionen zu nutzen, benötigt man die Adressen dieser. Dafür steht ihnen das Programm arwin zur Verfügung. Das Programm kann aus der Konsole wie folgt aufgerufen werden: arwin DLL FUNKTION Dabei wird für den Parameter DLL die DLL eingetragen und für FUNKTION die Funktion. Ein Beispiel Aufruf wäre: arwin Kernel32.dll ExitProcess Die Rückgabe ist eine Adresse in Hex-Format zum Beispiel 0x7c80a4b2 Um nun Shellcode zu schreiben benötigen wir Assembler-Code, der Anfang unseres Assembler-Files sollte wie folgt aussehen: [SECTION .text] ; set the code to be 32-bit BITS 32 global _start _start: nach start: kann mit der Programmierung begonnen werden. 5.1 Parameter an Funktionen übergeben Viele Funktionen erwarten Parameter, doch wie werden diese übergeben. Wie dies Funktioniert wird am folgenden Beispiel erläutert[2]. Grundpraktikum NDS - Buffer Overflows 2 4 8. Januar 2014 5 Start des Shellcodes [Section .text] BITS 32 global _start _start: 1 xor eax,eax ;nimmt Rückgabewert auf 2 xor ebx,ebx ; speichert String-Pointer 3 xor edx,edx ;speichert NULL 4 5 jmp short Befehl 6 BefehlReturn: 7 pop ebx 8 mov [ebx + 40], dl 9 xor eax,eax 10 push eax ;push 0 auf den Stack (2. Parameter) 11 push ebx ;push the command string onto the stack (1. Parameter) 12 mov ebx,0x7c8615b5 13 call ebx ;call WinExec(path,showcode) 14 xor eax,eax 15 push eax 16 mov ebx, 0x7c81ca82 17 call ebx ;call ExitProcess(0) 18 Befehl: 19 call BefehlReturn 20 db "cmd.exe /c net user PSUser PSPasswd /ADDN" Die Zahlen vor den Codezeilen gehören nicht zum Code. Sie geben nur die Codezeile an, zum besseren Verständnis. 1. In den Zeilen 1-3 werden die Register gelöscht, dies geschieht über xor um Null Bytes zu verhindern. 2. In der Zeile 5 wird ein Sprung zur Zeile 18 veranlasst 3. Zeile 19 ruft die Funktion in Zeile 6 auf, daraufhin wird Zeile 20 als Rücksprungadresse auf den Stack gespeichert. Diese Rücksprungadresse ist der Pointer auf unseren Text 4. Zeile 7 holt die eben gespeicherte Rücksprungadresse vom Stack 5. Zeile 8 hier wird das Null-Byte anstelle des N gesetzt, die Zahl 40 gibt dabei die Position an, nach welcher das Null-Byte gesetzt werden soll. Hierbei muss man wissen das EDX 32 Bit groß ist, DX 16 Bit und DL das Low Byte von DX ist und DH das High-Byte von DX. Deswegen wird hier ein Null-Byte gesetzt 6. in Zeile 10 übergeben wir den 2 Parameter der Funktion WinExec hier 0, da die cmd.exe ohne Pfadangabe gestartet werden kann. 7. Zeile 11 hier wird unser String als Parameter 1 übergeben 8. in Zeile 12 wird die Adresse übergeben an der unsere gewünschte Funktion steht 9. Zeile 13 führt die Funktion aus dabei werden die letzten beiden Stackeinträge als Parameter Grundpraktikum NDS - Buffer Overflows 2 5 8. Januar 2014 6 Durchführung genutzt. 10. Zeile 14 hier wird eax wieder gelöscht, da eax oft den Rückgabewert von aufgerufenen Funktionen enthält. 11. Zeile 15 hier wird 0 als Parameter für die Funktion ExitProcess aufgerufen. 12. Zeile 16 hier wird ebx mit der Adresse der Funktion von ExitProcess belegt 13. Zeile 17 ruft die Funktion an der Stelle ebx auf, also ExitProcess(0) Wie man erkennen kann, können Text-Pointer per call-Aufruf in den Stack geladen werden. Dies kann beliebig fortgeführt werden, um zum Beispiel noch andere Funktionen mit Parametern zu versorgen. Achten sie darauf das die Parameter der Funktionen in umgekehrter Reihenfolge übergeben werden und das EAX die Rückgabewerte von Funktionen enthält. Hinweis: Falls mal ein Parameter eine 1 statt einer 0 verlangt, weisen Sie nicht direkt eine 1 hinzu, sondern führen ein XOR mit anschließenden INC. 6 Durchführung Für diese Versuch stehen Ihnen die folgenden Programme zur Verfügung. • Cygwin darin enthalten gcc, nasm, hexedit, nano, vim • Ollydbg • xxd-shellcode.sh • XVI32 • arwin • shellcodetest.c In Cygwin finden sie in ihrem Home-Verzeichnis den Ordner shellcode, darin befindet sich das Shellskript xxd-shellcode.sh . Dieser Ordner ist wiederum aus Windows unter C:/cygwin/home/shellcode zu finden Um Assembler-Dateien zu schreiben können sie auch in Cygwin nano oder vim nutzen. Um eine Assembler Datei mit nasm zu kompilieren nutzen sie den folgenden Befehl nasm -f bin -o AUSGABE.BIN ASSEMBLER-FILE Daraufhin erhalten sie die kompilierte binär Datei. Damit sie aus dieser nicht den Shellcode von Hand abschreiben müssen, können sie das Programm xxd-shellcode nutzen. Als Parameter wird hier die per nasm erzeugte Binärdatei angegeben. ./xxd-shellcode.sh AUSGABE.BIN Sollten sie dennoch die Lust verspüren es von Hand zu machen, können sie das Programm Hexviewer in Windows nutzen oder sie geben den folgenden Befehl in cygwin ein hexdump -C AUSGABE.BIN Mit shellcodetest.c können Sie ihren Shellcode testen. Sollten Sie fragen zu den Programmen haben, konsultieren Sie das Internet oder Notfalls den Betreuer. Grundpraktikum NDS - Buffer Overflows 2 6 8. Januar 2014 7 Aufgabe 1 7 Aufgabe 1 7.1 Aufgabe 1.1 Ermitteln Sie die Adressen für die folgenden Funktionen und notieren Sie diese. • LoadLibraryA • GetProcAddress • ExitProcess • WinExec • MessageBoxA befindet sich in User32.dll 7.2 Aufgabe 1.2 Schreiben Sie ihren eigenen Shellcode der calc.exe aufruft. Nutzen Sie dafür WinExec. Die Funktion sieht wie folgt aus WinExec(Path, Showcode). Der zweite Parameter dieser Funktion soll 0 sein. Testen Sie den Shellcode mit shellcodetest.c. 7.3 Aufgabe 1.3 Schreiben Sie ihren eigenen Shellcode der eine MessageBox mit beliebiegen Text aufruft und die Buttons OK und CANCEL besitzt. Die Funktion MessageBoxA hat folgenden Aufruf[5] MessageBoxA(windowhandle,message,title,buttons). Als windowhandle wird NULL benutzt. Gehen Sie wie folgt vor. 1. Rufen sie per LoadLibraryA(DLL) die DLL user32.dll auf, der in EAX gespeicherte Rückgabewert der Funktion soll für GetProcessAddress genutzt werden 2. Rufen Sie GetProcessAddress(hmodule,funktionsname) auf, wobei hmodule der Rückgabewert von LoadLibraryA ist und der Funktionsname MessageBoxA ist 3. Der Rückgabewert von GetProcessAddress ist die Adresse der Funktion MessageBoxA, rufen Sie diese mit den entsprechenden Parameter auf 4. Rufen Sie anschließend ExitProcess(exitcode) aus um den Eltern-Prozess nicht abstürzen zu lassen, hierbei ist exitcode der Rückgabewert von MessageBoxA ist. Testen Sie ihren Shellcode mit shellcodetester.c. 8 Aufgabe 2 8.1 Aufgabe 2.1 Benutzen sie nun das Fuzzer Programm C:\BO\Aufgaben\3\test.exe um das Programm Winamp auf die benötigte Puffergröße zu testen. Der Aufrufsyntax ist dabei wie folgt: C:\BO\Aufgaben\3\test.exe <PUFFERGRÖßE> Grundpraktikum NDS - Buffer Overflows 2 7 8. Januar 2014 8 Aufgabe 2 Da Ollydbg im JIT Modus läuft, wird Ollydbg bei einem Ausnahmefehler den Programmfluss unterbrechen. Daraufhin sollten sie sich in Ollydbg die EIP Adresse anschauen. Ist diese 41414141 (AAAA), haben sie die richtige Puffergröße getroffen. Hier ist jedoch eines zu beachten, wenn der von ihnen gewählte Puffer zu klein ist, geschieht nichts (normaler Programmablauf). Ist der von ihnen gewählte Puffer zu groß, wird der Ausnahmefehler abgefangen (Ollydbg reagiert nicht). Das Fenster“, welches ” ihnen zur Verfügung steht, um den Puffer zu testen ist 7 Byte, wobei das 4. Byte ähnlich reagiert wie als wenn der Puffer zu groß ist. Geben sie die Größe des Puffers an, um den EIP zu überschreiben. Tipp: Die benötigte Puffergröße liegt zwischen 1015 und 1025 Byte. 8.2 Aufgabe 2.2 Das hier betroffene Modul ist in mp3.dll“, wenn sie sich die Adressierung in Ollydbg anschauen, wer” den sie bemerken das diese keine vorangestellte 0-Folge besitzt und Adressen somit direkt anspring” bar“ sind (sie benötigen jmp esp nicht mehr aus der ntdll.dll). Darum werden sie call esp (FFD4)“ ” aus der in mp3.dll statt dem vorherigen EIP benutzen (das Vorgehen zur Findung der Adresse ist das Selbe wie in Aufgabe 1.3, darum wird ihnen die Adresse vorgegeben). Des Weiteren müssten sie einen neuen Jumpcode erstellen, auch dieser wird ihnen vorgegeben. Schauen sie sich dessen Quelltext C:\BO\Aufgaben\3\jumpcode3.asm an und probieren sie einmal die BYTE“ Parameter wegzulassen (danach müssen sie den Quelltext neu ” kompilieren und mit XVI32 betrachten). Was bemerken sie und wie können sie sich das erklären (sollten sie das nicht erklären können, lassen sie die Erklärung weg. Schildern sie jedoch ihre Beobachtung und warum der Jumpcode nicht funktionieren würde. Sie müssen mindestens eine Hochsprache der Programmierung beherrschen (die Casting unterstützt) um dieses Phänomen zu beschreiben)? Modifizieren sie C:\BO\Aufgaben\3\exploit.c mit Hilfe der Puffergröße und kompilieren sie den Quelltext (Hinweis: Sie müssen BUF LEN und drei memcpy Funktionen verändern. Orientieren sie sich an den vorherigen Exploits um die memcpy Funktionen anzugleichen). Was können sie beobachten, wenn sie das Exploit ausführen? Tipp: Sollten sie etwas selbst nachprüfen wollen (Sprungweiten o.ä.), die Returnanweisung der in mp3.dll, nach welcher der Ausnahmefehler eintritt, liegt bei Offset 02005CB7. Außerdem besteht die Möglichkeit den ESP in Stack/Dump zu verfolgen (Rechtsklick mit der Maus auf das Register), damit sollten sie in der Lage sein die Parameter auch selbst zu finden. 8.3 Aufgabe 2.3 Fügen Sie in exploit.c statt den vorgegebenen Shellcode ihren eigenen ein. Dokumentieren Sie das Ergebnis. 8.4 Aufgabe 2.4 Modifizieren sie nun die Datei C:\BO\Aufgaben\3\Internetseite\attack.html Grundpraktikum NDS - Buffer Overflows 2 8 8. Januar 2014 8 Aufgabe 2 so, dass das local Exploit zu einem remote Exploit wird (Tipp: schauen sie sich den Quellcode genau an, es ist sehr einfach.). Beschreiben sie was sie geändert haben, und schlagen sie mind. eine Gegenmaßnahme zum Schutz gegen diese Attacke vor. 8.5 Aufgabe 2.5 Nun wechseln sie die Betrachtungsweise. Sie arbeiten nun (erfolgreich) als Angestellter bzw. sind selbstständig in der ITS Branche. Sie haben erfahren, dass in der Software einer ihrer Auftraggeber eine Sicherheitslücke besteht (Winamp). Sie haben bereits getestet, unter welchen Bedingungen das Programm abstürzt (Aufgabe 2.1). Benutzen sie die Testplayliste (sie liegt in dem Aufgabenverzeichnis (test.pls)) um die zwei Funktionen (dies wüssten sie unter realen Bedingungen nicht) herauszufinden, die in dem Modul in mp3.dll (auch das müssten sie erst herausfinden) die Rücksprungadresse überschreiben (eine Funktion überschreibt nicht den EIP selbst sondern schreibt ohne überprüfung eine beliebige Menge an Daten auf den Stack). Das Vorgehen ist nun (eigentlich) wie folgt: sie gehen in das Modul in mp3.dll und lassen alle ”intermodularen calls” anzeigen (Rechtsklick in den Code ! Search for !All intermodular calls), dann setzen sie alle Aufrufe als Breakpoint und lassen das Programm ausführen (F9) (ausgenommen sie wissen welcher Call am wahrscheinlichsten ist, dann neben sie nur diese/n Call/s). Nach jedem Breakpoint untersuchen sie den Stack (klicken sie in das Stackfenster und drücken sie Strg+B, danach geben sie als Suchstring 41414141 oder etwas anderes aus ihrem Puffer ein). Wird ihre Suchabfrage gefunden, geschieht das überschreiben vor dem jetzigen Breakpoint (sie müssen das Debuggen neu starten). Wurde der Suchwert nicht gefunden, lassen sie das Programm weiter ausführen (F9). Bei jedem neuen Breakpoint müssen sie den Stack untersuchen. Sie sollten dabei auch die Register beobachten (diese geben manchmal Hinweise darauf, wann etwas passiert. Man benötigt dazu aber i.d.R. meist Erfahrung mit den API Calls von Windows). Sie können also nun zählen wie oft sie F9 drücken müssen, bis der Stack überschrieben wird. Es ist jedoch so, dass sog. Threads erstellt werden und verursachen, dass es variiert wie oft sie weiter tracen müssen (dann können die Register wiederum helfen). Wenn sie herausgefunden haben, wann sie F9 nicht mehr drücken sollten, gehen sie von dort an mit F8 weiter vor. Sollten sie dabei über einen call“ kommen, müssen sie den Stack wieder durchsuchen und ” diesen call“ als Breakpoint setzen (Hinweis: Mit Minus“ können sie einen Schritt zurück gehen. ” ” Außerdem empfiehlt es sich die anderen Breakpoints zu deaktivieren, um das Tracen zu beschleunigen), falls der Stack überschrieben wurde. Nach einem Neustart des Debuggingprozesses, wird beim Ausführen der neue Breakpoint ausgeführt. Nun gehen sie mit F7 in den call“ hinein und fahren mit ” F8 fort. Dies wiederholt sich solange, bis sie (in unserem Beispiel) in eine Schleife kommen. In dieser Schleife zeigt Ollydbg ihnen Informationen über jeden Befehl innerhalb der Schleife an, sobald beim Tracen die Position des Befehls erreicht wird. Somit können sie die Stackpositionen leicht finden und beobachten wie der Stack überschrieben wird. Da dies sehr zeitaufwändig ist, bekommen sie einige Breakpoints und API Calls (intermodular calls) vorgegeben: Die erste Routine wird leichter gefunden, wenn sie nur Breakpoints auf CreateFileA setzen. Sie sollten dadurch auf die Adresse 02009836 stoßen (probieren sie trotzdem einmal das Tracen aus und geben sie an, wie oft sie F9 drücken mussten). Wenn sie nun den Stack durchsuchen, sollte dieser schon überschrieben worden sein (ein Mal). Daher scrollen sie etwas nach oben, dort finden sie einen Funktionsprolog (s. Unterprozesse, die (hier) zur Verwaltung gestartet werden) Wenn sie dort alle Sprungreferenzen anzeigen lassen (Find References To), sollten sie neun calls finden. Grundpraktikum NDS - Buffer Overflows 2 9 8. Januar 2014 8 Aufgabe 2 Starten sie den Debugprozess neu und setzen sie alle Calls der Form 02019xxx als Breakpoints. Sollten sie feststellen, dass auch bei diesen Breakpoints der Stack überschrieben wurde, nehmen sie den ersten call VOR ihrem Breakpoint und testen sie dies erneut. Wiederholen sie dies, bis sie einen Breakpoint gefunden haben andem folgendes gilt: vor dem call ist der Stack ok, danach ist er überschrieben. Tracen sie in diesen call und suchen sie dort genauso weiter. So sollten sie die erste Funktion schnell finden. Wenn sie die erste Funktion gefunden haben, lassen sie das Programm bis zum nächsten Return ausführen und kehren sie zum Aufrufer zurück. Danach lassen sie das Programm wieder bis zum Return ausführen und sollen so nahe der zweiten Funktion sein (sie können dies immer bis zu einem Return wiederholen und den Stack überprüfen, diese Methode ist ähnlich der mit den Calls). Nun tracen sie weiter und beobachten wieder das Programm (nach jedem Call den Stack untersuchen, denn er wird zweimal überschrieben). Sie sollten nun die zweite Funktion schnell finden können. Tipp: öffnen sie vor der Untersuchung einmal Winamp und laden sie die Testplayliste. Danach schließen sie Winamp wieder. Damit müssen sie die Playliste nicht immer neu laden, wenn sie die Untersuchung neu beginnen müssen. Tipp: Wenn sie eine Funktion gefunden haben, bei der sie vermuten das diese den Stack überscheibt, benutzen sie die Option Lock Stack“ um den Stack an der jetzigen Position im Auge zu behalten ” (Rechtsklick mit der Maus auf das Stackfenster. Es ist dabei immernoch möglich sich andere Teile des Stacks anzuschauen (Scrollen)). Geben sie die beiden Offsets an, die sie herausgefunden haben. Beschreiben sie den von ihnen eingeschlagenen Weg unter der Benutzung von F7/F8/F9 und den von ihnen verwendeten Breakpoints. Damit können sie ihrem Auftraggeber eine detailierte Auflistung der von ihnen gefundenen Ergebnisse liefern (Hinweis: Dieser Fehler wurde ab Version 5.13 in Winamp behoben.). Sollten sie diese Aufgabe erfolgreich bewältigt haben, haben sie eine gute Grundlage im Umgang mit Dateianalysen erworben. Interessierte Teilnehmer seien darauf hingewiesen, dass die letzte Aufgabe zum sog. Reverse Engineering gehört. Zu diesem Themenkomplex existieren sehr viele, sehr interessante Anwendungen. Grundpraktikum NDS - Buffer Overflows 2 10 8. Januar 2014 9 Fragen 9 Fragen 1. Was versteht man unter Shellcode? 2. Wie funktioniert ein statischer Funktionsaufruf im Shellcode? 3. Wie funktioniert ein dynamischer Funktionsaufruf? 4. Worauf muss geachtet werden, damit Shellcode funktioniert? 5. Wie kann ich Text in meinem Shellcode nutzen? 6. Wie füge ich ein NULL-Byte ans Ende eines String an? 7. In welcher Reihenfolge werden Parameter an Funktionen im Shellcode übergeben und wie wird dies gemacht? Grundpraktikum NDS - Buffer Overflows 2 11 8. Januar 2014 Literatur Literatur [1] Jack Koziol et. al. The Shellcoders Handbook, 2004. [2] Steve Hanna. Shellcoding for Linux and Windows Tutorial, 2004. http://www.vividmachines. com/shellcode/shellcode.html. [3] R. Hyde. The art of assembly language programming. baut/ArtOfAssembly/artofasm.html. http://cs.smith.edu/ thie- [4] Iczelion. Win32 assembly tutorials. http://win32assembly.programminghorizon.com/tutorials.html. [5] Windows MSDN. Messagebox function. http://msdn.microsoft.com/en-us/library/windows/ desktop/ms645505%28v=vs.85%29.aspx. [6] T. Werthmann. Survey on buffer overflow attacks and countermeasures, June 2006. [7] Wikipedia. Shellcode. http://en.wikipedia.org/wiki/Shellcode. [8] Wikipedia. Microsoft Windows library files, 2005. http://en.wikipedia.org/wiki/Microsoft_ Windows_library_files. Grundpraktikum NDS - Buffer Overflows 2 12 8. Januar 2014