Vista Update Crash beheben und vermeiden.

Da staunte ich nicht schlecht. So dachte ich bisher, das ein Windows Update meinem Betriebssystem nicht schaden könnte. Nunja, gestern wurde ich eines anderen belehrt. Nachdem ich manuell meine Auswahl an Patches installiert hatte, boote Vista zwar, hing allerdings im dritten Updateschitt fest und startete neu. Genauer gesagt das System stürzte ab. Und das ständig bei jedem neuen Versuch. Ärgerlich. Hatte ich eigentlich gestern Nacht etwas anderes vor. F8 mit Trallala half auch nicht.

Ich muss sagen, das Problem schien gestern bei mehreren aufzutreten, zumindest laß ich in einigen Foren etwas darüber, vor allem, das die Leute ihre Maschine neu aufsetzen wollten. Das ist natürlich immer eine Option, allerdings in meinem Falle wirklich die Letzte.

Ich danke Microsoft für ihren tollen Internetsupport. Die Lösung zu dem Windows Update Crash hätte ich so ohne weiteres nicht selbst herausgefunden. Dazu dieser Link:

http://support.microsoft.com/kb/949358/

Bei mir half Methode 3, ich hoffe allen Lesern bleibt das Problem erspart. Methode 1 und 2 funktionieren, vielleicht bei anderen Problemteilnehmern. :-)

Falls der Link eines Tages mal nicht erreichbar sein sollte, hier ein Auszug aus der Internetseite von den obigen gezeigten Link:

Methode 3: Umbenennen der Datei “Pending.xml” und anschließendes Bearbeiten der Registrierung

Hinweise Lesen Sie die folgenden wichtigen Hinweise, bevor Sie diese Problembehandlungsmethode anwenden.

  • Mit dieser Methode können Sie das im Abschnitt “Problembeschreibung” beschriebene Startproblem beheben, um Ihre Daten zu sichern, bevor Sie Windows neu installieren. Sie sollten diese Problembehandlungsmethode nur anwenden, wenn Sie vorhaben, Ihre Daten zu sichern und dann Windows neu zu installieren.
  • Wenden Sie diese Methode erst an, wenn Sie zuvor die anderen Methoden versucht haben.Hinweis Wenn der Computer nicht zum Starten von CD oder DVD konfiguriert ist, lesen Sie die Informationen hierzu in der mit dem Computer gelieferten Dokumentation.
  • Wenden Sie diese Methode nur an, wenn der Computer keine Wiederherstellungspunkte aufweist, oder wenn Sie den Computer nicht an einem Punkt starten können, an dem das Feature Systemwiederherstellung verfügbar ist.
  • Nach der Anwendung dieser Methode können bis zur Neuinstallation von Windows die folgenden Bedingungen vorliegen:
    • Ein Update, das installiert wird, wird möglicherweise nicht korrekt installiert.
    • Windows Update funktioniert möglicherweise nicht korrekt.
    • Wenn ein Update installiert wird, können Sie möglicherweise den Installationsvorgang nicht beenden.
    • Sie sind möglicherweise nicht in der Lage, bestimmte optionale Windows-Features zu aktivieren oder zu deaktivieren.
    • Bestimmte optionale Windows-Features funktionieren möglicherweise nicht korrekt.
    • Der Computer ist möglicherweise in einem ungeschützten Zustand.

Gehen Sie folgendermaßen vor, um die Datei “Pending.xml” umzubenennen und dann die Registrierung zu bearbeiten:

Starten Sie Windows Vista, und gehen Sie zu den Systemwiederherstellungsoptionen:

  1. Legen Sie das Windows Vista-Installationsmedium in das Laufwerk ein, und starten Sie den Computer neu.
  2. Wenn Sie gefragt werden, ob der Computer vom Datenträger neu gestartet werden soll, drücken Sie eine beliebige Taste.
  3. Konfigurieren Sie auf Aufforderung die von Ihnen gewünschten Optionen für Installationssprache, Uhrzeit und Währungsformat sowie Tastatur oder Eingabemethode, und klicken Sie auf Weiter.
  4. Klicken Sie auf der Seite Windows installieren auf Computer reparieren.
  5. Klicken Sie auf der Seite Systemwiederherstellungsoptionen auf die Version des Windows Vista-Betriebssystems, die Sie reparieren möchten, und klicken Sie auf Weiter.

