Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
smiiiiiiiiiiiiiiii — Очень очень очень очень очень очень очень длинное прерывание | Kitploit
Инструменты/GitHubGitHub/xoreaxeaxeax/smiiiiiiiiiiiiiiii
Анализ уязвимостейЭксплуатацияАппаратный ХакингАппаратная Безопасность
GitHubxoreaxeaxeax/smiiiiiiiiiiiiiiii

smiiiiiiiiiiiiiiii

Очень очень очень очень очень очень очень длинное прерывание

Репозиторий
1585151 месяц назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

smiiiiiiiiiiiiiiii

Эксплуатация System Management Mode с помощью очень очень очень очень очень очень очень длинного прерывания.

Обзор

Оказывается, можно сломать SMM — безопасную, привилегированную среду выполнения, работающую незаметно в фоне каждого x86 CPU — с помощью всего лишь одной неприлично долго выполняющейся машинной инструкции.

SMM требует, чтобы все ядра одновременно находились либо в SMM, либо вне SMM. Его модель безопасности не работает без этого — когда один поток входит в SMM, это заставляет все остальные тоже войти.

Чтобы сломать это, нам нужен кто-то, кто слишком занят, чтобы заметить, что он должен присоединиться к SMM.

Это работает примерно так:

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

В этот момент core 1 находится вне SMM, а core 0 — внутри, что позволяет core 1 атаковать core 0. Вот загвоздка: для этого нам нужна очень, очень, ооочень длинная инструкция — длиннее, чем любая инструкция когда-либо должна была выполняться. Большинство машинных инструкций на современном CPU быстрые: add занимает 1 цикл. Чтобы заставить core 1 отказаться от ожидания core 0, нам нужна инструкция на core 0, которая занимает около 4 000 000 000 циклов — более 1 секунды реального времени.

Тайм-аут в одну секунду

Прошивка x86 выполняет следующий код когда ядро CPU входит в SMM:

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

    CpuPause ();
  }

Код ожидает, пока все ядра войдут в SMM, или до 1 секунды, в зависимости от того, что произойдёт раньше. Чтобы заставить одно ядро выполнять код SMM, пока другое ядро продолжает выполняться вне SMM, нам нужно, чтобы это внешнее ядро оставалось непрерываемым в течение всей секунды — SMI обрабатывается на границе инструкции, поэтому любой разрыв между двумя инструкциями позволяет ожидающему SMI втянуть ядро в SMM. Поэтому задержка должна быть одной инструкцией: одной непрерываемой операцией, которая переживёт односекундный сбор.

Proof-of-Concept

Существует множество способов достичь запретной 1-секундной инструкции, и точный подход будет различаться от платформы к платформе. Но, в общем: найдите адрес MMIO с высокой задержкой, а затем убедите CPU читать с него как можно медленнее — злоупотребите недокументированной областью, которая отвечает на чтения крайне медленно, используйте самую широкую загрузку, которую даёт ISA, чтобы переместить как можно больше байтов через неё за одну инструкцию, и позвольте другим ядрам конкурировать за ту же шину, чтобы замедлить её ещё больше. Одно чтение, одна инструкция — и CPU застревает, удерживая её почти целую секунду.

Предоставленный proof-of-concept настроен для Zen 3 Ryzen 7 5800H, где широкая загрузка xmm из медленного MMIO по адресу 0xfcc68860 зависает достаточно долго, чтобы сломать сбор всех ядер:

mov     $0xfcc68860, %rsi   ; the target MMIO address
vmovdqu (%rsi), %xmm0       ; the very, very long load

PoC эксплуатирует это, сталкивая два ядра друг с другом. Одно ядро удерживается вне SMM длинной инструкцией — тесным циклом на очень медленной загрузке:

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

Тем временем другое ядро настраивает счётчики SMI для каждого ядра:

#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            */
}

Затем запускает шквал SMI:

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

И считывает итоги каждого ядра:

/* ...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");

Если счётчики расходятся, это означает, что одно ядро продолжало выполняться вне SMM, пока остальные были втянуты внутрь — оно пропустило SMI, которые обслуживали остальные.

Скачать инструмент