No eXecute: CPU-Erweiterungen schützen vor Angriffen

04.11.2004 von Detlef Jantz
Das neue NX-Bit im Speichermanagement aktueller AMD- und kommender Intel-Prozessoren soll Virenangriffe aktiv verhindern. Doch auch das Betriebssystem muss dabei mitspielen - und hier ist die Umsetzung noch halbherzig.

Mit Überschreiten der GHz-Grenze hat das Rennen um die reine Rechenleistung bei PCs an Bedeutung verloren. Durch die ständige Bedrohung von Viren und Trojanern ist die Sicherheit und Zuverlässigkeit von Computersystemen inzwischen zum Hauptinteresse des PC-Anwenders geworden. Die Fortschritte in der Absicherung eines PCs können mit den Fortschritten in der Rechenleistung jedoch nicht mithalten. Vor fast 20 Jahren hat Intel mit dem 80386 die Basis der gültigen x86-Prozessorarchitektur und deren Sicherheitsmechanismen gelegt. Doch seit 1985 hat es keine echte Weiterentwicklung für eine höhere Systemsicherheit gegeben, bis AMD 2003 mit dem Opteron vorpreschte.

AMD hat in alle Prozessoren der achten Generation ein neues Sicherheitsfeature implementiert: Das so genannte NX- (No-Execution-) Bit verspricht beim Opteron und Athlon 64 einen Schutz vor einem der häufigsten Angriffsvektoren von Schadprogrammen, dem Buffer Overflow mit Code auf dem Stack. Marketinggerecht bezeichnet AMD dieses Feature offiziell mit "Enhanced Virus Protection". Auch Intel hat diese Hardware-Erweiterung bei seinen neuen Prozessoren integriert, bezeichnet es aber als XD- (Execution-Disable-) Technologie.

Das NX-Bit liegt als zusätzliches Steuerbit in den Deskriptoren und Sicherungsbits für Speicherseiten. Setzt das Betriebssystem dieses Bit für den Stack-Bereich, erzeugt das Ausführen von Code auf dem Stack einen Ausnahmezustand in der CPU und informiert so das Betriebssystem. Ohne dessen Unterstützung bleibt das NX-Feature jedoch wertlos.

Microsofts Windows bietet den zusätzlichen Schutz optional mit dem SP2 für Windows XP und dem SP1 für Windows Server 2003. Hier sind die Schutzfunktionen unter dem Unwort "Datenausführungsverhinderung" zusammengefasst. Interessanterweise verbirgt sich dahinter weit mehr als nur das NX-Bit, so dass alle Benutzer von der erhöhten Sicherheit profitieren können - wenn sie den Schutz nur aktivieren würden. Auch etliche Linux-Distributionen unterstützen inzwischen das NX-Bit. Höchste Zeit also, sich die zu Grunde liegenden Techniken näher anzusehen und Marketing-Versprechen auf ihren Realitätsgehalt hin zu überprüfen.

Grundlagen des Speichermanagementes

Um zu verstehen, wie das NX-Bit mit den schon vorhandenen Prozessorkomponenten und bestehender Software zusammenarbeitet, ist Basiswissen über die x86-Architektur nötig. Die prinzipiellen Grundlagen, wie Speicherschutz und Adressverfahren überhaupt funktionieren, werden im Folgenden im Zusammenhang mit dem Einsatz bei den Schutzverfahren vorgestellt. Falls Sie diesen komplexen Hintergrund überspringen möchten, können Sie auf der Seite "Kernfrage NX - Funktionsprinzip" weiterlesen. Möchten Sie noch mehr Grundlagen zur X86-Speicherarchitektur erfahren, empfehlen wir unseren Beitrag x86-Programmierung und -Betriebsarten.

