Обновить
313
0
Николай Шлей@CodeRush

Firmware Security Engineer

Отправить сообщение

Поставил бы вам плюс за перевод, если бы вы указали, что а) это перевод, б) оригинальная статья выпущена в 2011 году.

https://invisiblethingslab.com/resources/2011/Attacking_Intel_TXT_via_SINIT_hijacking.pdf

Приятно, когда по теме что-то пишут на русском, но для специалиста в статье нет ничего нового и\или интересного, к сожалению.

наибольшую опасность сегодня представляют уязвимости в режиме SMM и подсистеме Intel ME

Не соглашусь. Наибольшую реальную опасность, на мой взгяд, представляют:
— отключенный или неверно настроенный UEFI SecureBoot, который по прежнему никак не могут включить по умолчанию по разным причинам. Т.к. технологию проектировали и в спешке, и при активном противостоянии OSS-сообщества, результат получится «ни жив, ни мертв», т.е. в теории у нас есть безопасная загрузка какая-то, а на практике UEFI CA доверять нельзя совсем (им за 10 лет подписали слишком много уязвимого), работающего механизма отзыва подписей нет (а тот, что есть в виде dbx и dbt страдает от комбинаторного взрыва), работающего механизма отзыва сертификатов нет (все попытки решить вопрос через Audit Mode и Deployment Mode можно считать провалившимися), придумывать что-то новое ни UEFI Forum, ни остальные не торопятся.
— отключенный, или неверно настроенный, или тривиально отключаемый условный BootGuard (т.е. все скопом технологии защиты от модификации прошивки на SPI NOR и\или предотвращения запуска неавторизованного модифицированного кода). Проблема неработоспособности статического корня доверия стоит у MS настолько остро, что они требуют наличия TPM 2.0 для Windows 11, и стремятся всеми силами выкинуть прошивку из цепочки доверия, и я их прекрасно понимаю.
— поистине огромное количество уязвимостей в драйверах, взаимодействующих с переменными NVRAM, вызванное плохим дизайном интерфейса GetVariable и SetVariable.
— практическая незащищенность подавляющего большинства прошивок от DMA-атак, которые за последние ~7 лет превратились из «нужен специалист с ФПГА за 5 килобаксов и куча кастомного кода» в «нужен донгл за 30 баксов и PCILeech с гитхаба».

Самое неприятное, что хочется отметить, это отсутствие и прогресса в безопасности UEFI относительно ее состояния от 2015 года, когда я про нее писал серию статей, и интереса вендоров к этому прогрессу. Годы идут, а мы решаем те же самые проблемы теми же самыми методами, игнорируя десятилетия усилий безопасников и системных программистов, занятых развитием современных ОС. Нельзя сказать, что никто вообще ничего не делает, но все, что делается — делается двумя с половиной вендорами для себя же, а независимого аудита этих «решений» либо не проводится совсем, либо его результаты сразу же засекречиваются по соглашению сторон.

Короче, с точки зрения реальной безопасности прошивок для Wintel PC — «мы в жопе, Баттхед».
Давайте я немного с другой стороны баррикад добавлю от лица простых (и непростых) инженеров, с которыми эти самые EPMы работают в известной фруктовой компании:
— Хороший EPM отличается от плохого в основном тем, что хороший ничего не забывает, никому не прощает, и действительно несет ответственность за свой продукт или фичу, а не только играет в «горячую картошку» с другими командами или своими же инженерами.
— Хорошему EPMу можно сказать «вот этот кусок работы другой команды нужен нам очень сильно, и желательно еще позавчера, нужна твоя помощь», и он действительно займется продвижением этой работы, а не ограничится «ну, я поговорил там, они сделают когда-нибудь, точно говорю».
— Одна из задач хорошего EPMа в том, чтобы снижать количество организационной работы у инженеров, т.е. он\она не таскает всю команду по встречам ради встреч, обсуждениям ради обсуждений, не обещает Program Office'у золотые горы с доставкой каждый вторник, и не пытается заниматься директивным управлением в обход работающей корпоративной иерархии. Т.е. надо очень хорошо понимать, что эксперту Васе вы не начальник, и пытаться ему приказывать не следует.

