
Der x86-Prozessor-Fuzzer
: der x86-Prozessor-Fuzzer
Der Sandsifter prüft x86-Prozessoren auf versteckte Instruktionen und Hardwarefehler, indem er systematisch Maschinencode generiert, um den Befehlssatz eines Prozessors zu durchsuchen und die Ausführung auf Anomalien zu überwachen. Sandsifter hat geheime Prozessorbefehle von allen großen Herstellern entdeckt; allgegenwärtige Softwarefehler in Disassemblern, Assemblern und Emulatoren; Schwachstellen in Enterprise-Hypervisoren; sowie sowohl harmlose als auch sicherheitskritische Hardwarefehler in x86-Chips.
Angesichts der Vielzahl existierender x86-Prozessoren besteht das Ziel des Tools darin, Nutzern zu ermöglichen, ihre eigenen Systeme auf versteckte Befehle und Fehler zu überprüfen.
Um einen grundlegenden Audit gegen Ihren Prozessor auszuführen:
sudo ./sifter.py --unk --dis --len --sync --tick -- -P1 -t

Der Computer wird systematisch nach anomalen Instruktionen durchsucht. In der oberen Hälfte sehen Sie die Instruktionen, die der Sandsifter gerade auf dem Prozessor testet. In der unteren Hälfte meldet der Sandsifter gefundene Anomalien.
Die Suche dauert je nach Geschwindigkeit und Komplexität Ihres Prozessors zwischen einigen Stunden und einigen Tagen. Wenn sie abgeschlossen ist, fassen Sie die Ergebnisse zusammen:
./summarize.py data/log

