Studienarbeit
Stack- und Heap-Overflow-Schutz
bei
Windows XP und Windows Vista
Fachbereich Informationstechnik
Studiengang Softwaretechnik und Medieninformatik
Semester: SWT6
Name: Johannes Hohenbichler
Datum: 20.08.2008
Version: 1.03
Betreuer: Dominik Schoop
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 2 -
I Inhaltsverzeichnis
I Inhaltsverzeichnis ......................................................................................................................... 1-2
II Abbildungsverzeichnis .................................................................................................................. 1-4
III Abkürzungsverzeichnis ................................................................................................................. 1-5
IV Toolsverzeichnis ........................................................................................................................... 1-6
V Besondere Darstellungsformen .................................................................................................... 1-7
1 Überblick ...................................................................................................................................... 1-8
2 Grundlagen – Systemarchitektur................................................................................................ 2-10
2.1 Speicherorganisation .......................................................................................................... 2-10
2.1.1 Virtueller Speicher ...................................................................................................... 2-10
2.1.2 Systemfunktionen....................................................................................................... 2-11
2.1.3 Speichersegmente ...................................................................................................... 2-13
2.1.4 Big- und Little-Endian ................................................................................................. 2-15
3 Grundlagen – Buffer Overflows .................................................................................................. 3-16
3.1 Buffer Overflows ................................................................................................................ 3-16
3.1.1 Off-By-One Buffer Overflows ..................................................................................... 3-17
3.1.2 Mit Buffer Overflows den Kontrollfluss ändern ......................................................... 3-18
3.1.3 Ausführen von beliebigem Code ................................................................................ 3-21
3.1.4 Klassische Stack-basierende Angriffe ......................................................................... 3-22
3.1.5 Exception Handler-basierende Angriffe ..................................................................... 3-25
3.1.6 Heap-basierende Angriffe .......................................................................................... 3-27
3.2 Shellcode und Payload ....................................................................................................... 3-29
3.2.1 Anforderungen an Shellcode ...................................................................................... 3-29
3.2.2 Besonderheiten von Windows-Shellcode .................................................................. 3-30
3.2.3 Was möglich ist ........................................................................................................... 3-30
3.2.4 Abstraktes Beispiel: Portbind Shellcode für Windows ............................................... 3-31
4 Das Sicherheits-Ensemble von Windows und seine Schwachstellen ........................................ 4-32
4.1 Das Windows-Zwei-Schichten-Modell................................................................................ 4-32
4.2 Zugriffsrechte, Authentifizierung und Access Token.......................................................... 4-33
4.2.1 Rechte von Prozessen unter Windows ....................................................................... 4-34
4.2.2 Windows Service Hardening ....................................................................................... 4-35
4.2.3 Rechte von Prozessen unter Windows Vista: UAC ..................................................... 4-35
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 3 -
4.3 PatchGuard ......................................................................................................................... 4-37
4.4 Process Exection Block (PEB) Randomization..................................................................... 4-37
4.5 Heap-Schutz ........................................................................................................................ 4-38
4.6 Visual Studio 2005 - Der "Windows-Compiler" .................................................................. 4-40
4.6.1 Standard Annotation Language (SAL) ......................................................................... 4-40
4.6.2 Optimierte Anordnung von Stack-Elementen (O2) .................................................... 4-42
4.6.3 Puffer-Sicherheitsüberprüfung (GS) ........................................................................... 4-43
4.6.4 Sichere Ausnahmebehandlung (SafeSEH) .................................................................. 4-47
4.6.5 Data Execution Prevention (DEP) ............................................................................... 4-48
4.6.6 Address Space Layout Randomization (ASLR) ............................................................ 4-51
4.7 Abschließender Vergleich: XP gegenüber Vista ................................................................. 4-52
5 Fazit ............................................................................................................................................ 5-54
A Literaturverzeichnis .................................................................................................................... 5-56
B Quellcode ................................................................................................................................... 5-60
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 4 -
II Abbildungsverzeichnis
Abbildung 2-1: 32-Bit-Windows Standard-Adresslayout nach [ 2 ] .................................................. 2-11
Abbildung 2-2: Prinzipielles Windows Prozess-Speicher-Layout nach [ 3 S. 182 ] und [ 4 S. 397 ] .. 2-13
Abbildung 2-3: Big-Endian im Speicher .............................................................................................. 2-15
Abbildung 2-4: Little-Endian im Speicher ........................................................................................... 2-15
Abbildung 3-1: Die Buffer buf0 und buf1 im Speicher ....................................................................... 3-18
Abbildung 3-2: Buffer Overflow von password_buffer in auth_flag .................................................. 3-21
Abbildung 3-3: Beispielhaftes Stackframe unter Windows allgemein ............................................... 3-22
Abbildung 3-4: Angriffsvektor ............................................................................................................ 3-23
Abbildung 3-5: Beispielhaftes Stackframe unter Verwendung von SEH [ 13 ] .................................. 3-27
Abbildung 4-1: Windows-Zwei-Schichten-Modell [ 4 ] ...................................................................... 4-33
Abbildung 4-2: Optimierte Anordnung von Stack-Elementen bei VS 2003 ....................................... 4-43
Abbildung 4-3: Beispielhaftes Stacklayout unter Verwendung von /GS bei VS 2005 [ 32 ] .............. 4-45
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 5 -
III Abkürzungsverzeichnis
ASLR Address Space Layout Randomization
BS Betriebssystem
DACL Discretionary Access Control List
DEP Data Execution Protection, auch bekannt als NX
DoS Denial of Service
Dll Dynamic Link Library
EH Exception Handler
GByte Gigabyte
IE Internet Explorer
LSA Local Security Authority Subsystem Service
NX No eXecute, auch bekannt als DEP
RET Returnaddress
SAL Standard Annotation Language
SEH Structured Exception Handling
SFP Saved Frame Pointer
SID Security Identifier
VS Visual Studio
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 6 -
IV Toolsverzeichnis
Programm Bezugsmöglichkeit
Windows power shell http://www.microsoft.com/windowsserver2003/technologies/management/power
shell/default.mspx
Strawberry Perl http://strawberryperl.com/
Process Explorer http://technet.microsoft.com/de-de/sysinternals/default(en-us).aspx
Display Heap Windows Server 2003 Resource Kit Tools
http://support.microsoft.com/kb/168609/de
Global Flags Debugging Tools for Windows
http://www.microsoft.com/whdc/devtools/debugging/default.mspx
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 7 -
V Besondere Darstellungsformen In dieser Arbeit kommen im Wesentlichen vier spezielle Gestaltungselemente zur Anwendung
1. Begriffserklärungen und Hinweise sind in einer Box der folgenden Art untergebracht
2. Kommandos
Kommandos die auf der Kommandozeile eingegeben werden (cmd.exe)
sind grau hinterlegt
3. Programmausgaben
Programmausgaben
sind orange hinterlegt
4. Quellcode / Ausschnitte aus Dateien
Auszüge aus Quellcode / Konfigurationsdatein
sind hellblau hinterlegt
Begriffserklärungen und Hinweise
Begriff: Beschreibung oder Definition des Begriffs bzw. Hinweistext
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 8 -
1 Überblick
Ausgangssituation
In der Vergangenheit waren Buffer-Overflows eines der Hauptsicherheitsrisiken für Software. In den
letzten Jahren haben Softwarehersteller an diesem Problem intensiv gearbeitet und den Schutz stark
erhöhen können. Das beweisen nicht zuletzt CVE1-Statistiken, die Windows Vista für das Jahr 2008
bis zum Erscheinen dies Dokuments, in dem Monat Juni, nur eine einzige Schwachstelle
bescheinigen, die direkt auf Buffer-Overflows zurückzuführen ist. [ 1 ]
Ziel dieser Arbeit
Das Ziel dieser Arbeit ist es, einen Überblick zu schaffen, welche Mechanismen die Betriebssysteme
Windows XP und Windows Vista zur Vermeidung und zur Schadensbegrenzung von Buffer Overflows
bieten. Dabei wird auf die Schwachstellen der vorhandenen Mechanismen eingegangen und es
werden Wege aufgezeigt, wie sich diese Schwachstellen praktisch auszunutzen lassen. Außerdem hat
es diese Arbeit zum Ziel, die Neuerungen von Windows Vista, dem noch weiter verbreiteten
Windows XP gegenüber zu stellen und so den sicherheitstechnischen Mehrwert von Windows Vista
darzulegen.
An wen richtet sich diese Arbeit
Diese Arbeit richtet sich an alle Leser, die an der definierten Zielsetzung interessiert sind. Zum
vollständigen Verständnis werden jedoch Grundkenntnisse der Programmiersprachen c und x86
Assembler vorausgesetzt. Für Buffer Overflows besonders relevante Punkte sind jedoch grundliegend
beschrieben, so dass die Arbeit auch für Leser ohne Vorkenntnisse aus dem Themengebiet "Buffer-
Overflows" verständlich sein sollte.
Gliederung dieser Arbeit
Die einzelnen Kapitel dieser Arbeit können für sich selektiv gelesen werden. Die beiden
Grundlagenkapitel(Kapitel 2, 3) bauen jedoch aufeinander auf und sollten von Beginn bis Ende
gelesen werden. Zudem wird im Hauptkapitel(Kapitel 4) auf die Angriffsmöglichkeiten bezug
genommen, die im Grundlagenkapitel "Buffer Overflows" erklärt werden.
In dem Kapitel 2 werden einige, für Buffer Overflows wichtige, Grundlagen zur Systemarchitektur
vorgestellt. Der Fokus liegt hierbei speziell auf Eigenheiten des NT-Kerns der Betriebssystemfamilie
Microsoft Windows.
1 National Vulnerability Database: http://nvd.nist.gov/
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 9 -
In dem Kapitel 3 wird eine Einführung in das Thema Buffer Overflows gegeben und es werden
einzelne Codestücke präsentiert. Um die Übersichtlichkeit an dieser Stelle nicht unnötig zu
beeinträchtigen sind die vollständigen Programme in einem Zip-Archiv(Kapitel B) zu finden. Ebenfalls
im Kapitel B, finden sich Hinweise zum Übersetzen der jeweiligen Programme mit dem Compiler der
Entwicklungsumgebung Visual Studio 2003 / 2005. Ziel dieses Kapitels ist es, die grundliegenden
Konzepte von Buffer Overflows zu umreißen und einige windows-spezifische Angriffe zu erläutern.
Das Hauptkapitel dieser Arbeit beschäftigt sich im Detail mit den verschiedenen Schutzmaßnahmen
von Windows XP und Vista. Hierbei wird vor allem auf den effektiven Nutzen der einzelnen
Maßnahmen eingegangen. In diesem Zusammenhang werden Implementierungs- und
Designschwachstellen aufgezeigt und objektiv beurteilt. Dabei wird auf die im Kapitel 3 vorgestellten
Angriffe eingegangen und es wird geklärt, warum die Angriffe noch, oder nicht mehr, funktionieren.
Abschließend folg eine Zusammenfassung der wesentlichen Erkenntnisse der wesentlichen
Erkenntnisse und kritischen Blick auf die derzeitigen Entwicklungen.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 10 -
2 Grundlagen – Systemarchitektur
In diesem Kapitel werden Grundlagen aus den Bereichen Betriebssystem- und Rechnerarchitektur
vorgestellt, die für ein fundiertes Verständnis von Buffer Overflows benötigt werden. Dabei wird
speziell auf Eigenheiten des NT-Kernels, der Betriebssystemfamilie Microsoft Windows, eingegangen.
2.1 Speicherorganisation
In diesem Abschnitt wird die Speicherorganisation von Windows XP und Windows Vista grundliegend
erläutert um ein eine Basis für das Verständnis, der in Kapitel 3 beschriebenen Angriffstechniken, zu
schaffen.
2.1.1 Virtueller Speicher
Bei 32-Bit-Windows-Systemen steht einer Anwendung theoretisch der maximal adressierbare
Speicher von 0x00000000 bis 0xFFFFFFFF zur Verfügung, was einer Größe von 2³² Byte = 4 GByte
entspricht. Dabei ist die kleinste adressierbare Einheit ein Byte groß.
Diese 4 GByte teilt Windows in zwei Hälften. Den höherwertigen Bereich verwendet es für
Betriebssystemfunktionen und den niederwertigen Bereich für das Programm selbst. Die Trennung
ist normalerweise, wie in der Abbildung 2-1 zu sehen ist, in der Mitte des Gesamtspeichers
vorgenommen. Dank dem Konzept des virtuellen Adressraums, ist es dabei nicht wichtig, welche
Menge an Arbeitsspeicher das System tatsächlich benötigt. Mit Hilfe der Hardware, zur
Adressvirtualisierung, kann das Betriebssystem die Umsetzung von physikalischen in virtuelle
Adressen erledigen, ohne dass sich ein laufendes Programm darum bemühen muss. Dabei kümmert
sich das Betriebssystem automatisch um das Ein- und Auslagern von Speicher.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 11 -
Benutzermodus-
Prozesse
(2GB)
Systemspeicher
(2GB)
0000000h
(Kleine Adressen)
FFFFFFFFh
(Große Adressen)
7FFFFFFFh
00000000h
80000000h
FFFFFFFFh
Abbildung 2-1: 32-Bit-Windows Standard-Adresslayout nach [ 2 ]
2.1.2 Systemfunktionen
Im Zusammenhang mit Buffer Overflows ist weniger die im letzen Kapitel vorgestellte
Speicheraufteilung interessant, sondern viel mehr die Art wie auf Systemfunktionen zugegriffen wird.
Im normalen Programmbetrieb werden alle benötigten Systemfunktionen, wie beispielsweise
sleep(), in den virtuellen Adressbereich der Anwendung eingeblendet. Beim Übersetzen des
Quellcodes erzeugt der Compiler automatisch die Befehle zum Laden der nötigen Systemfunktionen.
Die Adressen an denen die verschiedenen Systemfunktionen zu finden sind, sind innerhalb eines
Systems normalerweise immer gleich. Unterschiede bezüglich der Funktionsadressen gibt es lediglich
zwischen den einzelnen Windows-Versionen sowie zwischen den verschiedenen Service-Packs. Eine
wirkliche Ausnahme entsteht allerdings durch Address Space Layout Randomization (ASLR), auf das in
dem Kapitel 4.6.4 eingegangen wird.
Ein Beispiel:
Mit dem Programm dumpbin.exe, das Teil von Visual Studio 2005 ist, lässt sich die Basis-Adresse des
Windows-Kernels ermitteln:
PS C:\WINDOWS\system32> dumpbin /headers kernel32.dll | select-string -
pattern "image base" 7C800000 image base (7C800000 to 7C906FFF)
Um nun beispielsweise die Absolute Adresse der Sleep-Funktion zu ermitteln muss noch die relative
Adresse, ausgehend von der Basis-Adresse, ermittelt werden:
Hinweis
Unter 32-Bit-Windows lässt sich
die Aufteilung auch mittels einer
Bootoption in das Verhältnis 3GB
zu 1GB (Programmspeicher zu
Systemspeicher) ändern. Unter
64-Bit-Windows-Varianten ist die
Speicheraufteilung nahezu 50%
zu 50% [ 2 S. 14ff ] .
Außerdem gibt es die Address
Windowing Extensions (AWE) mit
deren Hilfe sich der virtuelle
Speicher vergrößern lässt [ 2 S.
383ff ]
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 12 -
PS C:\WINDOWS\system32> dumpbin /all kernel32.dll | select-string -pattern
"sleep" 7C8087E0: 73 6F 75 72 63 65 00 53 6C 65 65 70 00 53 6C 65 source.Sleep.Sle
831 33E 00002442 Sleep
832 33F 0000239C SleepEx
Aus der Basis-Adresse und der relativen Adresse ergibt sich die absolute Adresse der Funktion sleep()
7c800000h + 00002442h = 7c802442h
Wie bereits erwähnt ist diese Adresse bei jedem Programmstart, unter Berücksichtigung der oben
genannten Ausnahmen, gleich.
Tools-Hinweis
Die obigen Kommandos wurden nicht in der normalen Eingabeaufforderung, sondern in der
kostenlos über Microsoft erhältlichen Powershell, ausgeführt. Der Grund hierfür ist, dass in der
Powershell die Funktion select-string() zur Verfügung steht. Bezugsmöglichkeiten: siehe
Toolsverzeichnis
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 13 -
2.1.3 Speichersegmente
Der einem Prozess zur Verfügung stehende virtuelle Speicher, teilt sich wie in Abbildung 2-2 zu sehen
ist, in verschiedene Segmente auf. Wichtig sind hierbei vor allem die relative Position der Segmente
zueinander, sowie die Richtung des Schreibzugriffs. Der Schreibzugriff erfolgt immer von einer
Basisadresse in Richtung der höherwertigen Adressen.
Beispielhaftes
Stackframe
Gespeicherte Register der
aufrufenden Funktion
Lokale Variablen
Stack Frame Pointer (SFP)
Return Adresse (RET)
Parameter
Heap
.BSS
.DATA
.TXT
Stack
Systemspeicher
0000000h
(Kleine Adressen)
FFFFFFFFh
(Große Adressen)
Wachstumsrichtung
Heap entspricht einer Dynamischen
Erweiterung des BSS-Segments
(langlebige Daten)
Stack Registerinhalte
lokale Variablen
Funktionsparameter
(kurzlebige Daten)
.TXT Programmkode
.DATA Initialisierte
globale und statische Variablen
.BSS Nicht initialisierte
globale und statische Variablen
Prozess-Speicher
Sch
reib
rich
tun
g
Abbildung 2-2: Prinzipielles Windows Prozess-Speicher-Layout nach [ 3 S. 182 ] und [ 4 S. 397 ]
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 14 -
Stack
Der Stack ist das Speichersegment, das zum Ablegen kurzlebiger Daten dient. So werden auf dem
Stack beispielsweise lokale Variablen und Funktionsparameter abgelegt.
In Abbildung 2-2 ist, auf der rechten Seite, ein typisches Stackframe abgebildet. Anhand der Pfeile,
die die Wachstumsrichtung angeben, lässt sich erkennen, dass der Stack von großen Adressen in
Richtung kleiner Adressen wächst.
Das Prinzip eines Stacks, oder auch Stapelspeicher genannt, ist folgendes:
1. Sollen neue, kurzlebige Daten zwischengespeichert werden, so werden diese auf die bereits
auf dem Stack liegenden Daten von oben aufgelegt. Die Operation zum Auflegen neuer
Daten nennt sich "push".
2. Werden die auf dem Stack gelegten Daten zur Verarbeitung benötigt oder muss der Stack
aufgeräumt werden, so wird von oben, Stück für Stück, abgebaut. Die Operation zum
Herunternehmen von vorhandenen Daten nennt sich "pop".
Wenn innerhalb eines Prozesses eine Funktion aufgerufen wird, so werden die benötigten Daten, wie
in der Abbildung 2-2 auf der rechten Seite zu sehen ist, auf dem Stack abgelegt (push). Ist die
Funktion beendet, so werden die Daten in umgekehrter Reihenfolge wieder vom Stack genommen
(pop).
Der Teil des Maschinencodes, der ein Stackframe aufbaut, nennt sich Prolog und der abbauende Teil
nennt sich Epilog.
Genauere Informationen zur Funktionsweise des Stacks können in [ 5 ] gefunden werden.
Heap
Der Heap ist der dynamische Speicherbereich eines Prozesses. Er kann dynamisch in seiner Größe
wachsen, somit kann der Prozess dynamisch Speicher anfordern und freigeben.
Der Heap ist in Abbildung 2-2 im Bereich der niedrigen Speicheradressen zu sehen, was für Windows
typisch ist. Außerdem ist in der Abbildung 2-2 dargestellt, dass der Heap in Richtung großer Adressen
wächst.
Inhaltlich gesehen werden auf dem Heap, verglichen mit dem Stack, langlebigere Daten abgelegt.
Ein Prozess hat typischer Weise mehrere Heaps. Ein neuer Heap kann z. B. mit der Windows-API-
Funktion HeapCreate() angefordert und mit HeapDestroy() wieder freigegeben werden. Das
Anfordern eines Speicherbereiches erfolgt anschließend mit HeapAlloc() und wird analog mit
HeapFree() wieder freigegeben. Bei Verwendung des c++-Operators new, wird automatisch
Speicher von dem Standard-Heap des Prozesses angefordert.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 15 -
Wie bereits angedeutet, hat der Programmierer die Wahl. Entweder er verwendet die von der
Windows-API bereitgestellten Funktionen für das Heap-Management, oder er verwendet seine
eigene Heap-Verwaltung. [ 6 ]
Die von Windows standardmäßig verwendete Heap-Verwaltung organisiert den Speicher in einer
Reihe unterschiedlicher Listen, die zusammen den gesamten Heap beschreiben. Dabei gibt es unter
anderem, eine Liste für noch freie, kleine Speicherblöcke mit Größe 4KByte und eine separat
geführte Liste, die alle belegten Blöcke enthält. Zudem werden temporären Listen erstellt, die der
Geschwindigkeitserhöhung dienen. [ 7 ] [ 8 ] [ 9 ]
2.1.4 Big- und Little-Endian
Als Big- und Little-Endian, werden zwei verschiedene Darstellungsformen von Werten, im Speicher
bezeichnet.
Beispiel: Darstellung der Speicher-Adresse AABBCCDD Hex = 2864434397 Dez im Speicher
Big-Endian: Das höchstwertige Paar steht ganz links, wie in Abbildung 2-3 zu sehen.
BB CCAA DD00000000h FFFFFFFFh
Big-Endian
Abbildung 2-3: Big-Endian im Speicher
Little-Endian: Das höchstwertige Paar steht ganz rechts, wie in Abbildung 2-4 zu sehen.
CC BBDD AA00000000h FFFFFFFFh
Little-Endian
Abbildung 2-4: Little-Endian im Speicher
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 16 -
3 Grundlagen – Buffer Overflows
Ziel dieses Kapitel ist es, dem Leser die Grundkonzepte von Buffer Overflows zu vermitteln um so die
von Windows XP und Windows Vista verwendeten Schutzmechanismen besser beurteilen zu können.
Im Folgenden sind immer nur die unmittelbar relevanten Codeabschnitte gelistet. Die vollständigen
Programme mit Hinweisen zum Übersetzen und zugehöriger Programmausgaben sind im Anhang zu
finden.
3.1 Buffer Overflows
Im Kontext der Programmiersprache c, ist ein Buffer ein zusammenhängender Speicherbereich, der
Daten desselben Typs beinhaltet. In c werden Buffer häufig auch als Arrays bezeichnet.
Ein primitiver Buffer kann in c beispielsweise folgende Form haben:
char buf0[4] = "ABC\0";
In diesem Fall ist der Buffer 4 Byte groß und ist ein String-Buffer. Dabei dient das letzte Byte zur
Terminierung des Strings.
Ein Buffer Overflow, oder auch Puffer-Überlauf, passiert demnach, wenn die Grenzen des
vorgesehenen Speicherbereichs überschritten werden.
Die Folgen für das Gesamtsystem können dabei sehr unterschiedlich ausfallen.
So zeigt sich die gefährliche Seite von Buffer Overflows, wenn es dem Angreifer möglich ist
beliebigen Code einzuschleusen und seine Ausführung zu erreichen. In diesem Fall stehen dem
Angreifer nahezu unbegrenzte Möglichkeiten zur Verfügung. Von einem primitiven Beenden der
verwundbaren Software bis hin zum Erstellen von Benutzerkonten oder dem installieren eines Root-
Kits (Details zu Angriffen dieser Art in dem Kapitel 3.1.4).
Wichtiger Hinweis für Selbstversuche
Mit Visual Studio 2005 lassen sich die meisten Beispielprogramme nicht ohne weiteres mit den
erwarteten Ergebnissen übersetzen. Der Grund hierfür sind Optimierungen und
Schutzmechanismen, die der Visual Studio 2005 Compiler verwendet. Hinweise zum
„richtigen“ Übersetzen, sowie die vollständigen Programme finden sich jeweils im Anhang
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 17 -
Bei weniger kritischen Programmierfehlern kann es zu inkonsistenten Daten kommen die nicht
zwangsläufige einen Programmabsturz nach sich ziehen müssen und somit lange unentdeckt bleiben
können. Damit beeinträchtigen diese Fehler zwar den Nutzen der Software, die
Angriffsmöglichkeiten können aber, wie das Beispiel im nächsten Abschnitt zeigt, recht beschränkt
sein.
3.1.1 Off-By-One Buffer Overflows
Ein klassischer Buffer Overflow im Zusammenhang mit c-Strings ist der "Off-By-One"-Fehler. Dabei
vergisst der Programmierer entweder den bereits erwähnten String-Terminator mitzuzählen, oder er
ist bei der indexzählweise der Arrays unaufmerksam.
Mit folgenden Programmausschnitten sollen die Folgen eines Off-By-One Overflows verdeutlicht
werden. Das vollständige Programm mit Compiler-Optionen und vollständiger Ausgabe sind im
Quellcode-Archiv zu finden (Kapitel B).
//gekürzt...
char buf0[] = "1234";
char buf1[4] = "ABC\0";
strcpy(buf1,buf0);
Führt man das vollständige Programm aus, so erhält man folgende Ausgabe
~~~ vorher ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Adresse von buf0: 0012FF68 sizeof(buf0): 5 Byte
Adresse von buf1: 0012FF64 sizeof(buf1): 4 Byte
buf0 1234
buf1 ABC
~~~ nachher ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
buf0
buf1 1234
Betrachtet man diese Programmausgabe genauer, so fällt auf, dass der Buffer buf1 zwar den
gewünschten Inhalt erhalten hat, buf0 seinen Inhalt aber offenbar verloren hat.
Was hier passiert ist schnell erklärt: Es kommt zu einen Buffer Overflow, weil der Programmierer
vergessen hat, dass der Compiler an der Stelle char buf0[] = "1234"; automatisch ein 5-Byte
großes, null-terminiertes String-Array erstellt.
Deshalb überschreibt strcpy() mit dem '\0' den ersten Teil des Buffers buf0, der nach buf1 im
Speicher liegt. Die Abbildung 3-1 soll diesen Vorgang verdeutlichen.
Hinweis zum Speicherlayout: Die Anordnung von Variablen im Speicher wird immer zum Zeitpunkt
des Übersetzens festgelegt und wird von dem Compiler entschieden. Der Compiler folgt beim
Erstellen des Speicherlayouts zwar festen Regeln, eine feste Beziehung zwischen der Reihenfolge der
Quellcode: Kapitel-3-1-1_off-by-one\off-by-one.c
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 18 -
Definition/Deklaration im Quellcode und dem tatsächlichen Layout existieren jedoch nicht. Zur
Erinnerung: Der Heap unterliegt anderen Regeln, da dieser Speicher erst zur Laufzeit erstellt wird.
A '\0' 2 31CB 4 '\0'
buf1 buf0
1. Vorher
0x0012FF64 0x0012FF68
1 4 2 3'\0'32 4 '\0'3. Nachher
2. strcyp()
Abbildung 3-1: Die Buffer buf0 und buf1 im Speicher
Gibt man mittels printf("buf0 %s\n", buf0); den String buf0 aus, so wird nichts ausgegeben,
weil der String-Terminator bereits an erster Stelle steht und printf() mit dem Formatstring %s, nur
Zeichen bis zu dem ersten vorkommenden '\0' ausgibt.
Off-By-One Buffer-Overflows sind in den meisten Fällen nichts weiter als ärgerliche
Programmierfehler die relativ schwer zu finden sind. Der Nutzen ist für Angreifer bei
Programmierfehlern dieser Art meist sehr beschränkt. Hauptsächlich deshalb, weil der
Speicherbereich der durch den Benutzer beeinflusst werden kann, mit einer Speichereinheit (im
obigen Beispiel 1 Byte) nur sehr wenig Spielraum bietet. Die Folgen hängen aber davon ab, welche
Art von Informationen in den überschreibbaren Bereichen gespeichert sind.
Wie interessant selbst ein Off-By-One Buffer-Overflow werden kann zeigt der folgende Abschnitt.
3.1.2 Mit Buffer Overflows den Kontrollfluss ändern
Im dem folgenden Programm kann ein Buffer Overflow dazu verwendet werden eine Variable zu
überschreiben, die wesentlich für den Ablauf des Programms ist.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hacking.h"
int check_authentication(char *password) {
int auth_flag = 0;
char password_buffer[8] = {'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F'};
printf("~~~ vorher ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
printf("dump: password_buffer\n");
Quellcode: Kapitel-3-1-2_auth_overflow\auth_overflow.c
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 19 -
dump(password_buffer, 8);
printf("dump: auth_flag\n");
dump(&auth_flag, 4);
strcpy(password_buffer, password);
if(strcmp(password_buffer, "password") == 0)
auth_flag = 1;
if(strcmp(password_buffer, "adminpw") == 0)
auth_flag = 1;
printf("~~~ nachher ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
printf("dump: password_buffer\n");
dump(password_buffer, 8);
printf("dump: auth_flag\n");
dump(&auth_flag, 4);
return auth_flag;
}
int main(int argc, char *argv[]) {
//... gekürtzt
if(check_authentication(argv[1])) {
printf("\n-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
printf(" Zugang freigegeben.\n");
printf("-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
} else {
printf("\nZugang verweigert.\n");
}
getchar();
}
Hinweis: die Funktion dump() ist in der Include-Datei hacking.h definiert. Sie gibt von einer, per
ersten Parameter übergebenen Speicheradresse ausgehend, eine mit dem zweiten Parameter
definierte, Menge an Speicherinhalten, aus.
Das Programm übernimmt den ersten Parameter, den das Hauptprogramm übergeben bekommt und
kopiert ihn in der Funktion check_authentication() in einen Buffer, der als Zwischenspeicher
dient.
Stimmt das Passwort mit einem der gespeicherten Passwörter überein, so wird die Variable
auth_flag auf 1 gesetzt, was "wahr" entspricht.
Das Hauptprogramm nimmt den Rückgabewert der Funktion check_authentication() um
Zugang zu einem geschützten Bereich zu gewähren oder zu verweigern.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 20 -
Dabei gibt es in dem Programmfluss keinen Else-Zweig, der im Falle, keiner Übereinstimmung, die die
Variable auth_flag auf 0 setzen würde. Der Programmierer hat diesen Fall durch das Initaialisieren
mit 0 abgedeckt.
Gegen dieses Vorgehen ist prinzipiell nichts einzuwenden. Das Problem mit dem obigen Code ist
jedoch, dass die Funktion strcpy() unabhängig von der Größe des Zielbuffers password_buffer
alle Zeichen bis zum ersten '\0' kopiert.
Diese Frage lässt sich mit Hilfe der Programmausgabe beantworten:
~~~ vorher ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dump: password_buffer
0012FF54: 46 46 46 46 46 46 46 46 | FFFFFFFF
dump: auth_flag
0012FF5C: 00 00 00 00 | ....
... gekürzt
Wie hier zu sehen ist liegt die Variable auth_flag unmittelbar nach dem Buffer password_buffer
im Speicher.
Das bedeutet, sollte es dem Benutzer möglich sein, dem Programm als ersten Parameter mehr als
acht Zeichen zu übergeben, so findet durch strcpy()ein Buffer Overflow in den Speicherbereich
der Variable auth_flag statt.
Startet man das Programm beispielsweise folgendermaßen:
auth_overflow.exe 12345678A
So erhält man folgende Ausgabe:
~~~ vorher ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dump: password_buffer
0012FF54: 46 46 46 46 46 46 46 46 | FFFFFFFF
dump: auth_flag);
0012FF5C: 00 00 00 00 | ....
~~~ nachher ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dump: password_buffer
0012FF54: 31 32 33 34 35 36 37 38 | 12345678
dump: auth_flag);
0012FF5C: 41 00 00 00 | A...
-=-=-=-=-=-=-=-=-=-=-=-=-=-
Access Granted.
-=-=-=-=-=-=-=-=-=-=-=-=-=-
Wie zu sehen ist, hat der Benutzer mittels "12345678" acht Zeichen übergeben und noch ein
zusätzliches 'A' angehängt.
Wie in der Abbildung 3-2 zu sehen ist, wird das 'A' an die Speicheradresse 0x0012FF5C geschrieben.
Der Rückgabewert der Funktion check_authentication() ist als int deklariert und wird durch
das Programm als wahr oder falsch interpretiert. Da in der Programmiersprache c alle Werte ungleich
0 dem Wert "Wahr" entsprechen, wird im Falle eines Overflows der Zugang zum geschützten Bereich
gewährt.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 21 -
F F 0 00FF 0
password_buffer auth_flag
0x0012FF54 0x0012FF5C
F FFF
1 4 0 0A32 05 876
Overflowrichtung
1. Vorher
3. Nachher
2. strcyp()
Abbildung 3-2: Buffer Overflow von password_buffer in auth_flag
Dieses Beispiel zeigt eindrucksvoll, wie bereits ein einziges Zeichen an der richtigen Stelle genügen
kann, um den Ablauf eines Programms wesentlich zu beeinflussen.
Hinweis: Werden in diesem Programm mehr wie zwölf Zeichen übergeben, so stürzt das Programm
ab, da Informationen auf dem Stack überschrieben werden, die für den weiteren Programmablauf
benötigt werden. Abgesehen von Programmabstürzen, bietet diese Möglichkeit der Manipulation
von Werten, einen interessanten Ansatzpunkt für weitere Angriffsmöglichkeiten, auf die in den
folgenden Abschnitten eingegangen wird.
Bei dem zuletzt vorgestellten Overflow, ist außerdem zu bedenken, dass nicht nur Zahlenwerte und
Strings auf diese Weise manipuliert werden können. Es ist ebenso möglich Funktionspointer zu
überschreiben. Auf diese Weise kann wahlfrei, vorhandener, oder auch eingeschleuster
Programmcode ausgeführt werden.
Damit kommt dieses Grundagekapitel zu den "nützlicheren" Angriffsmöglichkeiten mittels Buffer
Overflows: Dem Ausführen von beliebigem Code.
3.1.3 Ausführen von beliebigem Code
Um auf einem Zielsystem beliebigen Code auszuführen sind prinzipiell immer zwei Schritte nötig
1. Den auszuführenden Code in den Arbeitsspeicher des Zielsystems einschleusen
2. Eine Möglichkeit finden den eingeschleusten Code ausführen zu lassen
Der erste Punkt lässt sich, ähnlich wie im Beispiel des letzten Abschnitts, mittels Programmparameter
erreichen.
Der zweite Punkt wird meistens durch das Manipulieren eins Funktionspointers erreicht. Dazu
können vom Programmierer selbst angelegte Funktionspointer verwendet werden, oder aber auch
auf dem Stack liegende Rücksprungadressen. [ 5 ]
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 22 -
Da die wirkliche Herausforderung mehr beim Ausführen, als beim Einschleusen liegt, werden in den
restlichen Abschnitten dieses Kapitels einige Möglichkeiten vorgestellt, um den Code zur Ausführung
zu bringen.
3.1.4 Klassische Stack-basierende Angriffe
Stack-basierende Angriffe verfahren normaler weise streng nach dem bereits vorgestellten Schema:
1. Den auszuführenden Code in Arbeitsspeicher des Zielsystems einschleusen
2. Eine Möglichkeit finden den gespeicherten Code ausführen zu lassen
Eine Möglichkeit den Code einzuschleusen haben wir bereits kennen gelernt: Die strcpy()-Funktion.
Kommen wir also zu Punkt zwei: Dem Starten des eingeschleusten Codes.
Bei klassischen Stack-basierenden Angriffen erfolgt das Starten des Codes durch das Manipulieren,
der auf dem Stack gespeicherten Rücksprung-Adresse(RET). Betrachtet man die in Abbildung 3-3
dargestellte Speicherbelegung, so stellt man fest, dass RET an einer höheren Adresse im Speicher
liegt als die lokalen Variablen.
Beispielhaftes
Stackframe
Wa
ch
stu
msrich
tun
g
Gespeicherte Register der
aufgerufenen Funktion
Lokale Variablen
Stack Frame Pointer (SFP)
Return Adresse (RET)
Parameter
0000000h
(Kleine Adressen)
FFFFFFFFh
(Große Adressen)
Ove
rflo
wrich
tun
g
Abbildung 3-3: Beispielhaftes Stackframe unter Windows allgemein
Da lokal angelegte String-Arrays (Buffer) nichts weiter sind als die in Abbildung 3-3 dargestellten
lokalen Variablen, ist es möglich, mit einer ausreichend großen Eingabe die Return-Adresse zu
überschreiben.
Damit der nächste Schritt, das Bestimmen der gewünschten Rücksprungadresse, einfacher ist, wird
als Füllmenge (um RET zu erreichen) ein spezieller Assembler-Befehl verwendet: ein NOP. NOP steht
für No OPeration und hat als einzige Aufgabe einen Maschinenzyklus zu verbrauchen. Danach führt
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 23 -
die CPU die Befehlsverarbeitung mit dem darauf folgenden Befehl fort. Typischer Weise werden an
dieser Stelle einige NOPs aufeinander folgen und bilden so einen NOP-Sled2.
Um nun den eingeschleusten Code ausführen zu lassen, muss RET auf den ersten eingeschleusten
Befehl zeigen. Wenn ein NOP-Sled verwendet wird, reicht es an dieser Stelle aus, einen beliebigen
Punkt auf dem NOP-Sled zu treffen. Das ist besonders hilfreich, weil der Compiler mit dem das
verwundbare Programm übersetzt wird möglicher Weise einige Optimierungen durchführt, die die
exakte Positionsbestimmung des ersten Befehls erschweren können. Aus demselben Grund ist es
üblich die gewünschte Return-Adresse mehrfach zu wiederholen.
Besondere Aufmerksamkeit muss man der Ausrichtung der eingeschleusten Return-Adresse widmen.
Das bedeutet man muss darauf achten, dass das erste Byte der selbst geschriebenen Return-Adresse
auch wirklich über das erste Byte der alten Return-Adresse geschrieben wird. Ohne Verwendung
eines Debuggers, lässt sich die korrekte Ausrichtung am einfachsten durch Probieren finden. Dabei
sollten maximal vier Versuche nötig sein, da eine Adresse bei 32-Bit-Systemen nur 4 Byte groß ist und
es somit nur vier Möglichkeiten gibt.
Die absolute Adresse des Puffers wird meist mittels eines Debuggers ermittelt und auf x86-Systemen
in Little-Endian-Anordnung eingebgeben. Interessant hierbei ist auch, dass der Stack eines Prozesses
immer an derselben Adresse beginnt, was bedeutet, dass auch hier Probieren zum Ziel führen kann.
Alternativ können zur Positionsbestimmung von Buffern auch Formatstring-Verwundbarkeit
verwendet werden [ 5 ] . Auf Formatstrings wird in dieser Arbeit jedoch nicht eingegangen, weil sie
nicht Teil des Themas "Buffer-Overflows" sind.
Insgesamt wird dem auszunutzenden Programm die in Abbildung 3-4 dargestellte Kombination
übergeben. Diese Kombination aus NOP-Sled, Payload3 und widerholter Return-Adresse, wird häufig
als Angriffsvektor bezeichnet.
NOP-sledRET
(mehrfach wiederholt)Payload
Abbildung 3-4: Angriffsvektor
Bleibt noch zu erwähnen, dass die Speichermenge die für den Payload zur Verfügung steht, durch die
Position der Return-Adresse begrenzt ist. Dieses Problem lässt sich aber durch einen relativen
Sprung, nach den Speicherbereich mit der Return-Adresse umgehen. [ 10 ]
2 NOP-Sled/NOP-Sledge: Übersetzt: NOP-Schlitten. Das bedeutet, eine Folge von NOPs führen direkt, ohne jede weitere
Funktion, zu dem nächsten „richtigen“ Maschinenbefehl. Beispielsweise dem ersten Befehl des Sehellcodes.
3 Der Payload/Shellcode besteht aus Maschinencode. Er ist der Teil des einzuschleusenden Codes, der die eigentliche
Funktionalität beinhaltet. Häufig werden die Begriffe Payload und Shellcode als Synonym verwendet. Details zu Shellcode werden in dem Kapitel 3.2 behandelt
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 24 -
Beispiel: stack-overflow.c im Quellcode-Ordner "Kapitel-3-1-4_stack-overflow"
Eine Variante des Programms auth_overflow.c ist unter dem Namen stack-overflow.c Quellcode-
Archiv zu finden. Dieses Programm bekommt seine Eingabe dabei nicht als Parameter, sondern liest
von einer Datei. Außerdem wird nicht die Funktion strcpy() verwendet, sondern die Funktion
memcpy(). Für diese Modifikationen gibt es zwei Gründe:
1. Mit der Windows-Eingabeaufforderung ist es nicht ohne weiteres möglich einem Programm,
per Parameter Zeichen zu übergeben, die nicht "druckbar" sind. Da das auf die meisten
Maschinenbefehle zutrifft, ist ein einfaches Einschleusen von Code über die Kommandozeile
nicht möglich. Abhilfe würde an dieser Stelle das Programm cat4 schaffen mit dem man die
Eingabe an das Programm umleiten kann. Cat ist aber nicht Bestandteil von Windows. Zudem
besteht das Problem der Parameterübergabe mit nichtdruckbaren Zeichen auch in den
meisten Debuggern. Aus diesem Grund liest das Demo-Programm aus einer Datei.
2. Wie in dem Abschnitt 2.1 beschrieben, liegt der für das Programm selbst zur Verfügung
stehende Speicher im niederen Adressbereich. Deshalb ist die Wahrscheinlichkeit sehr hoch,
dass der Buffer in dem der eingeschleuste Code liegt in einem Adressbereich liegt, der mit
zwei führenden Nullen (0x00AABBCC) beginnt. Das bedeutet, dass strcpy() die
Speicheradresse nicht mehr kopiert. Es gibt eine Reihe von Möglichkeiten den
eingeschleusten Code trotz dieses strcpy()-Problems zur Ausführung zu bringen
(beispielsweise "return to libc"). Um das Beispiel einfach zu halten wird dieses Problem an
dieser Stelle durch die Verwendung von memcpy() umgangen.
Trotz dieser zwei Vereinfachungen, bleibt das demonstrierte Prinzip in allen Fällen gleich: Den
Angriffsvektor einschleusen und den Maschinencode zur Ausführung bringen.
Ein funktionierender Angriffsvektor zu dem Programm stack-overflow.c ist ebenfalls im Quellcode-
Archiv zu finden. Dabei wird der Angriffsvektor mittels eines Perl-Skripts generiert. Der hierbei
verwendete Payload startet hierbei nichts weiter als den Windows-Taschenrechner clac.exe. Details
zur Erstellung von Payload folgt in dem Abschnitt 3.2.
4 cat ist ein Kommandozeilen-Tool aus der UNIX-Welt, mit dem sich unter anderem sehr einfach Eingaben aus einer Datei
lesen lassen. Das Tool gibt es auch für Windows
Tools-Hinweis
Die felxibelste Möglichkeit einen Angriffsvektor zu erstellen ist mit der Programmiersprach Perl.
Perl gibt es auch für Windows: Toolsverzeichnis IV
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 25 -
Gekürzte Ausgabe des Programms stack-overflow.exe
~~~ nachher ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dump(password_buffer...);
0012FA48: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 | ................
0012FA58: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 | ................
0012FA68: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 | ................
0012FA78: 29 c9 83 e9 dd d9 ee d9 74 24 f4 5b 81 73 13 b3 | ).......t$.[.s..
0012FA88: 87 5d 85 83 eb fc e2 f4 4f 6f 19 85 b3 87 d6 c0 | .]......Oo......
0012FA98: 8f 0c 21 80 cb 86 b2 0e fc 9f d6 da 93 86 b6 cc | ..!.............
0012FAA8: 38 b3 d6 84 5d b6 9d 1c 1f 03 9d f1 b4 46 97 88 | 8...]........F..
0012FAB8: b2 45 b6 71 88 d3 79 81 c6 62 d6 da 97 86 b6 e3 | .E.q..y..b......
0012FAC8: 38 8b 16 0e ec 9b 5c 6e 38 9b d6 84 58 0e 01 a1 | 8.....\n8...X...
0012FAD8: b7 44 6c 45 d7 0c 1d b5 36 47 25 89 38 c7 51 0e | .DlE....6G%.8.Q.
0012FAE8: c3 9b f0 0e db 8f b6 8c 38 07 ed 85 b3 87 d6 ed | ........8.......
0012FAF8: 8f d8 6c 73 d3 d1 d4 7d 30 47 26 d5 db f9 85 67 | ..ls...}0G&....g
0012FB08: c0 ef c5 7b 39 89 0a 7a 54 e4 3c e9 d0 a9 38 fd | ...{9..zT.<...8.
0012FB18: d6 87 5d 85 50 fa 12 00 50 fa 12 00 50 fa 12 00 | ..].P...P...P...
0012FB28: 50 fa 12 00 50 fa 12 00 50 fa 12 00 50 fa 12 00 | P...P...P...P...
0012FB38: 50 fa 12 00 50 fa 12 00 50 fa 12 00 50 fa 12 00 | P...P...P...P...
0012FB48: 50 fa 12 00 50 fa 12 00 50 fa 12 00 50 fa 12 00 | P...P...P...P...
0012FB58: ff | .
dump(&auth_flag, 4);
0012FA44: 00 00 00 00 | ....
Erklärung:
1. Der Wert 90 Hex entspricht einem NOP
2. Der rot markierte Bereich ist der Maschinencode zum Starten von calc.exe
3. Am Schluss folgt die mehrfach wiederholte Return-Adresse
3.1.5 Exception Handler-basierende Angriffe
Die Programmiersprache c bietet von sich aus keinerlei Möglichkeiten, Ausnahmen im
Programmablauf abzufangen. Eine solche Ausnahme ist beispielsweise eine Division durch Null. Mit
C++ wurde dieser Missstand behoben und es ist somit, durch Elemente der Programmiersprache,
möglich eine Ausnahmebehandlung durchzuführen. Das bedeutet, dass ein Programm, das eine
Division durch null durchführt, nicht mehr zwangsläufig abstürzt, sondern durch eine geeignete
Ausnahmebehandlung weiterlaufen kann. [ 11 ]
Microsoft hat für die Programmiersprache c eigene Elemente eingebracht, mit denen eine
Ausnahmebehandlung möglich wird: __try und __except
Diese Art der Ausnahmebehandlung nennt sich Structured Exception Handling (SEH). Im Unterschied
zu c++ wird die Art der Ausnahme mittels eines unsigned int ermittelt, während in c++ anhand des
Klassen-Typs unterschieden wird. [ 11 ] [ 12 ]
NOP-sled
RET
(mehrfach wiederholt)
Payload
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 26 -
Beispiel: Strukturierte Ausnahmebehandlung (SEH) - Division durch Null
#include <stdio.h>
int MyExceptionHandler(void);
int main(int argc,char *argv[]){
int a = 1000, b = 0, c = 0;
if(argc != 2){
printf("Divisor als Parameter uebergeben\n");
exit(0);
}
b = atoi(argv[1]);
/* Falls eine 0 als erster Programmparameter übergeben wird, wird
* eine EXCEPTION_INT_DIVIDE_BY_ZERO ausgelößt */
__try {
c = a / b;
printf("Ergebnis der Division %i / %i = %i\n", a, b, c);
} __except ( MyExceptionHandler() ){}
printf("Programm beendet sich\n");
return 0;
}
/* return 1, damit die Exception nicht and das
* Betriebsystem weitergereicht wird */
int MyExceptionHandler(void){
printf("Exception.. Ausnahme abgefangen und als behandelt markiert");
return 1;
}
SEH lässt sich im Zusammenhang mit Buffer Overflows nutzen, um eingeschleusten Code zur
Ausführung zu bringen. Dabei macht sich der Angreifer den Umstand zu nutze, dass die
Funktionsadresse der Funktion zur Ausnahmebehandlung, wie in Abbildung 3-5 zu sehen ist, auf dem
Stack gespeichert wird.
Quellcode: Kapitel-3-1-5_exception\exception.c
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 27 -
Beispielhaftes
Stackframe
Wa
ch
stu
msrich
tun
g
Gespeicherte Register der
aufgerufenen Funktion
Lokale Variablen
Stack Frame Pointer (SFP)
Return Adresse (RET)
Parameter
0000000h
(Kleine Adressen)
FFFFFFFFh
(Große Adressen)
Ove
rflo
wrich
tun
g
...
Pointer zur nächsten
SEH-Funktion
Pointer zur SEH-Funktion
Abbildung 3-5: Beispielhaftes Stackframe unter Verwendung von SEH [ 13 ]
Wie bei den klassischen Stack-basierenden Buffer Overflows, wird von einem verwundbaren Buffer
ausgehend, diese Funktionsadresse im Speicher überschrieben. Der Unterschied besteht lediglich
darin, dass die Behandlung der Ausnahme veranlasst werden muss, z. B. mit einer Division durch
Null. [ 14 ]
Interessant ist hierbei, dass jedes Programm mindestens einen, automatisch erstellten SEH besitzt,
den der main()-Routine.
Im Quellcode-Archiv findet sich im Ordner "Kapitel-3-1-5_exception_exploit" ein vollständiges
Beispiel, wie sich SEH unter Windows praktisch ausnutzen lässt.
3.1.6 Heap-basierende Angriffe
Heap-basierende Angriffe funktionieren prinzipiell genauso, wie alle anderen Buffer-Overflows auch.
Es werden Daten überschrieben, die nach einem verwundbaren Puffer im Speicher liegen. Der
einzige Unterschied besteht darin, dass, verglichen mit den anderen Datensegmenten, im Heap
andere Daten gespeichert sind.
Folgende Daten finden sich vermehrt bzw. nur auf dem Heap:
1. Nutzdaten. Beispielsweise die Variable auth_flag aus dem Abschnitt 3.1.2 (gibt es auch auf
beim Stack)
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 28 -
2. Daten die den Programmablauf steuern und vom Programmierer bewusst angelegt wurden
(auch auf dem Stack vorhanden, aber selten)
3. Daten die den Programmablauf steuern und vom Compiler automatisch angelegt werden
4. Daten die der Speicherverwaltung dienen. Beispielsweise das Windows-Heap-Management
Den Punkt "Nutzdaten", wurde bereits in dem Abschnitt 3.1.2 ausführlich behandelt und da an dieser
Stelle keine wesentlichen Unterschiede existieren, wird an dieser Stelle nicht näher darauf
eingegangen.
Der zweite Punkt ist vom prinzipiellen Vorgehen bereits bekannt.
Der Punkt Nummer Drei bietet interessante Möglichkeiten, ist in der Praxis jedoch kaum anzutreffen.
Punkt Nummer Vier hat in den letzten Jahren deutlich an Bedeutung gewonnen und ist vor allem im
Zusammenhang mit dem Windows-Heap-Management interessant. Deshalb wird im Folgenden das
prinzipielle Vorgehen bei Angriffen auf das Windows-Heap-Management erläutert.
Angriffe auf das Windows-Heap-Management
Wie bereits in dem Abschnitt 2.1.3 beschrieben, ist ein Heap, der mit HeapCreate()erzeugt wird,
durch eine Reihe von Listen organisiert. Wird mit der Funktion HeapAlloc() ein Speicherbereich
angefordert, so wird von der Heapverwaltung ein passendes Stück Speicher gesucht. Dieses Stück
Speicher wird, unmittelbar vor dem nutzbaren Bereich, mit einem Header versehen, der
Informationen für die Heapverwaltung enthält. [ 15 ] [ 8 ]
Bei Angriffen auf die Heapverwaltung ist es das Ziel, die Headerinformationen derart zu
manipulieren, dass eine begrenzte Menge an Daten an eine beliebige Stelle im Speicher geschrieben
werden kann. Hierbei macht sich der Angreifer zunutze, dass die Headerinformationen Pointer
enthalten, die zur Verkettung der Listen und zur Referenzierung des Nutzspeichers dienen. Beim
Anfordern und Freigeben von Speicher werden die Header teilweise kopiert und unter bestimmten
Bedingungen in einer doppelt verketteten Liste gespeichert. Zur Bestimmung der jeweiligen
Nachbarelemente werden die Headerinformationen verwendet. Somit ist es möglich, durch gezieltes
Überschreiben der entsprechenden Pointer, einen wahlfreien Schreibzugriff mit einer Datenmenge
von 4 Bytes zu erreichen. Dieser Vorgang lässt sich prinzipiell beliebig oft wiederholen, meist ist
jedoch eine Menge von 4 Bytes vollkommen ausreichend, da dies die Größe eines Pointers ist. Somit
lässt sich beispielsweise im Process Execution Block (PEB) ein Pointer überschreiben. Hier bietet sich
der Pointer auf die Funktion ExitProcess() an, die vor dem endgültigen Beenden des Prozesses
ausgeführt wird. Durch das Überschreiben des ExitProcess()-Pointers kann eingeschleuster Code
durch das Beenden des Programms zur Ausführung gebracht werden. [ 15 ] [ 8 ] [ 16 ] [ 17 ] [ 18 ] [
16 ] [ 19 ]
In der Praxis gibt es eine Vielzahl von Variationen der eben beschriebenen Methode. Hierbei haben
jedoch alle Varianten die Gemeinsamkeit, dass sie durch gezieltes Manipulieren der Header, Code zur
Ausführung bringen.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 29 -
Einen besonderen Reiz haben vor allem die Varianten, die es dem angegriffenen Programm
ermöglichen weiter zu laufen, indem sie die beschädigten Heapstrukturen wieder mit gültigen
Werten reparieren. Ein weiterer Grund für die gestiegene Popularität von Angriffen auf das
Heapmanagement sind vor allem Mechanismen, die zum Schutz des Stacks eingeführt wurden und
den Heap so zum schwächsten Glied der Kette werden ließen. Details zu aktuellen
Schutzmechanismen des Stacks werden im Kapitel 4.6 behandelt.
3.2 Shellcode und Payload
Die beiden Begriffe Shellcode und Payload werden heutzutage häufig als Synonym verwendet. Streng
genommen ist der Shellcode jedoch eine spezielle Form des Payloads:
1. Der Payload an sich ist der Teil des Angriffsvektors, der die eigentliche Funktionalität
beinhaltet, also beispielsweise das Starten des Windows-Taschenrechners.
2. Der Shellcode ist streng genommen ein spezieller Payload, der eine Shell
(Eingabeaufforderung) startet, mit der der Angreifer interagieren kann.
In dieser Arbeit wird häufig ebenfalls der Begriff "Shellcode", anstelle des historisch korrekten
Begriffes verwendet. Die Begründung ist die Tatsache, dass der Begriff Shellcode einen höheren
Wiedererkennungswert bietet und selbst in Printmedien gebräuchlicher ist.
Da das Thema Shellcode, bei sorgfältiger Behandlung, den Umfang dieser Arbeit bei weitem
sprengen würde, wird im Folgenden nur stichpunktartig auf Anforderungen an Shellcode
eingegangen.
3.2.1 Anforderungen an Shellcode
Anforderungen an die Darstellung des Shellcodes :
1. Zeichensatz: Shellcode unterliegt einigen Einschränkungen bezüglich der verwendbaren
Zeichen. Beispielsweise darf in Shellcode der durch strcpy() eingeschleust wird, nicht das
Zeichen 0x00 vorkommen, weil strcpy() nur bis zu diesem Zeichen kopiert. Außerdem werden
die eingegebenen Zeichen häufig von dem angegriffenen Programm geprüft und z. B. nur
druckbare Zeichen verarbeitet.
2. Kompatibilität: Die Kompatibilität von Shellcode ist unumgänglich auf eine Art der
Speicheranordnung beschränkt: entweder Big- oder Little-Endian.
3. Kodierung: Soll eine Funktion angegriffen werden die eine UTF-8 kodierte Zeichenfolge
erwartet, so muss außer der Big- und Little-Endian-Anordnung außerdem eine bestimmte
Reihenfolge von Zwei-Byte-Paaren eingehalten werden. [ 20 ]
4. Kompaktheit: Häufig ist die Menge an einschleusbaren Zeichen beschränkt.
5. Unentdeckt bleiben: Unter Umständen passiert der Shellcode auf dem Weg zum Ziel
Intrusion Detection Systeme (IDS), die die übertragenen Daten auf bekannte Schad-
Signaturen hin überprüfen.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 30 -
Anforderungen an die Logik des Shellcodes:
1. Betriebssystemabhängig: Da die meisten Betriebssysteme einen grundliegend
unterschiedlichen Zugriff auf Systemfunktionen haben, muss der Shellcode meistens
Betriebssystemspezifisch sein.
2. Behandlung der Anwendung: Unter bestimmten Umständen hat man die Möglichkeit, das
angegriffene Programm weiter laufen zu lassen und so die Wahrscheinlichkeit, das der
Angriff entdeckt wird stark zu reduzieren.
3.2.2 Besonderheiten von Windows-Shellcode
Verglichen mit Shellcode der unter Linux lauffähig ist, gibt es für Windows-Shellcode eine Reihe von
Besonderheiten
1. Windows-Shellcode ist größer als Linux-Shellcode [ 21 ]
2. Keine 1-zu-1-Abbildung der Bibliotheksfunktionen des Betriebssystems zu den Systemcalls auf
Kernelebene [ 21 ]
3. Die verwundbaren Buffer liegen meist in einem Speicherbereich, der mit 0x00… beginnt und
somit ein nicht verwendbares Zeichen darstellt.
3.2.3 Was möglich ist
Je nachdem welchen Anforderungen (siehe 3.2.1) der eingeschleuste Code unterliegt, ergeben sich
unterschiedliche Möglichkeiten:
1. Erweitern der Rechte durch angreifen von lokalen Prozessen die mit umfangreicheren Privilegien
ausgestattet sind.
2. Nachladen von Systemfunktionen, falls der Prozess eine für den Angriff wichtige Dll-Funktion5
nicht geladen hat, kann man diese Dll selbst nachladen.
3. Nachladen von Code, falls der eingeschleuste Code in seiner Größe beschränkt war, hat man die
Möglichkeit z. B. aus dem Internet Code nachzuladen. [ 21 ]
Wenn man davon ausgeht, dass man die Möglichkeit hat, eine unbegrenzte Menge an
eingeschleusten Code, mit Administrator-Rechten auszuführen, dann hat man praktisch keine
Einschränkungen mehr. Man kann beispielsweise:
1. Ein lokales Benutzer-Konto erstellen (Local Access)
2. Einen Prozess starten, der beliebige Befehle über das Netzwerk ausführt (Remote Access)
3. Einen Keylogger installieren, der sämtliche Aktivitäten des Benutzers aufzeichnet, inklusive
Tastatur- und Mausinteraktion (Spionage)
5 Dynamic Link Library (Dll)
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 31 -
3.2.4 Abstraktes Beispiel: Portbind Shellcode für Windows
An dieser Stelle folgt ein eine allgemeine Beschreibung, der Vorgehensweise, zum Starten einer
Remote-Shell: [ 21 ]
1. Suchen der Datei kernel32.dll
2. Auflösen der Symbole GetProcAddressA(), LoadLibraryA() sowie ExitProcess()
3. Laden der Winsock Bibliothek ws2_32.dll
4. eine Shell an einen TCP-Port binden
4.1. Socket erzeugen
4.2. Socket an Port binden
4.3. Auf dem Port auf eingehende Verbindung warten
4.4. Verbindung akzeptieren
5. Kommandointerpreter starten
6. Den Elternprozess sauber beenden oder die beschädigten Strukturen reparieren
Um nicht zu sehr vom eigentlichen Thema, den Buffer Overflows, abzukommen, wird an dieser Stelle
nicht weiter auf das Themengebiet Shellcode eingegangen. Interessierten sei [ 21 ] für weitere
Informationen empfohlen.
Es folgt nun eine Vorstellung der Verschiedenen Mechanismen in Windows, die dazu dienen den
Schaden durch Buffer-Overflows so gering wie möglich zu halten.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 32 -
4 Das Sicherheits-Ensemble von Windows und seine Schwachstellen
Dieses Kapitels hat es zum Ziel, die Frage nach dem betitelten Stack- und Heap-Overflow-Schutz bei
Windows XP und Windows Vista zu klären. Nicht eingegangen wird auf weitere nützliche Funktionen
zur Erhöhung der Sicherheit, die nichts direkt mit Buffer-Overflows zu tun haben.
Die vorhergegangenen beiden Grundlagenkapitel, haben sich im Wesentlichen damit beschäftigt,
welche Bedingungen, unter früheren Windowsversionen, gegeben sein mussten, um einem Buffer-
Overflow erfolgreich auszunutzen.
Dieses Kapitel beschäftigt sich zu Beginn damit, wie sich der Schaden, eines unter fremder Kontrolle
stehenden Programms, einschränken lässt und welche neuen Ansätze mit Windows Vista verfolgt
werden (bis einschließlich Kapitel 4.2).
Anschließend werden Methoden von Windows XP und Vista analysiert und bewertet, die es zum Ziel
haben, Angriffe mittels Buffer-Overflows so früh wie möglich zu entschärfen.
4.1 Das Windows-Zwei-Schichten-Modell
Den grundlegendsten Schutzmechanismus der Windows-Architektur bildet das Zwei-
Schichtenmodell.
Unter Windows ist die gesamte Funktionalität in zwei unterschiedlich privilegierte Bereiche
eingeteilt: [ 4 ]
Kernel-Mode (Ring 0): Der Modus mit den höchstmöglichen Privilegien – Keine
Einschränkungen beim Zugriff auf die Ressourcen des Kernels
User-Mode (Ring 1): Eingeschränkter Modus – Beim Zugriff auf Systemressourcen muss eine
ganze Abfolge von Funktionen abgearbeitet werden, die vom Ring0 als Services zur
Verfügung gestellt werden.
Häufig werden User- und Kernel-Mode wie in Abbildung 4-1 grafisch dargestellt. Dabei soll
symbolisiert werden, dass auf die innen liegenden Funktionen und Ressourcen nur über die
verbindende Schicht zugegriffen werden kann.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 33 -
Abbildung 4-1: Windows-Zwei-Schichten-Modell [ 4 ]
Im Ring0 finden sich vorrangig Gerätetreiber und Systemfunktionen. Im Ring1 hingegen findet sich
alles Übrige, z. B. ein Browser oder ein FTP-Server.
Schafft es ein Angreifer direkt im Ring0 einen Programmierfehler für sich zu nutzen, so stehen im
praktisch keine Hindernisse mehr im Weg. Allerdings erfordern Angriffe auf dieser Ebene sehr
spezifisches Detailwissen, das äußerst selten offen zugänglich ist. Dies ist auch der Grund dafür, dass
Angriffe auf den Ring0 verhältnismäßig selten vorkommen. Ein Beispiel für einen erfolgreichen
Angriff auf den Gerätetreiber diverser W-LAN-Chips ist der Angriff von Jon Ellch (Pseudonym: Jonny
Cache)[ 22 ] . [ 4 ] [ 23 ]
Meist ist es aus dem oben genannten Grund einfacher, eine verwundbare Anwendung im Ring1
anzugreifen. Jedoch haben Prozesse im Ring1 einen Prozess-Kontext, der einen
rechtebeschreibenden Token beinhaltet. Näheres dazu im nächsten Abschnitt.
4.2 Zugriffsrechte, Authentifizierung und Access Token
Meldet sich ein Benutzer an einem Windows-System an, so bekommt er vom Local Security Authority
Subsystem Service (LSA) ein Access Token zugeteilt. Dieser Token besteht aus einem Security
Identifier (SID), der zu seinem Benutzerkonto gehört, und einigen weiteren SIDs, die zu seinen
Gruppen gehören in denen er Mitglied ist. Eine solche SID ist eine 48 Bit lange Nummer, die
domainweit einzigartig ist. Außerdem enthält der Token, falls definiert, eine Liste von nicht erlaubten
SIDs und eine Liste mit Privilegien, die zu den jeweiligen SIDs gehören. Privilegien sind z. B. das Recht
einen Treiber zu laden (SeLoadDriverPrivilege) oder das Recht den Computer herunterzufahren
(SeShutdownPrivilege).[ 4 ] [ 24 ]
Ring1(User-Mode)
Ring0(Kernel-Mode)
Kernel
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 34 -
Alle Ressourcen, auf die ein Benutzer theoretisch zugreifen kann, haben eine so genannte
Discretionary Access Control List (DACL)6. Praktisch wird der Zugang auf die Ressource durch LSA
reglementiert. Das bedeutet, der Zugriff ist nur erlaubt, wenn eine der SIDs aus dem Token des
Benutzers in der DACL-Liste unter dem entsprechenden Privileg (Lesen, Schreiben usw.) zu finden ist.
[ 4 ]
Nach [ 4 ] lässt sich zur besseren Übersicht eine Einteilung in Subjekte und Objekte vornehmen
1. Subjekte: Einheiten, die Aktionen durchführt – unter Windows sind das Prozesse
2. Objekte: Sind die Empfänger einer Aktion – unter Windows zugriffsgeschützte Objekte mit
zugehörigen DACL wie z. B. Dateien und Registry-Einträge
4.2.1 Rechte von Prozessen unter Windows
Startet ein am System angemeldeter Benutzer einen Prozess, so wird in dem Prozess-Kontext der
Token des Benutzers gespeichert. Fortan darf der Prozess (Subjekt) auf alle Ressourcen (Objekte)
zugreifen, auf die auch der Benutzer durch seinen Token Zugriff hat.
Ist nun unter Windows XP ein Administrator am System angemeldet und startet den Internet
Explorer, so hat der Browser denselben Token wie der Administrator. Surft der Administrator nun
beispielsweise über eine Seite, die den populären Animated-Cursor Exploit7 eingebaut hat, so stehen
dem Angreifer keinerlei Hindernisse im Weg. Er hat dank des hoch-privilegierten Token, mit der SID
des angemeldeten Administrators, vollständigen Zugriff auf das gesamte System.
Mit Windows 2000 wurde die Möglichkeit eingeführt, einen Kindprozess/Thread mit einem
eingeschränkten Token zu starten. Der eingeschränkte Token kann, ausgehend von dem Original-
Token, wie folgt definiert werden: Privilegien entfernen, SIDs entfernen, nicht erlaubte SIDs
hinzufügen. Wurde ein Thread mit einem eingeschränkten Token gestartet, so ist er an die neuen
Einschränkungen gebunden. Allerdings ist es möglich dem Thread mit dem eingeschränkten Token,
wieder den uneingeschränkten Token zuzuweisen. Weil diese Möglichkeit besteht, empfiehlt es sich
die API-Funktion CreateProcessAsUser( ) zu verwenden, so dass diese Möglichkeit nicht mehr
besteht. [ 24 ]
Mit Windows Server 2003 wurde es möglich die Privilegien eines Prozess-Token dauerhaft
einzuschränken. Diese Möglichkeit ist aber ungleich der des eingeschränkten Token, da hier der
Prozess dauerhaft seine eigenen Privilegien beschneidet. Alle von ihm erzeugten Kindprozesse erben,
nach demselben Prinzip wie bei Windows 2000, den Token des Elternprozesses, z. B. einen, in den
Privilegien eingeschränkten. Die Möglichkeit die SIDs des Token zu modifizieren besteht hier nicht.[
24 ]
6 DACL wird in der Literatur häufig auch ohne das führende D, nur als Access Control List (ACL), verwendet.
Außerdem wird häufig der Ausdruck Security Descriptor als Synonym verwendet. 7 Animated-Cursor Exploit: http://www.securityfocus.com/advisories/7814
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 35 -
4.2.2 Windows Service Hardening
Da auch Windows-Services nichts weiter wie Prozesse sind, haben auch sie einen Token über den sie
im Betrieb ihre Berechtigungen erhalten. Für einen Angreifer sind damit die Standard-Services einer
Windows-Installation besonders interessant, weil sie aufgrund ihrer Funktionalität ständig laufen und
typischer Weise Systemfunktionen ausführen, die hohe Privilegien benötigen.
Mit Windows Server 2003 wurden zwei neue Service-Konten eingerichtet die den bisher
übermächtigen LocalSystem entlasten sollten: LocalService und NetworkService. Dabei sind die
beiden neuen Konten in den Rechten derart beschnitten, dass viele Services nicht mit ihnen arbeiten
können und deshalb den bisherigen LocalSystem weiterhin verwenden.[ 4 ]
Zur verbesserten Schadensbegrenzung wurde bei Windows Vista eine Reihe von Maßnahmen
eingeführt, die ein erheblich granulareres Rechtemanagement wie bisher ermöglichen:
1. Service-spezifische SIDs: Jeder Service hat eine eigene SID. Sinnvoller Weise bekommen nur
diejenigen Objekte in ihrer DACL die SIDs des speziellen Services eingetragen, die sie auch
wirklich benötigen.[ 4 ]
2. Eingeschränkte SIDs: Die RESTRICTED-SID kennzeichnet einen Prozess, der ein
eingeschränktes Token enthält. [ 25 ] (nicht auf Services beschränkt)
3. Reduzierte Privilegien für Services: Überflüssige Privilegien, wie das Debugging Privileg
wurden den Diensten generell entzogen [ 4 ]
4. Session 0 Isolation: Unter Windows Server 2003 und früheren Versionen, war es unter
Umständen möglich seine Privilegien durch Angriffe auf Services mit höheren Privilegien
innerhalb derselben Session zu erweitern. Diese Problem wird dadurch entschärft, dass nur
noch Services in der Session 0 laufen und alle vom User gestarteten Anwendungen in
eigenen Session (1 und höher) gestartet werden. [ 26 ] [ 27 ]
5. UAC: siehe nächster Abschnitt (nicht auf Services beschränkt)
4.2.3 Rechte von Prozessen unter Windows Vista: UAC
Es ist zwar bekannt, dass es sich nicht empfiehlt mit Administratorrechten im Internet zu surfen, die
Konsequenz als normaler Benutzer an einem System zu arbeiten, haben jedoch nur wenige
Anwender gezogen. Der Hauptgrund hierfür ist die mangelnde Unterstützung seitens Windows. So ist
es bis zu der Version "Vista" nötig gewesen, eine Druckerinstallation oder das Stellen der Uhrzeit mit
Administratorrechten zu erledigen.
UAC steht für User Account Control und soll das Arbeiten als eingeschränkter Benutzer erleichtern.
Dazu fragt Windows Vista den Benutzer, falls nötig, automatisch nach dem Passwort, für das
Benutzerkonto, dass zum ausführen der Aktion nötig ist. Dabei ist die Interaktion mit den BS solange
gesperrt, bis der Benutzer auf die Anfrage reagiert hat.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 36 -
Im Detail verwendet UAC eine neue Technik namens Mandatory Integrity Control (MIC). MIC ist eine
Erweiterung für die DACLs um sogenannte Integrity Level (IL). Gespeichert werden diese neuen
Rechte in den Mandatory ACLs (MACL).
Als IL wurden folgende vier Möglichkeiten eingeführt:
Low
Medium (als Standard)
High
System
Jeder Prozess hat in seinem Token zusätzlich ein IL gespeichert. Will ein Prozess mit einem niedrigen
IL auf eine Ressource mit einem höheren IL zugreifen, so ist die oben beschriebene Interaktion mit
dem Benutzer vonnöten.
Damit UAC funktioniert wurde der LSA modifiziert, so dass es jetzt zwei Arten von Token gibt:
einen gefilterten: ohne erweiterte Rechte
einen gelinkten: mit allen Originalrechten
Außerdem muss der Programmierer im Manifest seiner Anwendung das benötigte IL angeben.
Standardmäßig werden alle Prozesse mit dem gefilterten Token ausgeführt. Der gelinkte Token wird
nur verwendet, wenn eine Applikation, aufgrund des Eintrags im Manifest, nach erweiterten Rechten
fragt. Dieses Verhalten führt auch dazu, dass selbst ein angemeldeter Administrator zuerst vom
System um Erlaubnis gefragt wird, wenn die Aufgabe ein höheres IL erfordert.
Als Beispiel für eine sinnvolle Anwendung des UAC kann der Internet Explorer betrachtet werden:
Der Internet Explorer läuft per Voreinstellung mit Low-IL, was bedeutet, er kann nur auf
Objekte mit LOW-IL SIDs zugreifen. Standardmäßig sind das nur
%USERPROFILE%\AppData\LocalLow und der Registry-Key HKCU\Software\AppDataLow. Auf
alle anderen Systemressourcen hat der Prozess des IE keinen Zugriff, was die Sicherheit stark
erhöht.
Wird der IE mit aktivierten UAC betrieben, so wird diese Konstellation häufig als Protected Mode IE
(PMIE) oder auch Low Rights Internet Explorer (LoRIE) bezeichnet.
UAC ist die für den Benutzer offensichtlichste und auch eine der nützlichsten Sicherheitsmaßnahmen
zur Schadensbegrenzung. Allerdings empfinden viele Benutzer die ständige Nachfrage nach
erweiterten Rechten als störend. Außerdem funktionieren nicht alle Programme einwandfrei mit
UAC. Diese zwei Kritikpunkte führen dazu, dass viele Benutzer UAC Systemweit deaktivieren, was den
gesamten Nutzen hinfällig macht.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 37 -
4.3 PatchGuard
PatchGuard wurde von Microsoft entwickelt und hat es zum Ziel Software von Drittherstellern daran
zu hindern Änderungen am Kernel vorzunehmen. Dadurch soll potentiell gefährlicher Software
erschwert werden sich einzunisten.
Eingeführt wurde PatchGuard mit den Windows-Versionen Server 2003 mit SP1 (64-Bit) und XP
Professional x64. Eine Portierung auf die x86-Versionen ist derzeit nicht geplant. [ 28 ]
Da PatchGuard eine Reihe von Unzulänglichkeiten besitzt, die das Umgehen des Schutzes relativ
einfach machen, ist der tatsächliche Nutzen in Bezug auf Schadsoftware fraglich. Häufig wird sogar
behauptet, PatchGuard sei lediglich ein Instrument von Microsoft, um die Dritthersteller dazu zu
zwingen, saubereren und stabileren Code zu schreiben. [ 29 ]
Viel Kritik an dem System gab es auch von den Herstellern von Sicherheits-Software, wie Anti-Viren-
Software und Rootkit-Detection-Tools, da sich diese Produkte häufig an den, durch dieses System
nicht mehr erreichbaren Stellen, eingenistet haben, um so von einem möglichst uneingeschränkten
Punkt aus operieren zu können. [ 29 ]
Eine umfassende Analyse der neusten Version (v3) von PatchGuard ist im Internet unter [ 28 ] zu
finden.
4.4 Process Exection Block (PEB) Randomization
Überblick
Mit Windows XP SP28 wurde eine Funktionalität namens PEB-Randomization eingeführt. Ihr Ziel ist
es, Angriffe zu erschweren, die zur Codeausführung PEB-Einträge manipulieren. Im Process Exection
Block (PEB) sind vor allem für Angriffe interessante Funktions-Pointer gespeichert, wie ein Pointer auf
die Funktion ExitProcess().
Funktionsweise
Beim Programmstart wird die Basisadresse des PEB dynamisch gewählt. Dadurch ist ein Remote-
Exploit9, dass den PEB als Einstiegspunkt verwendet, nicht mehr zuverlässig, da die zu
überschreibende Adresse des Funktions-Pointers in dem, jetzt an einem zufälligen Ort im Speicher
liegenden, PEB gespeichert ist.
8 Funktionalität ist auch in Server 2003 SP1 / Vista vorhanden
9 Ein Remote-Exploit ist dadurch charakterisiert, dass der Angreifer entfernt über ein Netzwerk zugreift und
nicht an der Maschine selbst sitzt.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 38 -
Schwachstellen
Wie sich ein einer Untersuchung von Symantec herausstellte [ 30 ] , beschränkt sich die Anzahl der
Möglichkeiten, für die Basisadresse des PEB, auf 16. Hinzu kommt noch, dass die Adresse in 20% aller
Fälle gleich ist.
Effektiver Schutz
Die Möglichkeit verlässliche Remote-Exploits zu schreiben wurde reduziert. Die Option der Brute-
Force-Angriffe bleibt jedoch, mit einem recht hohen Erfolgsgrad, bestehen.
4.5 Heap-Schutz
Überblick
Wie in Abschnitt 3.1.6 beschrieben, kann es auch auf dem Heap zu Buffer-Overflows kommen. Um
den Schaden begrenzen zu können, wurden mit dem SP2 von Windows XP im Wesentlichen zwei
neue Features, für die von Windows bereitgestellte Heap-Verwaltung, eingeführt: [ 8 ]
Cookies auf dem Heap (vergleichbar mit denen der GS-Funktionalität des Stacks)
Plausibilitätsprüfung (sanity checking) der Headerinformationen der einzelnen Heap-
Segmente
Funktionsweise Cookies
Bei jedem Aufruf von HeapAlloc() wird vor und nach jedem Puffer auf dem Heap ein 1-Byte
großes, mit Pseudo-Zufallszahlen initialisiertes Cookie, abgelegt. [ 8 ]
Im Betrieb wird vor jedem Entnehmen eines Blocks aus der "Frei-Liste" geprüft, ob der Wert des
Cookies noch der Selbe ist, wie zum Zeitpunkt der Initialisierung. Dazu wird der Wert mit dem des
separat gespeicherten Original-Cookies verglichen. Hat sich der Wert geändert, so wird zuerst ein
HeapDestory() ausgeführt und anschließend wird eine Exception geworfen. Falls diese nicht
behandelt wird, wird das Programm beendet. [ 8 ]
Außerdem wurde ein sogenannter Low Fragmentation Heap (LFH) entwickelt, der Primär der
Performancesteigerung dient. Dieser LFH ist ebenfalls durch ein Cookie geschützt. Allerdings durch
eins der Größe 4-Byte. Durch das größere Cookie, wird das erraten des Werts und die
Wahrscheinlichkeit für erfolgreiche Brute-Force-Angriffe, stark reduziert. [ 17 ]
Funktionsweise Plausibilitätsprüfung
Die "Frei-Listen" sind als doppelt verkette Listen aufgebaut. Die Pointer, die zur Verkettung der Liste
in beide Richtungen dienen, nennen sich Blink, für das vorhergegangene Element und Flink, für das
nächste Element. [ 8 ]
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 39 -
Vor jedem Entnehmen eines Blocks aus der "Free-List" werden Blink und Flink auf ihre Plausibilität
hin geprüft. Das bedeutet, es wird geprüft, ob der der Blink aus dem Header des Folgeelements auch
tatsächlich auf das aktuelle Element zeigt. Dieselbe Prüfung wird in die andere Richtung vollzogen.
[ 8 ]
Schwachstellen
Innerhalb der Heap-Verwaltung gibt es nicht nur die oben genannten "Frei-Listen", sondern auch
Lookaside-Liste, die primär der Geschwindigkeitserhöhung dienen. Diese Listen sind nur einfach
verkette Listen und aus diesem Grund könnten die Pointer nicht auf Plausibilität hin geprüft werden..
Da aber unter XP mit SP2 der PEB und der Heap dynamische Startadressen haben, benötigt ein Brute-
Force-Angriff nach mehr wie 2000 Versuche, vorausgesetzt die Applikation läuft nach einem
fehlgeschlagenen Versuch weiter. [ 17 ]
Eine weitere Schwachstelle ist das nur 1-Byte große Cookie und die in Abschnitt 4.4 beschriebene,
schwache Zufallswahl des PEB-Speicherortes. Hinzu kommt noch die Tatsache, dass der LFH unter
Windows XP SP2 standardmäßig von keiner Applikation verwendet wird. [ 17 ]
Einen weiteren Angriff auf das Heap-Management beschreibt Alexander Anisimov. Dabei nutzt er die
Tatsache, dass die Cookie-Prüfung und die Plausibilitätsprüfung der Pointer nur unter bestimmten
Umständen stattfinden. So ist es Alexander Anisimov, unter einer Reihe von Voraussetzungen
möglich, die Blink- und Flink-Pointer derart zu manipulieren, dass ein wahlfreier Schreibzugriff von
1016 Bytes möglich ist. Die Voraussetzungen für diese Art von Angriff sind jedoch derart exotisch,
dass Microsoft an dieser Stelle keinen unmittelbaren Handlungsbedarf sieht. [ 8 ]
Eine etwas robustere Methode, als die von Alexander Anisimov, beschreibt Nicolas Falliere in [ 15 ] .
Dabei ist das Prinzip das gleiche: Es werden Blink- und Flink-Pointer überschrieben, dadurch kommt
es zu einem wahlfreien Schreibzugriff der Größe von 4-Byte. Dabei unterliegt dieser Angriff aber den
gleichen Problemen wie der Angriff, auf die einfach verketteten Lookaside-Listen. Es ist also auch hier
nur ein Brute-Force-Angriff möglich. [ 15 ]
Nach [ 31 ] werden die Lookaside-Listen in den aktuellen Windows-Versionen nicht mehr verwendet,
wodurch auf ihnen basierende Angriffe nicht mehr möglich sind.
Effektiver Schutz
Unter Windows XP mit SP1 war es aufgrund der fixen Speicherorte des PEB und des Heaps, sowie des
Fehlens, der oben beschrieben Neuerungen, möglich zuverlässige Remote-Exploits zu schreiben [ 17 ]
Mit Windows XP SP2 wurden Maßnahmen eingeführt, die das Entwickeln zuverlässiger Exploits
deutlich erschwert haben. Dennoch sind Brute-Force-Angriffe weiterhin möglich.
Hinweis: Die in diesem Abschnitt beschriebenen Schwachstellen und Verbesserungen beziehen sich
ausschließlich auf das Heap-Management von Windows. Programme die ihr eigenes Heap-
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 40 -
Management implementieren, profitieren von keiner der hier vorgestellten Neuerungen. Der Heap-
Schutz wurde von Microsoft dennoch durch andere, in diesem Dokument vorgestellte
Sicherheitsfunktionen, stark verbessert. Zu nennen sind in diesem Zusammenhang vor allem DEP,
SafeSEH und ASLR (Vista).
Insgesamt hat sich die Gefahr durch Heap-basierende Angriffe stark verringert. So dass sich Angriffe
zukünftig verstärkt auf Anwendungsdaten konzentrieren werden, die auf dem Heap liegen (frei
übersetzt nach [ 9 ] ).
4.6 Visual Studio 2005 - Der "Windows-Compiler"
Wie jedes andere Programm auch, müssen die Quelldateien eins Betriebssystems mit einem
Compiler in ausführbare Dateien übersetzt werden. Im Falle von Windows kommt bei Microsoft
Visual Studio (VS) zum Einsatz [ 32 ] .
Im Folgenden werden die, für Buffer-Overflows relevanten, Funktionen von VS 2005 vorgestellt und
mit den Verbesserungen gegenüber früher Schutzfunktionen verglichen. Der Focus wird hierbei auf
VS 200510 liegen, da dies der Compiler ist, mit dem das Betriebssystem Windows Vista übersetzt
wird. Außerdem wird der effektive Nutzen der Maßnahmen diskutiert.
4.6.1 Standard Annotation Language (SAL)
Option Beschreibung [ 33 ] Standard Windows Binaries
/analyze
(Compiler)
Codeanalyse in der Enterprise-Version - Windows Vista
Überblick
SAL dient der Compiler gestützten Qualitätssicherung des Codes und ist in den Versionen "Team
System" und "Team Edition" von VS 2005 mittels der Option /analyze verfügbar. Ihr Ziel ist es dem
Entwickler beim Übersetzen seiner Programme Hinweise zu geben, an welcher Stelle der
Programmcode möglicher weise nicht so arbeitet wie erwartet. Die Hauptaufgabe von SAL ist es
dabei, auf potentielle Buffer-Overflows aufmerksam zu machen. [ 31 ] [ 34 ]
10
In den verwendeten Quellen ist häufig die Rede von dem „Whidbey-Compiler“. Whidbey ist der Codename für Visual Studio 2005
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 41 -
Funktionsweise
Beim Erstellen des Quellcodes muss der Programmierer sogenannte Annotations in seinen Code
einbringen. Zum Beispiel die Annotation __out_ecount, wie in folgendem Beispiel zu sehen ist:
void FillString(
__out_ecount(cchBuf) TCHAR* buf,
size_t cchBuf,
char ch) {
for (size_t i = 0; i < cchBuf; i++) {
buf[i] = ch;
}
}
Quelle: [ 34 ]
Beim Kompilieren mit der /analyse Option wird VS in diesem Beispiel folgende Ausgabe erstellen:
c:\code\saltest\saltest.cpp(54) : warning C6203: Buffer overrun for non-stack buffer 'b' in
call to 'FillString': length '420' exceeds buffer size '400'
c:\code\saltest\saltest.cpp(54) : warning C6386: Buffer overrun: accessing 'argument 1', the
writable size is '200*2' bytes, but '420' bytes might be written: Lines: 53, 54
c:\code\saltest\saltest.cpp(54) : warning C6387: 'argument 1' might be '0': this does not
adhere to the specification for the function 'FillString': Lines: 53, 54
Quelle: (43)
Dabei gibt es eine Reihe weiterer Annotations, die der Programmierer in seinen Code verwenden
kann.
Da die ursprüngliche Hauptaufgabe von SAL darin bestand Buffer zu beschreiben, auf die lesend und
schreibend zugegriffen wird, versehen die Entwickler von Windows Vista alle entsprechenden
Funktionen mit Annotations, bevor das Produkt an den Kunden ausgeliefert wird. [ 34 ]
Schwachstellen
Da SAL eine Meta-Sprache ist, die zur Unterstützung von statischen Analysetools entwickelt wurde,
können dem entsprechend nur Fehler gefunden werden, die beim Kompilieren erkennbar sind.
Buffer-Overflows, die zur Laufzeit auftreten, weil die Puffergröße beispielsweise von einer
Benutzereingabe abhängt, können nicht erkannt werden. [ 34 ]
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 42 -
Effektiver Nutzen
Durch die Verwendung von SAL ist der Programmierer gezwungen sich mehr Gedanken über den
Ablauf seiner Funktionen zu machen. Zusammen mit einer konsequenten Anwendung und der
Berücksichtigung der Compilerwarnungen, hätten mit SAL bereits in der Vergangenheit einige Buffer-
Overflows vermieden werden können.
Da SAL eine automatisierte Neuerung zur Verbesserung der Code-Qualität ist, ist SAL eine effektive
Maßnahme gegen die Entstehung von Sicherheitslücken.
4.6.2 Optimierte Anordnung von Stack-Elementen (O2)
Option Beschreibung [ 33 ] Standard Windows
Binaries
/O2
(Compiler)
Erstellt schnellen Code. bei Release-Build Theoretisch alle
Überblick
Seit VS 2003 wird, beim Erstellen eins Release-Builds11, die Anordnung von Variablen (Puffern) auf
dem Stack optimiert. Dabei ist es das Ziel potentiell verwundbare Puffer an einer ungefährlicheren
Position anzulegen [ 35 ] .
Funktionsweise
Wie auf der Abbildung 4-2 zu erkennen ist, wird die lokale Variable auth_flag, vor dem potentiell
verwundbaren Puffer im Speicher angelegt. Da der Schreibzugriff immer nur in Richtung größer
werdender Adressen stattfindet, ist die Variable auth_flag in Sicherheit. Dasselbe Verfahren wird
auch bei dem Anlegen von Pointer angewendet.
11
Standardmäßig ist bei dem Profil „Release“, in Visual Studio, die Compiler-Option O2 aktiviert
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 43 -
Wa
ch
stu
msrich
tun
gpassword_buffer: char[32]
auth_flag: int
Stack Frame Pointer (SFP)
Return Adresse (RET)
Parameter
0000000h
(Kleine Adressen)
FFFFFFFFh
(Große Adressen)
Ove
rflo
wrich
tun
g
Stackframe
Ohne
Optimierung
auth_flag: int
password_buffer: char[32]
Stack Frame Pointer (SFP)
Return Adresse (RET)
Parameter
Stackframe
Mit
Optimierungint check_authentication(char *password) {
int auth_flag = 0;
char password_buffer[8];
strcpy(password_buffer, password);
if(strcmp(password_buffer, "password") == 0)
auth_flag = 1;
if(strcmp(password_buffer, "adminpw") == 0)
auth_flag = 1;
return auth_flag;
}
Quellcode
Abbildung 4-2: Optimierte Anordnung von Stack-Elementen bei VS 2003
Effektiver Schutz
Durch dieses Verfahren wird zwar der Schutz, von lokalen Variablen und Pointern, vor Buffer-
Overflows gewährt. Nicht geschützt sind diese Ziele jedoch vor Buffer-Underruns12.
Die größte Gefahr bleibt nach wie vor bestehen. Wie in der Abbildung 4-2 zu sehen ist, ist es immer
noch möglich, ausgehend von dem verwundbaren Puffer, die Returnadresse (RET) zu überschreiben
und so beliebigen Code zur Ausführung zu bringen. Kombiniert mit den im Folgenden vorgestellten
Mechanismen ergibt sich dennoch ein echter Mehrwert durch diese Optimierungen.
4.6.3 Puffer-Sicherheitsüberprüfung (GS)
Option Beschreibung [ 33 ] Standard [ 35 ] Windows
Binaries [ 32 ]
/GS
(Compiler)
Puffer-Sicherheitsüberprüfung aktiviert
seit VS 2005
teilweise bei
XP SP2, Vista
/GS-
(Compiler)
Puffer-Sicherheitsüberprüfung deaktivieren deaktiviert
seit Visual C++ 2002
teilweise bei
XP SP2, Vista
12
Zu einem Buffer-Underrun kann es beispielsweise durch fehlerhafte Pointerarithmetik kommen
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 44 -
Überblick
Hinter dem Compilerswitch /GS verbirgt sich eine Funktion namens Buffer Security Check. Das
Haupt-Ziel dieser Funktion ist es, ein Überschreiben der Return-Adresse zu erkennen und das
Programm gegebenenfalls abzubrechen. Unter Linux gibt es mit StackGuard und ProPolice Lösungen,
die diesem Prinzip ebenfalls folgen.
Verfügbar ist diese Option seit Visual C++ 2002 und standardmäßig aktiviert ist die Option seit VS
2005[ 35 ] . Dabei gilt es allerdings zu beachten, dass sich die Implementierungsdetails und damit der
effektive Schutz, seit der ersten Version stark verändert haben. Im Folgenden wird nur auf die
Implementierung von VS 2005 eingegangen.
Seit Windows XP SP2 bzw. Windows Server 2003 ist die Option auch in den meisten Windows-
Binaries Standard. [ 32 ]
Funktionsweise
Programme, die mit der /GS Option kompiliert wurden, initialisieren nach dem Programmstart 4Byte
großes Master-Cookie, mit nicht vorhersagbarem Inhalt. Wird anschließend im Programmverlauf eine
geschützte Funktion aufgerufen, so wird innerhalb des Funktionsprologs eine Kopie des Master-
Cookies, wie auf Abbildung 4-3 zu sehen, auf dem Stack platziert. Wichtig ist hierbei vor allem die
Position des Cookies auf dem Stack: es liegt nach den potentiell verbundbaren lokalen Variablen und
vor der Return-Adresse. Hat die Funktion ihre Arbeit erledigt, so wird innerhalb des Funktionsepilogs
der momentane Wert, des auf dem Stack liegenden Cookies, mit dem Master-Cookie verglichen.
Sollte innerhalb der Funktion ein Buffer-Overflow vorgekommen sein, der bis zu dem Cookie reicht,
so wird das an dieser Stelle erkannt. Gegebenenfalls wird anschließend eine Ausnahme geworfen
und falls diese nicht entsprechend behandelt wird, wird das Programm wird mit einer Fehlermeldung
abgebrochen. [ 32 ]
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 45 -
Beispielhaftes
Stackframe
Wa
ch
stu
msrich
tun
g
0000000h
(Kleine Adressen)
FFFFFFFFh
(Große Adressen)
Ove
rflo
wrich
tun
g
Gespeicherte Register der
aufgerufenen Funktion
Sichere Parameter
Lokale Variablen
Exception Handler
Cookie
Stack Frame Pointer (SFP)
Return Adresse (RET)
Verwundbare Parameter
Abbildung 4-3: Beispielhaftes Stacklayout unter Verwendung von /GS bei VS 2005 [ 32 ]
Ebenfalls auf Abbildung 4-3 zu sehen, ist ein Feld "Sichere Parameter". Diese Neuerung gibt es seit
Visual Studio 2005 und soll verhindern, dass durch verwundbare Funktionsparameter nachfolgende
Speicherbereiche überschrieben werden können. Aktiviert wird diese Funktionalität ebenfalls mit der
/GS Option. Dabei stellen die sicheren Parameter nichts weiter dar, wie eine Kopie der Original-
Parameter. Während des Funktionsablaufs wird ausschließlich mit der Kopie (den sicheren
Parametern) gearbeitet. Aufgrund ihrer Position auf dem Stack, kann durch das weiter unten
liegende Cookie, ein von dem Parametern ausgehende Buffer-Overflow ebenfalls erkannt werden. [
32 ]
Schwachstellen
Die offensichtlichste und auch von Microsoft offiziell dokumentierte Schwachstelle, ist die Tatsache,
dass das Cookie nur unter bestimmten Umständen angelegt wird. Begründet wird dieses Verhalten
vor allem durch den Overhead, der durch das zusätzliche Verwalten und Prüfen der Cookies entsteht.
Das bedeute praktisch, dass ein Prüfung mittels Cookie, unter folgenden Umständen trotz aktivierter
/GS Option nicht erfolgt: [ 33 ] [ 32 ]
Bei Funktionen, die keinen Puffer enthalten
Wenn die /O Optionen (Code optimieren) nicht aktiviert werden
Bei Funktionen mit variabler Argumentliste (...)
Bei Funktionen, die mit naked (C++) markiert sind
Bei Funktionen, die Inlineassemblycode in der ersten Anweisung enthalten
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 46 -
Wenn ein Parameter nur auf eine Art und Weise verwendet wird, die im Falle eines
Pufferüberlaufs höchstwahrscheinlich nicht ausgenutzt werden kann
Passend zu dem letzten Punkt, wurde erst kürzlich herausgefunden, dass Puffer von einer Größe
kleiner wie 5 Byte offenbar als nicht gefährlich eingestuft werden und somit keinen Schutz durch
Cookies besitzen. [ 32 ]
Die meisten der obigen Fälle kann der Entwickler glücklicher weise eliminieren, indem er das Pragma
strict_gs_check(on) verwendet [ 4 ] . Allerdings sollte bei diesem Vorgehen der zusätzliche
Overhead und die damit einhergehenden Performanceeinbußen nicht außer Acht gelassen werden.
Falls der Angreifer die Möglichkeit hat, einen wahlfreien Schreibzugriff der Größe 4-Byte
auszuführen, bevor der Cookie-Check durchgeführt wird, kann versucht werden das Master-Cookie
mit einem bekannten Wert zu überschreiben. Da es in der aktuellen Implementierung nur 256
mögliche Positionen für das Cookie gibt und der Speicherbereich beschreibbar ist, bieten sich hier
Brute-Force-Angriffe an. [ 32 ] [ 36 ]
Die gefährlichste Schwachstelle bei der Verwendung von /GS ist die Tatsache, dass man wie in der
Abbildung 4-3 zu sehen ist, von einem verwundbaren Puffer ausgehend ohne weiteres den Exception
Handler überschreiben kann. Wie in dem Abschnitt 3.1.5 kann dabei der Exception Handler anstelle
der Return-Adresse überschrieben werden. Diese Methode funktioniert deshalb, weil die Funktion
zum Prüfen des Cookies erst am Ende der Funktion aufgerufen wird. Bis dies geschieht kann ein
Angreifer eine Exception auslösen und somit die Ausführung des manipulierten Exception Handler
veranlassen[ 36 ] . Dieser Angriffsmöglichkeit begegnet VS mit der Einführung von SafeSEH auf das
später noch eingegangen wird.
Effektiver Schutz
/GS für sich allein bringt kaum einen Mehrwert, da durch das Manipulieren des Exception Handlers
weiterhin alle Möglichkeiten offen stehen (Windows XP SP1, Windows Server 2003 SP0, Vista).
In Verbindung mit SafeSEH (siehe nächster Abschnitt) jedoch, ist Microsoft hier ein sehr effektiver
Schutzmechanismus gelungen, der den Stack für Angreifer zunehmend uninteressanter werden lässt.
Wie eine aktuelle Studie von Symantec [ 32 ] zu dem Thema zeit, werden jedoch bei weitem nicht
alle ausführbaren Windows-Dateien von Windows XP und Vista mit der /GS Option kompiliert. Dabei
existiert bereits eine Liste mit Dateien, die ohne /GS Kompiliert wurden und somit nicht geschützt
sind. Außerdem wurde von Symantec, zur Erstellung der besagten Liste, ein Programm entwickelt,
dass in der Lage ist zu erkennen, ob ein Binary mit /GS kompiliert wurde. Mit diesen Hilfsmitteln sind
Angriffe auf ungeschützte Dateien bereits vorprogrammiert.
Dateien die mit /GS kompiliert wurden und zusätzlich zu dem eigentlichen Buffer-Overflow die
Möglichkeit eines wahlfreien 4-Byte-Schreibzugriffs bieten, sind aus den oben beschriebenen Grund
anfällig für Brute-Force-Angriffe. [ 32 ] [ 36 ]
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 47 -
Nicht vergessen werden darf bei diesem Mechanismus der Schadensbegrenzung jedoch, dass hier
keinerlei Schutz vor Denial of Service Angriffen (DoS)13 geboten wird.
Abschließend sein noch darauf hingewiesen, dass die meisten Programme von Microsoft heutzutage
mit /GS und /SafeSEH kompiliert werden.
4.6.4 Sichere Ausnahmebehandlung (SafeSEH)
Option Beschreibung [ 37 ] Standard Windows
Binaries [ 4 ]
/SAFESEH[:NO]
(Linker)
Abbild verfügt über sichere Ausnahmehandler ? teilweise bei
Windows XP SP2,
Windows Server
2003 SP1,
Windows Vista
Überblick
Die aktuelle Version der Linker-Option /SafeSEH wurde mit Windows XP SP2 / Server 2003 SP1
eingeführt und ist nur für x86-Architekturen verfügbar[ 37 ] [ 4 ] . Ihr Ziel ist es, der im vorherigen
Abschnitt angesprochene Möglichkeit, zum Umgehen der Cookie-Prüfung zu begegnen.
Hinweis: Die genaue Geschichte des SAFESEH-Option ist etwas unklar: Eine Funktion zum validieren
gab es scheinbar bereits mit Server 2003 SP0, unklar ist allerdings welche Funktionalität wann und
mit welchem Umfang eingeführt wurde.
Funktionsweise
Ein mit der /SafeSEH Option kompiliertes Programm, hat in dem Header der ausführbaren Datei
(PE-Header) eine Liste "Sicherer Exception Handler". Wenn im Verlauf des Programms eine
Ausnahme ausgelöst wird, so prüft die Laufzeitumgebung, ob der auf dem Stack liegende, zur
Ausführung vorgesehene, Exception Handler in der besagten Liste steht. Sollte im Programmverlauf
der Exception Handler manipuliert worden sein, so wird dies von Windows erkannt und das
Programm wird abgebrochen. [ 4 ]
13
Ziel von Denial of Service Angriffen ist es, einen Service oder Dienst für den Nutzer unverfügbar zu machen.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 48 -
Schwachstellen
Windows kann einen Exception Handler nur auf seine Richtigkeit überprüfen, wenn das Programm
mit der /SafeSEH Option kompiliert wurde. Dementsprechend sind alle DLLs und Programme von
Drittherstellern, die diese Option nicht verwenden weiterhin verwundbar. [ 14 ]
Effektiver Schutz
Zum Zeitpunkt der Analyse von Ben Nagy [ 14 ] im September 2006, waren keinerlei Möglichkeiten
bekannt, bei Binaries die mit /GS und /SafeSEH kompiliert wurden, die Return-Adresse oder den
Exception Handler als zuverlässigen Einstiegspunkt zu nutzen, um beliebigen Code zur Ausführung zu
bringen. [ 14 ]
Die Ansätze zum Angriff, auf die im letzten Abschnitt vorgestellten Cookies, bleiben jedoch weiterhin
bestehen und bieten einen Ansatzpunkt für weitergehende Analysen.
Auch bei diesem Mechanismus der Schadensbegrenzung darf nicht vergessen werden, dass hier
keinerlei Schutz vor Denial of Service Angriffen geboten wird.
4.6.5 Data Execution Prevention (DEP)
Option Beschreibung [ 37 ] Standard [ 37 ] Windows Binaries
/NXCOMPAT[:NO]
(Linker)
Gibt an, dass eine ausführbare Datei mit dem
Windows-Feature
Datenausführungsverhinderung kompatibel ist.
wenn die
Komponente
Vista erfordert
teilweise bei
Windows XP SP2,
Windows Server
2003 SP1,
Windows Vista
Überblick
Das Ziel von Hardware-DEP (Hardware-enforced DEP) ist es, Angreifern die Möglichkeit zu nehmen,
eingeschleusten Code von beliebigen Speichersegmenten ausgehend, ausführen zu können. Dabei ist
es bisher historisch bedingt gewesen, dass auf dem Stack und dem Heap liegende Daten ausgeführt
werden können, obwohl dies bei entsprechender Programmierung eigentlich nicht nötig ist.
Sollte bei Verwendung von Hardware-DEP dennoch versucht werden Code von einem als nicht
ausführbar markierten Bereich auszuführen, so wird eine Exception geworfen und falls diese nicht
abgefangen wird, wird das Programm beendet. [ 38 ]
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 49 -
Außer dem Hardware-DEP gibt es auch ein Software-DEP (Software-enforced DEP). Die
Namensgebung ist dabei nicht unbedingt logisch. Software-DEP wird nämlich bereits unter dem
Schlagwort SafeSEH geführt und hat es lediglich zum Ziel, Exception Handler auf Manipulationen hin
zu prüfen und das Programm gegebenenfalls abzubrechen (siehe Abschnitt 4.6.4). Software-DEP
kann in diesem Zusammenhang als eine Art Erweiterung zu Hardware-DEP gesehen werden. Für
Software-DEP ist keine spezielle Hardware-Unterstützung notwendig. [ 38 ] [ 39 ]
DEP ist seit Windows XP SP2 und Windows Server 2003 SP1 standardmäßig aktiviert. Hierbei sind
sowohl Software-DEP, als auch Hardware-DEP inbegriffen. [ 38 ]
Funktionsweise
Damit Hardware-DEP funktioniert wird ein Prozessor mit entsprechender Funktionalität benötigt. Bei
AMD heißt die entsprechende Funktion "no-execute" (NX), bei Intel "Execute Disable" (XD). [ 39 ]
Außerdem muss in der Datei Boot.ini bei 32-Bit-Systemen die Physical Address Extension (PAE)
aktiviert sein. Bei 64-Bit-Windows-Versionen ist PAE nicht nötig, weil die entsprechende
Funktionalität bereits nativ implementiert ist.
Software- und Hardware-DEP werden global mit dem Eintrag /noexecute=policy_level in der
Boot.ini konfiguriert. Dabei gibt es für policy_level folgende vier Einstellungsmöglichkeiten: [ 39 ]
1. OptIn: Ist unter Windows XP SP2 die Standardkonfiguration. Mit dieser Option gilt die
Datenausführungsverhinderung standardmäßig nur für Windows-Systembinärdateien. [ 39 ]
2. OptOut: Ist unter Windows 2003 Server SP1 [ 40 ] die Standardkonfiguration.
Datenausführungsverhinderung standardmäßig für alle Prozesse aktivieren. Es kann über
Registryeinträge, eine Liste mit Ausnahmen erstellt werden. [ 39 ]
3. AlwaysOn: Datenausführungsverhinderung gilt für das gesamte System. [ 39 ]
4. AlwaysOff: Für das gesamte System deaktivieren. [ 39 ]
Außer über die globalen Einstellungen, lässt sich DEP für DLLs auch mittels eins "Incompatible-Flags"
deaktivieren. [ 40 ]
Eine dauerhafte Aktivierung von DEP lässt sich mit der oben angegebenen Compiler-Option
/NXCOMPAT:YES erreichen [ 31 ] .
Im Betrieb wird bei Hardware-DEP für jede virtuelle Speicherseite ein Bit gesetzt, dass den
Speicherbereich entweder als ausführbar oder nicht ausführbar markiert. Wird im Betrieb von einem
als "nicht ausführbar" markierten Speicherbereich Code ausgeführt, so wird eine Exception geworfen
und falls sie nicht behandelt wird, wird der Prozess beendet.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 50 -
Schwachstellen
Im Wesentlichen haben alle Schwachstellen, die mit DEP in Zusammenhang gebracht werden, mit
dem Tradeoff zwischen Sicherheit und Kompatibilität zu tun, den Microsoft bei der Implementierung
von Hardware-DEP gegangen ist.
So werden in der Regel weder der Internet Explorer 7, noch Java unter Windows Vista SP1 / XP SP2
mit Hardware-DEP betrieben. Dadurch gelang es Shane Macauly und Alexander Sotrov im Rahmen
des Wettbewerbs "Pwn to Own" im April 2008 mittels Flash und Java, Hardware-DEP zu umgehen
und beliebigen eingeschleusten Code auszuführen. Diese, in Flash begründete Einstiegsmöglichkeit,
wurde bereits 6 Tage nach dem Bekanntwerden von Adobe behoben. [ 41 ] [ 42 ]
Eine weitere Schwachstelle von Hardware-DEP wurde bereits im Jahr 2005 gefunden [ 40 ] . Bei
dieser Methode nutzt der Angreifer die Möglichkeit, das Kompatibility-Flag vom User-Mode aus
nachträglich ändern zu können. Dabei muss es dem Angreifer allerdings bereits möglich sein, im Stil
von return2libc eigenen Code ausführen zu können. Außerdem benötigt er die Adressen mehrerer
Speicherregionen, die gezielt manipuliert werden müssen. Aufgrund der letzen Anforderung sind
Angriffe dieser Art unter Windows Vista nicht mehr zuverlässig möglich, da dort ASLR zur Verfügung
steht. Microsoft hat auf die Veröffentlichung des Angriffs von Alexander Anisimov mit der Aussage
reagiert, man glaube nicht, dies sei eine Schachstelle, weil der Angreifer bereits Code zur Ausführung
bringen können muss. Abgesehen davon sei DEP auch primär zum Schutz vor Remote-Angriffen
entwickelt worden. [ 43 ] [ 44 ]
Effektiver Schutz
Die Implementierung von DEP scheint, in Hinsicht auf Remote-Angriffe, bisher keine Schwachstellen
zu haben. Wünschenswert wäre es dennoch, die oben angesprochenen Unzulänglichkeiten
schnellstmöglich zu korrigieren, um so potentiellen neuen Angriffen so schwer wie möglich zu
machen.
Eine wirkliche Gefahr stellt die Abwärtskompatibilität von DEP dar. Hier sind die Dritthersteller
gefragt: Sie sollten schnellstmöglich sicherstellen, dass alle Ihre Produkte mit aktivierten Hardware-
DEP uneingeschränkt lauffähig sind.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 51 -
4.6.6 Address Space Layout Randomization (ASLR)
Option Beschreibung [ 37 ] Standard[ 4 ] Windows
Binaries [ 31 ]
/DYNAMICBASE[:NO]
(Linker)
Address Space Layout Randomization verfügbar und
Standard seit
VS 2005 SP1
Windows Vista
seit Beta2
Überblick
ASLR ist eine Funktionalität, die ausschließlich unter Windows Vista zur Verfügung steht und seit
Visual Studio 2005 SP1 auch für Eigenentwicklungen verfügbar ist. Das Ziel von ASLR ist es, Remote-
Angriffe, die es zum Ziel haben eigenen Code zur Ausführung zu bringen, so unzuverlässig wie
möglich zu machen. Ausschließen lässt sich diese Art von Angriff mit ASLR nicht, da das System
grundliegend auf einen begrenzten Grad an Wahrscheinlichkeit zurückgreift. [ 30 ]
Funktionsweise
Wird bei VS 2005 SP1 /DYNAMICBASE als Option beim Linken angegeben, so wird im PE-Header der
ausführbaren Datei ein Flag gesetzt, dass der Laufzeitumgebung mitteilt, dass ASLR verwendet
werden soll. [ 30 ]
Beim Bootvorgang von Windows Vista wird ein globales Image-Offset gewählt, von dem ausgehend
alle DLLs geladen werden. Dadurch ist es weiterhin effizient möglich, innerhalb aller Prozesse auf
eine gemeinsame Funktionalität einer DLL zuzugreifen. Außer dem globalen Image-Offset werden die
Basisadressen von der TXT-, DATA- und BSS-Segmente sowie der der DLLs, bei jedem Reboot neu
gewählt. Im Unterschied dazu, werden die Basisadressen des Stacks und der angelegten Heaps, bei
jedem Programmstart neu gewählt und sind für jeden Thread verschieden. Zusätzlich zu der
Basisadresse des Stacks, wird der Initial-Stack-Pointer dynamisch gewählt. [ 30 ]
Die Bestimmung der dynamischen Adressen erfolgt dabei durch Pseudo-Zufallszahlen. Die Menge der
möglichen Basisadressen ist dabei sehr unterschiedlich. So ist beispielsweise die Menge der
möglichen Adressen für den Initial Stack-Pointer auf einem 32-Bit-System 16.384, für die
Basisadresse des globalen Image-Offsets jedoch, existieren lediglich 256 Möglichkeiten. [ 30 ]
Nichts direkt mit dem eigentlichen ASLR der Linker-Option /DYNAMICBASE, hat die in Abschnitt 4.4
beschriebene dynamische Wahl des PEB zu tun. Dabei wird ebenfalls, bei jedem Programmstart, die
Adresse des PEB zufällig gewählt.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 52 -
Schwachstellen
Die offensichtlichste Schwachstelle von ASLR existiert bei lokalen Angriffen. Dabei muss ein Angreifer
lediglich einen eigenen Prozess starten und mittels eines Debuggers die globale Basisadresse
ermitteln. Hierbei sollte allerdings berücksichtigt werden, dass ALSR primär zum Schutz vor Remote-
Angriffen entwickelt wurde und somit ist es in der Regel nicht möglich, einen eigenen Prozess zu
starten, von dem diese Information abgeleitet werden kann. [ 30 ]
Eine wirkliche Schwachstelle hingegen ist die Tatsache, dass ähnlich wie bei GS und SafeSEH, noch
nicht alle Windows Binaries mit der entsprechenden Option kompiliert wurden. Nach [ 4 ] sind bei
Windows Vista Ultimate 1676 von 1767 Dateien mit ASLR kompiliert.
Einer Analyse von Symantec zufolge[ 30 ] , bestehen in der Implementierung von ASLR noch einige
Verbesserungsmöglichkeiten. Im Wesentlichen wird dabei die Häufigkeitsverteilung der
Basisadressen als verbesserungswürdig eingestuft. Die größte Schwachstelle in diesem
Zusammenhang betrifft die Basisadresse des PEB, die in 25% aller Fälle identisch ist. Außerdem zeigt
sich bei der Verwendung von HeapAlloc() eine sehr deutliche Häufigkeitsverteilung. Ausgehend
von diesen Implementierungsschwächen bieten sich Brute-Force-Angriffe geradezu an. [ 30 ]
Effektiver Schutz
Wie bereits erwähnt ist der Schutz vor lokalen Angriffen durch ASLR nahezu null.
Die Möglichkeit zuverlässige Remote-Exploits zu schreiben, wurde durch ASLR signifikant verringert.
Dabei bleibt jedoch die Möglichkeit der Brute-Force Angriffe bestehen. Dies könnte vor allem durch
die oben erwähnten Schwächen in der Häufigkeitsverteilung interessant werden. Da sich Microsoft
dieser Problematik jedoch bewusst ist und dieses Problem selbst auf eine
Implementierungsschwäche zurückführt, kann auf eine baldige Beseitigung dieser Unzulänglichkeit
gehofft werden. [ 30 ]
Auch bei diesem Mechanismus der Schadensbegrenzung darf nicht vergessen werden, dass hier
keinerlei Schutz vor Denial of Service Angriffen geboten wird.
4.7 Abschließender Vergleich: XP gegenüber Vista
Wie sich der folgenden Tabelle entnehmen lässt, sind viele Neuerungen der jüngeren Vergangenheit
auch in Windows XP enthalten. Diese Neuerungen für sich haben die Schwierigkeit zuverlässige
Exploits zu schreiben, die auf Buffer-Overflows basieren, stark erhöht. Laut CVE-Statistik [ 1 ] gab es
für Windows XP im Jahr 2007 noch 28 veröffentliche Schwachstellen, die direkt auf Buffer-Overflows
zurückzuführen waren. Im Jahr 2008 ist es, bis zum Druckzeitpunkt dieser Arbeit im Juni 2008, noch
keine einzige solche Schwachstelle. [ 1 ]
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 53 -
Tabelle 1: Sicherheitsmechanismen in XP und Vista
Windows XP Windows Vista
UAC und Service Hardening Nein Ja
Patchguard Ja,
nur bei 64Bit
Ja,
nur bei 64Bit
PEB Randomization Seit SP2 Ja
SAL Ja,
bei entsprechender
Entwicklungsumgebung
Ja,
bei entsprechender
Entwicklungsumgebung
Stackoptimierungen(O2) Ja,
muss beim Kompilieren
aktiviert werden
Ja,
muss beim Kompilieren
aktiviert werden
SafeSEH Seit SP2,
muss beim Linken aktiviert
werden
Ja,
muss beim Linken aktiviert
werden
DEP Seit SP2,
muss beim Linken aktiviert
werden
Ja,
muss beim Linken aktiviert
werden
ASLR Nein Ja,
muss beim Linken aktiviert
werden
Weitere Neuerungen wie UAC und ASLR, die nur Windows Vista und seinen Folgeversionen zugänglich sind, haben den Sicherheitsstandard noch weiter erhöht, so dass Buffer-Overflows als Einfallstor zunehmend unwahrscheinlicher werden. Außerdem schränken sie den Spielraum des eingeschleusten Codes stark ein, was ebenfalls einen sicherheitstechnischen Mehrwert darstellt. Im Fazit folgt nun eine kurze Zusammenfassung und eine Bewertung der Gesamtmenge an Maßnahmen, die in Windows XP und Windows Vista zum Einsatz kommen.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 54 -
5 Fazit
In den beiden ersten Kapiteln wurden einige traditionelle und einige neuere Angriffstechniken
vorgestellt, die auf Buffer-Overflows basieren und mit denen ein modernes Betriebssystem
heutzutage zurechtkommen muss. In dem letzten Kapitel wurden die Mechanismen vorgestellt, die
Windows Vista und frühere Versionen mitbringen, um sich gegen diese Gefahren zu wappnen. Dabei
ist es offensichtlich, dass Microsoft einen beachtlichen Entwicklungsaufwand investiert hat um den
Ruf des unsicheren "Blue-Screen-Windows" endgültig abzulegen.
Dabei sind neue Programmierpraktiken wie SAL entstanden, die den Entwicklern helfen Buffer-
Overflows erst gar nicht entstehen zu lassen und somit den wohl effektivsten Schutz gegen Buffer-
Overflows bietet. Sollten sich im Code von Drittherstellern, oder im Betriebssystem selbst dennoch
Buffer-Overflows finden, so wird der praktische Nutzen, durch die meisten in diesem Dokument
vorgestellten Mechanismen, auf Denial of Service Angriffe reduziert. Dies gilt allerdings nur, wenn die
gesamte Breite, an zur Verfügung stehenden Schutzmechanismen, verwendet wird. Das einfachste
Negativbeispiel ist ein Programm, das zwar mit /GS, aber nicht mit /SafeSEH kompiliert wurde. Hier
verwendet der Angreifer einfach den Exception Handler und nicht die Rücksprungadresse als
Einstiegspunkt.
Kritik und Lob zugleich verdient Windows Vista für seine Abwärtskompatibilität. So freut es
Dritthersteller, dass sie ihre Programme nicht aufwändig umschreiben müssen, um mit den neuen
Sicherheitsmechanismen kompatibel zu sein, denn sie bleiben einfach inkompatibel. Was den
Programmierer der Software freut, ist schlecht für die Gesamtsicherheit des Systems. Als
bekanntestes Negativbeispiel sei hier nochmals der Internet Explorer 7 genannt, der selbst heute
noch mit deaktivierten DEP das Tor zur Welt öffnet.
Sollte es einem Anwender gelingen, nur Programme zu betreiben, die alle zur Verfügung stehenden
Mechanismen verwenden, so betreibt er das mit Abstand sicherste Windows-System das es bisher
gab.
Dennoch ist "das sicherste" nicht gleichzusetzen mit "sicher". Dieser Tatsache ist sich auch Stephen
Toulouse (Senior Product Manager bei Microsoft Security Technology) bewusst, der sagt:
"Keins der Features aus Windows Vista, weder allein, noch zusammen, ist
kugelsicher. Dennoch erhöht sich der Schutz gegenüber Windows XP
signifikant" (Frei übersetzt nach [ 29 ] ).
Aus dieser richtigen, aber auch sehr unverfänglichen Aussage, lässt sich ablesen, wie schwer es ist,
den effektiven Schutz eines Betriebssystems zu beurteilen.
Um die gesamte Sicherheit von Windows Vista zu bewerten darf man nicht nur veröffentliche
Sicherheitslücken bewerten, sondern man muss auch Dienstleister, mit moralisch fragwürdiger
Motivation in seine Bewertung mit einbeziehen, die versprechen gegen Bezahlung funktionierende
Exploits zu liefern. Ebenso dürfen Hacker mit unterschiedlichen Idealen nicht vergessen werden, die
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 55 -
teilweise kein Interesse daran haben ihre "private Exploits" zu veröffentlichen, da Sie dadurch ihren
"Freiraum" verkleinern würden.
Auch wenn sich abschließend nicht sagen lässt "Windows Vista ist sicher", der Mehrwert den
Neuerungen wie UAC und ASLR gegenüber Windows XP bringen, ist unbestritten. Wer also vor der
Wahl steht XP oder Vista, dem sollte vom sicherheitstechnischen Standpunkt aus, auf jeden Fall zu
Vista geraten werden.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 56 -
A Literaturverzeichnis
1. Statistics. [Online] National Vulnerability Database, 15. 7 2008. http://nvd.nist.gov/.
2. Mark E. Russinovich, David A. Solomon. Windows Internals. Redmond : Microsoft Corporation,
2005. ISBN 3-86063-977-3.
3. James C. Foster, Vitaly Osipov, Nish Bhalla, Niels Heinen. Buffer Overflow Attacks: Detect, Exploit,
Prevent. Rockland : Syngress Publishing, Inc., 2005. ISBN 1-932266-67-4.
4. Joel Scambray, Stuart McClure. Hacking Exposed Windows: Windows Security Secrets & Solutions,
Third Edition. s.l. : McGraw-Hill, 2008. ISBN 978-0-07-149426-7.
5. Ericson, Jon. HACKING: THE ART OF EXPLOITATION, 2ND EDITION. San Francisco : NO STARCH
PRESS, 2008. ISBN 978-1-59327-144-2.
6. Know-how: Heap-Verwaltung Haufenakrobatik. Stiller, Andreas. 4, Hannover : Heise Zeitschriften
Verlag GmbH & Co. GK, 2007. ISSN 0724-8679.
7. Pufferüberläufe auf dem Heap und wie man sie ausnutzt. Lindner, Felix. 09, Hannover : Heise
Zeitschriften Verlag GmbH & Co. GK, 2006. ISSN 0724-8679.
8. Alexander Anisimov, Positive Technologies. Defeating Microsoft Windows XP SP2 Heap protection
and DEP bypass. [Online] 2004. [Zitat vom: 5. 4 2008.] http://www.maxpatrol.com/defeating-xpsp2-
heap-protection.htm.
9. Horovitz, Matt, Conover und Oded. Windows Heap Exploitation. [Online] [Zitat vom: 5. 4 2008.]
http://www.cybertech.net/~sh0ksh0k/projects/winheap/XPSP2%20Heap%20Exploitation.ppt.
10. Kallnik, Stephan, et al. Buffer-Overflows und andere Sollbruchstellen. heise Security. [Online] 30.
6 2003. [Zitat vom: 1. 4 2008.] http://www.heise.de/security/Buffer-Overflows-und-andere-
Sollbruchstellen--/artikel/37958/2.
11. Visual C++ Referenz. msdn. [Online] Microsoft Corporation. [Zitat vom: 17. 5 2008.]
http://msdn2.microsoft.com/de-de/library/de5awhsw.aspx.
12. Using an Exception Handler (Windows). msdn. [Online] Microsoft Corporation. [Zitat vom: 29. 4
2008.] http://msdn2.microsoft.com/en-us/library/ms681409%28VS.85%29.aspx.
13. Mangarae, Aelphaeis. SEH Overwrites Simplified v1.01. [Online] 27. 10 2007. [Zitat vom: 2. 4
2008.] http://www.milw0rm.com/papers/187.
14. Nagy, Ben. SEH (Structured Exception Handling) Security Changes in XPSP2 and 2003 SP1.
[Online] eEye Digital Security, 5. 12 2006. [Zitat vom: 16. 5 2008.]
http://www.eeye.com/html/resources/newsletters/vice/VI20060830.html.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 57 -
15. Falliere, Nicolas. Bypassing Windows heap protections. [Online] [Zitat vom: 11. 4 2008.]
http://packetstormsecurity.org/papers/bypass/bypassing-win-heap-protections.pdf.
16. Conover, Matt. Double Free Vulnerabilities. Vulnerabilities & Exploits. [Online] 1 2007. [Zitat vom:
1. 5 2008.]
http://www.symantec.com/enterprise/security_response/weblog/2007/01/double_free_vulnerabilit
ies_pa.html.
17. Conover, Matt & Horovitz, Oded. Windows Heap Exploitation. [Online] 12 2004. [Zitat vom: 5. 4
2008.] http://www.cybertech.net/~sh0ksh0k/projects/winheap/XPSP2%20Heap%20Exploitation.ppt.
18. Conover, Matt & w00w00 Security Team. w00w00 on Heap Overflows. [Online] 1 1999. [Zitat
vom: 1. 4 2008.] http://www.w00w00.org/files/articles/heaptut.txt.
19. c0ntex. Windows Heap Overflows using the Process Environment Block (PEB). [Online] [Zitat vom:
6. 4 2008.] http://www.milw0rm.com/papers/66.
20. Wana, Thomas aka. greuff. Writing UTF-8 compatible shellcodes. [Online] [Zitat vom: 2. 4 2008.]
http://www.phrack.org/issues.html?issue=62&id=9.
21. Tüllmann, Thorsten. Shellcode unter Windows, Linux und MacOS. [Online] 15. 2 2006. [Zitat vom:
4. 5 2008.] http://www.tm.uka.de/itm/uploads/folien/88/08-Thorsten_Tuellmann-Shellcode.pdf.
22. Kritische Lücke in Intels Centrino WLAN-Treibern. Heise Security. [Online] Heise Zeitschriften
Verlag GmbH & Co. GK, 2. 8 2006. [Zitat vom: 14. 5 2008.] Kritische Lücke in Intels Centrino WLAN-
Treibern.
23. Barnaby, Jack Senior. Remote Windows Kernel Exploitation - Step into the Ring 0. [Online] 2005.
[Zitat vom: 14. 5 2008.] http://research.eeye.com/html/papers/download/StepIntoTheRing.pdf.
24. Messier, Matt und Viega, John. Secure Programming Cookbook for C and C++. s.l. : O'Reilly, 2003.
0-596-00394-3.
25. Jesper M., Johansson. Sicherheit auf dem Prüfstand: Tools zum Verwalten von ACLs. TechNet
Magazin. [Online] 2008. [Zitat vom: 16. 5 2008.] http://technet.microsoft.com/de-
de/magazine/cc138006.aspx.
26. Impact of Session 0 Isolation on Services and Drivers in Windows Vista. Windows Hardware
Developer Central. [Online] 20. 12 2007. [Zitat vom: 16. 5 2008.]
http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-
d599bac8184a/Session0_Vista.docx.
27. Moore, Brett. Shattering By Example. [Online] 10 2003. [Zitat vom: 16. 5 2008.] http://security-
assessment.com/files/whitepapers/Shattering_By_Example-V1_03102003.pdf.
28. Skywing. PatchGuard Reloaded: A Brief Analysis of PatchGuard Version 3. [Online] 9 2007. [Zitat
vom: 17. 5 2008.] http://www.uninformed.org/?v=8&a=5&t=txt.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 58 -
29. Lemos, Robert. Vista raises the bar for flaw finders. [Online] 29. 1 2007. [Zitat vom: 17. 5 2008.]
http://www.securityfocus.com/news/11439.
30. Whitehouse, Ollie. An Analysis of Address Space Layout Randomization on Windows Vista™.
[Online] 2007. [Zitat vom: 2. 4 2008.]
http://www.symantec.com/avcenter/reference/Address_Space_Layout_Randomization.pdf.
31. Hellen, Ian und Kumar, Vishal. Security Engineering in Windows Vista. HITBSecConf2006 -
Malaysia. [Online] 18. 9 2006. [Zitat vom: 24. 5 2008.]
http://packetstormsecurity.org/hitb06/DAY_1_-_Ian_Hellen_and_Vishal_Kumar_-
_Security_Engineering_in_Vista.pdf.
32. Whitehouse, Ollie. Analysis of GS protections in Microsoft Windows Vista. [Online] 2007. [Zitat
vom: 18. 5 2008.] http://www.symantec.com/avcenter/reference/GS_Protections_in_Vista.pdf.
33. Visual C++-Compileroptionen. msdn. [Online] [Zitat vom: 17. 5 2008.]
http://msdn.microsoft.com/de-de/library/9s7c9wdw.aspx.
34. Howard, Michael. A Brief Introduction to the Standard Annotation Language (SAL). Michael
Howard's Web Log - A Simple Software Security Guy at Microsoft! [Online] 19. 5 2006. [Zitat vom: 27.
5 2008.] http://blogs.msdn.com/michael_howard/archive/2006/05/19/602077.aspx.
35. Branbray. Security Improvements to the Whidbey Compiler. http://blogs.msdn.com/. [Online] 11.
11 2003. [Zitat vom: 17. 5 2008.] http://blogs.msdn.com/branbray/archive/2003/11/11/51012.aspx.
36. Litchfield, David. Defeating the Stack Based Buffer Overflow Prevention Mechanism of Microsoft
Windows 2003 Server. [Online] 8. 9 2003. [Zitat vom: 2. 4 2008.]
http://www.nextgenss.com/papers/defeating-w2k3-stack-protection.pdf.
37. Visual C++-Linkeroptionen. msdn. [Online] [Zitat vom: 18. 5 2008.]
http://msdn.microsoft.com/de-de/library/y0zzbyt4.aspx.
38. How to Configure Memory Protection in Windows XP SP2. Microsoft TechNet. [Online] 9. 12
2004. [Zitat vom: 24. 5 2008.]
http://www.microsoft.com/technet/security/prodtech/windowsxp/depcnfxp.mspx.
39. A detailed description of the Data Execution Prevention (DEP) feature in Windows XP Service
Pack 2, Windows XP Tablet PC Edition 2005, and Windows Server 2003. Hilfe und Support. [Online]
26. 10 2006. [Zitat vom: 24. 5 2008.] http://support.microsoft.com/?scid=kb%3Ben-
us%3B875352&x=1&y=8.
40. skape und Skywing. Bypassing Windows Hardware-enforced Data Execution Prevention.
Uninformed - vol 2 article 4. [Online] 10 2005. [Zitat vom: 25. 5 2008.]
http://www.uninformed.org/?v=2&a=4.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 59 -
41. Erste Hintergründe zum Flash-Hack beim PWN-to-OWN-Wettbewerb. heise Security. [Online] 3. 4
2008. [Zitat vom: 24. 5 2008.] http://www.heise.de/security/Adobe-schliesst-sieben-Luecken-im-
Flash-Player--/news/meldung/106237.
42. Adobe schließt sieben Lücken im Flash-Player. heise Security. [Online] 9. 4 2008. [Zitat vom: 25. 5
2008.] http://www.heise.de/security/Adobe-schliesst-sieben-Luecken-im-Flash-Player--
/news/meldung/106237.
43. Microsoft: Fehler in Buffer-Overflow-Schutz ist keine Schwachstelle. heise online. [Online] 2. 2
2008. [Zitat vom: 25. 5 2008.] http://www.heise.de/newsticker/Microsoft-Fehler-in-Buffer-Overflow-
Schutz-ist-keine-Schwachstelle--/meldung/55851.
44. Buffer-Overflow-Schutz in Windows XP SP2 lückenhaft. heise Security. [Online] 31. 01 2005. [Zitat
vom: 25. 5 2008.] http://www.heise.de/security/Buffer-Overflow-Schutz-in-Windows-XP-SP2-
lueckenhaft--/news/meldung/55738.
45. Stephan Kallnik, Daniel Pape, Daniel Schröter, Stefan Strobel. http://www.heise.de. heise
Security. [Online] 3. 6 2003. [Zitat vom: 1. 4 2008.] http://www.heise.de/security/Buffer-Overflows-
und-andere-Sollbruchstellen--/artikel/37958/0.
46. Howard, Michael. Windows Vista Security – A Bigger Picture. http://blogs.msdn.com. [Online] 12.
6 2006. [Zitat vom: 17. 5 2008.]
http://blogs.msdn.com/michael_howard/archive/2006/06/12/628207.aspx.
47. One, Aleph. Smashing The Stack For Fun And Profit. [Online] [Zitat vom: 2. 4 2008.]
http://www.phrack.org/issues.html?issue=49&id=14#article.
48. skape. Understanding Windows Shellcode. [Online] 6. 9 2003. [Zitat vom: 31. 3 2008.]
http://nologin.org/Downloads/Papers/win32-shellcode.pdf.
49. talz. How-to exploit default exception handler to gain stability on win32. [Online] [Zitat vom: 16.
5 2008.] http://www.securityforest.com/wiki/index.php/Exploit:_Stack_Overflows_-
_Exploiting_default_seh_to_increase_stability.
Stack- und Heap-Overflow-Schutz bei Windows XP und Windows Vista
Seite - 60 -
B Quellcode
Der Quellcode wurde aus Platzgründen in einen Zip-Archiv ausgelagert. Diese Zip-Datei, sowie die
aktuelle Version dieses Dokuments, sind unter folgender Adresse erhältlich:
http://jssk.de/data/studienarbeit/Quellcode-Studienarbeit-BOs.zip
Sollten sich im Laufe der Zeit Änderungen ergeben, so dass der oben angegebenen Link nicht mehr
funktioniert, so bin ich unter folgender Kontaktadresse erreichbar.
Kontaktadresse: [email protected]
Inhalte des Qullecode-Archivs
Hinweise zum Kompilieren
Batchdateien zum Kompilieren mit Visual-Studio 2005 bzw. 2008
Quellcode zu dem Programmen
Beispielprogramme, fertig kompiliert
Beispielhafte Programmabläufe (Programmausgaben)
Perlskripte zum erstellen des Bytecodes
Beispielhaft erstellter Bytecode
Top Related