Die x86-Architektur verwaltet den Hauptspeicher immer in Blöcken mit typischen Größen von 4 KByte bis 4 MByte. Für das Management benötigt die Memory-Management-Unit (MMU) im Prozessor daher nicht alle Adressbits der logischen und der linearen Adresse (dazu mehr auf den nächsten Seiten). Vielmehr nutzt sie nur den oberen Teil des so genannten Speicher-Adressbitvektors der kompletten Adresse. Als großer Vorteil reduzieren sich dadurch der interne Speicherbedarf für Adressen und der Aufwand bei Adressberechnungen erheblich.

Diese Speicherblöcke lassen sich ohne die unteren, nicht-signifikanten Bits adressieren und mit speziellen Eigenschaften und Rechten ausstatten. Der Adressbitvektor wird während seiner Benutzung zu Speicherverwaltungszwecken in mehrere Teile geschnitten, wie beispielhaft im Bild dargestellt.

Diese einzelnen Teile aus einem Bitvektor kann der Prozessor dann an verschiedenen Stellen in unterschiedlichen Kombinationen nutzen. Für das Paging werden beispielsweise im Standardmodus von Windows die unteren 12 Bits nicht berücksichtigt. Hier arbeitet die CPU mit vier KByte-Speicherblöcken als kleinste Struktur. Dieses Verfahren der so genannten Teilbitvektoren ist außer bei Adressen auch in noch feinerer Unterteilung bei den Deskriptoren anzutreffen, dazu später mehr.

Teilbitvektoren

Teilbitvektoren führen zum nächsten wichtigen Verfahren, der Look-up- oder Indextabelle. Ein prinzipielles Beispiel mit einem 10-Bit-Teilvektor ist im nächsten Bild dargestellt. Ein Teilbitvektor kann innerhalb einer vorgegebenen Tabelle einzelne Einträge adressieren. Die maximale Größe der Tabelle ergibt sich aus der Länge des Teilbitvektors und der größten damit darstellbaren Adresse. Im Bild findet der Prozessor anhand des 10-Bit-Teilbitvektors mit dem Adresswert 600 in der Tabelle den Eintrag in Zeile 600 und liest deren 32-Bit-Wert 120000 aus.

Dieses Verfahren kommt in einem Prozessor an den unterschiedlichsten Stellen zum Einsatz, sei es beim Cache-Zugriff, beim Paging oder dem Auslesen von Deskriptoren für Speicherblöcke.

Für den Speicherschutz in x86-Prozessoren stellen Look-up-Tabellen das wichtigste Grundprinzip dar. Das Betriebssystem erzeugt für jeden Speicherblock einen Eintrag in einer Tabelle und legt darin die speziellen Eigenschaften eines Blocks fest. Die Kontrolle erfolgt also nicht für jedes Byte, sondern immer nur für zusammengehörige Bereiche. Bei jedem Zugriff auf eine Speicherstelle ermittelt der Prozessor aus den höherwertigen Bits der Adresse den zugehörigen Eintrag in der Schutztabelle. Diesen wertet er aus und prüft die Zugriffsberechtigungen anhand der darin eingetragenen Schutzbits.

Arten von Speicherzugriff

Die Speicheradressierungen und der dabei mögliche Speicherschutz sind Teilschritte einer festgelegten Reihenfolge innerhalb eines Programmablaufs. Seit seiner Erfindung durch J. von Neumann arbeitet ein Prozessor in einer Endlosschleife und führt fortwährend bestimmte Operationsschritte aus. Für den Speicherschutz interessieren hier besonders die drei prinzipiell möglichen Arten von Speicherzugriffen.

Codeworte schreibt ein Prozessor im Normalfall nicht in den Speicher. Typische Schadprogramme nutzen jedoch den gemeinsamen Speicher der Von-Neumann- Architektur, um Datenworte ersatzweise an Stellen zu schreiben, die der Prozessor später als Code interpretiert. Für mehr Schutz im Programmablauf gilt es, dies zu verhindern.

Für die Kodierung der drei möglichen Speicherzugriffsarten wären mindestens zwei Bits zum Definieren einer erlaubten oder verbotenen Aktion in den Indextabellen der Speicherverwaltung notwendig. Alternativ könnte man auch je ein Bit für jede der drei Aktionen nutzen. Das erhöht zwar den Speicherbedarf geringfügig, erlaubt aber eine einfachere Verifikation beim Speicherzugriff. In der Praxis werden diese einfach zu implementierenden Verfahren aber bei kaum einem Prozessordesign genutzt.

