Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
smiiiiiiiiiiiiiiii — Ein sehr sehr sehr sehr sehr sehr sehr langer Interrupt | Kitploit
Tools/GitHubGitHub/xoreaxeaxeax/smiiiiiiiiiiiiiiii
SchwachstellenanalyseExploitationHardware-HackingHardware-Sicherheit
GitHubxoreaxeaxeax/smiiiiiiiiiiiiiiii

smiiiiiiiiiiiiiiii

Ein sehr sehr sehr sehr sehr sehr sehr langer Interrupt

Repository anzeigen
1585vor 2 TagenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

smiiiiiiiiiiiiiiii

Ausnutzen des System Management Mode mit einem sehr sehr sehr sehr sehr sehr sehr langen Interrupt.

Übersicht

Es stellt sich heraus, dass man SMM – die sichere, hochprivilegierte Ausführungsumgebung, die unsichtbar im Hintergrund jeder x86-CPU läuft – mit nichts weiter als einer obszön lange laufenden Maschineninstruktion brechen kann.

SMM erfordert, dass alle Kerne entweder gleichzeitig in SMM oder gleichzeitig außerhalb von SMM sind. Sein Sicherheitsmodell funktioniert ohne das nicht – wenn ein Thread in SMM eintritt, zwingt er alle anderen ebenfalls hinein.

Um das zu brechen, brauchen wir nur jemanden, der zu beschäftigt ist, um zu bemerken, dass er zu SMM beitreten soll.

Es funktioniert ungefähr so:

root@kitploit:~
core 0 - start a long instruction
       |
       |
       |
core 1 - invite core 0 to smm
       |
       |
       |
core 1 - enter smm
       |
       |
       |
core 1 - wait for core 0
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
core 1 - wait for core 0
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
core 1 - wait for core 0
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
core 1 - wait for core 0
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
core 1 - wait for core 0
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
core 1 - wait for core 0
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
core 1 - wait for core 0
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
core 1 - wait for core 0
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
       |
core 1 - give up
core 1 - do secret smm stuff
core 1 - finish smm
       |
       |
       |
core 0 - join smm

An diesem Punkt ist Kern 1 außerhalb von SMM, während Kern 0 darin ist, wodurch Kern 1 Kern 0 angreifen kann. Hier ist der Haken: Damit das funktioniert, brauchen wir eine sehr, sehr, seeeehr lange Instruktion – länger, als eine Instruktion jemals dauern sollte. Die meisten Maschineninstruktionen auf einer modernen CPU sind schnell: add braucht 1 Zyklus. Um Kern 1 dazu zu bringen, das Warten auf Kern 0 aufzugeben, brauchen wir auf Kern 0 eine Instruktion, die ungefähr 4.000.000.000 Zyklen dauert – über 1 Sekunde Echtzeit.

Der Ein-Sekunden-Timeout

x86-Firmware führt den folgenden Code aus, wenn ein CPU-Kern in SMM eintritt:

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

    CpuPause ();
  }

Der Code wartet darauf, dass alle Kerne in SMM eintreten – oder bis zu 1 Sekunde, je nachdem, was zuerst eintritt. Damit ein Kern SMM-Code ausführt, während ein anderer Kern außerhalb von SMM weiterläuft, muss dieser Außenkern für die gesamte Sekunde uninterruptierbar bleiben – ein SMI wird an einer Instruktionsgrenze angenommen, daher ist jede Lücke zwischen zwei Instruktionen eine Tür, durch die der anstehende SMI geht, um den Kern hineinzuziehen. Die Verzögerung muss also eine einzelne Instruktion sein: eine uninterruptierbare Operation, die das Ein-Sekunden-Rendezvous überdauert.

Proof-of-Concept

Es gibt viele Wege, um die verbotene Ein-Sekunden-Instruktion zu erreichen, und der genaue Ansatz wird von Plattform zu Plattform unterschiedlich sein. Aber grob gesagt: Finde eine MMIO-Adresse mit hoher Latenz und überzeuge dann die CPU, so langsam wie möglich davon zu lesen – missbrauche eine undokumentierte Region, die Lesezugriffe im Schneckentempo beantwortet, und nutze dann den breitesten Load, den die ISA dir gibt, um eine lächerliche Menge Bytes in einer einzigen Instruktion darüber zu transportieren, idealerweise während die anderen Kerne auf denselben Bus drängeln, sodass das Ganze unter Konkurrenz nur noch keucht. Ein Read, eine Instruktion, und die CPU bleibt für den Großteil einer Sekunde daran hängen.

Der bereitgestellte Proof-of-Concept ist auf einen Zen 3 Ryzen 7 5800H abgestimmt, bei dem ein breiter xmm-Load aus langsamem MMIO bei 0xfcc68860 lange genug stockt, um das All-Cores-Rendezvous zu brechen:

root@kitploit:~
mov     $0xfcc68860, %rsi   ; the target MMIO address
vmovdqu (%rsi), %xmm0       ; the very, very long load

Das PoC nutzt dies aus, indem es zwei Kerne gegeneinander antreten lässt. Ein Kern wird durch die lange Instruktion – eine enge Schleife über den sehr langsamen Load – außerhalb von SMM gehalten:

root@kitploit:~
/* the victim core: spin on the ~1-second load, too busy to answer the SMI */
for (;;)
    asm volatile ("vmovdqu (%0), %%xmm0" :: "r"(mmio) : "xmm0");