Verwenden Sie die Systemwiederherstellungsoptionen, um die Datei “Pending.xml” umzubenennen und die Registrierung zu bearbeiten:

  1. Klicken Sie auf der Seite Systemwiederherstellungsoptionen auf Eingabeaufforderung.
  2. Geben Sie cd C:\windows\winsxs ein, und drücken Sie die [EINGABETASTE].
  3. Geben Sie ren pending.xml pending.old ein, und drücken Sie die [EINGABETASTE].
  4. Geben Sie regedit ein, und drücken Sie die [EINGABETASTE].
  5. Wählen Sie HKEY_LOCAL_MACHINE aus.
  6. Klicken Sie im Menü Datei auf Struktur laden.
  7. Gehen Sie zu folgendem Ordner:
    C:\windows\system32\config\components
  8. Wenn Sie zur Eingabe eines Namens aufgefordert werden, geben Sie Offline_Components ein.
  9. Suchen Sie im Registrierungs-Editor den folgenden Registrierungsteilschlüssel, und löschen Sie ihn:
    HLKM\Offline Components\AdvancedInstallersNeedResolving
    HKLM\Offline Components\PendingXmlIdentifier

Beenden Sie den Registrierungs-Editor:

  1. Geben Sie exit an der Eingabeaufforderung ein, um den Registrierungs-Editor zu beenden.
  2. Drücken Sie die EINGABETASTE.
  3. Klicken Sie auf Neu starten.

Auf der Seite von Microsoft gibt es zu diesem Problem Patches. Diese müssen einzeln seperat eingespielt werden.

Windows Vista x86 Systeme: http://www.microsoft.com/downloads/details.aspx?displaylang=de&FamilyID=5639710d-dfbf-4527-806e-9a1634d0cc8e

Windows Vista x64 Systeme: http://www.microsoft.com/downloads/details.aspx?displaylang=de&FamilyID=54235949-b5db-4fe2-a841-ef938217b285

Ein frohes Weiterarbeiten!

Gruß
42fx

Posted in IT | Tagged , , , , , | Kommentare deaktiviert

Das Problem von Null-Bytes im Shellcode

Soll ein Shellcode in ein Programm übergeben werden, so wird dies meist mit den C-Funktionen sprintf(), read() und strcpy() in dem Speicher der Applikation injiziert. Den meisten Programmieren ist bekannt, das diese Stringfunktionen der Sprache C davon ausgehen, das der zu verarbeitende String durch ein NULL-Byte abgeschlossen bzw. terminiert wird. Genau diesem Fakt liegt ein Problem zu Grunde, möchte ein Angreifer seinen Shellcode durch eine dieser Funktionen dem Opferprogramm übergeben. Der Shellcode darf keine NULL-Bytes beinhalten, da ansonsten der Rest des Shellcodes nicht ausgeführt wird. Das NULL-Byte im Programmcode wird als String-Termination erkannt. Der nachfolgende Code wird verworfen.

Natürlich gibt es zu diesem Problem eine Abhilfe. Der Programmierer vermeidet durch einen Trick, das sein Shellcode NULL-Bytes beinhaltet. Auf diese Weise kann der Code vollständig übergeben werden, ohne das es eine böse Überraschung durch beispielsweise UNIX-Systemaufrufe gibt. Soll der Shellcode beispielsweise einen Systemaufruf vollführen und dabei ein Parameter an das Programm übergeben, so muss dieser String NULL-terminiert sein. Jedoch darf die C-Funktion dieses Stück nicht als Abschluß der Eingabe interpretieren.

Hierzu ein kleines Beispiel. Möchte der Programmierer ein normales Programm in Assembler schreiben, nehmen wir das bekannte “Hello world!”, so könnte er folgendermaßen den String definieren:

“Hello world!”,0×00