Самое смешное, что мы над этим драйвером с говорящим именем уже успели посмеяться и в 2020 году, и раньше еще, но никому, кроме ребят из ESET, не пришло тогда в голову отреверсить этот драйвер, просто посмеялись и дальше пошли работу работать. Вывод: иногда надо верить говорящим именам, и если на заборе написано известное слово из трех букв, то за ним могут быть не только дрова.

Anyway, in LenovoVideoInitDxe.efi it reads the battery status from the EC (register 0x38, which we came across in part 2 when decoding the ACPI tables, as well as register 0xd1 which has some additional battery status flags). Depending on certain bits in those registers, it may print one or other message.
Цитата отсюда.
Хорошая статья, только лучше было бы сделать дамп оригинальной прошивки, и модифицировать уже его, так получится перенести все индивидуальные данные, даже не зная, где они хранятся. Еще у других ноутбуков HP бывают случаи защиты тома DXE от модификации, но эта защита успешно обходится (1, 2, 3), если на ноутбуке не включен BootGuard.
BIY уникальна тем, что там быстро появляются не только просто правила, но и мета-правила (т.е. правила, действующие на сами правила, TEXT IS FLOAT), и даже пара-правила (т.е. правила, действующие вне текущего уровня, LEVEL IS YOU). Пусть это и не про «алгоритмы», но и «массирует» те же аналитические отделы мозга, что и решение задач про алгоритмы.
Думаю, что оставшаяся без Directly Responsible Individual часть проекта обязательно сломается скорее раньше, чем позже, и вместо одного дорого умника понадобится пять, чтобы либо оперативно разобраться, починить, снова назначить DRI, и реанимировать эту часть, либо ударным трудом переписать, чтобы все снова заработало хоть как то.

Видел несколько успешных проектов с размазанным владением, но в них всегда был «дежурный DRI на сегодня», и было их там не шестеро средних, а трое сильных, которые сообща владели дюжиной проектов разного размера, и могли перебрасывать и свои силы, и силы своих ассистентов уровней поменьше с тех мест, где уже нормально, на те, где все еще все в огне и мы в аду.

Проблема автобусного фактора вокруг единицы у очень многих ключевых сотрудников, от которого страдают и работодатель, и сами ключевые сотрудники — она понятная, и решается в основном заваливанием этих сотрудников плюшками (чтобы не уходили к конкурентам), и стратегическими длинными отпусками в тот момент, когда ключевые сотрудники начинают подгорать (чтобы не уезжали в Монголию пасти скот), но вот такие вот решения намного лучше работают на практике, чем попытки размазать реальное владение, которое неизбежно приводит к многократно опробованному и повторенному «общее — значит ничьё».
Хакинтош и UEFI SecureBoot — это не про то несколько, и я точно не призываю закрыть всю загрузку наглухо и никого не впускать и не выпускать, потому что это другая крайность, и я сам ее не люблю так же сильно, как и описанную в этой статье «гуляй-рванину».

Тем не менее, многолетний практически опыт подсказывает, что любые технологии обеспечения безопасности, которые отключить проще, чем настроить, будут при первых сложностях с их настройкой или проблемах, вызванных неверной настройкой, отключены навсегда, зачастую прямо на заводе. А если они еще и по-умолчанию отключены — никто даже не пойдет их включать или тестировать, «нам тут работать надо, а не херней страдать». Это потом уже любой хакер Вася за 15 минут делает себе ботнет из 100500 машин, и идет ими майнить монеро или ддосить своего соседа Петю, но производителя это все не начинает волновать никак — его устройства уже на рынке, деньги он уже получил, а дальше все эти проблемы — это проблемы Васи и Пети.

