
Фаззер для процессора x86
: фаззер процессора x86
Sandsifter проводит аудит процессоров x86 на наличие скрытых инструкций и аппаратных ошибок, систематически генерируя машинный код для поиска в системе команд процессора и отслеживая аномалии выполнения. Sandsifter обнаружил секретные инструкции процессоров от всех крупных производителей; повсеместные программные ошибки в дизассемблерах, ассемблерах и эмуляторах; уязвимости в корпоративных гипервизорах; а также как безвредные, так и критически важные для безопасности аппаратные ошибки в чипах x86.
Учитывая множество существующих процессоров x86, цель инструмента — дать пользователям возможность проверить свои системы на наличие скрытых инструкций и ошибок.
Для выполнения базового аудита вашего процессора:
sudo ./sifter.py --unk --dis --len --sync --tick -- -P1 -t

Компьютер систематически сканируется на наличие аномальных инструкций. В верхней части отображаются инструкции, которые sandsifter в данный момент тестирует на процессоре. В нижней части sandsifter сообщает об обнаруженных аномалиях.
Поиск может занять от нескольких часов до нескольких дней, в зависимости от скорости и сложности вашего процессора. Когда поиск завершится, обобщите результаты:
./summarize.py data/log

Обычно обнаруживается несколько миллионов незадокументированных инструкций вашего процессора, но в основном они делятся на небольшое количество различных групп. После группировки аномалий инструмент обобщения пытается отнести каждую инструкцию к одной из категорий:
Нажмите 'Q' для выхода и получения текстового отчёта о сканировании системы:
Результаты сканирования иногда сложно автоматически классифицировать инструментами, и может потребоваться ручной анализ. Если вам нужна помощь в анализе результатов, не стесняйтесь отправить файл ./data/log на адрес [email protected]. В этот лог не включается никакая личная информация, кроме марки, модели и ревизии процессора (из /proc/cpuinfo).
Сканирование с помощью sandsifter выявило незадокументированные возможности процессоров в десятках категорий опкодов, ошибки в корпоративных гипервизорах, ошибки практически во всех основных инструментах дизассемблирования и эмуляции, а также критические аппаратные ошибки, создающие уязвимости безопасности в самом процессоре.
Подробности результатов можно найти в проекте whitepaper.
(TODO: подробное перечисление результатов)
Sandsifter требует предварительной установки дизассемблера Capstone: http://www.capstone-engine.org/. Capstone обычно устанавливается с помощью:
sudo apt-get install libcapstone3 libcapstone-dev
sudo pip install capstone
Sandsifter собирается командой:
make
и запускается командой
sudo ./sifter.py --unk --dis --len --sync --tick -- -P1 -t
Флаги передаются sifter с помощью --flag, а injector — с помощью -- -f.
Пример:
sudo ./sifter.py --unk --dis --len --sync --tick -- -P1 -t
Флаги sifter:
--len
поиск различий в длине всех инструкций (инструкций, которые выполнялись
иначе, чем ожидал дизассемблер, или не существовали, когда
дизассемблер ожидал их)
--dis
поиск различий в длине допустимых инструкций (инструкций, которые
выполнялись иначе, чем ожидал дизассемблер)
--unk
поиск неизвестных инструкций (инструкций, о которых дизассемблер не знает,
но которые успешно выполняются)
--ill
обратная сторона --unk, поиск недопустимых дизассемблирований (инструкций,
которые не выполняются успешно, но распознаются дизассемблером)
--tick
периодическая запись текущей инструкции на диск
--save
сохранение прогресса поиска при выходе
--resume
возобновление поиска с последнего сохранённого состояния
--sync
запись результатов поиска на диск по мере их обнаружения
--low-mem
не хранить результаты в памяти
Флаги injector:
-b
режим: полный перебор
-r
режим: рандомизированный фаззинг
-t
режим: туннелированный фаззинг
-d
режим: внешне направленный фаззинг
-R
режим сырого вывода
-T
режим текстового вывода
-x
периодический вывод прогресса в stderr
-0
разрешить разыменование нулевого указателя (требует sudo)
-D
разрешить дублирующиеся префиксы
-N
без поддержки NX-бита
-s seed
при случайном поиске, значение зерна
-B brute_depth
при полном переборе, максимальная глубина поиска
-P max_prefix
максимальное количество префиксов для поиска
-i instruction
инструкция, с которой начать поиск (включительно)
-e instruction
инструкция, на которой закончить поиск (исключительно)
-c core
ядро, на котором выполнять поиск
-X blacklist
игнорировать указанную инструкцию
-j jobs
количество одновременных задач
-l range_bytes
количество байт базовой инструкции в каждом поддиапазоне
m: Режим — изменить режим поиска (полный перебор, случайный или туннелированный) для sifter
q: Выход — завершить работу sifter
p: Пауза — приостановить или возобновить поиск
Сканирование поддерживает четыре различных алгоритма поиска, которые можно задать в командной строке или переключать горячими клавишами.
sudo
Для наилучших результатов инструмент следует запускать от имени root. Это необходимо для того, чтобы процесс мог отобразить в память страницу по адресу 0, что требует прав root. Эта страница предотвращает segfault многих инструкций при обращениях к памяти, что позволяет более точно анализировать ошибки.
Префиксы
Основное ограничение глубины поиска инструкций — количество байтов префиксов для исследования, причём каждый дополнительный байт префикса увеличивает пространство поиска примерно в 10 раз. Ограничьте количество байтов префиксов флагом -P.
Цвета
Интерфейс sifter рассчитан на терминал с 256 цветами. Хотя детали сильно различаются в зависимости от вашего терминала, примерно это можно сделать командой:
export TERM='xterm-256color'
GUI
Интерфейс предполагает, что терминал имеет не меньше определённого размера; если интерфейс отображается некорректно, попробуйте увеличить размер терминала; этого часто можно добиться уменьшением размера шрифта терминала.
В некоторых случаях может быть желательно или необходимо запускать инструмент без графического интерфейса. Это можно сделать, запустив injector напрямую:
sudo ./injector -P1 -t -0
Для фильтрации результатов прямого вызова injector можно использовать grep. Например,
sudo ./injector -P1 -r -0 | grep '\.r' | grep -v sigill
ищет инструкции, по которым процессор и дизассемблер не сошлись в длине (grep '.r'), но инструкция успешно выполнилась (grep -v sigill).
Целевой фаззинг
Во многих случаях полезно направить фаззер на конкретную цель. Например, если вы подозреваете, что эмулятор имеет ошибки вокруг повторяющихся префиксов 'lock' (0xf0), вы можете направить фаззер на поиск в этой области пространства инструкций с помощью флагов -i и -e:
sudo ./sifter.py --unk --dis --len --sync --tick -- -t -i f0f0 -e f0f1 -D -P15
Старые системы
Для сканирования очень старых систем (процессоры i586, системы с малым объёмом памяти) передайте флаг --low-mem в sifter и флаг -N в injector:
sandsifter — исследовательский проект Кристофера Домаса (@xoreaxeaxeax).
sudo ./sifter.py --unk --dis --len --sync --tick --low-mem -- -P1 -t -N
Если вы замечаете, что сканирование завершается слишком быстро (например, за секунды), это обычно означает, что для вашего процессора требуются эти флаги.
32 vs. 64 бита
По умолчанию sandsifter собирается под разрядность хост-ОС. Однако некоторые инструкции ведут себя по-разному при выполнении в 32-битном процессе по сравнению с 64-битным. Для изучения этих сценариев иногда полезно запустить 32-битный sandsifter на 64-битной системе.
Чтобы собрать 32-битный sandsifter на 64-битной системе, необходимо установить Capstone как 32-битный; инструкции для этого можно найти на http://www.capstone-engine.org/.
Затем sandsifter должен быть собран для 32-битной архитектуры:
make CFLAGS=-m32
После этого можно исследовать 32-битное пространство инструкций на 64-битной системе.