Speicher-Segmentierung

Beim 80386, dem Urahn des heutigen Pentium, hat Intel 1985 die Segmentprüfung mit geschachtelten Zugriffsebenen für den Speicherschutz eingebaut. Neben dieser Weiterentwicklung des 80286-Prozessors bekam er zusätzlich eine Paging-Einheit inklusive einer weiteren Kontrollfunktion für Schreib-/Lesezugriffe.

Intels Speicherschutz nutzt eine Segmentierung des Arbeitsspeichers in Blöcke. Einzelne Speicherstellen darin adressiert der Prozessor über eine Startadresse des zugehörigen Segments und eine Offset-Adresse innerhalb des Blocks. Die sich aus dem Segment ergebende lineare Adresse rechnet die MMU jedoch nochmals um. Durch dieses nachgeschaltete Paging ist der Einsatz von virtuellem Speicher durch eine Auslagerung auf die Festplatte möglich. Diese Pages verwaltet der Prozessor wie vorher schon die Segmente in einer Tabelle, die auch die Reihenfolge der Blöcke definiert.

Segment Translation und Page Translation laufen in der MMU aller x86-Prozessoren nacheinander bei jedem Speicherzugriff im so genannten Protected Mode (=Geschützten Modus) ab. Die Segmentwandlung lässt sich prinzipiell nicht ausschalten. Das Paging könnte man zwar umgehen, doch gängige x86- Betriebssysteme wie Windows und Linux verwenden es intensiv zum Speichermanagement.

Anwendungsprogramme bekommen von dieser doppelten Umsetzung überhaupt nichts mit. Sie arbeiten intern nur mit logischen Adressen, die aus einem 16-Bit-Selektor und einem 32-Bit-Offset bestehen. Die Segment Translation wandelt die logische zunächst in eine lineare Adresse um. Dazu sucht sie mit dem Selektor als Index in der lokalen oder globalen Deskriptortabelle die passende Segmentbeschreibung, den so genannten Segmentdeskriptor. Der acht Byte große Deskriptor enthält die lineare Basisadresse sowie die Größe des Segments. Die lineare Adresse ergibt sich dann aus der Basisadresse plus dem Offset. Durch die Größenangabe im Tabelleneintrag kann die MMU ermitteln, ob ein Zugriff eventuell außerhalb des Speicherblocks erfolgt und entsprechend eine Exception auslöst.

Page Translation

Die lineare Adresse ist aber noch nicht die physikalische Speicheradresse, also die Adresse, mit der die CPU Hardware-seitig den Hauptspeicher anspricht. Die physikalische Adresse wird erst durch die Page Translation aus der linearen Adresse berechnet. Dazu dienen die oberen 20 Bits der linearen Adresse wiederum als Indizes in einer Page Directory Tabelle und einer Page Tabelle. Diese Tabellen bestimmen dann die physikalische Lage der Speicherseiten. Die unteren 12 Bits der linearen Adresse durchlaufen den ganzen Prozess unverändert. Sie dienen als Offset innerhalb der 4 KByte großen Seiten und ergeben schlussendlich die komplette physikalische Adresse.

Durch Paging im Standardmodus von Windows und Linux werden die 20 höchstwertigen Adressbits also auf neue Werte abgebildet, während die zwölf niederwertigsten Adressbits als Offset unverändert übernommen werden. Durch Manipulation der Page-Deskriptoren lassen sich Bereiche im Speicher austauschen, ohne Daten umkopieren zu müssen. Zudem enthalten die Page-Deskriptoren zwei Zugriffsrechtebits. Eines davon erlaubt den Schreibzugriff. Das andere regelt, ob nur das Betriebssystem oder auch Anwendungen auf die Page zugreifen dürfen.