Selbstverständlich haben wir nun einen Shellcode, der ein NULL-Byte enthält, das sollte vermieden werden. Um jetzt das Problem zu umgehen, läßt der Programmierer den String zur Laufzeit terminieren, indem er ein NULL-Bytean das Ende stellt. Hierzu ein Beispiel.

XOR EAX, EAX
MOV BYTE [EBX + 13], AL

Nun wird das Register EBX als Pointer auf den String “Hello world!” verwendet. Der Programmierer setzt nun den Inhalt von EAX gleich 0 bzw. NULL, indem er sich der XOR Operation bedient und diese mit dem Register selbst ausführt. Auf diese Weise ist egal, welcher Wert sich vorher dort befand, das Ergebnis ist dannach 0 bzw. NULL. Anschließend schreibt der Programmierer AL, das sind 8-Bit aus dem 32-Bit EAX Register, an den Offset 13 unseres Strings. Nachdem der Programmierer diese Anweisungen ausgeführt hat, ist der String “Hello world!” NULL-terminiert, ohne das ein NULL-Byte im Programmcode vorkommt.

Wählt der Programmierer die falschen Register oder Datentypen, so kann das Ergebnis des Shellcodes NULL-Bytes enthalten. Die ASM-Anweisung MOV EAX, 1 wird beispielsweise im Compiler in

MOV EAX, 0×00000001

umgewandelt. Der Programmierer hat explizit angewiesen, das 32-Bit Register EAX mit 1 zu belegen, der Compiler erzeugt eine entsprechendes Übersetzungsergebnis. Wenn der Programmierer statt EAX das 8-Bit Register AL verwendet, so steht keine NULL-Byte im Shellcode, ausgeliefert vom Compiler. Es wird von einem Register kopiert, das einen Wert, den der Programmierer haben möchte, beinhaltet. Durch die XOR-Operation wurde der Wert entsprechend gesetzt. Der Programmierer muss kein NULL-Byte übertragen, da die XOR Anweisung ein NULL-Byte als Ergebnis im Register herstellt, dieses nun im EAX Register zur Verfügung steht. Wenn nur 8 Bit davon gebraucht werden, so zieht sich der Programmierer diese 8-Bit mit dem AL Register, ein Teilstrück von EAX, heraus.

Posted in Sicherheit | Tagged , , , , , , | Kommentare deaktiviert

Prozessoren und Programmierstil – Gefahrenquelle für Pufferüberläufe

Gefahrenquellen für Pufferüberläufe gibt es in den Programmiersprachen C und C++ häufig. Auch der Stil, wie der Programmierer ein Programm gestaltet, hat maßgeblich Einfluß auf die Wahrscheinlichkeit von Pufferüberläufen durch einen Angreifer.

Die Eigentümlichkeiten, der am häufigsten eingesetzten Prozessoren, wie auch die Besonderheiten der Sprachen C und C++, machen das Auftreten von Pufferüberläufen für wahrscheinlich. Programme geschrieben in diesen Sprachen bestehen zum Teil aus Unterprogrammen. Diese besitzen lokale Variablen.

Bei den heutigen modernen Prozessoren ist es üblich, die Rücksprungadresse eines Unterprogramms und die lokalen Variablen auf den Stack zu legen. Der Stack ist ein Stapel, der nach dem LIFO Prinzip arbeitet. Dabei werden bei dem Aufruf des Unterprogramms zunächst die Rückkehradresse und anschließend die lokalen Variablen auf den Stack gespeichert. Bei Prozessoren der modernen Generation, wie beispielsweise dem Intel Pentium, wird der Stack durch eingebaute Befehle in der CPU verwaltet. Der Stack wächst zwingend nach unten. Werden Datenfelder oder Zeichenketten (Strings) in den lokalen Variablen verwendet, werden sie meist nach oben geschrieben. Wird nun die Feldgrenze nicht überprüft, so kann der Angreifer damit durch das Überschreiten des Feldes die Rückkehradresse auf dem Stack erreichen und diese gegebenenfalls absichtlich verändern. Wenn dies gelingt, springt das Unterprogramm nicht zur vorgesehenen Adresse zurück.

Dazu ein beliebtes Beispiel. Das folgendes Programmstück in C zeigt die Gefahr eines Pufferüberlaufes:

void eingabe_zeichenkette()
{   char zeichenkette[2342];        // Das Feld ist eigentlich ein Zeiger
    if ( gets (zeichenkette) )      // gets bekommt den Zeiger
                                    // an dieser Stelle gibt es keine
                                    // Überprüfung!!
        schau_kette_an (zeichenkette);
}

Bei Mikroprozessoren, die den Stack weiter nach unten wachsen lassen, sieht der Stack vor dem Aufruf von der Funktion gets folgendermaßen aus:

+++++++++++++++++++++++
+  Rücksprungadresse  +
+++++++++++++++++++++++
+  2342. Zeichen      +
+++++++++++++++++++++++
+  . . .              +
+++++++++++++++++++++++
+  . . .              +
+++++++++++++++++++++++
+  3. Zeichen         +
+++++++++++++++++++++++
+  2. Zeichen         +
+++++++++++++++++++++++
+  1. Zeichen         +  <---- Stackpointer
+++++++++++++++++++++++

Der Stack wächst hier nach unten, die Variable wird nach oben überschrieben. Würde der Angreifer eine Kopie des Programms besitzen, das er genauer analysieren kann, so könnte er weitaus mehr Code überschreiben und dem Programm völlig neue Fähigkeiten übergeben. Auf diese Weise lassen sich auch größere Menge Code in ein System einschleusen.

Betrachte man nochmals unser Beispiel. Die Funktion gets, aus der C Standardbibliothek, liest eine Zeile von der Eingabe ein und schreibt diese Zeichen ab zeichenkette[0] in den Stack hinein. Jedoch prüft die Funktion gets die Länge der Zeichen nicht. Sollte die Eingabe länger sein, als der dafür vorgesehene Speicher, so bemerkt das gets nicht.

Die Funktion gets erhält, ganz nach der Semantik von C, nur die Speicheradresse als Pointer. Dabei fehlt völlig die verfügbare Länge der Zeichenkette. Wenn man nun jetzt 2346 Zeichen eingibt, so überschreiten die letzten 4 Bytes die Rücksprungadresse. Es wird hier angenommen, das eine Adresse 32 Bit lang ist, also 4 Bytes. Der Angreifer, kann in den ersten 2342 Bytes ein von ihm gestaltetes Programm eingeben und nur mithilfe der Manipulation der Rücksprungadresse dieses zur Ausführung bringen.

Schaue man sich nun den Stackaufbau in der modifizierten Art an.

++++++++++++++++++++++++++++++++++++
+  modifizierte Rücksprungadresse  +
++++++++++++++++++++++++++++++++++++
+ line, 2342. Zeichen              +
++++++++++++++++++++++++++++++++++++
+ . . .    . . .                   +
++++++++++++++++++++++++++++++++++++
+ line, 5. Zeichen 3. Byte im Code +
++++++++++++++++++++++++++++++++++++
+ line, 4. Zeichen 2. Byte im Code +
++++++++++++++++++++++++++++++++++++
+ line, 3. Zeichen                 +  <-- Ziel der Rücksprungadresse
++++++++++++++++++++++++++++++++++++      Hier Programmcodestart.
+ line, 2. Zeichen                 +
++++++++++++++++++++++++++++++++++++
+ line, 1. Zeichen                 +  <-- Stackpointer
++++++++++++++++++++++++++++++++++++

Der Angreifer kann durch diese Fähigkeit versuchen weitere Informationen über das System zu erlangen. Würde Beispielsweise es sich hierbei um ein UNIX System handeln und der betroffene Prozess besitzt bereits root-Rechte so kann der Angreifer die Dateien /etc/passwd und /etc/shadow auslesen und daraus versuchen die Kennwörter wiederherzustellen. Sehr alte UNIX Derivate legen sogar diese Kennwörter unverschlüsselt ab. In diesem Fall steht anschließend dem Systemzugriff nichts mehr im Wege.

Posted in Sicherheit | Tagged , , , , , , , , , , , , , , , , , , , , | Kommentare deaktiviert

Pufferüberläufe durch den Einsatz von Programmiersprachen

