- Главная
- Блог
- Информационная безопасность
- Введение в отладчик OllyDbg
Введение в отладчик OllyDbg
Что такое OllyDbg?
Как сам писал автор, Олег Юшук, “OllyDbg это 32-битный отладчик на уровне ассемблера под операционную систему Windows. Его функционал заточенный под работу с бинарным кодом делает этот отладчик чрезвычайно полезным в случае, когда необходимо отладить программу без доступа к ее исходному коду.” Олли это также динамический отладчик. Это значит, что она позволяет пользователю менять код программы прямо по-ходу исполнения. Это очень важно, в случаях когда мы экспериментируем с бинарником, пытаясь понять как тот работает. Помимо этого, Олли обладает множеством полезных функций, что делает ее одним из лучших отладчиков для реверс-инжиниринга (мы сейчас не говорим об отладке на уровне ядра).
Описание
Вот картинка основного окна Олли:
Как видно, основное окно CPU разбито на четыре части: Disassembly (дизассемблер), Registers (регистры), Stack (стек) и Dump (дамп). Ниже будет представлено описание каждой секции.
1. Disassembly (дизассемблер)
В этой секции находится дизассемблированный код загруженного в Олли бинарника. Тут отображаются команды в бинарном виде и в виде ассемблерных инструкций. Первая колонка содержит адрес в памяти соответствующей инструкции. Вторая колонка – это то, что называют опкоды (операционные коды) – в языке ассемлера каждая инструкция соответствует как минимум одному коду (или нескольким). Это тот код, который непосредственно понимает и исполняет процессор. Эти опкоды образуют машинный язык, язык компьютера. Если бы вы посмотрели на исполняемый файл через хекс-редактор вы бы увидели набор этих кодов и ничего больше. Одна из основных задач Олли переводить этот машинный язык в форму, более понятную человеку – в язык ассемблера. Третья колонка как раз и отображает команды в формате языка ассемблера.
Возможно, тому, кто не знает ассемблера эти команды кажутся такими же непонятными как машинный код, но по мере практики становится понятно, что язык ассемблера гораздо проще для восприятия и понимания, чем сырой машинный код.
Последняя колонка это комментарии, оставленные Олли. Иногда они могут содержать имя вызываемой API-функции (если Олли смогла ее определить), например CreateWindow или GetDlgItemX. Олли также пытается помочь нам в понимании кода, давая имена функциям, которые не являются API-функциями. Например на картинке выше, видно вызовы функций с именами “ImageRed.00510C84″ и “ImageRed.00510BF4″.
Может быть это и не очень-то говорящие имена, но в процессе анализа мы можем понять, что делает та или иная функция и дать ей более осмысленное имя. В этой колонке мы может также писать свои комментарии. Для этого нужно дважды щелкнуть по одной из линий на этой колонке и высветится окно, куда свой комментарий и необходимо ввести. Эти комментарии сохранятся автоматически, и будут отображаться и в следующие разы.
2. Register (регистры)
Каждый процессор обладает набором регистров. Регистры представляют собой временные хранилища информации, что-то вроде переменной в высокоуровневых языках программирования. Вот более детальный вид окна регистров:
На самом верху вы видим непосредственно регистры процессора. Регистры поменяют свой цвет с черного на красный, если они были изменены в результате выполнения предыдущей команды. Можно также дважды кликнуть по какому либо регистру и понять его значение самому. Регистры широко используются для различных целей, как мы увидим в будущем.
Средняя секция содержит так называемые флаги, которые меняют свое значение в результате определенных операций (например при сравнение двух чисел: если они равны тогда во флаг записывается единица, нет – то ноль). Они тоже играют важную роль.
Последняя секция содержит FPU-регистры или регистры математического сопроцессора.
Они используются, когда процессор проводит операции над вещественными числами. В процессе реверс-инжиниринга не так часто приходится с ними сталкиваться, в основном когда имеешь дело с шифрованием.
3. Stack (стек)
Стек – это секция памяти зарезервированная для хранения временного списка данных. Эти данные включают в себя указатели к адресам в памяти, строки, переменные и, очень важно, адреса возвратов – места в программе куда необходимо вернуться после выполнения функции. Когда в программе в каком-либо месте вызывается какая-либо функция мы передаем этой функции управление, что бы она могла выполнить то, что нужно. Но в конце это функции необходимо вернуться туда, откуда он была вызвана и продолжить дальше исполнять следующие команды. Для этого и нужен адрес возврата.
Вещь, которую нужно знать о стеке это то, что это структура, работающая по принципу “первый вошел – последний вышел”. Представьте себе стопку листов. Мы можем либо положить на эту стопку еще один лист, либо снять верхний. Что бы добраться например, до четвертого листа сверху, нам необходимо перед этим снять три листа, которые выше него. Так, в общих чертах, и работает стек.
На этой картинке, первый столбец это адрес в памяти каждого элемента, второй столбец – это шестнадцатеричный код – значение, которое хранятся в стеке и последний столбец это комментарии Олли, о каждом элементе – то что он смогла установить. Например, на картинке напротив верхнего элемента стека стоит комментарий “RETURN to kernel…” Это адрес, который процессор расположил на стеке, что бы знать куда вернуться, когда текущая функция будет исполнена.
Если мы захотим изменить какой-либо элемент стека, нужно кликнуть по нему правой кнопкой мыши и в открывшемся меню выбрать пункт “modify”.
4. Dump (дамп)
Раннее в этом туториале, когда мы говорили о “сырых” опкодах которые процессор непосредственно считывает и исполняет, я упомянул, что мы может посмотреть эти коды в хекс-редакторе. Секция Dump в Олли как раз и предсталяет собой простой встроенный хекс-редатор. В нем мы можем посмотреть на сырой код программы, расположенный в оперативной памяти. Помимо шестнадцатеричных кодов, тут также можно увидеть символы, которые соответствуют тем или иным кодам, согласно ASCII. Итак, первая колонка в окне секции Dump – это адреса в памяти, вторая – сырой бинарный код, представленный в шестнадцатеричном формате, третья – символы.
Тулбар
Давайте теперь рассмотрим тулбар, который предоставляет нам Олли
Здесь расположены основные функции для запуска кода. Имейте также ввиду, особенно если вы новичек, все эти кнопки дублируются в вернем выпадающем меню в разделе “Debug”, так что если вы не уверены что означает та или иная кнопка – можете посмотреть там.
Я сделаю несколько заметок об функциях некоторых кнопок. “Re-load” означает перезапуск приложения с последующей остановкой на точке входа. Все изменения, внесенные вами в код, будут удалены, некоторые брейкпоинты (точки останова) будут отключены и приложение прервет исполнение кода. “Run” и “Pause” делают то, что следует из их названия. “Run” – запускает исполнение кода, “Pause” – временно останавливает, с возможностью потом продолжить с этого момента. “Step In” означает выполнить одну строчку кода и затем остановиться. Если этой строчкой кода является вызов функции, то мы переходим внутрь этой функции. “Step Over” делает тоже самое, но не заходит внутрь функций, а исполняет их целиком за один раз. “Animate” это тоже самое как постоянно жать “Step-In” или “Step-Over” но делать это достаточно медленно, чтобы успевать самому видеть ход исполнения. Эта функция не так часто используется, но бывает интересно посмотреть за ходом исполнения кода, особенно в случаях когда мы имеем дело с самомодифицирующемся кодом и можем вживую наблюдать за его изменениями. Похоже, я забежал слишком вперед.
Рассмотрим теперь иконки для управления окнами:
Каждая из этих иконок открывает окно, некоторые из которых пользуются часто, некоторые – редко. Что бы лучше самому с ними разобраться можно просто покликать на все подряд и посмотреть какое окно, открывает каждая кнопка. Каждая эта кнопка дублируется в верхнем выпадающем меню в разделе “View”, так что можете также заглянуть туда. Давайте пройдемся по нескольким основным окнам прямо сейчас.
1. (M)emory (память)
Окно “Memory” отображает все блоки памяти, выделенные программой. Это включает основные секции запущенного приложения (в данном случае “Showstr” в столбце “Owner”). Ниже вы также можете видеть множество других секций – это DLL, который программа загрузила в память и планирует использовать. Если дважды кликнуть по какой либо из этих строчек, откроется окно показывающее дизассемблированный код (или просто шестандцатеричный дамп) этой секции. Это окно также показывает тип каждого из блоков, права доступа, размер и адрес в памяти, где эта секция загружена.
2. (P)atches (патчи)
Это окно отображает все патчи, которые вы сделали. Патч означает изменение в коде. Заметьте, что в столбце “State” отображается значение “Active”. Это означает, что все изменения, сделанные в коде, актуальны на данный момент. Если вы перезапустите приложение, кликнув на “Re-load”, все изменения сбросятся и в столбе “State” напротив каждого сделанного вами патча появится значение “Disabled”. Вы также можете активировать-деактивировать патчи если кликните на выбранный вами патч, удерживая кнопку пробела. С столбце “Old” отображается оригинальная строчка кода, в стобце “New” – измененная.
3. (B)reakpoints (точки останова)
В этом окне отображены все поставленные вами брейкпоинты. Как мы увидим дальше это окно часто используется при отладке.
4. (K)all Stack (вызовы в стеке)
Как видно, автор программы выбрал не совсем верную букву для этой иконки, т.к. английское слово Call вообще-то начинается с “C” :)
Это окно отличается от того стека, который мы видели ранее. Оно дает гораздо больше информации о вызовах, сделанных в коде программы, значениях которые передаются вызванным функциям, и много чего еще.
В следующем туториале я выложу свою “прокаченную” версию Олли с расширенным функционалом:
Контекстное меню
В завершении я бы хотел также быстро представить контекстное меню Олли, которое открывается при клике левой кнопкой мыши. Оно предоставляет довольно много полезных функций, так что не плохо было бы с ним ознакомится. Если мы кликнем правой кнопкой мыши в секции дизассемблера мы увидим следующее:
Я пройдусь по самым часто-используемым функциям, с остальными вы разберетесь сами, по мере накопления опыта.
“Binary” – редактирование бинарных данных побайтого. Это место где вы можете изменить строчку “Не зарегистрировано” на “Зарегистрировано” :)
“Breikpoints” – установка брейкпоитов (точек останова) на какую-либо строчку кода. Существует несколько типов брейкпоинтов, мы подробнее рассмотри их в следующем туториале.
“Search for” предоставляет функции по поиску данных в бинарнике, таких как строки, вызовы функций и т.д.
“Analysis” заставляет Олли заново провести процесс анализ кода, с которым вы сейчас работаете. Иногда Олли затрудняется отличить код от данных (т.к. с точки зрения процессора это все лишь набор битов), и эта функция заставляет Олли учитывать то, в каком месте кода вы сейчас находитесь и попытаться понять, как эта секция должна будет выглядеть.
Также обратите внимание, что мое меню немного отличается от вашего, т.к. я установил себе некоторые плагины, которые добавляют в Олли определенный функционал. Я подробнее расскажу об этом в дальнейшем.