Bekannt ist das Paging-Verfahren auch als Virtual Memory. Die linearen Adressen simulieren dabei einen großen, idealen Speicher, der von den Einschränkungen des tatsächlich vorhandenen physischen Speichers entkoppelt ist. Das Prinzip der Page-Deskriptoren erlaubt es auch, Seiten auf die Festplatte auszulagern und den physikalischen Speicher abwechselnd für mehrere Seiten im Bereich der linearen Adresse zu verwenden.

Ursprünglich war dies einmal der wichtigste Anwendungsfall für das Paging. Bei Hauptspeichergrößen von einigen MByte erwies sich ein Auslagern der 4 KByte großen Seiten auf Festplatte als sehr effizientes Speichermanagement. Mit den derzeit üblichen Hauptspeichergrößen haben sich die Ziele aber gewandelt. Dies zeigen Adresserweiterungen wie PSE (Page Size Extension) und PAE (Physical Address Extension), die mit Seitengrößen von 2 und 4 MByte arbeiten.

Kernfrage NX - Funktionsprinzip

Ein Erfolg der x86-Architektur liegt in der ständig gewahrten Abwärtskompatibilität neuer Modelle trotz der Einführung immer neuer Features. Mit fortschreitendem Alter einer Prozessorfamilie steigt deren virtueller Wert, da immer mehr Software dafür erhältlich ist. x86-PCs werden nicht so sehr wegen ihres Hardware-Designs gekauft, sondern weil dafür ein riesiges Software-Angebot vorhanden ist.

Aus dieser Notwendigkeit der zwingenden Kompatibilität zum Vorgänger lassen sich eine ganze Reihe Erweiterungen zum 386 finden, die Intel und AMD im Laufe der letzten 20 Jahre angestückelt haben.

Erweiterungen der x86-Familie

Bezeichnung

Funktion

Eingeführt ab

1 i386 Core

Der 386-Kern, das Herz zur Ausführung der meisten Befehle.

i80386

2 FPU 387

Fließkomma-Einheit für Fließkomma-Rechnungen auch nach dem IEEE-754-Standard für binäre Fließkomma-Arithmetik.

Beim i80386 noch als externer Coprozessor, ab dem i80486 integriert.

3 MMX

Multimedia Extensions, SIMD (Single Instruction Multiple Data) Vektoroperationen auf mehren Daten in einem Befehl, beschränkt auf Integerdaten.

Ab Pentium MMX.

4 3DNow!

Weitere Multimedia Extension mit einer Zielrichtung auf schnellere 3D-Berechnungen, kurze Fließkomma-Operationen möglich.

AMD ab K6-2.

5 Enhanced 3DNow!

Befehlserweiterung zu 3DNow.

AMD ab Athlon.

6 SSE

Streaming SIMD Extensions, längere Fließkomma-Operationen möglich.

Intel ab Pentium-III.

7 SSE2

Streaming SIMD Extensions Version 2, Befehlserweiterung zu SSE.

Intel ab Pentium 4.

8 SSE3

Streaming SIMD Extensions Version 3, Befehlserweiterung zu SSE2.

Intel ab Xeon mit EM64T.

9 PSE

Page Size Extension: Anstelle der Pages mit 4 KByte sind auch Page-Größen von 4 MByte möglich.

Ab Pentium.

10 PAE: Physical Adress Extension

Speicheradressierung mit 36 physikalischen Adressbits (64 GByte), logischer Speicher pro Prozess auf 4 GByte beschränkt, zusätzlich variable Page-Größen.

Ab Pentium-Pro, Pentium-II.

11 LM Long Mode

Langer Speicheradressmodus mit 64 Bit, mit nur 52 physischen Adressbits.

AMD ab Opteron/Athlon 64, Intel mit EM64T.

12 Pg/WP

Write Protect: Erweiterte Schutzfunktion in der Paging-Verwaltung.

Ab Pentium.

13 Pg/NX

No Execute: Erweiterungsfunktion in der Paging-Verwaltung.

Ab Athlon 64.