Währenddessen aktiviert ein anderer Kern die SMI-Zähler pro Kern:

root@kitploit:~
#define MSR_PERF_CTL0  0xc0010200        /* AMD core perf event-select MSR */
#define MSR_PERF_CTR0  0xc0010201        /* the paired 48-bit counter      */

for (int cpu = 0; cpu < ACTIVE_CPUS; cpu++) {
    msr_write(cpu, MSR_PERF_CTL0, 0x43002b);  /* EN | OS | USR | event 0x2b */
    msr_write(cpu, MSR_PERF_CTR0, 0);         /* zero the count            */
}

Dann feuert er einen Sturm von SMIs:

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

Und liest die Bilanz jedes Kerns zurück:

root@kitploit:~
/* ...fire the storm, then read every core's tally back... */
uint64_t delta = smi_max - smi_min;
if (delta)
    puts("!!! a core ran outside SMM");

Die Zähler erzählen die Geschichte. Wenn sie divergieren, lief ein Kern außerhalb von SMM weiter, während die anderen hineingezogen wurden – er überlebte SMIs, die die übrigen ohne ihn abarbeiteten.

SMI-Zähler-Divergenz in Aktion

Und das ist das gesamte Ergebnis: SMMs einziges Versprechen – dass nichts anderes läuft, während es läuft – zerfällt angesichts einer einzigen absurd langen Instruktion.

Ausnutzung

SMMs Sicherheit beruht auf einer einfachen Annahme: Während es läuft, läuft nichts anderes.

Es gibt 100+ SMM TOCTOU CVEs da draußen: ein SMM Handler prüft einen Wert im gemeinsamen Speicher, dann nutzt er ihn. Alles, was du für die Ausnutzung brauchst, ist, diesen Wert zwischen Prüfung und Verwendung neu zu schreiben – und schon bist du in SMM. Aber diese Probleme liegen in freier Wildbahn schlummernd und weitgehend ungepatcht vor, wegen einer Annahme: Für die Ausnutzung muss etwas den gemeinsamen Speicher während SMM ausgeführt wird verändern, und wegen des SMM-Rendezvous befinden sich keine CPU-Kerne außerhalb von SMM, um einen Angriff zu starten. Der einzige Weg hinein – oder so dachten wir – war ein DMA-fähiges Peripheriegerät, das hinter dem Rücken der CPU schreibt – physischer Zugang, ein böswilliges Gerät –, sodass die gesamte Klasse als Hardwareproblem abgetan wird.

SMI-Desynchronisation beseitigt die Voraussetzung: Ein externer Kern – ohne physischen Zugang oder Hardware – kann jetzt laufen, während SMM ausgeführt wird – und plötzlich werden die schlummernden CVEs aus Software heraus ausnutzbar.

In diesem Projekt haben wir nur gezeigt, dass sich das Fenster öffnet; aber genau dieses Fenster war der Grund, warum diese Bugs für sicher gehalten wurden.

Portierung auf deine Plattform

Das standardmäßige vmovdqu bei 0xfcc68860 im Proof-of-Concept ist eine langsame Stelle auf dieser Kiste – einem Zen 3 Ryzen 7 5800H – und wahrscheinlich nirgendwo sonst. Um das Rendezvous auf deiner Kiste zu brechen, musst du die lange Instruktion neu justieren, sodass der Stall dein SMM-Timeout überdauert. Ein paar Tipps, wie das geht:

  1. Ziel auf dein MMIO. Finde eine langsame MMIO-Region auf deiner Plattform mit mmiotic.
  2. Verbreitere den Read. Steigere -r xmm → ymm → zmm, bis der Stall das Rendezvous-Timeout überschreitet.
  3. Tausche die Instruktion. Wenn kein einzelner MMIO-Read langsam genug ist, brauchst du eine andere pathologisch lange Instruktion; die asm-hall-of-shame zeigt, wie man sie findet.

Erstellen

root@kitploit:~
make          # builds smiiiiiiiiiiiiiiii

Verwendung

Die Standardwerte sind auf eine einzige Maschine abgestimmt. Auf allem außer einem Zen 3 Ryzen 7 5800H solltest du keine Divergenz erwarten, bis du die lange Instruktion neu justierst – siehe Portierung auf deine Plattform.

Führe das Tool aus, um wiederholt die sehr-sehr-lange Instruktion auszulösen und dabei den SMI-Zähler jedes Kerns auf eine Divergenz zu beobachten:

root@kitploit:~
sudo ./smiiiiiiiiiiiiiiii          # default: -r xmm at 0xfcc68860

Optionen:

Autor

smiiiiiiiiiiiiiiii ist ein Forschungsvorhaben von Christopher Domas (@xoreaxeaxeax).

Tool herunterladen
OptionStandardBeschreibung
-r xmm|ymm|zmmxmmVektorregisterbreite für den zeitgesteuerten MMIO-Read (16/32/64 Bytes). Falls kein SMI-Zähldelta beobachtet wird, rät das Tool, auf die nächste Größe zu wechseln.
-a <phys-addr>0xfcc68860Zielphysische Adresse für die MMIO-Timing-Schleife (hexadezimal 0x... oder dezimal).
-h, --help—Verwendung ausgeben und beenden.