Именно поэтому любые подобного рода технологии нормально заработают только тогда, когда: а) они будут включены по умолчанию, б) пользоваться ими будет намного проще, чем отключить совсем. Именно так получилось сделать и на T2, на Apple Silicon, и я считаю последнюю итерацию своим самым большим достижением в карьере на данным момент — несложно настраиваемый SecureBoot, позволяющий загружать любой пользовательский код (после проверки пароля и доказательства физического присутствия), и при этом не отключаемый принципиально, и доставленный на миллионы машин простых пользователей, которые массово на него не жалуются. А UEFI SecureBoot как отключали, так и продолжат отключать при любом чихе, а потом страдать от загрузочных вирусов и перехватчиков паролей.
Не, это не намеренно, это просто никто даже не пытался ничего включать и настраивать, потому что это и дорогое время инженера, и возможные сложности с обновлениями, и вероятность неверной настройки и последующего отзыва оборудования.

На самом деле, только когда производитель достаточно именитый, чтобы уязвимости в его устройствах начали портить ему имидж и продажи, вот только тогда этот самый производитель начинает заставлять своих инженеров что-то делать кроме «отключил и не трогаешь», искать на рынке специалистов по безопасности, деньги им платить, вот это все. Что говорить, если даже крупные производители десктопных плат (Asus, Asrock, MSI и Gigabyte) на безопасность своих прошивок и софта кладут свои огромные таёжные приборы, а уж китайским суньхуньвчаям это все до фонаря и подавно…
Там выше написали уже, но в долине таких зарплат у действительно хороших мидлов и сеньеров давно уже нет, потому что цены на жилье такие, что 110к на семью из трех человек в Сан Франциско — это порог бедности.
Сходите на levels.fyi и посмотрите на total compensation, там меньше 200к нет практически ни у кого уже, а серьезные товарищи с опытом могут рассчитывать на примерно от 200к базы + 100к акциями до 300к базы + 1м акциями, и даже выше, в зависимости от специальности, ниши, умения себя продать и желания играть в big FAANG switcheroo, т.е. менять работу каждые пару лет с повышением текущей зарплаты на 20-40% каждый раз. Тем, кто в switcheroo играть не хочет, может повезти с акциями, которые у FAANGов за последние 4 года выросли в ~10 раз, и потому те, кто их продавать не торопились (базы на все хватало), сейчас уже либо все долларовые миллионеры, либо успешно платят ипотеки за дома на Гавайях.
Комментарии лгут, и компилятор их игнорирует. Код нужно так писать, чтобы комментарии были нужны исключительно для объяснения архитектурных моментов, которые из непосредственно кода реконструировать сложно из за разницы в уровне абстракции. Все остальное должно быть написано так, чтобы поняли и человек, и машина, и статический анализатор очень помогает в том, чтобы прояснить моменты, которые для человека очевидны в одну сторону, а для машины — в другую, вон как с упомянутой выше разницей между memset и memset_s, с as-if rule, и прочими вещами, про которые ребята из СиПроВер постоянно статьи пишут. Писать же человеку одно, а машине другое — гарантировать себе проблемы с тем, что теперь непонятно, чему верить, что на самом деле имел в виду автор, и зачем он это имел в виду.
иногда последствия самых вроде безобидных команд могут быть не сразу очевидными
Зачастую, эти последствия бывают неочевидными даже для самих разработчиков процессора, целая плеяда микроархитектурных атак вроде Spectre, Meltdown, Foreshadow, RIDL, Fallout и остальных — отличное тому подтверждение. Знать и понимать — надо, конечно, но надо тоже осознавать пределы своего понимания, а то ведь я до сих пор вижу в индустрии людей, которые в своем ассемблерном коде старательно избегают pipeline hazard'ы, которых их нынешний процессор давно уже не боится, а на Pentium Pro их код запускаться точно уже не будет…

