
Reproducción del ataque microarquitectónico Retbleed (CVE-2022-29900/29901) en gem5. Desbordamiento de RSB, fuga por canal lateral Flush+Reload y una mitigación lfence verificada.
Una reproducción práctica de Retbleed (CVE-2022-29900 / CVE-2022-29901) — el ataque microarquitectónico de 2022 que rompió la defensa "Retpoline" al demostrar que las instrucciones ret, consideradas seguras durante mucho tiempo, pueden ser secuestradas cuando el Return Stack Buffer (RSB) de la CPU se desborda.
Este proyecto simula el ciclo de vida completo del ataque sobre un modelo de CPU x86 Out-of-Order en gem5: desencadenar un desbordamiento del RSB, filtrar datos secretos byte a byte a través de un canal lateral de caché Flush+Reload, y luego verificar una mitigación por software (lfence) que cierra la fuga.
Proyecto de curso — Arquitectura Avanzada de Computadoras, Otoño 2025, CUNY City College Autores: Abdul Kalam Mansoor & Rebiha Selmani
Los ataques estilo Spectre demostraron que la ejecución especulativa deja efectos secundarios a nivel de caché incluso cuando la CPU "deshace" una predicción errónea. La solución de la industria — Retpoline — reemplazó los saltos indirectos peligrosos con instrucciones ret, bajo la suposición de que los retornos se predicen de forma segura desde una pequeña pila de hardware (el RSB). Retbleed demostró que esa suposición es falsa: agota el RSB con recursión profunda, y la CPU recurre silenciosamente al mismo predictor inseguro que Retpoline fue diseñado para evitar.
| Etapa | Qué ocurre |
|---|---|
| 1. Disparo | rsb_deep_call() recurre 32 niveles de profundidad, desbordando el RSB de 16 entradas. Cuando la recursión se desenrolla, el RSB queda vacío. |
| 2. Fallback | Con el RSB vacío, la CPU recurre al Branch Target Buffer (BTB) para predecir el objetivo del ret — el cual un atacante puede envenenar. |
| 3. Gadget | La ruta especulativa secuestrada ejecuta gadget(), que lee un byte de la contraseña secreta y lo usa para indexar en probe_array, trayendo una página de ese arreglo a la caché. |
| 4. Espía Flush+Reload | Antes del ataque, cada página de probe_array se vacía de la caché (_mm_clflush). Después de que se cierra la ventana especulativa, el programa mide el tiempo de acceso a cada posible valor de byte (__rdtscp) — el que regresa rápido (acierto de caché) revela el byte secreto. |
Repetir esto para cada byte de ROOT_PASSWORD reconstruye todo el secreto sin haber llamado nunca arquitectónicamente a gadget().
| Modo | Latencia de acceso | Resultado |
|---|---|---|
Vulnerable (SECURE_MODE sin definir) | ~49 ciclos (acierto de caché) | Secreto filtrado byte a byte, confirmado por indicadores rojos HIT! |
Parcheado (SECURE_MODE definido, _mm_lfence() inyectado) | >150 ciclos (fallo de caché / ruido) | El ataque falla — la salida muestra SAFE / Found: ??? |
El lfence obliga a la CPU a resolver la dirección de retorno antes de que cualquier instrucción posterior pueda ejecutarse, colapsando la ventana especulativa antes de que el gadget llegue siquiera a tocar memoria dependiente del secreto.
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
El PoC fue compilado y medido bajo gem5 (DerivO3CPU, un modelo out-of-order — necesario porque los modelos in-order no implementan ejecución especulativa):
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
Para alternar entre el comportamiento vulnerable y el parcheado, comenta/descomenta esta línea al inicio de retbleed.c:
#define SECURE_MODE
El código usa intrinsics reales de x86 (
_mm_clflush,__rdtscp,_mm_lfence) y también puede compilarse y ejecutarse de forma nativa en hardware x86 (gcc -O0 -o retbleed src/retbleed.c) para una demostración más rápida — los resultados variarán según las propias mitigaciones de la CPU anfitriona (eIBRS, parches de microcódigo, etc.), lo cual es en sí mismo una ilustración útil de cuán exhaustivamente se ha parcheado esta clase de bug desde 2022.
lfences adicionales) midieron una sobrecarga de rendimiento del 14–39% en hardware afectado.