Eine Ursache für Pufferüberläufe ist der Einsatz von Programmiersprachen, die nicht die Fähigkeit besitzen, die Grenzen von Speicherbreichen zu überwachen. Damit wird eine Bereichsüberschreitung von Speicherbereichen nicht verhindert, bzw. bemerkt. Zu dieser Gruppe von Programmiersprachen gehört besonders die Sprache C. Diese Sprache legt das Hauptgewicht auf Performance. Ursprünglich lag ebenso auch ein gewisses Gewicht auf die Einfachheit des Compilers. C sowie auch die Weiterentwicklung C++ verzichtet auf die Überwachung von Speichergrenzen. Der Programmierer ist teilweise gezwungen den entsprechenden Code zur Überwachung von Hand zu schreiben. Der Programmierer verzichtet manchmal absichtlich oder aber auch aus Nachlässigkeit auf diesen zusätzlichen Code. Zudem kommt es ebenso auch vor, das der Code zur Überwachung fehlerhaft implementiert wird, bzw. dieser Code nicht oder nur unzureichend getestet wird. Neben dieser Problematik stellt im Falle von C++ der komplexe Sprachumfang und die Standardbibliothek sehr viele Konstrukte zur Verfügung, die fehleranfällig sind, zu denen es in vielen Fällen kaum eine Alternative gibt.

Die Programmiersprache C++ bietet im professionellen Bereich nur eingeschränkte Möglichkeiten zur selbsttätigen Überprüfung von Feldgrenzen. Ursprünglich wurde sie als C-Aufsatz entwickelt und stellt eine vollständige Obermenge der Programmiersprache C dar. Hierbei läßt sich das Risiko von Pufferüberläufen bei der Verwendung von modernen Sprachmitteln, wie der automatischen Speicherverwaltung, weitestgehend vermieden.

Jedoch wird von diesen Möglichkeiten nicht immer Gebrauch gemacht. Das liegt zumal an der Gewohnheit des Entwicklers, an Kompatibilitätsgründe zu vorhandenem älteren C-Code und an Systemaufrufen, die aus Performancegründen, in C-Konvention geschrieben worden sind.

In C bzw. C++ sind Laufzeitüberprüfungen dieser Art nicht vorhanden. Bei Sprachen, wie beispielsweise Turbo Pascal oder ADA sind Überprüfungen zur Laufzeit Bestandteil der Sprache. Jedoch kann der Entwickler auch in C++ bzw. C in einigen Anwendungsfällen diese Überprüfungen mit Smart Pointern nachrüsten.

Die meisten Programmiersprachen definieren unter anderem auch Standardbibliotheken. Dies bedeutet bei der Wahl einer Sprache meist auch die Verwendung der entsprechenden Standardbibliotheken, die sich nicht immer sicher einsetzen lassen.

Im Fall der Programmiersprache C und C++ enthält die Standardbibliothek eine Menge von gefährlichen Funktionen, die zum Teil gar keine sichere Verwendung zulassen und zu denen zum Teil keine Alternativen bestehen. Jedoch gibt es zu diesen nur zum Teil eine Alternative.

Um die Gefahr von Pufferüberläufen durch die Verwendung von Programmiersprachen zu verringern oder auszuschließen, können Sprachen eingesetzt werden, die konzeptionell sicherer als C oder C++ sind. Ein sehr viel geringeres Risiko besteht zum Beispiel bei den Programmiersprachen der Pascal Familie, wie ADA, Delphi und Modula. Fast ausgeschlossen sind Pufferüberläufe bei der Programmiersprache Java. Hier wird ständig die Ausführung des Bytecodes überwacht. Dies heißt jedoch nicht, das dieses Problem niemals auftritt, denn auch in Java gibt es Pufferüberläufe. Die Ursache liegt im Luafzeitsystem mehrerer JRE Versionen.

Posted in Sicherheit | Tagged , , , , , , , , , , , | Kommentare deaktiviert

Welche Gefahren existieren durch Pufferüberläufe?

Generell kann gesagt werden, das ein Pufferüberlauf zu einem Absturz des betreffenden Programms führen kann. Bei einem Pufferüberlauf werden die Anwendungsdaten verfälscht. Dies kann zur Beschädigung der Datenstrukturen der Software in der Laufzeitumgebung führen.