Про ситуацию с «кэша нет» думать уже не хочу, прошу пардону, потому что и лень, и «так верстают только мудаки (тм)». Можно пойти почитать мануал на тему «кто там в память сбрасывает свой architectural state, и при каких условиях», вспомнить про сегментную адресацию и thread local storage, и прочие разные штуки, но я уже в пижаме и мне уже слишком влом.
То, что чтений может быть больше одного — это нетрудно сделать, TLB-промаха достаточно для того, чтобы процессор вынужден был выполнить трансляцию адресов, для которой понадобится одно или несколько обращений к таблице трансляции (в зависимости от того, как именно настроен paging).
С несколькими записями тоже проблем нет — кладем инструкцию последним байтом страницы, заполняем кэши так, чтобы ничего ни с этой, ни со следующей страницы в них не было, выполняем на эту нашу инструкцию nop неожиданный дальний переход — pipeline flush, cache flush, протокол когерентности заставил сделать write-back как минимум двух вымытых из кэшей линий (которые теперь заменили одна с конца этой страницы, ее запросил декодер, а другая — с начала следующей, эту запросил префетчер).
Хорошая задача, но нуждается в дополнительных уточнениях условий, потому что реально худший случай может быть CXL-устройством, подключенным в адресное пространство процессора, которое при попытке декодировать с него nop пойдет этот самый доступ в память осуществлять, а процессору скажет подождать немного, пока оно не закончит, и ждать он там может до ишачьей пасхи, или пока вочдог всех не прибьет.

Если подразумевать, что ничего такого у нас нет, и задача без особого подвоха, то получится примерно «пошли декодировать, нарвались на начало длинного нопа с префиксами, который попал посередине на границу физических страниц, при этом в TLB ничего нет нужного, и потому надо идти в память декодировать, и еще оказалось, эта вторая страница не исполняемая, ошибка декодирования, кровь, кишки, распидорасило, охулиард записей в память на логи и крэш-дамп».

image
Мерять надо, понятно, но мой собственный палец (это которым «в небо») говорит, что арифметические операции, выполняемые целиком на ALU, выполняются нынче за один такт (на современных х86 после Skylake это так даже для 256- и 512-битовых регистрах), а половина примерно мувов из регистра в регистр — за ноль (потому что там внизу регистровый файл, и переименование фактически бесплатное). L1D на этих же процессорах умеет при идеальных условиях читать две линии по 512 бит за такт, или писать одну, но там если самому с выравниванием не заморочиться хоть немного, можно попасть на границу кэш-линии (и просесть вдвое на ровном месте), или физической страницы (и просесть в ~200 раз), ну и плюс мы тут всяко не одни исполняемся, и из кэша наше игровое поле может вымыть в любой момент…

Короче, мерять надо все равно, и написать кучу разных вариантов, но обычно те, кто это все умеет и практикует — они уже на работе сыты этим всем по горло. Студентам зато можно дать в качестве задачи со звездочкой.
%macro memtoreg 4
xor r10, r10
mov r10b, byte [stor + %4]
xor r11, r11
mov r11b, byte [stor + %3]
xor r12, r12
mov r12b, byte [stor + %2]
xor r13, r13
mov r13b, byte [stor + %1]
%endmacro

Все было плюс-минус хорошо до вот этого момента, байтоебили экономили память, изучали платформу и регистры, радовались, а потом пошли копировать в регистры и обратно по одному байту, потому что на этой платформе за неправильное выравнивание bus error не прилетит.

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

Понятно, что все это буйство оптимизации разобьется все равно об последующее копирование 16 параметров в стек для printf, но без него статья получается странная, потому что непонятно, зачем оно все, если на С можно написать ровно то же самое, только проще в разы.

Надо будет написать статью про современное применение ассемблера там, где он реально нужен — в прошивке до инициализации оперативной памяти или cache-as-ram, в ядре ОС для перехода во всякие хитрые режимы исполнения и выхода из них, и т.п.
Можно, я гарантирую это. Статью саму комментировать не буду, потому что в успех вот этих войн обиженных тетенек против мегакорпораций в твиттере верю не очень сильно.

Информация

В рейтинге
Не участвует
Дата рождения
Зарегистрирован
Активность

Специализация

Инженер встраиваемых систем, Системный инженер
Ведущий