Доброго времени суток форумчане!
Введение.
SMM - что это такое и как это можно использовать на практике:
System Management Mode - это отдельный изолированный от ОС режим работы процессора. Если рассматривать кольца доступа в вашей системе smm будет находиться после гипервизора, однако стоит учесть очень важный момент который является переломным, гипервизор - изолирован от гостевой ос, а smm изолирован от всей системы.
При каких условиях процессор переходит в smm, как он туда переходит и зачем.
Очень часто, а скорее почти без исключений процессор переходит в smm только из-за критических ситуаций (p.s только что в момент написания статьи узнал что еще из-за платформенных задач), и именно то что он изолирован от системы он это делает наиболее "прозрачно", когда это происходит процессор сохраняет состояние текущей системы (регистры флаги и др) в области памяти SMRAM, после чего начинает выполнение кода обработчика, после того как код выполнился за дело берется инструкция RSM, а именно resume from smm, она берет "снапшот" из SMRAM и возращает процессор в том режиме в котором он находился до срабатывания триггера, а именно SMI, smi - system management interrupt это и есть тот "триггер" который заставляет процессор на микросекунды передать управление изолированной среде, ввиде простого примера в legacy bios многие аппаратные события были SMI, т е при нажатии выключения или перезагрузки на корпусе вашего пк, процессор входил в smm и выполнял инструкции модулей, сейчас же все иначе. Сейчас же как я и упоминал smm используется в более критических ситуациях, а сейчас аппаратные событие чаще выполняются ACPI / SCI.
При срабатывании smi также все ядра переходят в smm, даже если прерывание затронуло одно ядро, остальные также приостанавливают работу и входят в smm, обычно в режим ожидания. На всякий случай уточним что ос не может перехватить или контролировать smi так же, как обычные прерывания, smi не проходит через обычную таблицу векторов прерываний (IDT), вместо этого его обработка целиком проходит на уровне прошивки внутри smm.
Как ос может взаимодействовать с smm.
Как я уже и говорил smm и система НИКАК не пересекаются, однако все же система может взаимодействовать с smm, самый явный способ через прошивку, к примеру при работе с uefi-переменными(uefi-variables) винда вызывает прошивку, и та нередко обрабатывает запросы в smm. Такие вызовы smm из среды ос осуществляются через smi драйвер винды пишет в соответствующий порт/регистр, передавая команды смм обработчикам. Но винда прямого доступа не имеет, они стараются это минимизировать до нуля дабы не загружать систему (например использую acpi).
LINUX.
В линуксе почти все также, однако есть утилиты которые в реальном времени позволяют проанализировать smi и т п (я к сожалению не глубоко это изучал, но нашел утилиту hwlatdetect) - название говорит само за себя
.
SMM в прошивках bios/uefi.
В современных прошивках smm организован в виде отдельных модулей/драйверов, загружаемых на этапе инициализации системы. Каждый драйвер после иницализации регистрирует свой smi обработчик - эти модули загружаются в нам уже знакомую smram. Также есть смысл добавить что smram очень сильно защищена протоколом TSEG, (tseg простыми словами говоря это специально выделенный сегмент) также smram аппаратно защищена чипсетом, он вытставляет бит блокировки.
Можно ли использовать smm в maas.
С точки зрения нынешней ситуации это почти невозможно, для того чтобы создать свой smm модуль вам придется работать прошивать биос, соответсвенно как это можно использовать не на своем пк понять сложно...
Как создать свой smm модуль и как его использовать.
Создать свой модуль можно, в данном случае писать много кода я не буду, и модуль тоже, я лишь дам два рабочих способа вызова smi и расскажу о концепте на котором я остановился. Концепт работы который я делал это связка usermoda который использует smm как библиотеку посылая ей "команды". (Для работы данного метода у вас должен быть биос который поддерживает uefi variables или же TPM (fTPM2.0)
вызов через uefi v.
вызов используя tpm
Данные отрывки кода вырванны из одного и наверное единственного проекта который ввиде PoC показывает как это все работает, если хотите его найти он будет первый в поиске по запросу SMM.
И одно из не мало важных протокол ZEPTA который связывает юзермод и смм.
Выделение в отдельной секции.
С Этим разобрались.
Как компилировать и прошивать.
вам нужен будет edk2 проект (https://github.com/tianocore/edk2), очень часто бывают проблемы даже в настройке окружения для компиляции дельный гайд:
.
Представим вы собрали проект, на выходе у вас будет .efi, дальше вы должны будете скачать uefi tool 0.28.0 желательно(https://github.com/LongSoft/UEFITool/releases/tag/0.28.0)
вот тут нажимает open image file -> заходим на сайт производителя мат-платы и качаем биос, если скачанный биос не в нужном разрешении просто либо меняйте его либо открывайте так нажимая all files вместо конкретных расширений. Дальше когда вы открыли вы будете видеть много секций, нажимайте cntrl + f, и в окошке выбирайте unicode, и дальше вводите OA3, и потом увидите много результатов там будут написаны оффсеты - они вам не нужны, кликайте на второй результат вас перенесет на секцию, удостоверьтесь что в колонке справа название OA3_SMM и метка тоже должна быть smm module -> дальше делайте вот так:
и выбирайте ваш модуль.
OA3_smm почти не нужный модуль отвечающий за активацию винды, да и сейчас активировать винду можно очень просто и без этого, так что он был выбран для замены, в правой колонке всегда будут видны названия модулей, если не хотите жертвовать oa3 можете выбрать свой модуль, только желательно прогуглить за что отвечает дабы не убить систему, еще если вдруг тут будут те кто побегут прошивать ДЕЛАЙТЕ ЭТО ТОЛЬКО НА МАТЕРИНКЕ У КОТОРОЙ ЕСТЬ bios flashback иначе есть шанс того что вы убьете микросхемы и придется покупать программатор.
Хотел бы сказать всем спасибо за то что прочитали статью, первый опыт написания статей если данная тема будет интересной думаю проблем написать модуль нету, если я что то где то не учел пожалуйста скажите, потому что писал я это уже довольно долго и почти заснувший
Введение.
SMM - что это такое и как это можно использовать на практике:
System Management Mode - это отдельный изолированный от ОС режим работы процессора. Если рассматривать кольца доступа в вашей системе smm будет находиться после гипервизора, однако стоит учесть очень важный момент который является переломным, гипервизор - изолирован от гостевой ос, а smm изолирован от всей системы.
При каких условиях процессор переходит в smm, как он туда переходит и зачем.
Очень часто, а скорее почти без исключений процессор переходит в smm только из-за критических ситуаций (p.s только что в момент написания статьи узнал что еще из-за платформенных задач), и именно то что он изолирован от системы он это делает наиболее "прозрачно", когда это происходит процессор сохраняет состояние текущей системы (регистры флаги и др) в области памяти SMRAM, после чего начинает выполнение кода обработчика, после того как код выполнился за дело берется инструкция RSM, а именно resume from smm, она берет "снапшот" из SMRAM и возращает процессор в том режиме в котором он находился до срабатывания триггера, а именно SMI, smi - system management interrupt это и есть тот "триггер" который заставляет процессор на микросекунды передать управление изолированной среде, ввиде простого примера в legacy bios многие аппаратные события были SMI, т е при нажатии выключения или перезагрузки на корпусе вашего пк, процессор входил в smm и выполнял инструкции модулей, сейчас же все иначе. Сейчас же как я и упоминал smm используется в более критических ситуациях, а сейчас аппаратные событие чаще выполняются ACPI / SCI.
При срабатывании smi также все ядра переходят в smm, даже если прерывание затронуло одно ядро, остальные также приостанавливают работу и входят в smm, обычно в режим ожидания. На всякий случай уточним что ос не может перехватить или контролировать smi так же, как обычные прерывания, smi не проходит через обычную таблицу векторов прерываний (IDT), вместо этого его обработка целиком проходит на уровне прошивки внутри smm.
Как ос может взаимодействовать с smm.
Как я уже и говорил smm и система НИКАК не пересекаются, однако все же система может взаимодействовать с smm, самый явный способ через прошивку, к примеру при работе с uefi-переменными(uefi-variables) винда вызывает прошивку, и та нередко обрабатывает запросы в smm. Такие вызовы smm из среды ос осуществляются через smi драйвер винды пишет в соответствующий порт/регистр, передавая команды смм обработчикам. Но винда прямого доступа не имеет, они стараются это минимизировать до нуля дабы не загружать систему (например использую acpi).
LINUX.
В линуксе почти все также, однако есть утилиты которые в реальном времени позволяют проанализировать smi и т п (я к сожалению не глубоко это изучал, но нашел утилиту hwlatdetect) - название говорит само за себя
SMM в прошивках bios/uefi.
В современных прошивках smm организован в виде отдельных модулей/драйверов, загружаемых на этапе инициализации системы. Каждый драйвер после иницализации регистрирует свой smi обработчик - эти модули загружаются в нам уже знакомую smram. Также есть смысл добавить что smram очень сильно защищена протоколом TSEG, (tseg простыми словами говоря это специально выделенный сегмент) также smram аппаратно защищена чипсетом, он вытставляет бит блокировки.
Можно ли использовать smm в maas.
С точки зрения нынешней ситуации это почти невозможно, для того чтобы создать свой smm модуль вам придется работать прошивать биос, соответсвенно как это можно использовать не на своем пк понять сложно...
Как создать свой smm модуль и как его использовать.
Создать свой модуль можно, в данном случае писать много кода я не буду, и модуль тоже, я лишь дам два рабочих способа вызова smi и расскажу о концепте на котором я остановился. Концепт работы который я делал это связка usermoda который использует smm как библиотеку посылая ей "команды". (Для работы данного метода у вас должен быть биос который поддерживает uefi variables или же TPM (fTPM2.0)
вызов через uefi v.
Код:
#define EFI_VARIABLE_NON_VOLATILE 0x00000001
#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004
extern "C"
{
NTSYSAPI NTSTATUS NTAPI RtlAdjustPrivilege(
ULONG Privilege,
BOOLEAN Enable,
BOOLEAN Client,
PBOOLEAN WasEnabled
);
NTSYSCALLAPI NTSTATUS NTAPI NtSetSystemEnvironmentValueEx(
PUNICODE_STRING VariableName,
LPGUID VendorGuid,
PVOID Value,
ULONG ValueLength,
ULONG Attributes
);
}
void TriggerSmiUefiRuntimeVariable()
{
BOOLEAN e = false;
const NTSTATUS status = RtlAdjustPrivilege(22, true, false, &e);
if (!NT_SUCCESS(status))
{
printf("adm r. missing");
return;
}
GUID guid = { 0 };
UNICODE_STRING name = RTL_CONSTANT_STRING(L"ZeptaVar");
char buffer[8];
NtSetSystemEnvironmentValueEx(
&name,
&guid,
buffer,
sizeof(buffer),
EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS
);
}
вызов используя tpm
Код:
#include <tbs.h>
#pragma comment(lib, "tbs.lib")
void TriggerSmiTpmAcpi()
{
BYTE buffer[256] = { 0 };
UINT32 size = sizeof(buffer);
TBS_RESULT result = TBS_SUCCESS;
PTBS_HCONTEXT context = new TBS_HCONTEXT;
TBS_CONTEXT_PARAMS2 params = { 0 };
params.version = TPM_VERSION_20;
params.asUINT32 = 0;
params.includeTpm20 = TRUE;
result = Tbsi_Context_Create(
(PCTBS_CONTEXT_PARAMS)¶ms,
context
);
if (result != TBS_SUCCESS)
{
printf("Could not create context: %x\n", result);
delete context;
return;
}
RtlZeroMemory(buffer, sizeof(buffer));
buffer[0] = 0x00000005u;
result = Tbsi_Physical_Presence_Command(
*context,
buffer,
sizeof(DWORD),
buffer,
&size
);
if (result != TBS_SUCCESS)
{
printf("Command error: %x\n", result);
}
Tbsip_Context_Close(*context);
delete context;
}
И одно из не мало важных протокол ZEPTA который связывает юзермод и смм.
Код:
#pragma pack(1)
typedef struct _SmmCommunicationProtocol
{
UINT8 magic;
UINT8 process_name[30];
UINT16 module_name[30];
UINT64 offset;
UINT64 read_size;
UINT8 read_buffer[30];
UINT64 smi_count;
} SmmCommunicationProtocol;
#pragma pack()
Выделение в отдельной секции.
Код:
#pragma section(".ZEPTA", read, write)
__declspec(allocate(".ZEPTA"))
volatile SmmCommunicationProtocol protocol;
Код:
strcpy_s((char*)protocol.process_name,
sizeof(protocol.process_name),
"explorer.exe");
wcscpy_s((wchar_t*)protocol.module_name,
sizeof(protocol.module_name) / sizeof(UINT16),
L"explorer.exe");
protocol.offset = 0;
protocol.read_size = 15;
memset(protocol.read_buffer, 0, sizeof(protocol.read_buffer));
TriggerSmi(TpmAcpi); // или TriggerSmi(UefiRuntime)
С Этим разобрались.
Как компилировать и прошивать.
вам нужен будет edk2 проект (https://github.com/tianocore/edk2), очень часто бывают проблемы даже в настройке окружения для компиляции дельный гайд:
Представим вы собрали проект, на выходе у вас будет .efi, дальше вы должны будете скачать uefi tool 0.28.0 желательно(https://github.com/LongSoft/UEFITool/releases/tag/0.28.0)
вот тут нажимает open image file -> заходим на сайт производителя мат-платы и качаем биос, если скачанный биос не в нужном разрешении просто либо меняйте его либо открывайте так нажимая all files вместо конкретных расширений. Дальше когда вы открыли вы будете видеть много секций, нажимайте cntrl + f, и в окошке выбирайте unicode, и дальше вводите OA3, и потом увидите много результатов там будут написаны оффсеты - они вам не нужны, кликайте на второй результат вас перенесет на секцию, удостоверьтесь что в колонке справа название OA3_SMM и метка тоже должна быть smm module -> дальше делайте вот так:
и выбирайте ваш модуль.
OA3_smm почти не нужный модуль отвечающий за активацию винды, да и сейчас активировать винду можно очень просто и без этого, так что он был выбран для замены, в правой колонке всегда будут видны названия модулей, если не хотите жертвовать oa3 можете выбрать свой модуль, только желательно прогуглить за что отвечает дабы не убить систему, еще если вдруг тут будут те кто побегут прошивать ДЕЛАЙТЕ ЭТО ТОЛЬКО НА МАТЕРИНКЕ У КОТОРОЙ ЕСТЬ bios flashback иначе есть шанс того что вы убьете микросхемы и придется покупать программатор.
Хотел бы сказать всем спасибо за то что прочитали статью, первый опыт написания статей если данная тема будет интересной думаю проблем написать модуль нету, если я что то где то не учел пожалуйста скажите, потому что писал я это уже довольно долго и почти заснувший