Letztere Aktion kann die Rücksprungadresse eines Unterprogramms mit beliebigen Daten überschreiben. Durch diese Manipulation kann ein Angreifer durch die Übermittlung von beliebigen Maschinencode mit beliebigen Assemblerbefehlen einen injezierten Codeblock in einem anfälligen Prozess ausführen. Dieser Code arbeitet selbstverständlich mit den Privilegien des manipulierten Prozesses. Der eingeschleuste Programmcode hat in der Regel das Ziel, dem Angreifer einen Zugang zum System zu verschaffen. Auf diese Weise ist es möglich beispielsweise eine root-Shell für die Fernadministration zu erzeugen. Auch Malware, bzw, Würmer verwenden diese Angriffstechnik in weit verbreiteten Server- und Clientprogrammen.

Möglicherweise ist das begehrteste Ziel bei UNIX-System der Root-Zugang. Der Angreifer hat damit sämtliche Zugriffsrechte und kann beliebige weitere Manipulationen durchführen, bzw. ebenso auch weitere Spuren verwischen. Oft wird missverstanden, das ein Pufferüberlauf, der nur zu den Rechten eines normalen Benutzers führt ungefährlich ist. Oft ist das Erreichen des so begehrten Root-Zugangs einfacher, wenn der Angreifer bereits Benutzerrechte besitzt. Das Stichwort lautet: Rechteerweiterung bzw. Privilege escalation.

Ebenso sind Angriffe auf Basis von Pufferüberläufen ein wichtiges Thema in der IT-Sicherheit und der Netzwerksicherheit. Diese Art von Angriffen können nicht nur über jegliche Bautypen von Netzwerken versucht werden, sondern ebenso auch lokal auf dem System selbst. Behoben werden diese Probleme meistens kurzfristig durch die Auslieferung von Fehlerkorrekturen bzw. Patches der Hersteller.

Neben Fehler in der Programmierung einer Software, die auch durch Nachlässigkeiten verursacht werden können, werden Pufferüberläufe vor allem durch auf der Von-Neumann-Architektur basierenden Rechnersystemen ermöglicht. Hier liegen Daten und Programm im gleichen Speicher. Diese Hardwarenähe ist unter Assembler, wie auch unter C ein Problem. Auch andere Programmiersprachen sind betroffen. Interpretierte Sprachen, wie beispielsweise Java sind, abgesehen von Fehler in den Interpretern, in der Regel nicht anfällig. Diese Interpreter haben normalerweise die vollständige Kontrolle über die Speicherbereiche der Daten.

Posted in Sicherheit | Tagged , , , , , , , , , , , , , , , , , , , , | Kommentare deaktiviert

Was sind Pufferüberläufe oder auch Buffer Overflows?

Die Pufferüberläufe, auch sehr häufig Buffer Overflows genannt, gehören zu den häufigsten Sicherheitslücken bzw. Sicherheitsproblemen in aktuellen Softwareprodukten. Diese Überläufe lassen sich unter anderem über das Internet ausnutzen, um speziellen Code in ein Programm einzuschleusen, der durch geschickte weitere Manipulationen ausgeführt wird.

Der Pufferüberlauf wird im westentlichen dazu verwendet, durch einen Fehler in einem Programm, Datenmengen in einen dafür reservierten Speicherbereich, einem Puffer, zu schreiben. Mit diesem Vorgang werden die nachfolgenden Informationen im Ziel-Speicherbereich überschrieben.

Von einem Pointer Overflow wird gesprochen, wenn keine Datenblöcke geändert werden, sondern nur eine Zieladresse eines einzelnen Datensatzes. Hier wird nach einem Zeiger (Pointer), der anzeigt, wo der Datensatz im Puffer hingeschrieben werden soll, verändert.

Posted in Sicherheit | Tagged , , , , , , , , , | Kommentare deaktiviert

Hello world!

Willkommen bei 42fx.de Diese Website behandelt einige einfache Bereiche der Informationstechnik.

Posted in IT | Kommentare deaktiviert