Для кого она нужна?
1) начинающих реверсеров, знающих особенности обратного проектирования, и желающих изучить такой отладчик как GDB
2) как подсказка тем кто постоянно работает с IDA, Ghidra или любым другим мощным и надежным инструментом, но в силу тех или иных обстоятельств решить задачу проще и быстрее с помощью GDB, и не очень хочется залезать в официальную документацию и снова все вспоминать
Основные команды
Запуск
Общий синтаксис выбора исполняемого файла для анализа
gdb program_nameЗапустить выполнение программы
run | rПрисоединиться к gdbserver
target remote host:portПрисоединиться к процессу, отключиться от него
attach PID / detachВыйти из gdb
quit | q
CTRL + DСтатический анализ
Выбрать синтаксис ассемблера
set disassembly-flavor intel/attПросмотреть информацию об архитектуре, секциях
info file Получение списка функций
info functions | i funcПолучение asm-листинга функции
disas func_name
disas address Если у вас есть исходники (можем собрать с опцией -g3 для gcc) или исследуемая программа содержит отладочную информацию, можем посмотреть листинг ее исходного кода
list func_nameДинамический анализ
Установить аргументы для каждого запуска программы и посмотреть их
set args
show argsРаспределение виртуальной памяти
info proc mappingsПросмотр регистров
registersОтладка
Шаг с заходом в функцию
step | sШаг с прыжком через вызываемую подпрограмму
next | nВыполнить до нужной строки, адреса
until | u number_of_list_string
until | u *func_name+offset
until | u *addressИнформация об аргументах функции, локальных переменных (для файлов, содержащих отладочную информацию) и фрейме текущей функции
info args
info locals
info frameПросмотреть список процессов и выбрать интересующий
info threads
thread numberСпособы расстановки breakpoints
b func_name
b *func_name+offset
b *addressПосмотреть список точек останова, включить или отключить, удалить breakpoint
info break
disable/enable breakpoint_number
delete breakpoint_number
ignore breakpoint_number n // остановится на этой точке пройдя ее n разПродолжить выполнение до следующего breakpoint-а
continue | cПросмотр стека
telescope
telescope $rsp+64Для отображения значения по указанному адресу используется команда x, где через "/" указывается формат вывода
x/i - инструкция
x/x - hex
x/s - строка
x/a - адреса также размер вывода
x/b - 8-bit
x/h - 16-bit
x/w - 32-bit
x/g - 64-bitПример
x/64bx
x/i $pcПередача аргумента командной строки
run $(python -c "print('A'*32 + '\xde\xad')")
run $(echo "asdf\\xde\xad")Для передачи значений функциям ввода
run <<< $(python -c "print('A1'*3)")
run <<< $(echo "asdf\xde\xad")Gdb Сервер
Запустить сервер gdb для отладки
gdbserver host:port programReverse Debug
Все мы проходили через этот неловкий момент когда во время отладки мы проскочили интересующую нас функцию, и теперь снова надо перезапускать отладчик, проходить тот же путь на CFG и т.п. Чтобы избежать этого, в gdb есть такая фишка как Reverse Debug, позволяющая сохранить состояние программы и обратно отладить до него.
Для этого, после запуска отладчика укажем gdb, что хотим начать использовать reverse debug и стоит сохранять состояния программы
recordПосле этого станут доступны следующие команды
reverse-step
reverse-nextСоздание дампа
Сдампить участок памяти ( часто необходимо при работе с распаковщиками )
dump memory output_file start_addr end_addrНастройка для работы
Для того чтобы закрепить вывод команды, скажем просмотр инструкций во время отладки и отображения регистров можно воспользоваться командой display
display/5i $pc
display/g $rax
display/g $rbx
display/g $rcxДелаем жизнь проще с GEF
Для эффективного использования gdb лучше воспользоваться плагином gef, он уже включает в себя удобный закрепленный вывод, используемый при динамическом анализе, а также набор собственных команд расширяющий возможности нашего универсального отладчика. Рассмотрим некоторые наиболее полезные.
Посмотреть состояние aslr, включить/отключить
aslr
aslr on/offДля проверки исполняемого файла на наличие ASLR, Canary, PIE и т.д.
checksecПосмотреть чанки
heap chunksНаходясь в функции можем получить значение канарейки и адрес, где она расположена
canaryЧуть более удобный вывод, чем info proc mappings
vmmapПросмотр регистра флагов и изменение их
flags
flags -Flag_name +Flag_nameПомощь для поиска уязвимостей форматной строки (установка на них точек останова, информация по найденным функциям)
format-string-helperСоздание паттерна и его поиск
pattern create 128
pattern search 0x61616167
pattern search $rbpПоиск строк по шаблону
search-pattern patternПатчинг
patch byte/word/dword/qword address valueПечать массива в формате удобном для копирования в python код. Параметр b должен быть 8/16/32/64, l контролирует длину массива
Пример
print-format -b 64 -l 1 $rspДля поиска шеллкода по шаблону
shellcode search pattern
shellcode get shellcode_numberКсорим значения в памяти и регистрах
xor display address/register size xor_key
xor patch address/register size xor_key
nckma
Может посоветуете по такому вопросу… Пытаюсь отладить некоторую программу, запускаю ее по команде run. Она стартует и потом выскакивает segfault.
Казалось бы я могу посмотреть backtrace и понять в какой функции произошло и посмотреть весь стек вызовов. Однако происходит что-то странное — в стеке вызовов например одна функция memcpy() откуда вызвана не понятно, предыдущих функций в списке нет.
Или бывает другое — показана функция в которой сегфаулт, но она по идее вообще никогда не должна вызываться. Такое впечатление, что программа просто улетает неизвестно куда…
Один случай я таки смог понять и отловить. Очень странное дело. Обнаружил, что если есть C функция объявленная как int func(), но программист не делает return result (не возвращает никакого значения), то такой код может оказывается валить программу, происходит переход по случайному адресу. Это происходит иногда при компиляции с gcc8.
Думаю в моем случае еще что-то такое происходит… но как найти с помощью gdb?
Когда случается segfault, то уже видимо поздно.
Отлаживать от старта программы по шагам вряд ли получится, так как там в программе много асинхронных потоков.
win32asm
По описанию похоже на битый стек.
Я бы посоветовал погонять с ASAN/MSAN/TSAN, а если только в gdb — то, возможно, record и обратное исполнение что-нибудь покажут. Ну или руками попытаться раскрутить стек, глядишь, что получится.
void_one
Выглядит как оптимизированный бинарник, нужно компилировать с -O0.
staticmain
Вы собираете release версию, в которой отсутствует debug информация. Для ее добавления компилируйте с "-g".
nckma
Флаг -g используется.
staticmain
Значит падение происходит в сторонней/системной библиотеке, которая собрана без отладочной информации. Установите соотвествующие -dev пакеты или пересоберите библиотеки
vyo
Обычно в -dev пакеты кладут заголовки, отладочные символы отдельно пакуются в -dbg.
void_one
1) "-g" не отменяет оптимизацию, нужно чтобы явно был выставлен уровень -O0.
2) Отладочные символы для сторонних библиотек ставятся в пакетах -dbg. Для Ubuntu и Debian эти пакеты лежат в отдельных репозиториях, которые нужно подключать.