14 486/586+

Zusätzliche Befehle wie BSWAP und CMOV.

Ab 486.

15 AMD64:

Kompletter zusätzlicher neuer 64-Bit-Befehlssatz, ehemals als x86-64 bezeichnet.

AMD ab Opteron/Athlon64, Intel ab EM64T.

16 EM64T

Intels Version des neuen AMD-64-Bit-Befehlssatzes.

Xeon "Nocona"

17 HT: Hyper- Threading

Simuliert zwei Prozessorkerne durch wenige Doppeleinheiten.

Intel ab Pentium 4 HT Northwood.

18 Dualcore

Echter Doppelprozessor mit zwei Prozessorkernen auf einem Die, die sich den Prozessorsockel teilen.

Ab 2005.

Das Bild und die zugehörige Tabelle sind nicht als vollständige Aufzählung aller Erweiterungen zu sehen. Sie sollen vielmehr die verschiedenen Richtungen der x86-Erweiterungen aufzeigen und die Einordnung zusammengehöriger Begriffe ermöglichen.

Auch andere Prozessorhersteller wie NexGen, IDT Centaur, Cyrix, VIA C3 und Transmeta mussten sich der strengen Abwärtskompatibilität beugen. Selbst geringe Abweichungen führten immer wieder zu Rückschlägen im Markt, an denen etliche der aufgeführten Hersteller letztendlich gescheitert sind.

Schreibschutz im Page-Deskriptor

Erste Speicherschutzerweiterungen hat Intel bereits beim 80386 eingeführt. Dafür wurde ein Bit in den Page-Deskriptoren spendiert, mit denen sich eine Page zumindest schreibschützen ließ (R/W-Bit). Der damit erreichbare Effekt ist jedoch gering, da zum Beispiel der Stack-Bereich beschreibbar sein muss. Zum damaligen Zeitpunkt war aber die Problematik von sich im Daten- bzw. Stack-Bereich einnistenden Virenprogrammen nicht absehbar.

Ein weiteres S/U- (Supervisor/User-) Bit im Page-Deskriptor regelt den Zugriff nur für das Betriebssystem oder auch für Anwenderprogramme. Da jedoch auch Anwenderprogramme, die bei Windows zudem oft im Kontext des Administrators laufen, sehr viel Freiheit genießen, stellt dies keinen wirklichen Schutz gegen Angriffe dar.

Über die Segmentdeskriptoren ließe sich die Sicherheit erhöhen, da der Protected Mode vier Benutzerrechtsstufen (CPL 0..3, Current Privilege Level) unterscheiden kann. Windows und Linux nutzen davon jedoch nur zwei Stufen, CPL 0 für das System und CPL 3 für User. Die Segmentverwaltung ist zudem kompliziert und alle damit verbundenen Aktionen sind sehr zeitaufwendig. Die Umgehung der Segmentverwaltung galt daher bislang als erstrebenswertes Ziel für Programmierer.

Mit den vorhandenen Möglichkeiten können der i80386 und die meisten seiner Nachfahren nicht zwischen den Speicherzugriffen Codeworte lesen (CR) und Datenworte lesen (DR) unterscheiden. Ein Schutz vor einer Code-Einschleusung auf den Stack war daher bislang nicht möglich.

Speicherschutz beim i80386

Page Descriptor

Page Descriptor

Segment Descriptor

Erlaubte Zugriffsart

Bemerkung

S Supervisor, CR Code Read, DR Data Read, DW Data Write

Supervisor / User-Bit

Read / Write-Bit

Current Privilege Level

0

0

0, 1, 2

S CR DR DW

Supervisor-Recht, alle Zugriffe (R/W hier ohne Funktion!)

0

1

0, 1, 2

S CR DR DW

Supervisor-Recht, lesen und schreiben

1

0

3

-- CR DR --

User-Recht, nur lesen

1

1

3

-- CR DR DW

User-Recht, lesen und schreiben

Mehr Schutz durch NX-Bit

