
The x86 processor fuzzer
: фаззер для процессоров 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 выявило недокументированные функции процессоров в десятках категорий кодов операций, недостатки в корпоративных гипервизорах, ошибки почти во всех основных инструментах дизассемблирования и эмуляции, а также критические аппаратные ошибки, открывающие уязвимости безопасности в самом процессоре.
Подробности результатов можно найти в документе проекта.
(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, а инжектору через -- -f.
Пример:
sudo ./sifter.py --unk --dis --len --sync --tick -- -P1 -t
Флаги sifter:
--len
поиск различий в длине для всех инструкций (инструкций, которые
выполнились иначе, чем ожидал дизассемблер, или не
существовали, когда дизассемблер их ожидал)
--dis
поиск различий в длине для корректных инструкций (инструкций, которые
выполнились иначе, чем ожидал дизассемблер)
--unk
поиск неизвестных инструкций (инструкций, о которых дизассемблер не
знает, но которые успешно выполняются)
--ill
обратное --unk, поиск некорректных дизассемблирований (инструкций, которые
не выполняются успешно, но которые дизассемблер распознает)
--tick
периодическая запись текущей инструкции на диск
--save
сохранение прогресса поиска при выходе
--resume
возобновление поиска с последнего сохраненного состояния
--sync
запись результатов поиска на диск по мере их обнаружения
--low-mem
не хранить результаты в памяти
Флаги инжектора:
-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
Интерфейс предполагает, что терминал имеет как минимум определенный размер; если интерфейс отображается неправильно, попробуйте увеличить размер терминала; это часто можно сделать, уменьшив размер шрифта в терминале.
В некоторых случаях может быть желательно или необходимо запустить инструмент без графического интерфейса. Это можно сделать, запустив инжектор напрямую:
sudo ./injector -P1 -t -0
Для фильтрации результатов прямого вызова инжектора можно использовать 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 инжектору:
sandsifter — исследовательский проект Кристофера Домаса (@xoreaxeaxeax).
sudo ./sifter.py --unk --dis --len --sync --tick --low-mem -- -P1 -t -N
Если вы заметили, что ваше сканирование завершается слишком быстро (например, сканирование завершается за секунды), это обычно означает, что эти флаги необходимы для сканируемого вами процессора.
32 против 64 бит
По умолчанию sandsifter собирается для разрядности хост-операционной системы. Однако некоторые инструкции ведут себя по-разному при выполнении в 32-битном процессе по сравнению с 64-битным. Для изучения этих сценариев иногда полезно запускать 32-битный sandsifter на 64-битной системе.
Чтобы собрать 32-битный sandsifter на 64-битной системе, Capstone должен быть установлен как 32-битный; инструкции для этого можно найти на http://www.capstone-engine.org/.
Затем sandsifter должен быть собран для 32-битной архитектуры:
make CFLAGS=-m32
Таким образом, 32-битное пространство инструкций можно исследовать на 64-битной системе.