Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
smiiiiiiiiiiiiiiii — Un interrupt muy muy muy muy muy muy muy largo | Kitploit
Herramientas/GitHubGitHub/xoreaxeaxeax/smiiiiiiiiiiiiiiii
Análisis de VulnerabilidadesExplotaciónHacking de HardwareSeguridad de Hardware
GitHubxoreaxeaxeax/smiiiiiiiiiiiiiiii

smiiiiiiiiiiiiiiii

Un interrupt muy muy muy muy muy muy muy largo

Ver Repositorio
15857hace 23 díasRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

smiiiiiiiiiiiiiiii

Explotando el Modo de Gestión del Sistema con una interrupción muy muy muy muy muy muy muy larga.

Resumen

Resulta que puedes romper el SMM — el entorno de ejecución seguro y ultra privilegiado que se ejecuta de forma invisible en segundo plano en cada CPU x86 — con nada más que una instrucción de máquina obscenamente larga.

El SMM requiere que todos los núcleos estén o bien en SMM o bien fuera de SMM al mismo tiempo. Su modelo de seguridad no funciona sin esto — cuando un hilo entra en SMM, hace que todos los demás también entren.

Para romper esto, todo lo que necesitamos es alguien demasiado ocupado para notar que se supone que debe unirse al SMM.

Funciona más o menos así:

root@kitploit:~
core 0 - inicia una instrucción larga
       |
       |
       |
core 1 - invita al core 0 al smm
       |
       |
       |
core 1 - entra en smm
       |
       |
       |
core 1 - espera al core 0
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
core 1 - espera al core 0
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
core 1 - espera al core 0
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
core 1 - espera al core 0
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
core 1 - espera al core 0
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
core 1 - espera al core 0
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
core 1 - espera al core 0
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
core 1 - espera al core 0
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
core 1 - se rinde
core 1 - hace cosas secretas del smm
core 1 - termina el smm
       |
       |
       |
core 0 - se une al smm

En este punto, el core 1 está fuera del SMM mientras que el core 0 está dentro, lo que permite al core 1 atacar al core 0. Aquí está el truco: para que esto funcione necesitamos una instrucción muy, muy, muuuuy larga — más larga de lo que cualquier instrucción debía tardar. La mayoría de las instrucciones de máquina en una CPU moderna son rápidas: add tarda 1 ciclo. Para conseguir que el core 1 se rinda esperando al core 0, necesitamos una instrucción en el core 0 que tarde alrededor de 4,000,000,000 de ciclos — más de 1 segundo de tiempo real.

El tiempo de espera de un segundo

El firmware x86 ejecuta el siguiente código cuando un núcleo de CPU entra en SMM:

root@kitploit:~
  for (Timer = StartSyncTimer ();
       !IsSyncTimerTimeout (Timer, mTimeoutTicker) && SyncNeeded;
       )
  {
    mSmmMpSyncData->AllApArrivedWithException = AllCpusInSmmExceptBlockedDisabled ();
    if (mSmmMpSyncData->AllApArrivedWithException) {
      break;
    }

    CpuPause ();
  }

El código espera a que todos los núcleos entren en SMM, o hasta 1 segundo, lo que ocurra primero. Para conseguir que un núcleo ejecute código SMM mientras otro núcleo permanece ejecutando fuera del SMM, necesitamos que ese núcleo externo permanezca ininterrumpible durante el segundo completo — un SMI se toma en un límite de instrucción, por lo que cualquier hueco entre dos instrucciones permite que el SMI pendiente lleve al núcleo al SMM. El retraso, por tanto, tiene que ser una única instrucción: una operación ininterrumpible que supere la reunión de un segundo.

Prueba de concepto

Hay muchas formas de alcanzar la prohibida instrucción de 1 segundo, y el enfoque exacto variará de plataforma a plataforma. Pero, aproximadamente: encuentra una dirección MMIO de alta latencia, y luego convence a la CPU para que lea de ella lo más lentamente posible — abusa de una región no documentada que responde a las lecturas a paso de tortuga, usa la carga más ancha que el ISA te ofrezca para mover tantos bytes como sea posible a través de ella en una sola instrucción, y deja que los otros núcleos compitan por el mismo bus para ralentizarla aún más. Una lectura, una instrucción, y la CPU queda atascada sosteniéndola durante la mayor parte de un segundo.

La prueba de concepto proporcionada está ajustada para un Zen 3 Ryzen 7 5800H, donde una carga xmm ancha desde MMIO lento en 0xfcc68860 se detiene el tiempo suficiente para romper la reunión de todos los núcleos:

root@kitploit:~
mov     $0xfcc68860, %rsi   ; la dirección MMIO objetivo
vmovdqu (%rsi), %xmm0       ; la carga muy, muy larga

La PoC explota esto enfrentando a dos núcleos entre sí. Un núcleo se mantiene fuera del SMM mediante la instrucción larga — un bucle cerrado sobre la carga muy lenta:

root@kitploit:~
/* el núcleo víctima: gira en la carga de ~1 segundo, demasiado ocupado para responder al SMI */
for (;;)
    asm volatile ("vmovdqu (%0), %%xmm0" :: "r"(mmio) : "xmm0");

Mientras tanto, otro núcleo arma los contadores SMI por núcleo:

root@kitploit:~
#define MSR_PERF_CTL0  0xc0010200        /* MSR de selección de evento de rendimiento del núcleo AMD */
#define MSR_PERF_CTR0  0xc0010201        /* el contador de 48 bits emparejado      */