Mit dem Pentium brachte Intel eine Verbesserung des Speicherschutzes in Form des WP- (Write Protect) Bits. Es kann das Verhalten beim Paging umschalten, so dass das R/W-Bit auch im Supervisor-Mode einen Schreibzugriff verhindert. Erst dies erlaubt einen Schreibschutz von Supervisor-Seiten gegenüber dem System selbst. Dies war der erste Patch zu einem systematisch korrekteren Verhalten, der mit dem NX-Bit aktuell weiter ausgebaut wird.

Mit dem NX-Bit beim Athlon 64 erhält die Paging-Einheit eine weitere Verbesserung des Speicherschutzes, die eine genauere Unterscheidung der Speicherzugriffe erlaubt. NX ist als ein neues Bit an der obersten Stelle 63 des erweiterten Page-Deskriptors neu definiert und wird mit einer 1 aktiviert. Die Speicherseite eines solchermaßen aktivierten Page-Deskriptors darf keine Maschinencode-Leseoperationen (CR) mehr liefern. Legt ein Angreifer Code auf dem so geschützten Stack oder Datenbereich ab und versucht dann, diesen auszuführen, löst der Prozessor eine Exception aus.

Dieses NX-Bit steht allerdings nur im erweiterten Adressierungsmodus PAE zur Verfügung, der mit seinen längeren Page-Deskriptoren als inkompatible Änderung gegenüber dem 386 nicht unproblematisch ist.

Speicherschutz beim Athlon 64 mit NX-Bit

Page Descriptor

Page Desc.

Page Desc.

Segment Descriptor

Erlaubte Zugriffsart

Bemerkung

S Supervisor, CR Code Read, DR Data Read, DW Data Write, NX No Execution

Supervisor / User-Bit, Position 2

Read / Write-Bit, Position 1

NX-Bit, Position 63

Current Privilege Level

0

0

0

0, 1, 2

S CR DR --

Supervisor-Recht, nur lesen

0

1

0

0, 1, 2

S CR DR DW

Supervisor-Recht, lesen und schreiben

1

0

0

3

-- CR DR --

User-Recht, nur lesen

1

1

0

3

-- CR DR DW

User-Recht, lesen und schreiben

0

0

1

0, 1, 2

S -- DR --

Supervisor-Recht, nur Daten lesen

0

1

1

0, 1, 2

S -- DR DW

Supervisor-Recht, nur Daten lesen und schreiben

1

0

1

3

-- -- DR --

User-Recht, nur Daten lesen

1

1

1

3

-- -- DR DW

User-Recht, nur Daten lesen und schreiben

Für die Schutzbits NX und WP gibt es Flags in den Kontrollregistern des Prozessors, die deren Zusatzfunktion überhaupt erst freischalten. Dort lässt sich auch das Paging mit größeren Seiten im PSE- und PAE-Modus aktivieren.

Flags in Kontrollregistern

Funktion

Kontrollbit

Kontrollbit Register + Name

NX

EFER.NXE

Extended Feature Enable Register, NX-Enable

WP

CR0.WP

Write-Protect Enable

PSE

CR4.PSE

Page Size Extension Enable

PAE

CR4.PAE

Physical Adress Extension Enable

Windows XP SP2

Microsoft hat zur Verbesserung der Manipulationssicherheit in Windows XP mit dem Service Pack 2 und in Windows 2003 mit dem Service Pack 1 einige Verbesserungen eingeführt. Diese betitelt der Software-Konzern mit Data Execution Prevention (DEP), zu Deutsch "Datenausführungsverhinderung" recht treffend: DEP soll das Ausführen von Code aus Datenbereichen heraus verhindern. Zum Einsatz kommen dabei mehrere Verfahren, die je nach Schutzmaßnahme unter Hardware-DEP und Software-DEP zusammengefasst sind.

