
Внедряемый отладчик реального режима x86 для обратной разработки BIOS и отладки произвольного кода реального режима через последовательный кабель, с интеграцией GDB и поддержкой аппаратных точек останова/наблюдения.
BREAD (BIOS Reverse Engineering & Advanced Debugger) — это 'внедряемый' отладчик реального режима x86, который может отлаживать произвольный код реального режима (на реальном оборудовании) с другого ПК через последовательный кабель.
BREAD появился в результате множества неудачных попыток обратного проектирования устаревших BIOS. Учитывая, что подавляющее большинство — если не весь — анализ BIOS выполняется статически с помощью дизассемблеров, понимание BIOS становится чрезвычайно сложным, поскольку невозможно узнать значение регистров или памяти в данном фрагменте кода.
Несмотря на это, BREAD также может отлаживать произвольный код в реальном режиме, например загрузочный код или программы DOS.
Быстрая демонстрация:
https://user-images.githubusercontent.com/8294550/217709970-9007a1e3-7352-470d-a22f-cbb5219d5547.mp4
Изменение имени строки CPU через BREAD
Этот отладчик разделен на две части: отладчик (написанный полностью на ассемблере и работающий на отлаживаемом оборудовании) и мост, написанный на C и работающий на Linux.
Отладчик — это внедряемый код, написанный в 16-битном реальном режиме, и может быть размещен в BIOS ROM или любом другом коде реального режима. При выполнении он настраивает соответствующие обработчики прерываний, переводит процессор в режим пошагового выполнения и ожидает команды на последовательном порту.
Мост, с другой стороны, является связующим звеном между отладчиком и GDB. Мост общается с GDB через TCP и пересылает запросы/ответы отладчику через последовательный порт. Идея моста заключается в том, чтобы убрать сложность пакетов GDB и установить более простой протокол для связи с машиной. Кроме того, более простой протокол позволяет уменьшить конечный размер кода, что упрощает внедрение отладчика в различные среды.
Как показано на следующей диаграмме:
+---------+ simple packets +----------+ GDB packets +---------+
| |--------------->| |--------------->| |
| dbg | | bridge | | gdb |
|(real HW)|<---------------| (Linux) |<---------------| (Linux) |
+---------+ serial +----------+ TCP +---------+
Благодаря реализации GDB-заглушки, BREAD имеет множество функций из коробки. Поддерживаются следующие команды:
Обратное проектирование сырого бинарного файла, такого как BIOS, в GDB автоматически подразумевает отсутствие его исходных символов. Однако по мере продвижения процесса RE пользователь/программист/хакер получает лучшее понимание определенных частей кода, а инструменты статического анализа, такие как IDA, Cutter, Ghidra и другие, позволяют добавлять аннотации, комментарии, определения функций и многое другое. Эти улучшения значительно повышают продуктивность пользователя.
С учетом этого в проекте есть сопутствующий скрипт Python под названием symbolify.py. Получив список символов (адрес метки), он генерирует минимальный ELF-файл с добавленными этими символами. Затем этот ELF можно загрузить в GDB позже и использовать для значительного упрощения процесса отладки.
Файл символов может содержать пробелы, пустые строки, комментарии (#) и комментарии в строке с адресом. Адреса могут быть в десятичном или шестнадцатеричном формате, а метки/символы (разделенные одним или несколькими пробельными символами) могут иметь вид [a-z0-9_]+, как в (реальный пример можно найти в symbols/ami_ipm41d3.txt):
#
# This is a comment
#
0xdeadbeef my_symbol1
0x123 othersymbol # This function does xyz
# Example with decimal address
456 anotherone
Например, учитывая файл символов, доступный в symbols/ami_ipm41d3.txt, пользователь может сделать что-то вроде:
$ ./simbolify.py symbols/ami_ipm41d3.txt ip41symbols.elf
Затем загрузить его в GDB следующим образом:
(gdb) add-symbol-file ip41symbols.elf 0
add symbol table from file "ip41symbols.elf" at
.text_addr = 0x0
(y or n) y
Reading symbols from ip41symbols.elf...
(No debugging symbols found in ip41symbols.elf)
(gdb) p cseg_
cseg_change_video_mode_logo cseg_get_cpuname
(gdb) p cseg_
Обратите внимание, что даже автодополнение GDB работает как ожидалось, удивительно?
Сколько? Да. Поскольку отлаживаемый код не знает, что его отлаживают, он может мешать отладчику несколькими способами, например:
Переход в защищенный режим: Если отлаживаемый код переключается в защищенный режим, структуры для обработчиков прерываний и т.д. изменяются, и отладчик больше не будет вызываться в этой точке кода. Однако возможен прыжок обратно в реальный режим (восстановление полного предыдущего состояния), что позволит отладчику снова работать.
Изменение IDT: Если по какой-либо причине отлаживаемый код изменяет IDT или её базовый адрес, обработчики отладчика не будут правильно вызваны.
Стек: BREAD использует стек и предполагает, что он существует! Его не следует вставлять в места, где стек еще не настроен.
Для отладки BIOS существуют и другие ограничения: невозможно отлаживать код BIOS с самого начала (bootblock), так как для правильной работы BREAD требуется минимальная настройка (например, RAM). Однако можно выполнить "теплую перезагрузку", установив CS:EIP в F000:FFF0. В этом сценарии инициализация BIOS может быть отслежена снова, так как BREAD уже загружен. Обратите внимание, что "путь кода" инициализации BIOS при теплой перезагрузке может отличаться от холодной, и поток выполнения может быть не совсем таким же.
Для сборки требуются только GNU Make, компилятор C (такой как GCC, Clang или TCC), NASM и машина с Linux.
Отладчик имеет два режима работы: опрос (по умолчанию) и на основе прерываний:
Режим опроса — это самый простой подход, который должен хорошо работать в различных средах. Однако из-за природы опроса возникает высокая загрузка ЦП:
$ git clone https://github.com/Theldus/BREAD.git
$ cd BREAD/
$ make