
Reproduktion des Retbleed (CVE-2022-29900/29901) Micro-Architectural-Angriffs in gem5. RSB-Underflow, Flush+Reload-Seitenkanal-Leak und eine verifizierte lfence-Mitigation.
Eine praktische Reproduktion von Retbleed (CVE-2022-29900 / CVE-2022-29901) — dem Mikroarchitektur-Angriff aus dem Jahr 2022, der die „Retpoline"-Verteidigung aushebelte, indem er bewies, dass ret-Instruktionen, die lange als sicher galten, gekapert werden können, wenn der Return Stack Buffer (RSB) der CPU unterläuft.
Dieses Projekt simuliert den vollständigen Angriffslebenszyklus auf einem x86-Out-of-Order-CPU-Modell in gem5: Auslösen eines RSB-Underflows, Ausleiten geheimer Daten Byte für Byte über einen Flush+Reload-Cache-Seitenkanal und anschließendes Verifizieren einer Software-Mitigation (lfence), die das Leck schließt.
Kursprojekt — Advanced Computer Architecture, Herbst 2025, CUNY City College Autoren: Abdul Kalam Mansoor & Rebiha Selmani
Spectre-artige Angriffe zeigten, dass spekulative Ausführung Side-Effects auf Cache-Ebene hinterlässt, selbst wenn die CPU eine falsche Vorhersage „rückgängig macht". Der Branchen-Fix — Retpoline — ersetzte gefährliche indirekte Sprünge durch ret-Instruktionen, unter der Annahme, dass Returns sicher aus einem kleinen Hardware-Stack (dem RSB) vorhergesagt werden. Retbleed zeigte, dass diese Annahme falsch ist: Erschöpft man den RSB durch tiefe Rekursion, fällt die CPU stillschweigend auf denselben unsicheren Prädiktor zurück, den Retpoline vermeiden sollte.
| Phase | Was passiert |
|---|---|
| 1. Auslösen | rsb_deep_call() rekursiert 32 Ebenen tief und überläuft den 16-Einträge-RSB. Wenn die Rekursion abgebaut wird, ist der RSB leer. |
| 2. Fallback | Mit leerem RSB fällt die CPU auf den Branch Target Buffer (BTB) zurück, um das ret-Ziel vorherzusagen — den ein Angreifer vergiften kann. |
| 3. Gadget | Der gekaperte spekulative Pfad führt gadget() aus, das ein Byte des geheimen Passworts liest und damit in probe_array indexiert, wodurch eine Seite dieses Arrays in den Cache geladen wird. |
| 4. Flush+Reload-Spion | Vor dem Angriff wird jede Seite von probe_array aus dem Cache geflusht (_mm_clflush). Nachdem das spekulative Fenster geschlossen ist, misst das Programm die Zugriffszeit auf jeden möglichen Byte-Wert (__rdtscp) — derjenige, der schnell zurückkommt (Cache-Hit), verrät das geheime Byte. |
Wiederholt man dies für jedes Byte von ROOT_PASSWORD, rekonstruiert man das gesamte Geheimnis, ohne jemals architektonisch gadget() aufzurufen.
| Modus | Zugriffslatenz | Ergebnis |
|---|---|---|
Verwundbar (SECURE_MODE undefiniert) | ~49 Zyklen (Cache-Hit) | Geheimnis Byte für Byte ausgeleitet, bestätigt durch rote HIT!-Indikatoren |
Gepatcht (SECURE_MODE definiert, _mm_lfence() injiziert) | >150 Zyklen (Cache-Miss / Rauschen) | Angriff schlägt fehl — Ausgabe zeigt SAFE / Found: ??? |
Das lfence zwingt die CPU, die Rücksprungadresse aufzulösen, bevor irgendeine nachfolgende Instruktion ausgeführt werden kann, wodurch das spekulative Fenster kollabiert, bevor das Gadget jemals geheimnisabhängigen Speicher berührt.
src/
retbleed.c # Full PoC: trigger, gadget, Flush+Reload spy, and lfence mitigation (toggle via SECURE_MODE)
docs/
Retbleed_Report.pdf # Full written report: methodology, related work, gem5 setup, results
Retbleed_Attack_Demonstration.pptx # Slide deck used to present the project
Der PoC wurde unter gem5 gebaut und gemessen (DerivO3CPU, ein Out-of-Order-Modell — erforderlich, da In-Order-Modelle keine spekulative Ausführung implementieren):
gcc -O0 -static -o retbleed src/retbleed.c
./build/X86/gem5.opt configs/deprecated/example/se.py \
--cpu-type=DerivO3CPU --caches --l2cache \
--l1d_size=64kB --l1i_size=64kB --cmd=retbleed
Um zwischen verwundbarem und gepatchtem Verhalten zu wechseln, kommentieren Sie diese Zeile am Anfang von retbleed.c aus bzw. ein:
#define SECURE_MODE
Der Code verwendet echte x86-Intrinsics (
_mm_clflush,__rdtscp,_mm_lfence) und kann auch nativ auf x86-Hardware kompiliert und ausgeführt werden (gcc -O0 -o retbleed src/retbleed.c) für eine schnellere Demo — die Ergebnisse variieren je nach den eigenen Mitigations der Host-CPU (eIBRS, Microcode-Patches usw.), was selbst eine nützliche Veranschaulichung dafür ist, wie gründlich diese Fehlerklasse seit 2022 gepatcht wurde.
lfences) verursachten 14–39 % Performance-Overhead auf betroffener Hardware.