Für das Hardware-DEP steht an erster Stelle das bereits beschriebene NX-Bit beim Paging-Schutz des Prozessors. Beim Hardware-DEP schützt ein 32-Bit-Windows per default nur den Stack. Das 64-Bit-Windows geht einen Schritt weiter und sichert auch die dynamischen Speicherpools. Damit ist aber immer noch keine vollständige Abdeckung aller Daten erreicht. Versucht ein Programm, Code aus einem geschützten Datenbereich auszuführen, erzeugt die Hardware-DEP die Systemfehlermeldung "STATUS_ACCESS_VIOLATION (0xc0000005)".

Unter Software-DEP hat Microsoft mehrere Adresskontrollen an den Schnittstellen zum Betriebssystem zusammengefasst. Betrachtet man die Adresslage verschiedener Speicherbereiche eines Programms, ergibt sich standardmäßig folgende Reihenfolge der Blöcke: Code - Daten - Dynamische Puffer - Heap - Stack. Übergibt ein Programm bei einem Systemaufruf eine Adresse als Parameter, so kann das Betriebssystem prüfen, auf welchen der Blöcke die Adresse verweist. Stellt Windows dabei eine Inkonsistenz fest, bricht es das Programm ab.

Als wichtigstes Beispiel sei hier der Fall genannt, dass ein Programm einen Betriebssystemaufruf zur Anmeldung eines Interrupt-Vektors oder einer Callback-Routine macht. Software-DEP überprüft dabei, in welchem Block die anzumeldende Funktion abgelegt ist und akzeptiert keine Adressen aus Datenbereichen. Das Ausführen von Programmroutinen und demzufolge die Akzeptanz von Codevektoren wird somit ausdrücklich auf die Bereiche beschränkt, die der Compiler bei der Erstellung des Programms dafür angelegt hat.

Software-DEP für jedermann

Tritt der Sonderfall auf, dass ein Programm Code zur Laufzeit dynamisch erzeugt und diesen aufführen will, muss es dafür einen speziellen Speicherbereich anfordern. Dieser erhält bereits bei der Allocation eine extra Ausführungsberechtigung, so dass die Software-DEP bei einem Codesprung in diesen "Datenbereich" keinen Alarm schlägt.

Microsoft zählt die AMD64-Familie mit Opteron und Athlon 64 und den Intel Xeon mit EM64T als geeignete Prozessoren für Hardware-DEP auf. Bei allen anderen Prozessoren ist zumindest die Software-DEP einsetzbar, da sie keinerlei besondere Hardware voraussetzt. Beim Software-DEP sind in Zukunft weitere Verbesserungen zu erwarten, da das Windows-Programmiererteam die Bereichskontrollen an sehr vielen Stellen einsetzen kann. Letztlich muss der Hersteller die gesamte System-Software auf diese Möglichkeit hin durchforsten und umschreiben.

In Windows XP mit SP2 schützt Microsoft nur einen Teil der Betriebssystemroutinen und den Stack durch DEP. Das größte Problem bereitet dabei die bestehende und alte Software, die von diesen schon länger proklamierten und jetzt aktiv kontrollierten Regeln nichts wissen will. Dies gilt vor allem für Treiberprogramme, die zur Laufzeit spezielle Code-Patches und adaptierte Routinen erzeugen.

Ausnahmeregelung

Mit dem Anspruch, unsaubere Programme trotz der Kontrollkollision mit DEP noch ausführen zu können, sind Kompromisse nötig. Diese unterlaufen und entwerten das DEP, sind aber nötig, um die Kompatibilität von Betriebssystem und Anwendungsprogrammen zu erhalten.

Wenn ein Programm sich nicht an die Regeln zur Allocation von Speicher mit Ausführungsberechtigung hält und zudem eine eigene Codeladeroutine nutzt, muss das Betriebssystem zunächst von einer Virusaktivität ausgehen. Microsoft bietet aber verschiedene Optionen an, DEP abzuschwächen, um derartige Programme dennoch laufen lassen zu können.

Zum einen kann der User über die Systemeigenschaften im Unterpunkt "Erweitert / Systemleistung / Datenausführungsverhinderung" bei aktiviertem DEP einzelne Programme von der Prüfung ausschließen. Zum anderen kann man dort auch das globale Verhalten von DEP einstellen. Hier stehen allerdings nur zwei der vier Optionen offen.

