ANTICHAT

ANTICHAT (https://forum.antichat.xyz/index.php)
-   Электроника и Фрикинг (https://forum.antichat.xyz/forumdisplay.php?f=21)
-   -   Эксплуатирование Движка Управления Intel - Часть 2: Включение RED разблокировки JTAG на Intel ME 11.x (INTEL-SA-00086) (https://forum.antichat.xyz/showthread.php?t=570357)

g00db0y 31.12.2019 19:36

Цитата:


Оригинал статьи находится здесь: Exploiting Intel’s Management Engine – Part 2: Enabling Red JTAG Unlock on Intel ME 11.x (INTEL-SA-00086) | KaKaRoTo's Blog

Привет, друг! Давно не виделись! Я начинаю эту статью сразу после того, как опубликую первую часть: Понимание TXE PoC PT.

Если вы не читали первую часть, то прочтите её прямо сейчас, потому что это всего лишь продолжение моего предыдущего поста, но из-за его длины я решил разделить его на несколько частей.

Теперь, когда мы знаем, как работает существующий эксплойт TXE, но нам нужно перенести его на ME 11.x. К сожалению, метод systracer очень сложно воспроизвести, так как вы контролируете только несколько битов в адресе возврата и имеете возможность изменить адрес возврата на тот, который действителен, но это не приводит к аварийному завершению, а возвраты корректно в наш ROP - очень сложны. В моем случае, я фактически начал портировать его на ME 11.0.0.1180, который даже не установил значения systracer, так что у меня не было выбора, кроме как посмотреть эксплойт, объясненный в презентации BlackHat Europe 2017: Использование метода memcpy.

Сбор необходимой информации

Я избавлю вас от подробностей показа любого реверснутого кода и просто перейду к делу.
  • Раздел MFS использует фрагменты по 64 байта каждый.
  • Функция чтения MFS читает во временный буфер размером 1024 байта, и если части файловой системы последовательны, она может читать несколько частей (до 16) одновременно.
  • Файл "/home/mca/eom" в файле MFS fitc.cfg должен содержать один байт со значением 0x00
  • DCI должен быть активирован с помощью множителей опорной частоты процессорных ядер (или просто CPU Straps) в IFD (Intel Flash Descriptor).
  • Есть альтернативный вектор выполнения, который может произойти: если в MFS есть домашний раздел (индекс файла 8), это может привести к тому, что эксплойт не сработает, поэтому убедитесь, что раздел MFS не имеет файла с индексом 8 (подробнее об этом позже).
  • В связи с вышесказанным, необходимо включить HAP бит. Если ME загрузится полностью (т.е. не будет отключен через HAP), то домашний раздел будет создан в MFS и эксплойт перестанет работать. Вместо этого ME перестанет работать должным образом и машина станет кирпичом.
  • Структура контекста разделяемой памяти со смещением 0x68 контекста syslib, внутри этого контекста, со смещением 0x28, находится указатель на дескрипторы разделяемой памяти, а со смещением 0x2C - количество корректных дескрипторов разделяемой памяти.
  • Обратите внимание, что контекст разделяемой памяти находится внутри системного контекста, а не просто указатель на него, поэтому указатель на дескрипторы разделяемой памяти находится со смещением 0x90 (0x68 + 0x28) системного контекста
  • Дескрипторы блоков общей памяти имеют размер 0x14 и формат , где flags, устанавлены в 0x11, работают нормально (думаю, бит 0 отвечает за 'in use', не уверен насчет бита 4, но он был установлен в схеме как init_trace_hub), а thread_id в нашем случае установлен как 0.
Что бы понять запутанные последние пункты о дескрипторах общей памяти, вот немного измененный график с одного из слайдов презентации BlackHat Europe 2017 :

https://forum.antichat.xyz/attachmen...7805377953.png

Слайд 43 "Как взломать выключенный компьютер или запустить неподписанный код в движке управления Intel".

Мой старый Librem 13 - это аппарат на Skylake, и я использовал его для всех своих тестов, так как его очень легко запускать и без проблем проводятся различные тесты. Librem 13 имеет ME версию 11.0.18.1002 (если кто-то захочет протестировать на определенном версии).

Теперь, первое, что нам нужно сделать, это выяснить, где находится наш стек. Для этого мы открываем модуль BUP в IDA и проверяем самую первую функцию, которая вызывается из точки входа (перед основной).

https://forum.antichat.xyz/attachmen...7805406618.png

Эта функция инициализирует контекст syslib, структуру TLS и стек, поэтому мы найдем в нем тщательно закодированные значения всех этих вещей. Вот как это выглядит :

https://forum.antichat.xyz/attachmen...7805414363.png

Теперь я знаю, что мой адрес стека для ME 11.0.18.1002 - 0x60000, а syslib контекст - 0x82CAC с размером 0x218 (пока это не очень полезная информация).

Что я буду делать дальше? Нужно идти к точке входа и следовать за вызовами push/pop/call/ret, чтобы получить полную картину стека до интересующего меня memcpy, как я делал это в своей предыдущей статье. Вот результат :

Код:


[CODE]
ME 11.0.18.1002 STACK - bup_entry :
0x60000: STACK TOP
0x5FFEC: TLS

0x5FFE8: ecx - arg to bup_main
0x5FFE4: edx - arg
0x5FFE0: eax - arg
0x5FFDC: retaddr - call bup_main
0x5FFD8: saved ebp of bup_entry

0x5FFD4: 0 - arg to bup_run_init_scripts
0x5FFD0: retaddr - call bup_run_init_scripts
0x5FFCC: saved ebp of bup_main
0x5FFC8: saved edi
0x5FFC4: saved esi
0x5FFC0: saved ebx
0x5FFBC: var_10

0x5FFB8: retaddr - call bup_init_trace_hub
0x5FFB4: saved ebp of bup_run_init_scripts
0x5FFB0: saved esi
0x5FFAC: saved ebx
0x5FC64: STACK esp-0x348
0x5FFA8: security cookie
0x5FC80: ct_data
0x5FC6C: si_features
0x5FC68: file_size
0x5FC64: bytes_read

0x5FC60: edx - arg to bup_dfs_read_file
0x5FC5C: eax - arg
0x5FC58: esi - arg
0x5FC54: 0 - arg
0x5FC50: "/home/bup/ct" - arg
0x5FC4C: retaddr - call bup_dfs_read_file
0x5FC48: saved ebp of bup_init_trace_hub
0x5FC44: saved edi
0x5FC40: saved esi
0x5FC3C: saved ebx
0x5FB9C: STACK esp-0xA0

0x5FB98: 0 - arg to bup_read_mfs_file
0x5FB94: edi - arg
0x5FB90: esi - arg
0x5FB8C: eax - arg
0x5FB88: 7 - arg
0x5FB84: retaddr - call bup_read_mfs_file
0x5FB80: saved ebp of bup_dfs_reads_file

0x5FB7C: eax - arg to bup_read_mfs_file_ext
0x5FB78: sm_block_id - arg
0x5FB74: size - arg
0x5FB70: offset - arg
0x5FB6C: file_number - arg
0x5FB68: msf_desc - arg
0x5FB64: retaddr - call bup_read_mfs_file_ext
0x5FB60: saved ebp of bup_read_mfs_file
0x5FB5C: saved edi
0x5FB58: saved esi
0x5FB54: saved ebx
0x5F6E8: STACK esp-0x46C

0x5F6E4: ebx - arg to sys_write_shared_mem
0x5F6E0: ebx - arg
0x5F6DC: eax - arg
0x5F6D8: cur_offset - arg
0x5F6D4: sm_block_id - arg
0x5F6D0: var_478 - arg
0x5F6CC: retaddr - call sys_write_shared_mem
0x5F6C8: saved ebp of bup_read_mfs_file_ext
0x5F6C4: saved edi
0x5F6C0: saved esi
0x5F6BC: saved ebx
0x5F6AC: STACK esp-0x10

0x5F6A8: ebx - arg to memcpy_s
0x5F6A4: edi - arg
0x5F6A0: edx - arg
0x5F69C: esi - arg
0x5F698: retaddr - call memcpy_s
0x5F694: saved ebp of sys_write_shared_mem
0x5F690: saved edi
0x5F68C: saved esi
0x5F688: saved ebx

0x5F684: copysize - arg to memcpy
0x5F680: edi - arg
0x5F67C: ebx - arg
0x5F678: retaddr - call memcpy 2->4", а затем спрашиваете у него ID.

Эта топология определена в XML-файле, и я написал скрипт, который сгенерировал XML-файл, который, по сути, перебирает все возможности. Так что для каждого устройства я определяю 8 под-устройств, а для каждого из этих под-устройств я определяю 8 других под-устройств, до глубины 4 или даже не помню, сколько их. Поэтому, потратив несколько дней на то, чтобы разобраться в этом, я просто написал этот скрипт:

Python:


Код:

def
genTaps
(
max
,
depth
=
0
,
max_depth
=
1
,
parent
=
"SPT_TAP"
)
:
res
=
""
for
i
in
xrange
(
0
,
max
,
2
)
:
name
=
"%s_%s"
%
(
parent
,
i
)
res
+=
(
'  '
*
depth
+
'\n'
%
(
name
,
i
,
max
,
i
,
max
)
)
if
depth
+
1
\n'
)
return
res
# ProductInfo.xml needs this line added :
#
# Or whatever parent/prefix you use for the initial call set in TapName

Затем я назвал его и сгенерировал новый файл OpenIPC/Data/Xml/SPT/TapNetworks.LP.xml, добавил строку в файл ProductInfo.xml, чтобы сказать ему, что есть 'Box' узел со всеми этими TAP устройствами, затем снова запустил OpenIPC. И о чудо! Он принимает конфигурационный файл (после N-ой попытки, конечно, но давайте проигнорируем это...)!

Файл tap networks теперь весит 500KB и имеет эту огромную иерархию в около 3000 устройств, большинство из которых не существовало и выдало ошибку, когда OpenIPC попытается сканировать их idcode, и поэтому не будет добавлять их в окончательный список устройств (думая, что они просто выключены), но как только это будет сделано, он должен перечислить все устройства, которые на самом деле доступны в JTAG-цепочки.

Наконец, я запустил этот маленький код в консоли IPC python :

Python:


Код:

def
displayValidIdcodes
(
prefix
=
""
)
:
for
d
in
ipc
.
devs
:
if
d
.
name
.
startswith
(
prefix
)
:
idcode
=
d
.
idcode
(
)
proc_id
=
d
.
irdrscan
(
0x2
,
32
)
if
proc_id
!=
0
:
idcode
+=
" ("
+
proc_id
.
ToHex
(
)
+
")"
print
(
"%s : %s"
%
(
d
.
name
,
idcode
)
)

Глядя на все конфигурационные файлы с различных платформ , и пытаясь понять схему, я заметил, что процессоры ядра имеют два идентификационных кода. Первый, использующий IR (Instruction Register, как я думаю) скан-код 0xC позволяя каждому другому устройству, что дает нам реальный Idcode устройства, но, используя код IR сканирования 0x2, он дает нам 'тип процессора' или что-то в этом роде...

Как только я запустил вышеприведенный скрипт, он выдал мне список всех устройств (только одно), которые имеют не нулевой ID процессора, и которые раскрывают ядро CSME! Благодаря этому, я знаю его положение в иерархии, и я могу очистить xml файл, чтобы оставить только это устройство и дать ему правильное имя и правильную конфигурацию, чтобы я мог отлаживать его, и т.д....

XML:


Код:


Кстати, это происходит на OpenIPC_1.1917.3733.100, а ключ расшифровки - 1245caa98aefede38f3b2dcfc93dabfd, так что мы можем просто расшифровать файлы OpenIPC с помощью :

Код:

python config_decryptor.py -k 1245caa98aefede38f3b2dcfc93dabfd -p C:\Intel\OpenIPC_1.1917.3733.100
Скорее всего, будет другая версия OpenIPC, если вы будете использовать последнюю версию Intel System Studio (думаю, у меня была версия 2019.4) и, следовательно, другой ключ дешифровки. Вы можете легко найти свой собственный, воспользовавшись инструкциями, которые PT выпустил вместе со своим POC репозиторием.

Есть еще одна заключительная проблема, которую необходимо решить. Всякий раз, когда я открываю OpenIPC с включенной машиной, она дает сбой из-за некоторого конфликта в конфигурации между ME ядром и основным процессором, поэтому мне нужно подключиться к машине перед тем, как я ее включу, подключиться к OpenIPC, затем включить машину, и она работает. Я уверен, что кто-то сможет придумать правильную XML конфигурацию, которая позволит мне отлаживать и ME, и процессорные ядра одновременно, но на самом деле мне это не нужно, поэтому я не тратил впустую все свое время, пытаясь добиться этого. Обратите внимание, что TXE PoC для Apollolake страдает от той же проблемы, и патчи к OpenIPC, которые выпустил PT, удаляют ядра процессора, чтобы предотвратить этот конфликт.

Независимо от этого, разница для конфигурационных файлов добавлена в мой репозиторий форком IntelTXE-PoC, и просто убедитесь, что вы запустили OpenIPC перед включением основного процессора, и все должно быть в порядке.

И всё! Поздравляю, теперь вы можете отлаживать ME 11.x на машине Skylake или Kabylake!

https://forum.antichat.xyz/attachmen...7806415228.png

Отладка CSME на Skylake

Подошел конец истории . В следующий раз я расскажу вам о том, как я написал быстрый USB-контроллер для CSE и как я заставил CSME нарушить работу USB и SATA-контроллеров во время загрузки ОС, что сделало все USB/SATA-накопители недоступными!

В этой заметке вы увидели выпуск проекта MFSUtil и порт ME 11.x на IntelTXE PoC, в следующей (либо завтра, либо в пятницу) я выпущу множество инструментов и скриптов, которые я использовал для работы с JTAG, так что вы можете делать более легкое нажатие на процессор ME, не борясь с ограничением библиотеки OpenIPC.

Спасибо всем

Апдейт
: Вчера, когда я спешил написать это сообщение (я писал его около 8 часов и было 4 утра), я забыл добавить небольшое спасибо всем тем, кто помогал мне на протяжении всего этого путешествия. Конечно, Mark Ermolov и Maxim Goryachy из компании Positive Technologies за то, что проделали большую часть работы и были снисходительны, ответив на все мои вопросы. Dmitry Sklyarov - за то, что вычислили формат раздела MFS и за то, что записали его для остальных, а также Peter Bosch, который дал полезные советы и помог мне немного лучше понять боковой канал, David Barksdale, который дал мне подсказку, как найти адрес стека из той первой функции в буп коде, а также, возможно, некоторые другие, перед которыми я извиняюсь за то, что не помню их сейчас (это было слишком давно...).

Еще раз спасибо за чтение!


Время: 12:43