for (int cpu = 0; cpu < ACTIVE_CPUS; cpu++) {
    msr_write(cpu, MSR_PERF_CTL0, 0x43002b);  /* EN | OS | USR | evento 0x2b */
    msr_write(cpu, MSR_PERF_CTR0, 0);         /* pon el contador a cero            */
}

Luego dispara una tormenta de SMIs:

root@kitploit:~
asm volatile ("outb %%al, $0xb2" :: "a"(0));  /* patea el puerto 0xb2 -> #SMI    */

Y lee el recuento de cada núcleo:

root@kitploit:~
/* ...dispara la tormenta, luego lee el recuento de cada núcleo... */
uint64_t delta = smi_max - smi_min;
if (delta)
    puts("!!! un núcleo se ejecutó fuera del SMM");

Si los recuentos divergen, significa que un núcleo siguió ejecutándose fuera del SMM mientras los demás fueron arrastrados — se perdió los SMIs que el resto atendió.

Para ilustrar esto mejor, podemos ejecutar la prueba de concepto detrás de una GUI innecesariamente llamativa y completamente inútil, rastreando los contadores SMI en cada núcleo, para verlos ejecutarse en perfecta sincronía hasta que un núcleo extremadamente retrasado rompe su sincronización requerida:

Divergencia del contador SMI en acción

La única garantía del SMM — que nada más se ejecute mientras él lo hace — se desmorona ante una única instrucción absurdamente larga.

Explotación

La seguridad del SMM se basa en una suposición simple: mientras se ejecuta, nada más lo hace.

Hay más de 100 CVEs de TOCTOU de SMM por ahí: un manejador de SMM comprueba un valor en memoria compartida, luego lo usa. Todo lo que necesitas para explotar es reescribir ese valor entre la comprobación y el uso, y estás dentro del SMM. Pero estos problemas permanecen inactivos y en gran medida sin parchear en el mundo real, debido a una suposición: la explotación requiere que algo modifique la memoria compartida mientras el SMM se ejecuta, y debido a la reunión del SMM ningún núcleo de CPU está fuera del SMM para lanzar un ataque. La única vía de entrada era un periférico con capacidad DMA escribiendo a espaldas de la CPU — acceso físico, un dispositivo malicioso — por lo que toda la clase se descarta como un problema de hardware.

La desincronización del SMI elimina el requisito que mantenía segura la plataforma: un núcleo externo, sin acceso físico ni hardware requerido, ahora puede ejecutarse mientras el SMM se ejecuta — y los CVEs latentes se vuelven explotables desde software.

Mitigaciones

Probablemente no haya ninguna, que es lo que hace que este problema sea algo más interesante que los problemas tradicionales de SMM. Mantén el tiempo de espera, y la reunión se rompe fácilmente. Elimina el tiempo de espera, y un núcleo legítimamente atascado cuelga la plataforma en el primer SMI. Aumenta el tiempo de espera, y matas el rendimiento en plataformas de muchos núcleos que se ven obligadas a poner en reposo todos los núcleos en cada entrada al SMM. No está claro cuál es el mejor camino a seguir, o si siquiera hay un camino a seguir en absoluto.

Hasta entonces, la solución recomendada es no ejecutar ninguna instrucción larga.

Portar a tu plataforma

El vmovdqu predeterminado en 0xfcc68860 en la prueba de concepto es un punto lento en esta máquina — un Zen 3 Ryzen 7 5800H — y probablemente en ningún otro lugar. Para romper la reunión en tu máquina, necesitarás reajustar la instrucción larga para que la detención supere tu tiempo de espera del SMM. Algunos consejos sobre cómo hacerlo:

  1. Apunta a tu MMIO. Encuentra una región MMIO lenta en tu plataforma con mmiotic.
  2. Amplía la lectura. Sube -r xmm → ymm → zmm hasta que la detención cruce el tiempo de espera de la reunión.
  3. Cambia la instrucción. Si ninguna lectura MMIO individual es lo suficientemente lenta, necesitas una instrucción patológicamente larga diferente; el asm-hall-of-shame muestra cómo encontrarlas.

Compilación

root@kitploit:~
make          # compila smiiiiiiiiiiiiiiii

Uso

Los valores predeterminados están ajustados para una máquina. En cualquier cosa que no sea un Zen 3 Ryzen 7 5800H, no esperes divergencia hasta que reajustes la instrucción larga — consulta Portar a tu plataforma.

Ejecuta la herramienta para disparar repetidamente la instrucción muy-muy-larga mientras observas el contador SMI de cada núcleo en busca de una divergencia:

root@kitploit:~
sudo ./smiiiiiiiiiiiiiiii          # predeterminado: -r xmm en 0xfcc68860

Opciones:

OpciónPredeterminadoDescripción
-r xmm|ymm|zmmxmmAncho del registro vectorial para la lectura MMIO cronometrada (16/32/64 bytes). Si no se observa un delta en el recuento de SMI, la herramienta aconseja subir al siguiente tamaño.
-a <dirección-física>0xfcc68860Dirección física objetivo para el bucle de temporización MMIO (hex 0x... o decimal).
-h, --help—Imprime el uso y sale.

Referencias

  • DEF CON 2026 – Weaponizing Uselessness

Autor

smiiiiiiiiiiiiiiii es un esfuerzo de investigación de Christopher Domas (@xoreaxeaxeax).

Descargar herramienta