Typischerweise werden mehrere Millionen undokumentierte Instruktionen auf Ihrem Prozessor gefunden, diese fallen jedoch im Allgemeinen in eine kleine Anzahl verschiedener Gruppen. Nachdem die Anomalien gruppiert wurden, versucht das Zusammenfassungstool, jede Instruktion einer Problemkategorie zuzuordnen:
Drücken Sie 'Q', um zu beenden und eine textbasierte Zusammenfassung des Systemscans zu erhalten:
Die Ergebnisse eines Scans können für die Tools manchmal schwer automatisch zu klassifizieren sein und erfordern möglicherweise manuelle Analyse. Für Hilfe bei der Analyse Ihrer Ergebnisse können Sie die Datei ./data/log gerne an [email protected] senden. Keine persönlichen Informationen, außer der Prozessor-Hersteller, -Modell und -Revision (aus /proc/cpuinfo) sind in diesem Log enthalten.
Das Scannen mit dem Sandsifter hat undokumentierte Prozessorfunktionen in Dutzenden von Opcode-Kategorien, Fehler in Enterprise-Hypervisoren, Fehler in nahezu jedem großen Disassemblierungs- und Emulationswerkzeug sowie kritische Hardwarefehler aufgedeckt, die Sicherheitslücken im Prozessor selbst öffnen.
Details der Ergebnisse finden Sie im Projekt- Whitepaper.
(TODO: detaillierte Aufzählung der Ergebnisse hier)
Sandsifter erfordert die vorherige Installation des Capstone-Disassemblers: http://www.capstone-engine.org/. Capstone kann normalerweise mit installiert werden:
sudo apt-get install libcapstone3 libcapstone-dev
sudo pip install capstone
Sandsifter kann mit gebaut werden:
make
und wird dann ausgeführt mit
sudo ./sifter.py --unk --dis --len --sync --tick -- -P1 -t
Flags werden mit --flag an den Sifter und mit -- -f an den Injektor übergeben.
Beispiel:
sudo ./sifter.py --unk --dis --len --sync --tick -- -P1 -t
Sifter-Flags:
--len
Suche nach Längenunterschieden in allen Instruktionen (Instruktionen, die
sich anders ausgeführt haben als vom Disassembler erwartet, oder nicht
existierten, als der Disassembler sie erwartete)
--dis
Suche nach Längenunterschieden in gültigen Instruktionen (Instruktionen, die
sich anders ausgeführt haben als vom Disassembler erwartet)
--unk
Suche nach unbekannten Instruktionen (Instruktionen, die der Disassembler nicht
kennt, aber erfolgreich ausgeführt werden)
--ill
die Umkehrung von --unk, Suche nach ungültigen Disassemblierungen (Instruktionen, die
nicht erfolgreich ausgeführt werden, die der Disassembler aber anerkennt)
--tick
schreibt periodisch die aktuelle Instruktion auf die Festplatte
--save
Speichert den Suchfortschritt beim Beenden
--resume
Setzt die Suche ab dem zuletzt gespeicherten Zustand fort
--sync
Schreibt Suchergebnisse sofort auf die Festplatte, sobald sie gefunden werden
--low-mem
Speichert Ergebnisse nicht im Arbeitsspeicher
Injektor-Flags:
-b
Modus: Brute-Force
-r
Modus: Randomisiertes Fuzzing
-t
Modus: Tunnel-Fuzzing
-d
Modus: Extern gesteuertes Fuzzing
-R
Rohausgabe-Modus
-T
Textausgabe-Modus
-x
Schreibt periodischen Fortschritt nach stderr
-0
Erlaube Null-Dereferenzierung (erfordert sudo)
-D
Erlaube doppelte Präfixe
-N
Kein NX-Bit-Support
-s seed
Bei zufälliger Suche, Startwert
-B brute_depth
Bei Brute-Force-Suche, maximale Suchtiefe
-P max_prefix
Maximale Anzahl zu durchsuchender Präfixe
-i instruction
Instruktion, bei der die Suche beginnen soll (inklusiv)
-e instruction
Instruktion, bei der die Suche enden soll (exklusiv)
-c core
Kern, auf dem die Suche ausgeführt werden soll
-X blacklist
Die angegebene Instruktion auf die schwarze Liste setzen
-j jobs
Anzahl der gleichzeitig auszuführenden Jobs
-l range_bytes
Anzahl der Basisinstruktionsbytes in jedem Unterbereich
m: Modus - ändert den Suchmodus (Brute-Force, Zufall oder Tunnel) für den Sifter
q: Beenden - beendet den Sifter
p: Pause - pausiert oder hebt die Pause der Suche auf
Das Scannen unterstützt vier verschiedene Suchalgorithmen, die über die Befehlszeile eingestellt oder über Hotkeys umgeschaltet werden können.
sudo
Für beste Ergebnisse sollte das Tool als root-Benutzer ausgeführt werden. Dies ist notwendig, damit der Prozess eine Seite an Adresse 0 in den Speicher einblenden kann, was Root-Rechte erfordert. Diese Seite verhindert, dass viele Instruktionen bei Speicherzugriffen einen Segfault verursachen, was eine genauere Fehleranalyse ermöglicht.
Präfixe
Die hauptsächliche Einschränkung für die Tiefe einer Instruktionssuche ist die Anzahl der zu untersuchenden Präfixbytes, wobei jedes zusätzliche Präfixbyte den Suchraum um etwa einen Faktor 10 vergrößert. Begrenzen Sie die Präfixbytes mit dem -P-Flag.
Farben
Die Schnittstelle des Sifters ist für ein 256-Farben-Terminal ausgelegt. Während die Details je nach Terminal stark variieren, kann dies grob mit erreicht werden:
export TERM='xterm-256color'
GUI
Die Schnittstelle setzt voraus, dass das Terminal mindestens eine bestimmte Größe hat; wenn die Schnittstelle nicht richtig dargestellt wird, versuchen Sie, die Terminalgröße zu vergrößern; dies kann oft durch Verkleinern der Terminal-Schriftgröße erreicht werden.
In einigen Fällen kann es wünschenswert oder notwendig sein, das Tool ohne die grafische Oberfläche auszuführen. Dies kann durch direktes Ausführen des Injektors erfolgen:
sudo ./injector -P1 -t -0
Um die Ergebnisse eines direkten Injektor-Aufrufs zu filtern, kann grep verwendet werden. Zum Beispiel,
sudo ./injector -P1 -r -0 | grep '\.r' | grep -v sigill
durchsucht nach Instruktionen, bei denen Prozessor und Disassembler sich über die Instruktionslänge uneinig waren (grep '.r'), die Instruktion aber erfolgreich ausgeführt wurde (grep -v sigill).
Gezieltes Fuzzing
In vielen Fällen ist es wertvoll, den Fuzzer auf ein bestimmtes Ziel zu lenken. Wenn Sie beispielsweise vermuten, dass ein Emulator Fehler bei wiederholten 'lock'-Präfixen (0xf0) aufweist, könnten Sie den Fuzzer mit den Flags -i und -e auf diesen Bereich des Instruktionsraums lenken:
sudo ./sifter.py --unk --dis --len --sync --tick -- -t -i f0f0 -e f0f1 -D -P15
sandsifter ist ein Forschungsprojekt von Christopher Domas (@xoreaxeaxeax).
Legacy-Systeme
Zum Scannen viel älterer Systeme (i586-Klasse-Prozessoren, Systeme mit wenig Speicher) übergeben Sie das --low-mem-Flag an den Sifter und das -N-Flag an den Injektor:
sudo ./sifter.py --unk --dis --len --sync --tick --low-mem -- -P1 -t -N
Wenn Sie beobachten, dass Ihre Scans zu schnell abgeschlossen werden (z. B. ein Scan in Sekunden), liegt dies typischerweise daran, dass diese Flags für den von Ihnen gescannten Prozessor erforderlich sind.
32 vs. 64 Bit
Standardmäßig ist Sandsifter so gebaut, dass es auf die Bitanzahl des Host-Betriebssystems abzielt. Einige Instruktionen haben jedoch ein anderes Verhalten, wenn sie in einem 32-Bit-Prozess ausgeführt werden, verglichen mit einem 64-Bit-Prozess. Um diese Szenarien zu erkunden, ist es manchmal wertvoll, einen 32-Bit-Sandsifter auf einem 64-Bit-System auszuführen.
Um einen 32-Bit-Sandsifter auf einem 64-Bit-System zu bauen, muss Capstone als 32-Bit installiert werden; die Anweisungen hierfür finden Sie unter http://www.capstone-engine.org/.
Dann muss Sandsifter für eine 32-Bit-Architektur gebaut werden:
make CFLAGS=-m32
Damit kann der 32-Bit-Instruktionsraum auf einem 64-Bit-System erkundet werden.