Eingelocht

Seite 3: Zahlenjongleur

Inhaltsverzeichnis

Die Kunst eines Exploits besteht im richtigen Setzen der Rücksprungaddresse. Sie muss als absoluter Wert an die Stelle der Rücksprungadresse geschrieben werden. Ein Angreifer weiß aber nicht, wo sein Code beginnt, da ja bereits andere Daten auf dem Stack liegen. Als Trick stellt man dem eigentlichen Assembler-Code einfach mehrere NOP-Befehle voran, die nur ein Byte groß sind. Ist die Rücksprungadresse nun falsch, so landet man im schlechtesten Fall an irgendeinem NOP-Befehl. Diese werden abgearbeitet, bis man zum eigentlichen Code kommt.

Der Code wird mit der Zahl 17 XOR-verknüpft

Eine weitere Hürde beim Einschleusen von Code besteht darin, dass die meisten Systeme das Ende einer Zeichenkette mit dem Wert "0" markieren, dieser in ausführbarem Code aber recht häufig auftaucht. Beim Kopieren einer Zeichenkette hören die Systemfunktionen beim ersten Zeichen mit diesem Wert auf: Der Code wird dann nur unvollständig übertragen. Auch hier greift man wieder zu Tricks: Zuweisungen wie mov 0,eax werden durch das gleichwertige "xor eax,eax" ersetzt. Alternativ kann man den Code mit einem Wert X über XOR verknüpfen. Den Wert X manipuliert man so lange, bis die Zeichenkette keine Nullen mehr enthält. Allerdings muss man diesem Code nun ein paar Zeilen Asssembler voranstellen, die das wieder rückgängig machen.

Der Aufbau eines Strings für einen Buffer-Overflow-Exploit

Schließlich muss man auch in einem solchen Exploit gelegentlich auf eigene Daten wie den String "/bin/bash" zugreifen. Da die absolute Position des Strings im Speicher nicht bekannt ist, muss die Adressierung relativ erfolgen. Doch relativ wozu? Auch hier greifen die Programmierer von Exploits zu einem Trick: Sie springen mit einem relativen Jump-Befehl an das Ende ihres Codes, hinter dem sich die benötigten Variablen befinden. Dort simulieren sie via call einen Funktionsaufruf auf den nächsten abzuarbeitenden Befehl. Dabei schiebt das System die nächste Adresse - also die des Stringanfangs - auf den Stack. Von dort kann man sie via pop in ein beliebiges Register befördern. Schon hat der Programmierer seinen Zeiger auf den eigenen Datenbereich.

Ein relativer Sprung wird vorbereitet

Natürlich will der Angreifer in seinem Exploit Dateizugriffe oder den Start eines Programms nicht selbst in Assembler programmieren. Deshalb greift er auf Funktionen des jeweiligen Betriebssystems zurück. Linux bietet über den Software-Interrupt 0x80 Zugang zu allen wichtigen Funktionen. Um eine neue Datei anzulegen, genügt es, vor dem Aufruf von int 0x80 einige Register entsprechend zu präparieren. EBX muss die Adresse des Strings mit dem Dateinamen enthalten, ECX sorgt für passende Zugriffsrechte und EAX wählt mit dem Wert 0x8 den Systemaufruf create() aus. Mit 0x80 erhält man auch Zugriff auf die Funktion execve(), über das man externe Programme wie die Shell "/bin/sh" starten kann.

Unter Windows kann der Exploit-Code direkt alle Funktionen des Windows-APIs nutzen, die das Programm einbindet. Befindet sich darunter die Funktion LoadLibrary, kann der Angreifer auch beliebige Funktionen nachladen. Beim Aufruf der Windows-API-Funktionen müssen sich die Übergabeparameter wie bei einem normalen Funktionsaufruf in der richtigen Reihenfolge auf dem Stack befinden.