Eine bessere Kontrolle erlaubt der manuelle Eintrag direkt in die boot.ini. Der Schalter /noexecute=policy_level steuert das Verhalten und bietet folgende Optionen:

Windows-Startoptionen in der boot.ini

policy_level

Beschreibung

OptIn (default Konfiguration)

Bei Systemen mit Hardware-DEP (NX-Prozessor) ist DEP aktiv für einige Systemroutinen und für Anwendungsprogramme, die DEP explizit einschalten.

OptOut

DEP wird generell eingeschaltet. Für Anwendungsprogramme kann DEP explizit in der Systemsteuerung oder durch Hilfsprogramme deaktiviert werden.

AlwaysOn

DEP ist immer an und kann weder global noch programmspezifisch ausgeschaltet werden. Dies ist der einzig wirklich sichere Modus, der aber Probleme verursachen kann.

AlwaysOff

Hierdurch wird DEP komplett ausgeschaltet, Windows XP verhält sich wie vor dem SP2. Selbst der PAE-Modus wird ohne ein explizites Einschalten durch die /PAE-Schaltoption nicht genutzt.

Erstaunlich ist, dass die Default-Konfiguration DEP nicht generell aktiviert ist. Für ein sicheres System sollte man auf jeden Fall "AlwaysOn" verwenden. Treten dabei Probleme auf, ist "OptOut" und der manuelle Ausschluss des kritischen Programms von der Prüfung die beste Wahl.

Fazit

Das NX-Bit der kommenden Prozessorgeneration steht nur im erweiterten Adressierungsmodus PAE zur Verfügung. Dieser Speicheradressierungsmodus schließt bei etlichen Betriebssystemen eine Nutzung generell aus. Davon betroffen sind zum Beispiel Windows Me und Windows 98. Da der neue Hardware-Schutz aber mit Windows XP, Windows Server 2003 und aktuellen Linux-Distributionen problemlos zusammenarbeitet, profitieren ein großer Teil der installierten Basis und alle PC-Neugeräte davon.

Die Notwendigkeit, die Prozessorarchitektur des x86 umzugestalten, bleibt jedoch weiterhin bestehen. Für einen präzise einsetzbaren Speicherblockschutz bräuchte eine MMU ein umfassendes und an allen Stellen einheitliches Schutzbitangebot. Bei vier Privilegienebenen und drei Speicherzugriffswegen würden dafür fünf Bit in jedem Deskriptor genügen. Doch die Hersteller der Prozessoren und der Betriebssysteme fürchten Inkompatibilitäten zur bestehenden Plattform.

Immerhin stehen den Betriebssystementwicklern mit dem WP-Bit und aktuell dem NX-Bit etliche Möglichkeiten zur Verbesserung der Sicherheit offen. Das derzeitige Einfallstor für viele Viren, die per Buffer Overflow Code in den Stack einschmuggeln, kann NX durchaus schließen. Bedingung dafür ist die korrekte Implementierung des PAE-Modus auf allen Systemebenen, insbesondere durch Updates aller systemnahen Software, Treiber und Utilities. Solange es aus Kompatibilitätsgründen eine Option gibt, DEP zur Laufzeit zu deaktivieren, bleibt der Schutz jedoch löchrig.

Aber auch ohne neue Hardware bieten Windows XP und das SP2 eine erweiterte Schutzfunktion. Die Plausibilitätskontrolle von Callback-Adressen via Software-DEP ist sicherlich ein nützliches Feature. Doch hilft sie wenig, wenn der User sie nicht explizit einschaltet.

Andere potenzielle Einfallsbereiche sind in Windows und Linux noch nicht abgesichert. Hier gilt es, die Betriebssysteme weiter nachzubessern. Insofern sind NX und das SP2 der Anfang einer strikten Entwicklung zu mehr Sicherheitsfunktionen und nicht deren Ende. (ala)