ЛАБОРАТОРНЫЕ РАБОТЫ
ЛАБОРАТОРНАЯ РАБОТА №0
Тема: Дисассемблеры и отладчики
Вам выдан рабочий модуль программы (COM файл). При запуске этой программы производится запрос пароля, после чего дается заключение о правильности прохода через пароль. Ваша задача:
1) Используя отладчик AFD или TD пройти по программе, найти место, где происходит дешифровка пароля и расшифровать его, после чего снова запустить программу, ввести правильный пароль и получить подтверждение о правильности прохода через пароль.
2) Используя дизассемблер SOUSER
— дизассемблировать выданную программу
— автоматически построить блок схему алгоритма ее работы
— найти в тексте программы место проверки пароля и подавить проверку
— заново ассемблировать программу и представить ее преподавателю, продемонстрировав, что программа теперь не запрашивает пароль (или успешно завершается при любом пароле).
3) Оформить электронный отчет, в котором отразить:
— титульный лист;
— тему лабораторной работы и задание на лабораторную работу;
— описание этапов дешифровки пароля и экранные формы отладчика, использованные при дешифровке пароля;
— описание этапов дизассемблирования программы и экранные формы дизассемблера, использованные при этом, в отчет включить УЧАСТОК дизассемблированной программы, в котором происходит дешифровка и обработка пароля;
— описание этапов автоматического построения блок-схемы алгоритма программы, в отчет включить УЧАСТОК блок-схемы алгоритма, в котором происходит дешифровка и обработка пароля;
— описание приемов, примененных для подавления обработки пароля, в отчет включить УЧАСТОК дизассемблированной программы измененный Вами с целью подавления обработки пароля;
— описание порядка ассемблирования программы;
— вид экрана после срабатывания откорректированной программы.
Пример выполнения ЛАБОРАТОРНОЙ РАБОТЫ №0
Реверс программы OOO_07.COM
Введение
Цель работы: произвести обратную разработку программы OOO_07.COM.
Для выполнения цели поставлен ряд задач:
— Разобраться в структуре программы OOO_07.COM;
— Найти правильный пароль;
— Сделать вывод по результатам проведенной работы.
1 Знакомство с программой
Программа OOO_07.COM (в дальнейшем программа) представляет из себя консольное приложение для DOS. Запустим его в DOS-Box и введем пароль 123 (рисунок 17).
Рисунок 17 — Внешний вид программы
Давайте попробуем отладить программу при помощи AFD.
2 Отладка программы в AFD
Откроем программу в AFD и найдем то место, где обрабатывается пароль (рисунок 18).
Рисунок 18 — Поиск по тексту
Как видно из рисунка, то место, в котором обрабатывается пароль представляет из себя цикл, состоящий из 5-ти итерации. На каждой итерации регистру BL присваивается символ кодовой фразы, защитой в программу. Далее каждый символ складывается по модулю 2 со значением 0x76 (118). После чего результат операции сравнивается с очередным введенным символом и если они не равны, то выполнение программы завершается. Давайте посмотрим память, по смещению 0x201 (513) (рисунок 19).
Рисунок 19 — Память с зашифрованным паролем
Таким образом наш пароль представляет из себя 5 символов 0xF2 (242), 0xF8 (248), 0xFA (250), 0xFE (254), 0xFC (252), каждый из которых необходимо сложить по модулю 2 со значением 0x76 (118):
— 0xF2 ^ 0x76 = 0x84 (132 = «Д»);
— 0xF8 ^ 0x76 = 0x8E (142 = «О»);
— 0xFA ^ 0x76 = 0x8C (140 = «М»);
— 0xFE ^ 0x76 = 0x88 (136 = «И»);
— 0xFC ^ 0x76 = 0x8A (138 = «К»).
Мы получили кодовую фразу «ДОМИК». Введем ее, чтобы проверить нашу гипотезу (рисунок 20).
Рисунок 21 — Ввод правильного пароля
3 Работа с Sourcer
Дизассемблируем программу при помощи Sourcer (рисунок 22—24).
Рисунок 22 — Внешний вид Sourcer с загруженной программой
Рисунок 23 — Запуск процесса дизассемблирования
Рисунок 24 — Сгенерированный Sourcer листинг
Сконвертируем полученный листинг в. asm файл (рисунки 25—26).
Рисунок 25 — Процесс обработки листинга
Рисунок 26 — .asm файл
Исправим исходный код так, чтобы он всегда выводил правильный ответ без ввода пароля (рисунки 27—28).
Рисунок 27 — Исправленная программа
Рисунок 28 — Компиляция, линковка и проверка программы
Заключение
При выполнении работы на практике была произведена обратная разработка программы OOO_07.COM при помощи интерактивного дизассемблеро IDA Pro Freeware.
По итогам работы были выполнены следующие задания:
— Разобрался в структуре программы OOO_07.COM;
— Нашел правильный пароль;
— Сделал вывод по результатам проведенной работы.
ЛАБОРАТОРНАЯ РАБОТА №1
Тема: Olly dbg 32
Описать функционал приложения по отладке программного обеспечения. Обязательно подробно описать одну из функций, не пересекаясь с другими студентами из группы по описываемой функции.
Пример выполнения ЛАБОРАТОРНОЙ РАБОТЫ №1
Отладчик OllyDbg
Введение
Цель работы: рассмотреть функционал отладчика OllyDbg и выполнить его детальное описание.
Для выполнения цели поставлен ряд задач:
— Описать функционал отладчика OllyDbg;
— Рассмотреть возможности отладчика OllyDbg;
— Сделать вывод по результатам проведенной работы.
1 Описание
OllyDbg — shareware 32-битный отладчик уровня третьего кольца защиты (ring-3) для операционных систем Windows, предназначенный для анализа и модификации откомпилированных исполняемых файлов и библиотек, работающих в режиме пользователя (ring-3).
OllyDbg выгодно отличается от классических отладчиков (таких, как SoftICE) интуитивно понятным интерфейсом, подсветкой специфических структур кода, простотой в установке и запуске. Для того, чтобы разобраться в принципе работы OllyDbg, достаточно лишь базовых знаний в области языка ассемблера. По этим причинам OllyDbg рекомендуют к использованию даже новичкам.
Последняя версия программы на старом движке — 1.10, не обновлялась с мая 2004 года. Однако 12 ноября 2006 года на официальном сайте был опубликован анонс новой, второй версии продукта. Со 2 июня 2010 года доступна первая новая версия OllyDbg 2.0 без приставки «бета».
В октябре 2013 года была анонсирована 64-битная версия отладчика. В декабре 2013 на сайте появилась информация о прогрессе в разработке.
Как уже было описано ранее, на данный момент имеется две версии программы: релизная старая версия 1.10 и новая, полностью переписанная c нуля, версия 2.01. В данной работе будет рассматриваться новая версия 2.01.
1.1 Возможности
— Поддерживаемые процессоры: вся серия 80x86, Pentium и совместимые; расширения MMX, 3DNow! И SSE до версии SSE4 включительно (SSE5 пока не поддерживается).
— Поддерживаемые форматы отображения данных: hex-код, ASCII, юникод, 16- и 32-битные целые числа со знаком и без знака, 32-, 64- и 80-битные числа с плавающей запятой (float).
— Способы отображения дизассемблированного кода: MASM, IDEAL, HDA.
— Мощный анализатор кода, распознающий процедуры, циклы, ветвления, таблицы, константы и текстовые строки.
— Развёрнутая система поиска: поиск всех возможных констант, команд, последовательностей команд, текстовых строк и ссылок в коде на адрес.
— Распознание и расшифровка более двух тысяч типичных функций Windows API и языка C.
— Распознание и расшифровка PE-заголовка.
— Эвристический анализ стека, распознание адресов возврата в родительскую процедуру.
— Простые, условные и протоколирующие точки остановки (breakpoints).
— Пошаговая отладка с протоколированием хода выполнения (run trace).
— Индивидуальный файл конфигурации (UDD) для каждого отлаживаемого приложения.
— Поддержка большого количества плагинов.
2 Работа с отладчиком OllyDbg
2.1 Основная функциональность
2.1.1 Форматы данных
Окна дампа отображают данные во всех обычных форматах: шестнадцатеричный, ASCII, Unicode, 16-и 32-разрядные целые числа со знаком/без знака/шестнадцатеричные, дизассемблеры (MASM, IDEAL или HLA).
2.1.2 Запуск отладчика
Мы можем определить исполняемый файл в командной строке, выбрать в меню, перетаскивать файл в OllyDbg, перезапускать последнюю отлаживаемую программу или присоединяться к уже выполняющемуся процессу. Инсталляция не необходима, поэтому можно запустить OllyDbg с внешнего носителя.
2.1.3 Отладка DLL
С OllyDbg мы можем отладить автономные библиотеки динамической связи (DLL). OllyDbg автоматически запускает маленькую выполнимую программу, которая загружает библиотеку и позволяет нам вызывать её экспортируемые функции.
2.1.4 Анализ
Анализатор — одна из наиболее значительных частей OllyDbg. Он распознает процедуры, циклы, таблицы, константы и строки, внедренные в код, хитрые конструкции, запросы к функциям API, номера параметров функции, секции импорта и так далее. Анализ делает двойной код намного более читаемым, облегчает отладку и уменьшает вероятность сбоев. Анализатор не ориентируется на компилятор и одинаково хорошо работает со всеми Windows программами.
2.1.5 Объектный сканер
OllyDbg просматривает объектные файлы или библиотеки (форматы OMF И COFF), извлекает из них код, сегментирует и определяет местонахождение их в отлаживаемой программе.
Полная поддержка Unicode`а. Почти все операции, доступные для строк ASCII также доступны для строк Unicode`а, и наоборот.
2.2 Горячие клавиши
Горячие клавиши позволяют уменьшить временные затраты на поиск нужной функциональности в меню. Без этой возможности отладчик потеряет свое удобство. Начнём с панели управления:
— Первая кнопка — открыть файл (гор. кл. F3)
— Вторая кнопка — перезапустить файл (гор. кл. Ctrl+F2)
— Третья кнопка — закрыть файл (гор. кл. Alt+F2)
— Четвёртая кнопка — запустить программу (гор. кл. F9)
— Пятая кнопка — приостановить запуск (гор. кл. F12)
— Шестая кнопка — трассировать с заходом в подпрограммы (гор. кл. F7)
— Седьмая кнопка — трассировать без захода в подпрограммы (гор. кл. F8)
— Восьмая кнопка — запустить автоматическую трассировку заходя в подпрограммы (гор. кл. Ctrl+F11)
— Девятая кнопка — запустить автоматическую трассировку без захода в подпрограммы (гор. кл. Ctrl+F12)
— Десятая кнопка — выполнить программу до выхода из подпрограммы (гор. кл. Ctrl+F9)
— Одиннадцатая кнопка — перейти на адрес (гор. кл. Ctrl+G)
Все остальные кнопки на панели управления будут рассмотрены позже.
Необходимые команды:
— Ctrl+A — провести анализ кода
— Ctrl+C — копировать данные
— Ctrl+F7 — включить режим, когда код будет выполняться, как будто бы мы нажали и не отпускаем кнопку F7
— Ctrl+F8 — включить режим, когда код будет выполняться, как будто бы мы нажали и не отпускаем кнопку F8
— Shift+F8 — продолжить трассировку программы, даже если возникла исключительная ситуация
— Shift+F9 — продолжить запуск программы, даже если возникла исключительная ситуация
— Ctrl+T — настройки авто-трейсера
— Ctrl+F11 — Запуск автоматической трассировки с заходом в подпрограммы
— Ctrl+F12 — Запуск автоматической трассировки без захода в подпрограммы
— F2 — Поставить брейкпоинт на выделенной строке
2.3 Плагины
Плагины — неотъемлемая часть OllyDbg. Без них отладка программы выполняется намного сложнее. Ниже приведен список плагинов, позволяющих упростить отладку приложений с кратким описанием:
— OllyExt — прячет отладчик от обнаружения при помощи различных техник.
— Olly Script — позволяет писать скрипты для помощи в отладке.
— Olly Dump — позволяет дампить отлаживаемый процесс и за одно восстанавливает у него импорт.
— Command Bar — в отладчике появляется строка, где можно вводить команды для отладчика. Справка приведена в приложении А.
2.4 Внешний вид
С отладчиком OllyDbg очень легко работать. На рисунке 29 приведен внешний вид с загруженной тестовой программой.
Рисунок 29 — Внешний вид OllyDbg
Детальное описание каждого пункта:
— (желтый) Виртуальные адреса.
— (зеленый) Машинный код.
— (синий) Дизассемблированный листинг (команды ассемблера).
— (красный) Комментарий отладчика.
— (фиолетовый) Регистры общего назначения.
— (серый) EIP регистр (показывает виртуальный адрес следующей выполняемой команды).
— (розовый) Флаги процессора.
— (оранжевый) Регистр флагов.
— (светло зеленый) Сегментные регистры.
— (бардовый) FPU (Floating Point Unit) регистры.
— (охра) Дамп памяти.
— (ультрамариновый) Стек.
2.4.1 Главное окно
В этом окне происходит сама отладка. Все инструкции приведены в дизассемблированном виде. Мы можем перемещать указательную строку при помощи курсора. При помощи указательной строки мы можем выбирать, какие данные скопировать, какую изменить команду, куда поставить брейкпоинт и т. д. Сбоку выделен адрес, который должен выполниться следующим. Между колонкой адресов и колонкой дизассемблированного листинга есть колонка с машинным кодом инструкции. Самая последняя колонка содержит в себе комментарии.
Рисунок 30 — Главное окно отладчика
2.4.2 Окно регистров
В окне регистров отображаются все 32-битные регистры, регистры флагов и различные другие регистры. Для того, чтобы изменить регистр надо щёлкнуть по его значению 2 раза и ввести новое значение. Реверсировать регистр флага можно путём двойного щелчка по одному из них.
Рисунок 31 — Окно регистров
2.4.3 Панель стека
В панели стека, можно изменить нужные нам байты в памяти, ставить брейкпоинты, подсматривать правильные рег. коды и т. д.
Рисунок 32 — Панель стека
2.4.4 Панель дампа оперативной памяти
В панели дампа памяти приведен слепок оперативной памяти, с загруженной в него отлаживаемой программой и всеми ее данными. В данной панели можно изменять нужные нам байты, а также выводить содержимое памяти в разнообразных форматах (ASCII, HEX, Unicode и т.д), кликнув по панели правой кнопкой мыши и выбрав нужный пункт меню.
Рисунок 33 — Дамп оперативной памяти
2.5 Знакомство с главным меню
2.5.1 Меню File
Рисунок 34 — Меню File
— Open — открыть файл для отладки;
— Set new arguments — задать новые аргументы выполнения программы;
— Attach — присоединиться к уже запущенному процессу для отладки;
— Detach — отсоединиться от процесса;
— Exit — выйти.
2.5.2 Меню View
Рисунок 35 — Меню View
— Log — Просмотреть лог о загрузке файла и т. д. (горячая клавиша: Alt+L);
— Executable modules — Посмотреть все модули, которые использует отлаживаемое приложение. (горячая клавиша: Alt+E);
— Memory map — Просмотреть карту памяти. На рисунке приведен ее внешний вид;
— List of windows — Просмотреть огромное количество информации об окнах, классах и т. д. используемых программой;
— Threads — Посмотреть все потоки программы, заморозить их, изменить их приоритет, убить их;
— CPU — Открыть главное окно. (горячая клавиша: Alt+C);
— Handles — Просмотреть Handle`ы;
— Watches — Просмотр значения какого-либо выражения;
— Search results — Вывод результатов поиска;
— Run Trace — Просмотреть лог трассировки;
— Patches — Просмотреть список всех изменений, которые мы сделали в программе, отменить все изменения и т. д. (горячая клавиша: Ctrl+P);
— INT3/Memory/Hardware Breakpoints — Просмотреть все брейкпоинты, отключить, удалить их. (горячая клавиша: Alt+B, Alt+Y, Alt+H);
— VEH/SEH Chain — Посмотреть, поставить брейкпоинт на все объявленные Seh`и или Veh`и;
— Call Stack — Просмотреть все вызовы выполнения код в стеке. (горячая клавиша: Alt+K);
— Source files — просмотр всех исходных файлов отлаживаемой программы4
— File — Шестнадцатеричный редактор файлов;
— Drive — Шестнадцатеричный редактор томов.
Рисунок 36 — Внешний вид memory map
— Первая колонка — адрес, по которому загружены различные секции файла, DLL библиотек.
— Вторая колонка — размер в памяти секции.
— Третья колонка — обычно название модуля.
— Четвёртая колонка — название секций.
— Пятая колонка — что содержится в секции.
Все остальные колонки не важны, т.к. в них отражены атрибуты секций в памяти. (горячая клавиша: Alt+M)
2.5.3 Меню Debug
Рисунок 37 — Меню Debug
— Run — Запуск приложения;
— Run tread — Запуск потока;
— Step into — Эквивалент F7;
— Step over — Эквивалент F8;
— Execute till return — Выполнить программу до выхода из подпрограммы;
— Restart — Перезапуск отлаживаемой программы;
— Close — Закрытие отлаживаемой программы;
— Set affinity — привязать процесс отладки к определенному ядру (определенным ядрам);
— Create function library — создать функциональную библиотеку
2.5.4 Меню Trace
Рисунок 38 — Меню Trace
— Clear run trace — Очистить контекст авто трассировки;
— Close run trace — Остановить авто трассировку;
— Animate into — Эквивалент постоянно нажатой F7;
— Animate over — Эквивалент постоянно нажатой F8;
— Trace into — Авто трассировка с заходом в подпрограммы;
— Trace over — Авто трассировка без захода в подпрограммы;
— Run hit trace — Запуск трассировки до первого breakpoint;
— Discard hit trace — Отмена трассировки до breakpoint;
— Set condition — Назначить условие для авто трассировки;
— Set protocol — Задать цели протоколирования во время авто трассировки.
2.5.5 Меню Plugins
Рисунок 39 — Меню Plugins
Показывает текущие установленные плагины и их параметры.
2.5.6 Меню Options
Рисунок 40 — Меню Options
— Options (гор. кл — Alt+O) — Все настройки отладчика;
— Load oprions — Импорт настроек;
— Save options — Экспорт настроек;
— Edit shortcuts — Редактирование горячих клавиш.
Остальные пункты меню не представляют технического интереса, по
Заключение
При выполнении работы на практике был рассмотрен и изучен многофункциональный отладчик OllyDbg, проведен обзор его основных функций. С помощью данного отладчика возможна отладка 32-битных приложений на базе операционной системой Windows.
По итогам работы были выполнены следующие задания:
— Описан функционал отладчика OllyDbg;
— Рассмотрены возможности отладчика OllyDbg;
— Сделан вывод по результатам проведенной работы.
ПРИЛОЖЕНИЕ А
Помощь по плагину Command Bar
Объяснение команд для Command Bar. Все команды, которые я посчитал лишними, были удалены из данного списка.
Выражения
— CALC [выражение] — Вычеслить значение выражения
Дизассемблер
— AT [выражение] — Перейти на адрес в дезассемблере
— FOLLOW [выражением] — Перейти на адрес в дезассемблере
— ORIG — Перейти на текущий адрес (EIP)
— — Перейти на текущий адрес (EIP)
Дамп и стек
— D [выражение] — Перейти на адрес в дампе
— DUMP [выражение] — Перейти на адрес в дампе
— DA [выражение] — Дамп в формате ассемблера
— DB [выражение] — Дамп в шестнадцатеричной системе
— DC [выражение] — Дамп в ASCII кодировке
— DD [выражение] — Дамп как адреса (стек формат)
— DU [выражение] — Дамп в UNICODE кодировке
— DW [выражение] — Дамп в шестнадцатеричном word формате
— STK [выражение] — Перейти на адрес в стеке
Трансляция
— A [выражение] [, команда] — Дезассемблировать адрес
Метки и комментарии
— L выражение, метка — Связывает символическую метку с адресом
— C выражение, комментарий — Устанавливает комментарий для адреса
Брейкпоинты
— BP [выражение] [,условие] — Устанавить брейкпоинт
— BPX [имя функции] — Установить брейкпоинты на все инструкции в модуле, которые вызывают [имя функции]
— BC [адрес] — Удалить контрольную точку по адресу
— MR expression1 [,expression2] — Установить брейкпоинт на память на доступ на определённый участок
— МВТ expression1 [, expression2] — Установить брейкпоинт на память на запись на определённый участок
— MD — Удалить брейкпоинт на память
— HR [адрес] — Установить Hardware брейкпоинт на один байт на доступ на адрес
— HW [адрес] — Установить Hardware брейкпоинт на один байт на запись по адресу
— HE [адрес] — Установить Hardware брейкпоинт на выполнение комманды по адресу
— HD [номер брейкпоинта] — Удалить Hardware брейкпоинт под номером
Команды трассировки
— STOP — Сделать паузу в трассировке
— PAUSE — Сделать паузу в трассировке
— RUN — Запустить программу
— G [адрес] — Выполнить до адреса
— GE [expression] — Выполнить до адреса
— S — Эквевалент F7
— SI — Эквевалент F7
— SO — Эквевалент F8
— TR — Выполнить программу до выхода из подпрограммы
OllyDbg окна
— LOG — Окно просмотра лога
— MOD — Посмотреть выполняемые модули
— MEM — Открыть окно карты памяти
— CPU — Открыть главное окно программы
— BRK — Открыть окно просмотра брейкпоинтов
— OPT — Настройки
Разные команды
— EXIT — Выйти из Olly
— QUIT — Выйти из Olly
— OPEN [имя файла] — Открыть файл для отладки
— CLOSE — Закрыть отлаживаеммую программу
— RST — Перезапустить отлаживаеммую программу
— HELP — показывают справку (данный текст, но непереведённый)
— HELP — Olly показывают справку Oll
— HELP APIfunction — справка по API функциям
ПРИЛОЖЕНИЕ Б
Подробная информация о брейкпоинтах
Olly поддерживает несколько видов брейкпоинтов:
— Обычный брейкпоинт, где первый байт команды, на которой Вы хотите прерваться заменяется на INT3 (Trap to Debugger). Мы можем разместить брейкпоинт, выбирая команду в дизассемблере и нажимая F2, или через всплывающее меню. Когда мы нажимаем F2 второй раз, когда брейкпоинт уже установлен, он будет удалён. Количество брейкпоинтов INT3 неограниченно. Когда мы закрываем отлаживаемую программу, или отладчик, Olly автоматически сохраняет брейкпоинты. Запрещено устанавливать брейкпоинт на данных или в середине команды! Olly предупредит, если произойдет попытка установки брейкпоинта вне секции кода. Мы можем выключить это предупреждение в настройках защиты. В некоторых случаях Отладчик может вставить собственные временные контрольные точки брейкпоинты INT3.
— Условный брейкпоинт (гор. кл. Shift+F2) — обычный брейкпоинт INT3 с условием. Каждый раз, когда отладчик сталкивается с таким брейкпоинтом, оценивает его выражение и, если результат является ненулевым, или выражение недействительно, останавливает отлаживаемую программу.
— Условный брейкпоинт с ведением лога (гор. кл. Shift+F4) — условный брейкпоинт с ведением лога, чтобы регистрировать значение выражения или параметров известной функции каждый раз, когда брейкпоинт выполняется.
— Брейкпоинт на память. Olly позволяет ставить единственный брейкпоинт на память одновременно. Мы выбираем некоторую часть памяти в дезассемблере или дампе центрального процессора и используем всплывающее меню, чтобы установить брейкпоинт на ней. Предыдущий брейкпоинт на память, если таковой вообще имеется, будет автоматически удален. У нас есть два варианта: остановка на доступе к памяти (чтение, запись или выполнение) и только на запись. Чтобы установить брейкпоинт, Olly изменяет атрибуты блоков памяти, содержащих данные.
— Аппаратный брейкпоинт (доступен только при использовании отладчика под Windows ME, NT, 2000 или XP). 80x86-совместимые процессоры позволяют нам устанавливать 4 аппаратных брейкпоинта. В отличие от брейкпоинта на память, аппаратные брейкпоинты не замедляют скорость выполнения, но охватывают только до 4 байтов.
— Однократная остановка на доступе к памяти (доступна только под Windows NT, 2000 и XP). Мы можем установить его в окне Memory на целый блок памяти через всплывающее меню или нажимая F2. Этот брейкпоинт особенно полезен, если мы хотим перехватить запросы к некоторому модулю.
— Автотрассировка — мы должны указать условие (гор. кл. Ctrl+T), при котором отладчик остановит программу. Следует обратитт внимание, что эта опция может значительно (до 20%), замедлить скорость выполнения программы.
OllyDbg также может остановить выполнение программы на некоторых событиях, например при загрузке или выгрузке DLL, зарождению или завершению потока.
ЛАБОРАТОРНАЯ РАБОТА №2
Тема: X64dbg
Описать функционал приложения по отладке программного обеспечения. Обязательно подробно описать одну из функций, не пересекаясь с другими студентами из группы по описываемой функции. Обязательно найти отличия не пересекающиеся с другими студентами.
Пример выполнения ЛАБОРАТОРНОЙ РАБОТЫ №2
Отладчик x64dbg
Введение
Цель работы: рассмотреть функционал отладчика x64dbg и выполнить его детальное описание.
Для выполнения цели поставлен ряд задач:
— Описать функционал отладчика x64dbg;
— Рассмотреть возможности отладчика x64dbg;
— Сделать вывод по результатам проведенной работы.
1 Описание
x64dbg — современный отладчик с открытым исходным кодом. В отличие от ollydbg, x64dbg может использоваться для отладки как 32-битных, так и 64-битных приложений. Он имеет простой в использовании графический интерфейс с возможностью перевода на русский язык и предлагает различные функции отладки.
Данный отладчик (в настоящее время) состоит из трех частей:
— DBG;
— GUI;
— Bridge.
DBG — это отладочная часть отладчика. Он обрабатывает отладку (с использованием TitanEngine) и предоставляет данные для графического интерфейса.
GUI — это графическая часть отладчика. Он построен поверх Qt и обеспечивает взаимодействие с пользователем.
Bridge — это коммуникационная библиотека для части DBG и GUI (и, возможно, для частей, которые появятся в будущем). Bridge можно использовать для работы над новыми функциями без необходимости обновлять код других частей.
1.1 Основные возможности
— Полнофункциональная отладка файлов DLL и EXE (TitanEngine Community Edition);
— Поддержка 32-битной и 64-битной Windows от Windows XP до Windows 10;
— Встроенный ассемблер (XEDParse / Keystone / asmjit);
— Быстрый дизассемблер (Zydis);
— C-подобный синтаксический анализатор выражений;
— Логирование;
— Заметки;
— Просмотр карты памяти;
— Представление модулей и символов;
— Просмотр исходного кода;
— Просмотр потоков;
— Контенточувствительный просмотр реестра;
— Просмотр стека вызовов;
— SEH просмотр;
— Перечисление дескрипторов, привилегий и TCP-соединений;
— Дамп памяти с несколькими типами данных;
— Динамическое представление стека;
— Исполняемый патч;
— Динамически распознавать модули и строки;
— База данных пользователей (JSON) для комментариев, ярлыков, закладок и т. Д.;
— Поддержка базового отладочного символа (PDB);
— Расширяемый, отлаживаемый язык сценариев для автоматизации;
— Поддержка плагинов с растущим API;
— Базовая поддержка анти-отладки.
1.2 Продвинутые возможности
— Декомпилятор (snowman);
— Встроенный реконструктор импорта (Scylla);
— Анализ;
— Условные точки останова и трассировка с большой гибкостью;
— Сбор данных во время трассировки.
1.3 Возможности GUI
— Интуитивно понятный и знакомый, но новый пользовательский интерфейс;
— Боковая панель в стиле IDA со стрелками перехода;
— IDA-подобная подсветка токенов инструкций (выделение регистров, команд и т. д.);
— Полностью настраиваемая цветовая схема и быстрые клавиши;
— График потока управления;
— Встроенная мнемоника и реестр помощи;
— Сворачивание кода;
— Простая интеграция с пользовательскими инструментами (меню избранного).
2 Работа с отладчиком x64dbg
2.1 Внешний вид
С отладчиком x64dbg очень легко работать. На рисунке 41 приведен внешний вид с загруженной тестовой программой.
Рисунок 41 — Внешний вид x64dbg
Детальное описание каждого пункта:
— (красный) Окно дизассемблирования.
— (желтый) Окно регистров.
— (зеленый) Окно дампа.
— (синий) Окно стека.
2.1.1 Окно дизассемблирования
Рисунок 42 — Окно дизассемблирования
Данное окно показывает дизассемблирование всех инструкций отлаживаемой программы. Это окно представляет дизассемблирование в линейном режиме и синхронизируется с текущим значением регистра указателя инструкции (eip для x86 / rip для x64).
Окно дизассемблирования делится на 5 колонок:
— (красный) Графические указатели, регистровые и указатели на точку останова;
— (желтый) Виртуальные адреса памяти;
— (оранжевый) Машинный код;
— (зеленый) Дизассемблерный листинг (команды ассемблера);
— (синий) Комментарии отладчик (или наши комментарии).
2.1.2 Окно регистров
Рисунок 43 — Окно регистров
В окне регистров отображаются все 32-битные или 64-битные регистры (в зависимости от разрядности отладчика), регистры флагов и различные другие регистры. Для того, чтобы изменить регистр надо щёлкнуть по его значению 2 раза и ввести новое значение. Реверсировать регистр флага можно путём двойного щелчка по одному из них.
Приведем описание каждого типа регистров:
— (красный) — Регистры общего назначения;
— (оранжевый) — Дополнительные регистры общего назначения;
— (желтый) — RIP регистр (показывает виртуальный адрес следующей выполняемой программы);
— (зеленый) — Регистры флагов и значений каждого флага;
— (голубой) — Указатели на SEH (Structured Exception Handling);
— (синий) — Сегментные регистры;
— (фиолетовый) — FPU (Floating Point Unit) регистры;
— (коричневый) — Регистры тегов сопроцессора;
— (розовый) — Регистры управления сопроцессором;
— (охра) — Регистры состояния сопроцессора;
— (пурпурный) — регистр управления/статуса SIMD (single instruction, multiple data) и состояния используемых флагов;
— (светло зеленый) — Регистры блока XMM;
— (лазурный) — Регистры блока YMM;
— (ультрамарин) — Отладочные регистры.
2.1.3 Окно дампа
Рисунок 44 — Окно дампа
Данное окно отображает стандартный шестнадцатеричный дамп памяти. Можно использовать окно дампа для проверки содержимого любого действительного адреса памяти в отлаженном процессе. Форму представления данных можно менять, нажав правой кнопкой мыши на окно и выбрав нужный тип представления.
Описание колонок:
— (красный) — Виртуальный адрес программы в оперативной памяти;
— (оранжевый) — Данные в формате HEX;
— (желтый) — Данные в формате ASCII.
2.1.4 Окно стека
Рисунок 45 — Окно стека
В данном окне отображается содержимое стэка по мере выполнения программы. В стэк могут помещаться как адреса, так и какие-то строковые, числовые значения и другие значения. Аргументы функций также помещаются в стэк перед вызовом самой функции. Некоторые упаковщики кладут в стэк адрес на OEP (оригинальную точку входа).
Описание колонок:
— (красный) — Виртуальный адрес;
— (оранжевый) — Данные, расположенные по виртуальному адресу;
— (желтый) — Комментарии.
2.2 Главное меню
2.2.1 Меню File
Рисунок 46 — Меню File
Меню файла содержит следующие подменю:
— Open. Действие Open позволяет открыть исполняемый файл для его отладки. Это может быть EXE-файл или DLL-файл. (Команда для этого действия — InitDebug / initdbg / init)
— Recent Files. Подменю «Recent Files» содержит несколько ранее отлаженных записей. Оно не включает файлы, которые не могут быть отлажены программой. Записи для этого подменю можно найти в разделе «Recent Files» INI-файла конфигурации. Данный файл можно редактировать, чтобы удалить записи.
— Attach. Attach позволяет подключаться к запущенному процессу. Он покажет диалоговое окно со списком запущенных процессов и позволит выбрать один из них для присоединения. В настоящее время можо подключаться только к исполняемому файлу той же архитектуры, что и программа. (например, мы не можем подключиться к 64-битному процессу с помощью x32dbg). Если какой-либо исполняемый файл в данный момент отлаживается, то присоединение к другому процессу завершит работу предыдущей отлаживаемой программы. (Команда для этого действия — AttachDebugger / attach)
— Detach. Это действие отключает отладчик от отлаживаемого процесса, позволяя отладчику работать без управления. Это действие невозможно выполнить, если отладка исполняемого файла не запущена. (Команда для этого действия — DetachDebugger / detach)
— Import database. Данное действие позволяет импортировать базу данных. (Соответствующая команда для этого действия — dbload / loaddb)
— Export database. Данное действие позволяет экспортировать несжатую базу данных. (Команда для этого действия — dbsave / savedb)
— Patch File. Открывает диалог патча. Мы можем просмотреть свои патчи и применить их к файлу в диалоговом окне.
— Change Command Line. Отображение текущих аргументов командной строки отлаживаемой программы в диалоговом окне и возможность их изменения. Аргументы командной строки будут сохранены в базе данных для дальнейшего использования.
— Restart as Admin. Перезапуск x64dbg и текущий отладчик с правами администратора.
— Exit. Завершение отладчика. Если какой-либо процесс отлаживается этой программой, он также будет остановлен.
2.2.2 Меню Views
Рисунок 47 — Меню View
Меню Views будет рассмотрено в пункте 2.3
2.2.3 Меню Debug
Рисунок 48 — Меню Debug
Это меню содержит действия, показанные на рисунке 48. Мы не можем использовать какие-либо из этих пунктов меню, кроме «Restart», когда не отлаживаем.
— Run. Освобождает блокировку и позволяет программе запуститься. (Команда для этого действия — run / go / r / g)
— Run until selection. Освобождает блокировку и позволяет программе работать, пока не встретится первая точка останова.
— Pause. Попытка приостановить отлаживаемую программу, когда она запущена, или попытка остановить анимацию. (Команда для этого действия — pause)
— Restart. Выполняет команду InitDebug / initdbg / init с самым последним использованным файлом.
— Close. Завершает текущую отлаживаемую программу и прекращфет ее отладку. (Команда для этого действия — StopDebug / stop / dbgstop)
— Step into. Выполняет шаг отладки, используя Trap-Flag. (Команда для этого действия — StepInto / sti)
— Step over. Когда инструкция EIP / RIP не является вызовом, выполняется StepInto, иначе программа продолжает отладку до тех пор, пока не покинет вызываемую функцию. (Команда для этого действия — StepOver / step / sto / st)
— Execute till return. Переходит по инструкциям, пока текущая инструкция, на которую указывает EIP или RIP, не станет инструкцией ret. (Команда для этого действия — StepOut / rtr)
— Run to User Code. Запуск отладчика, пока не будет достигнут код пользователя. Эквивалентно RunToParty 0. (Команда для этого действия — RunToUserCode/rtu)
Подменю Advanced содержит немного расширенные функции, описанные выше, поэтому их описание не приводится.
2.2.4 Меню Trace
Рисунок 49 — Меню Trace
Это меню содержит действия, показанные на рисунке 49. Ни один из пунктов не будет работать, если не запущена отладка.
— Animate into. Выполнение команды StepInto / sti автоматически с постоянной частотой.
— Animate over. Автоматическое выполнение команды StepOver / step / sto / st с постоянной частотой.
— Animate Command. Открывает диалоговое окно для ввода команды и выполняет ее с постоянной частотой.
— Trace into. Вводим выражение. Отладчик выполняет команду StepInto, пока не будет выполнено указанное условие или пока не будет достигнуто максимальное количество шагов.
— Trace over. Вводим выражение. Отладчик выполняет команду StepOver, пока не будет выполнено указанное условие или пока не будет достигнуто максимальное количество шагов.
Остальные пункты данного меню узконаправлены, а поэтому было принято решение их не описывать.
2.2.5 Меню Plugins
Рисунок 50 — Меню Plugins
Это меню включает в себя все доступные меню плагинов. Когда плагин устанавливается, то он может зарегистрироваться в этом меню. Мы можем обратиться к документации плагина для получения дополнительной информации.
2.2.6 Меню Favourites
Рисунок 51 — Меню Favourites
Это меню можно настроить. Когда мы нажимаем пункт меню «Manage Favourite Tools», появляется диалоговое окно. Мы можем добавлять в меню свои собственные инструменты, а также назначать им горячие клавиши. По умолчанию путь к инструменту или скрипту будет отображаться в меню, но если мы зададим его описание, оно будет отображаться в меню.
— Если добавить %PID% в командную строку инструмента, он будет заменен (десятичным) PID отлаживаемого кода (или 0, если не отлаживается).
— Если добавить %DEBUGGEE%, он добавит (без кавычек) полный путь отлаживаемого объекта.
— Если добавить %MODULE%, он добавит (без кавычек) полный путь к модулю, который сейчас находится в дизассемблированном виде.
— Если добавить %-???? -% он выполнит форматирование строки для всего, что помещено вместо»????». Пример: %- {cip} -% будет заменено шестнадцатеричным значением cip.
В настоящее время в это меню можно вставить три типа записей: Инструмент, Сценарий и Команда.
2.2.7 Меню Options
Рисунок 52 — Меню Options
Меню опций содержит следующие записи:
— Preferences. Показать диалог настроек. Можно изменять различные настройки в диалоговом окне.
— Appearance. Показать диалог Appearance. Можно настроить цветовую схему или шрифт в диалоговом окне.
— Shortcuts. Показать диалог shortcuts. Можно настроить сочетания клавиш для большинства операций.
— Customize menus. Показать диалог «Customize menus». Можно щелкнуть по узлам, чтобы развернуть соответствующее меню и установить или снять отметку с пунктов меню. Отмеченный пункт появится в разделе «Дополнительные команды» меню, чтобы сократить отображаемое меню. Можно убрать все пункты меню, которые не используются.
— Topmost. Фиксирует главное окно над другими окнами (или перестаньте это делать).
— Reload style. css. Если этот файл присутствует, будет применена новая цветовая схема, указанная в этом файле.
— Set Initialization Script. Установите сценарий инициализации глобально или для отлаживаемого приложения. Если указан глобальный сценарий инициализации, он будет выполняться, когда программа находится в системной точке останова или точке останова присоединения для каждого отлаживаемого кода. Если указан сценарий инициализации для каждого отлаживаемого объекта, он будет выполнен после завершения глобального сценария инициализации. Можено очистить настройку скрипта, очистив путь к файлу и щелкнув «OK» в диалоговом окне просмотра.
— Import settings. Импортировать настройки из другого файла конфигурации. Соответствующие записи в файле конфигурации переопределят текущую конфигурацию, но отсутствующие записи останутся неизменными.
— Theme. Выбор внешнего вида отладчика.
— Languages. Разрешить выбирать язык для программы. «Американский английский — Соединенные Штаты» — родной язык программы.
2.2.8 Меню Help
Рисунок 53 — Меню Help
— Calculator. Показывает калькулятор, который может выполнять оценку выражений, преобразование шестнадцатеричного числа в десятичное и многое другое.
— Check for Updates. Подключение к серверу, чтобы узнать, доступна ли обновленная версия этого программного обеспечения.
— Blog. Посещение официальный блог.
— Donate. Сделать пожертвование команде разработчиков.
— Report Bug. Сообщить об ошибке в этом программном обеспечении.
— Manual. Открыть руководство пользователя.
— FAQ. Посмотреть решение часто задаваемых вопросов.
— About. Информация об этом программном обеспечении.
— Generate crash dump. Создать исключение для создания аварийного дампа. Это может помочь, если программное обеспечение зависнет. Можное отправить этот аварийный дамп команде разработчиков, чтобы они помогли исправить ошибку.
2.3 Views
В данном пункте приведено описание некоторых пунктов меню View/
2.3.1 CPU
Рисунок 54 — Вид CPU
Этот вид является основным. Он включает в себя представление регистров, представление разборки, представление дампа и представление часов, представление стека и информационное окно.
2.3.2 Graph
Рисунок 55 — Вид Graph
Представление Graph содержит граф потока управления. Когда мы используем команду graph или контекстное меню (горячая клавиша G по умолчанию), отображается граф потока управления.
Есть два режима отображения графа потока управления: нормальный режим и режим обзора.
В режиме обзора программа будет рисовать весь граф потока управления в области окна, но не выводить дизассемблированный код. Когда выполняется трассировка первой инструкции, когда на этой странице памяти включена запись трассировки, весь базовый блок будет показан другим цветом (по умолчанию — зеленый).
Представление графа теперь является частью представления ЦП.
2.3.3 Log
Рисунок 56 — Вид Log
Это представление включает все сообщения журнала. Когда адрес выводится в сообщении журнала, он отображается в виде гиперссылки. Можно щелкнуть по нему, чтобы просмотреть его в разборке или в дампе, в зависимости от его прав доступа к памяти.
Рисунок 57 — Контекстное меню Log
В представлении журнала есть следующее контекстное меню:
— Clear. Очистить представление журнала.
— Select All. Выделить весь текст журнала.
— Copy. Скопировать выделенный текст.
— Save. Сохранить журнал в текстовый файл.
— Copy To Notes. Скопировать выделенный текст в глобальные заметке или заметки отлаживаемой программы.
— Disable Logging / Enable Logging. Отключает или включает вывод журнала. Когда ведение журнала отключено, в журнал больше не выводятся сообщения.
— Auto Scrolling. Включает или отключает автопрокрутку. Если этот параметр включен, представление журнала будет прокручиваться вниз по мере поступления новых сообщений журнала.
— Redirect Log. Перенаправить сообщение журнала в файл. Если включить эту функцию, все сообщения будут сохраняться в текстовом файле в кодировке UTF-16. Сообщение будет сохранено в текстовый файл независимо от того, включено ли ведение журнала.
2.3.4 Notes
Рисунок 58 — Вид Notes
В представлении «Notes» есть два текстовых поля для редактирования, одно глобальное и одно для отлаживаемого приложения. Любой введенный здесь текст будет сохранен и будет восстановлен в будущих сеансах отладки, чтобы пользователь мог удобно делать заметки. Глобальные заметки будут храниться в файле «notes. txt» в рабочем каталоге. Примечания отладчика будут храниться в базе данных отладки.
Нельзя редактировать заметки для каждого отлаживаемого приложения, пока не запущена отладка.
2.3.5 Call Stack
Рисунок 59 — Вид Call Stack
В представлении Call Stack отображается стек вызовов текущего потока. В нем 6 столбцов.
— (красный) Address — это базовый адрес кадра стек:
— (оранжевый) To — это адрес кода, на который нужно вернуться:
— (желтый) From — вероятный адрес процедуры, которая будет возвращена;
— (зеленый) Size — это размер кадра стека вызовов в байтах;
— (голубой) Comment — это краткое описание кадра стека вызовов;
— (синий) Party — описывает, является ли процедура, к которой нужно вернуться, пользовательским или системным модулем.
Когда активна опция «Show Suspended Call Stack Frame» в контекстном меню в представлении стека вызовов, он будет искать возможные адреса возврата по всему стеку. Когда он неактивен, он будет использовать стандартный алгоритм обхода стека для получения стека вызовов. Обычно он дает больше результатов, когда активна опция «Show Suspended Call Stack Frame», но некоторые из них могут не быть фактическими кадрами стека вызовов.
Заключение
При выполнении работы на практике был рассмотрен и изучен многофункциональный отладчик x64dbg, проведен обзор его основных функций. С помощью данного отладчика возможна отладка 64-битных приложений на базе операционной системой Windows.
По итогам работы были выполнены следующие задания:
— Описан функционал отладчика x64dbg;
— Рассмотрены возможности отладчика x64dbg;
— Сделан вывод по результатам проведенной работы.
По итогам работы были выявлены следующие основные отличия от OllyDbg:
— Имеется возможность построить граф вызовов, не устанавливая дополнительных плагинов.
— Возможность добавления собственных сторонних инструментов и скриптов через меню Favourites> Manage Favourite Tools.
— Есть возможность импорта и экспорта базы данных настроек и отлаживаемых проектов.
— Присутствует больше возможностей для отладки приложений, благодаря командам в подменю Debug> Advanced.
— Есть возможность мониторить TCP-соединения, открываемые отлаживающимся приложением.
ЛАБОРАТОРНАЯ РАБОТА №3
Тема: IDA Free
Описать функционал приложения по отладке программного обеспечения. Обязательно подробно описать одну из функций, не пересекаясь с другими студентами из группы по описываемой функции.
Пример выполнения ЛАБОРАТОРНОЙ РАБОТЫ №3
Интерактивный дизассемблер IDA Freeware
Введение
Цель работы: рассмотреть функционал интерактивного дизассемблера IDA Pro Freeware и выполнить его детальное описание.
Для выполнения цели поставлен ряд задач:
— Описать функционал интерактивного дизассемблера IDA Freeware;
— Рассмотреть возможности интерактивного дизассемблера IDA Freeware;
— Сделать вывод по результатам проведенной работы.
1 Описание
IDA Pro Disassembler (Interactive DisAssembler) — интерактивный дизассемблер, который широко используется для реверс-инжиниринга. Он отличается исключительной гибкостью, наличием встроенного командного языка, поддерживает множество форматов исполняемых файлов для большого числа процессоров и операционных систем.
Позволяет строить блок-схемы, изменять названия меток, просматривать локальные процедуры в стеке и многое другое. В последних версиях имеет встроенный отладчик x86 и ARM.
IDA, до определенной степени, умеет автоматически выполнять анализ кода, используя перекрестные ссылки, знание параметров вызовов функций стандартных библиотек, и другую информацию. Однако вся сила его проявляется в интерактивном взаимодействии с пользователем. В начале исследования дизассемблер выполняет автоматический анализ программы, а затем пользователь с помощью интерактивных средств IDA начинает давать осмысленные имена, комментировать, создавать сложные структуры данных и другим образом добавлять информацию в листинг, генерируемый дизассемблером, пока не станет ясно, что именно и как делает исследуемая программа.
Дизассемблер имеет консольную и графическую версии. Поддерживает большое количество форматов исполняемых файлов. Одной из отличительных особенностей IDA Pro является возможность дизассемблирования байт-кода виртуальных машин Java и. NET. Также поддерживает макросы, плагины и скрипты, а последние версии содержат интегрированный отладчик.
Существует несколько версий IDA Pro — бесплатная (freeware), стандартная (standard) и расширенная (advanced). Бесплатная версия обладает ограниченными возможностями по сравнению со стандартной и расширенной версиями — поддерживается только архитектура x86 и отсутствует поддержка подключаемых модулей.
2 Работа с интерактивным дизассемблером IDA Pro
2.1 Начало работы
В данной работе рассматривается версия IDA Pro Freeware, в которой, как упоминалось ранее, присутствуют некоторые ограничения. Первым делом выберем программ для дизассемблирования и откроем ее в IDA Pro (рисунок 60).
Рисунок 60 — Загрузка файла в IDA Pro
В данном меню мы выбираем в каком формате загрузить исследуемую программу. В нашем случае присутствует 2 варианта: бинарный и совместимый с процессором 80386. Так же можем явно выбрать тип процессора, на котором программа будет запущена.
Теперь разберем некоторые флаги секции Options:
— Create FLAT group — данная опция означает, что сегментные регистры будут использовать flat имена, вместо реальных сегментных имен. Помимо этого, так же создается группа, которая будет отображать flat память.
— Load resources — данная опция включает сегмент. rsrc в дизассемблерный листинг.
— Manual Load — данная опция позволяет задать базовый адрес образа и предупреждает пользователя, перед включением это секции в дизассемблерный листинг. Она также позволяет нам выделить необычные или переименованные секции.
Поставим галочки напротив всех, описанных выше опций и запустим IDA Pro. После того, как вы прокликали везде далее мы попадаем на главный экран.
2.2 Главный экран
Рисунок 61 — Главный экран
Разберем все основные области главного экрана:
— (красный) Полное представление графа выполнения программы (в данный момент там изображен белый квадрат, так как данная часть исполняемой программы содержит только один исполняемый узел).
— (оранжевый) Перечень всех имен функций, которые смог обнаружить дизассемблер.
— (желтый) Основное окно, в котором отображается основная информация об отлаживающей программе (в данный момент — укрупненный граф выполнения).
— (зеленый) Консольная строка, показывающая сообщения, генерируемые IDA Pro и строка ввода команд.
— (голубой) Разметка отлаживаемой программы по секторам (каждый сектор имеет свои цвет, легенда расположена ниже).
2.3 Виды представления
Над основным окном присутствуем множество вкладок, каждая из которых показывает новый данные об дизассемблированной программе.
2.3.1 IDA View-A
Основное представление, показывающее граф выполнения и ассемблерный код.
2.3.2 Hex View-1
Рисунок 62 — Представление Hex View-1
Данное представление выводит все символы программы в Hex-кодах.
2.3.3 Structures
Рисунок 63 — Представление Structures
В данном представлении приведен перечень структур, с которыми работает дизассемблированная программа.
2.3.4 Enums
Рисунок 64 — Представление Enums
Данное представление выводит все перечисления, присутствующие в программе.
2.3.5 Imports
Рисунок 65 — Представление Imports
В данном представлении приведены адреса импортируемых функций, их названия, а также название импортируемой библиотеки.
2.3.6 Exports
Рисунок 66 — Представление Exports
В данном представлении приведены названия экспортируемых функций, их адреса, а также функции, из которых они экспортируются.
2.4 Меню
Рассмотрим более подробно пункты меню.
2.4.1 Меню File
Рисунок 67 — Меню File
Рассмотрим все пункты меню:
— New instance — Запустить заново IDA Pro;
— Open — Открыть файл для дизассемблирования;
— Load file — Загрузка файлов в разных форматах;
— Produce file — Сгенерировать файл, на основе открытого в редакторе;
— Script file — Загрузка файла скрипта для IDA Pro;
— Script command — диалоговое окно, в котором вводятся скрипы для IDA Pro;
— Save — Быстрое сохранение;
— Save as — Новое сохранение;
— Take database snapshot — Сделать снимок базы данных;
— Close — Закрыть;
— Quick start — Новый запуск IDA Pro;
— Exit — Выход из программы.
2.4.2 Меню Edit
Рисунок 68 — Меню Edit
Рассмотрим все пункты меню:
— Copy — Копировать выделение;
— Begin selection — Начать выделение (аналог зажатой кнопки Shift);
— Select all — Выделение всего;
— Select identifier — Выделить идентификатор, если на него наведен курсор;
— Export data — экспортировать выделенные данные в нужно формате в файл;
— Code — Преобразовать выделенный блок в код;
— Data — Преобразовать выделенный блок в данные;
— Struct var — Преобразование выделенного блока, в дну из структур, обнаруженных при анализе кода приложения;
— Strings — Преобразовать выделенные данные в строку;
— Array — Преобразовать выделенные данные в массив байт;
— Undefine — Отменить выполненное преобразование;
— Rename — Переименовать выделенную строку;
— Operand Type — Перевести выделенный фрагмент в другую систему счисления;
— Comments — Вставка комментария;
— Segments — Работа с сегментами (создание и редактирование сегментов кода);
— Structs — работа со структурами;
— Functions — Работа с функциями;
— Patch program — Произвести патч программы;
2.4.3 Меню Jump
Рисунок 69 — Меню Jump
Команды в данном меню аналогичны командам из отладчиков, а потому рассматриваться не будут.
2.4.4 Меню Search
Рисунок 70 — Меню Search
Рассмотрим все пункты меню:
— Next code — Переход к следующей строке кода;
— Next data — Переход к следующим данным;
— Next explored — Переход к следующей видимой команде;
— Next unexplored — Переход с следующей неисследованной команде;
— Immediate value — Переход к следующему введенному значению;
— Next immediate value — Переход к следующему значению, равному выделенному;
— Text — Поиск текста;
— Next text — Поиск следующего вхождения выделенного текста;
— Sequence of bytes — Поиск следующей последовательности введенных байт;
— Next sequence of bytes — Переход к следующей последовательности байт, равной выделенной;
— Next function — Переход к следующей строке выполнения;
— Next void — Переход к следующей пустой команде;
— Error operand — Переход к следующей ошибке в исходном коде;
— All void operands — Показать все вхождения пустых команд;
— All error operands — Показать все вхождения ошибок исходного кода;
— Search direction — Смена направления поиска.
2.4.5 Меню View
Рисунок 71 — Меню View
Основные элементы данного меню описывались в главе 3.
2.4.6 Меню Debugger
Рисунок 72 — Меню Debugger
Команды в данном меню аналогичны командам из отладчиков, а потому рассматриваться не будут.
2.4.7 Меню Options
Рисунок 73 — Меню Options
В данном меню приведены опции программы, отвечающие в основном за визуальное оформление.
2.4.8 Меню Windows
Рисунок 74 — Меню Windows
Данное меню отвечает за визуальное представление окон на главном экране.
2.4.9 Меню Help
Рисунок 75 — Меню Help
В данном меню приведена справка по IDA Pro.
Заключение
При выполнении работы на практике был рассмотрен и изучен многофункциональный интерактивный дизассемблер IDA Pro Freeware и проведен обзор его основных функций. С помощью данного интерактивного дизассемблера возможна отладка исполняемых приложений на базе операционной системы Windows.
По итогам работы были выполнены следующие задания:
— Описан функционал интерактивного дизассемблера IDA Freeware;
— Рассмотрены возможности интерактивного дизассемблера IDA Freeware;
— Сделан вывод по результатам проведенной работы.
ЛАБОРАТОРНАЯ РАБОТА №4
ЗАДАНИЕ ПО ВАРИАНТАМ
1. Изменить 1 байт продемонстрировать что программа приняла серийный номер.
2. Изменить ключевой условный переход
3. Изменить ключевой безусловный переход
4. Описать процесс формирования серийного номера.
5. Описать процесс распаковки серийного номера.
6. Изменить 2 байта продемонстрировать что программа приняла серийный номер
7. Построить граф работы программы
8. Исследовать и определить длины серийного номера, имени
9. Исследовать и определить адерса имени и серийного номера
10. Изменить произвольное количество байт (более 2), продемонстрировать что программа приняла серийный номер
11. Определить константы для упаковки серийного номера
12. Определить ключевые участки кода ответственные за упаковку серийного номера.
13. Определить константы для распаковки серийного номера
14. Определить константы для распаковки серийного номера
15.* Получить действительную пару имя, серийный номер (это задание может сделать любой если затрудняется сделать свой вариант)
16.* Написать патч для приложения (это задание может сделать любой если затрудняется сделать свой вариант)
17.** Написать кейген для приложения (это задание может сделать любой если затрудняется сделать свой вариант).
Задания с одной звездой это средний уровень.
Задание с двумя звездами это высокий уровень.
Пример выполнения ЛАБОРАТОРНОЙ РАБОТЫ №4
Реверс d2k2_crackme01.exe
Введение
Цель работы: Произвести обратную разработку программы d2k2_crackme01.exe.
Для выполнения цели поставлен ряд задач:
— Разобраться в структуре программы d2k2_crackme01.exe;
— Построить граф работы программы;
— Написать кейген для приложения;
— Сделать вывод по результатам проведенной работы.
1 Знакомство с программой
Запустим программу d2k2_crackme01.exe (в дальнейшем программу) и посмотрим, что она из себя представляет (рисунок 76).
Рисунок 76 — Внешний вид программы
Как можно заметить, мы имеем дело с графическим приложением. Давайте попробуем ввести имя «Админ» и серийный номер «1234» и посмотрим на ответ (рисунок 77).
Рисунок 77 — Неверное имя пользователя и серийный номер
Мы не угадали. Давайте посмотрим на разрядность программы. Для этого откроем ее в Hex-редакторе и обратим внимание на смещение 0xB0 (рисунок 78).
Рисунок 78 — Вид программы в Hex-редакторе
Данная программа 32-х битная. Откроем ее в IDA Pro Freeware и начнем изучение.
2 Изучение программы в IDA Pro
2.1 Первый взгляд
После того, как мы открыли программу в IDA Pro, то попали в функцию start. Она нас особо не интересует. Мы знаем вывод при неправильном вводе, давайте попробуем найти его в программе (рисунки 79—80).
Рисунок 79 — Параметры поиска
Рисунок 80 — Результат поиска
Мы нашли код, который выполняется при неверном вводе данных. Давайте посмотрим на полный граф выполнения (рисунок 81).
Рисунок 81 — Граф работы программы
Давайте определим какой путь выполнения нужен для успешного ввода кода. Для этого попытаемся найти что-то, похожее на строку успеха (рисунок 82).
Рисунок 82 — Корректное завершение программы
2.2 Разбор алгоритма
Перейдем к началу функции и попробуем восстановить алгоритм проверки пары «Имя — Серийный номер». Когда пользователь нажимает кнопку Try, то управление передается на инструкции, приведенные на рисунке 83.
Рисунок 83 — Действия, после нажатия кнопки Try
В этом блоке кода вызывается функция GetDlgItemA с параметрами hDlg, nIDDlgItem, lpString, cchMax (согласно конвекции, параметры передаются функции через стек, причем в обратном порядке). Рассмотрим передаваемые параметры более подробно:
— cch — максимальное количество символов в строке (в нашем случае оно равно 0x28 = 40 символов);
— lpString — адрес буфера, в который запишется введенная строка (для удобства переименуем в pName);
— nIDDlgItem — дескриптор виджет, из которого получаем текст (в нашем случае строка ввода имени);
— hDlg — дескриптор диалогового окна, содержащего виджет.
Далее идет проверка, возвращаемого значения на 0, и если количество введенных символов равно 0, то мы переходи к коду, представленному на рисунке 84.
Рисунок 84 — Выполнение программы, если имя содержит 0 символов
Таким образом, можно сделать вывод, что поле ввода имени не должно быть пустым. Пройдем далее по ходу выполнения алгоритма (рисунок 85).
Рисунок 85 — Продолжение алгоритма
Мы видим, что если al строго больше 0x20 = 32 (число символов в имени), то выполнение переходит по адресу loc_40137C (рисунок 86).
Рисунок 86 — Имя превышает 32 символа
Таким образом, на данный момент мы знаем, что наше имя не должно быть пустым и должно содержать не более 32 символов. Продолжаем анализ (рисунок 87).
Рисунок 87 — Продолжение алгоритма
Мы видим, что если al строго меньше 0x05 = 5 (число символов в имени), то выполнение переходит по адресу loc_401391 (рисунок 88).
Рисунок 88 — Имя имеет длину от 1 до 4
Теперь мы знаем, что имя может иметь длину в диапазоне от 5 до 32 символов. Смотрим далее (рисунок 89).
Рисунок 89 — Продолжение алгоритма
Теперь в регистр ebx загружается адрес введеного нами имени, значение в регистре ecx зануляется, регистру al присваивается значение 5 (раньше там хранилась длина имени) и зануляется edx. Пока ничего интересного идем дальше (рисунок 90).
Рисунок 90 — Продолжение алгоритма
Теперь мы работам с циклом. Из последнего блока цикла (а именно из команд dec al, cmp al, 0, jz …) можем сделать вывод, что он работает столько раз, сколько указано в al, т.е. 5 раз.
На каждом шаге цикла в регистр cl записывается очередное значение по адресу [pName + edx], т.е. очередной байт из введенного имени, производится сложение по модулю 2 с числом 0x29 = 41 и сравнивается с числом 0x41 = 65.
Если полученное значение больше, либо равно данному, то оно далее сравнивается с числом 0x5a = 90. И если меньше или равно ему, то выполнение переходит по адресу loc_40128f.
В любом другом случае вместо данного числа в регистр cl записывается значение 0x52 = 82. После этого к нему добавляется значение al (5 минус порядковый номер символа, считая с 0) и управление передается по адресу loc_40128f.
Далее по адресу byte_40313c [edx] (переименуем в pResultOne) записывается полученное значение из регистра cl, а по адресу byte_40313d [edx] записывается 0, после чего значение в регистре edx увеличивается на 1, в регистре al уменьшается на 1 и происходит проверка выхода из цикла.
Как только обработаны первые 5 байт введенного имени, то значение в регистре edx обнуляется, а в регистр eax записывается 5 и программа продолжает работу далее (рисунок 91).
Рисунок 91 — Продолжение алгоритма
Очередной цикл. Из последнего блока цикла снова делаем вывод, что он работает 5 раз.
На каждом шаге цикла в регистр cl записывается очередное значение по адресу [pName + edx], т.е. очередной байт из введенного имени, производится сложение по модулю 2 с числом 0x27 = 39, после чего к полученному значению прибавляется значение al (5 минус порядковый номер символа, считая с 0), потом увеличиваем результат на 1 и сравниваем с числом 0x41 = 65.
Если полученное значение больше, либо равно данному, то оно далее сравнивается с числом 0x5a = 90. И если меньше или равно ему, то выполнение переходит по адресу loc_4012c8.
В любом другом случае вместо данного числа в регистр cl записывается значение 0x4d = 77. После этого к нему добавляется значение al (5 минус порядковый номер символа, считая с 0) и управление передается по адресу loc_40128f.
Далее по адресу byte_403142 [edx] (переименуем в pResultTwo) записывается полученное значение из регистра cl, а по адресу byte_403142 [edx] записывается 0, после чего значение в регистре edx увеличивается на 1, в регистре al уменьшается на 1 и происходит проверка выхода из цикла.
Как только обработаны первые 5 байт введенного имени, то снова вызывается функция GetDlgItemA, с теми же параметрами, что и ранее, только с номером виджета, равным 4 (id для виджета ввода серийного номера) и снова производится проверка на то, равна ли длина введенной строки 0.
Если она равна 0, то управление передается по адресу loc_401352 (рисунок 92).
Рисунок 92 — Длина введенного серийного номера равна 0
Если серийный номер не равен 0, то управление передается далее (рисунок 93).
Рисунок 93 — Продолжение алгоритма
Здесь сначала происходит проверка на то, чтобы длина не была больше 0x0a = 10, а затем и меньше этого значения, иначе управление передается на команды из рисунка 2.14. То есть, получается, что длина серийного номера всегда равно 10. Продолжаем анализ (рисунок 94).
Рисунок 94 — Продолжение алгоритма
Теперь обнуляются регистры eax, ebx, ecx и edx, а в регистр eax записывается адрес буфера с серийным номером. После этого в регистр bl, загружается первый байт серийного номера, в регистр dl — первый байт результата из первого цикла, после чего значение первого символа серийного номера сравнивается с 0, и если это условие выполнилось, то выполнение переходит по адресу loc_4013a6 (рисунок 95).
Рисунок 95 — Выполнение алгоритма, если первый байт серийного номера равен 0
Как видим, это то, что мы хотим. Однако не существует печатного символа с кодом 0, поэтому придется разобрать оставшуюся часть алгоритма (рисунок 96).
Рисунок 96 — Продолжение алгоритма
К значению dl добавляется 5 и оно сравнивается с 0x5a = 90. Если полученное значение строго больше, то выполнение передается по адресу loc_401341, иначе из dl вычитаем 0x0d = 14.
После этого складываем dl по модулю 2 с 0x0c = 12 и сравниваем с 0x41 = 65.
Если полученное значение меньше, то dl присваиваем 0x4b = 75, добавляем значение из cl и переходим по адресу loc_40133a.
Иначе сравниваем dl с 0x5a = 90 и если оно меньше, либо равно, то dl присваиваем 0x4b = 75, вычитаем значение из cl и переходим по адресу loc_40133a.
Увеличиваем значение ecx на 1, сравниваем dl и bl и если они не равны, то получаем вывод как на рисунке 2.14, а иначе повторяем все действия с момента на рисунке 2.17.
Таким образом обобщим информацию, которую мы имеем:
— Имя должно содержать от 5 до 32 символов;
— В первом цикле for для получения массива pResultOne участвуют всегда только первые 5 байт имени;
— Во втором цикле for для получения массива pResultTwo участвуют всегда только первые 5 байт имени;
— Серийный номер содержит ровно 10 символов;
— Последняя часть алгоритма представляет из себя цикл while и работает до тех пор, пока не обработает все байты серийного номера и значений из массивов pResultOne и pResultTwo. При этом после очередного цикла while значение очередного байта серийного номера не должно быть равно очередному преобразованному байту из массива pResultOne и pResultTwo.
Напишем Keygen, который всегда будет генерировать правильные значения пары «Имя — Серийный номер». Результат работы Keygen’а представлен на рисунках 97—98.
Рисунок 97 — Результат работы Keygen. exe
Рисунок 98 — Пара «Имя — Серийный номер» принята программой
Заключение
При выполнении работы на практике была произведена обратная разработка программы d2k2_crackme01.exe при помощи интерактивного дизассемблеро IDA Pro Freeware.
По итогам работы были выполнены следующие задания:
— Разобрался в структуре программы d2k2_crackme01.exe;
— Построил граф работы программы;
— Написал кейген для приложения;
— Сделал вывод по результатам проведенной работы.
ПРИЛОЖЕНИЕ А
Исходный код Keygen
Листинг 1 — Исходный код Keygen на C++
ЛАБОРАТОРНАЯ РАБОТА №5
Тема: Лаборатории Касперского (ЗАДАНИЕ ПО ВАРИАНТАМ)
1. Изменить 1 байт продемонстрировать что программа приняла серийный номер.
2. Изменить ключевой условный переход
3. Изменить ключевой безусловный переход
4. Описать процесс формирования серийного номера.
5. Описать процесс распаковки серийного номера.
6. Изменить 2 байта продемонстрировать что программа приняла серийный номер
7. Построить граф работы программы
8. Исследовать и определить длины серийного номера, имени
9. Исследовать и определить адерса имени и серийного номера
10. Изменить произвольное количество байт (более 2), продемонстрировать что программа приняла серийный номер
11. Определить константы для упаковки серийного номера
12. Определить ключевые участки кода ответственные за упаковку серийного номера.
13. Определить константы для распаковки серийного номера
14. Определить константы для распаковки серийного номера
15.* Получить действительную пару имя, серийный номер (это задание может сделать любой если затрудняется сделать свой вариант)
16.* Написать патч для приложения (это задание может сделать любой если затрудняется сделать свой вариант)
17.** Написать кейген для приложения (это задание может сделать любой если затрудняется сделать свой вариант).
Задания с одной звездочкой это средний уровень.
Задание с двумя звездами это высокий уровень.
Пример выполнения ЛАБОРАТОРНАЯ РАБОТА №5
Реверс CrackMe от Лаборатории Касперского
Введение
Цель работы: произвести обратную разработку программы crackme01_x64.exe.
Для выполнения цели поставлен ряд задач:
— Разобраться в структуре программы crackme01_x64.exe;
— Построить граф работы программы;
— Написать кейген для приложения;
— Сделать вывод по результатам проведенной работы.
1 Знакомство с программой
Запустим программу crackme01_x64.exe (в дальнейшем программу) и посмотрим, что она из себя представляет (рисунок 99).
Рисунок 99 — Внешний вид программы
Как можно заметить, мы имеем дело с графическим приложением. Давайте попробуем ввести серийный номер «1234» и посмотрим на ответ (рисунок 100).
Рисунок 100 — Неверный серийный номер
Мы не угадали. Давайте посмотрим на разрядность программы. Для этого откроем ее в Hex-редакторе и обратим внимание на смещение 0xD8 (рисунок 101).
Рисунок 101 — Вид программы в Hex-редакторе
Данная программа 64-х битная. Откроем ее в IDA Pro Freeware и начнем изучение.
2 Изучение программы в IDA Pro
2.1 Первый взгляд
После того, как мы открыли программу в IDA Pro, то попали в функцию start. Она нас особо не интересует. Мы знаем вывод при неправильном вводе, давайте попробуем найти его в программе (рисунки 102—103).
Рисунок 102 — Параметры поиска
Рисунок 103 — Результат поиска
Мы нашли код, который выполняется при неверном вводе данных. Давайте посмотрим на полный граф выполнения (рисунок 104).
Рисунок 104 — Граф работы программы
Давайте определим какой путь выполнения нужен для успешного ввода кода. Для этого попытаемся найти что-то, похожее на строку успеха (рисунок 105).
Рисунок 105 — Корректное завершение программы
2.2 Разбор алгоритма
Перейдем к началу функции и попробуем восстановить алгоритм проверки серийного номера. Когда пользователь нажимает кнопку Check, то управление передается на инструкции, приведенные на рисунке 106.
Рисунок 106 — Действия, после нажатия кнопки Try
В этом блоке кода вызывается функция GetDlgItemTextA с параметрами hDlg, nIDDlgItem, lpString, cchMax (согласно конвенции, параметры передаются функции через регистры, причем сначала заполняются регистры RCX, RDX, R8, R9 для целых чисел, а после заполняется стек https://docs.microsoft.com/ru-ru/cpp/build/x64-calling-convention?view=vs-2019#parameter-passing). Рассмотрим передаваемые параметры более подробно:
— cchMax — максимальное количество символов в строке (в нашем случае оно равно 0x40 = 64 символа) (регистр R9);
— lpString — адрес буфера, в который запишется введенная строка (регистр R8);
— nIDDlgItem — дескриптор виджет, из которого получаем текст (в нашем случае строка ввода серийного номера) (регистр RDX);
— hDlg — дескриптор диалогового окна, содержащего виджет (регистр RCX).
Скалярное возвращаемое значение не больше 64 бит возвращается посредством RAX (сюда входит тип __m64). Нескалярные типы, включая типы с плавающей точкой, тип Double и векторные типы, такие как __m128, __m128i, и __m128d, возвращаются в XMM0. Состояние неиспользуемых битов в возвращаемом значении в RAX или XMM0 не определяется.
Далее адрес введенной строки передается в регистр RCX, а значение, которое вернула функция GetDlgItemTextA (количество введенных символов) — в регистр RDX, после чего происходит вызов функции, расположенной по адресу sub_140001000.
Если функция возвращает 0 (посредством регистра RAX), то программа завершается неуспешно (рисунок 107), иначе выполнение программы переходит к инструкциям, показанным на рисунке.
Рисунок 107 — Выполнение программы, если функция вернула не 0
2.3 Патчинг
Давайте явно поменяем инструкцию jz на jnz, чтобы программа принимала любой номер. Для этого найдем ее смещение относительно начала сегмента кода (рисунок 108).
Рисунок 108 — Адрес команды в памяти
Смещение в данном случае равно 0x140001167 — 0x140001000 = 0x167. Откроем исполняемый файл в Hex-редакторе и изменим код команды jz (0x74 0x28) на jnz (0x75 0x28) (рисунок 109).
Рисунок 109 — Измененная программа
Теперь запустим ее с серийным номером 1234 и посмотрим на результат (рисунок 110).
Рисунок 110 — Программа приняла серийный номер
Теперь программа способна принимать любой серийный номер (ну почти). Данное решение не является красивым, поэтому вернемся к разбору функции проверки серийного номера.
2.4 Функция sub_140001000
Посмотрим на граф выполнения (рисунок 111).
Рисунок 111 — Граф выполнения функции
Посмотрим на первый блок выполнения (рисунок 112).
Рисунок 112 — Начало выполнения функции
Первым делом в регистр r8 записывается адрес введенной строки, и ее длина сравнивается со значением 0x13 (19). Если длина не равна 0x13, то выполнение переходит к инструкциям на рисунке 113.
Рисунок 113 — Длина строки не равна 0x13
Значение в регистре EAX приравнивается к 0 и происходит возврат из функции. Этот результат нас не устраивает, а значит теперь мы знаем, что длина серийного номера должна быть равна 0x13. Продолжаем анализ алгоритма (рисунок 114).
Рисунок 114 — Длина строки равна 0x13
Здесь мы приравниваем к 0 значение в регистре EDX, записываем в регистр RAX адрес 4-го символа в строке (отчет ведем с 0) и обнуляем значение в регистре ECX. Остальные 3 команды мне непонятны, потому что на первый взгляд они ничего не делают. Продолжаем анализ (рисунок 115).
Рисунок 115 — Продолжение алгоритма
На данном рисунке происходит проверка значение по адресу из регистра RAX и сравнивается со значением 0x2d (» -»). Если оно не равно, то происходит переход к операциям из рисунка 2.12. Данное сравнение происходит 2 раза (пока значение в регистре ECX не станет равным 3). Значение ECX увеличивается на 1 перед каждой проверкой, а значение в регистре RAX увеличивается на 5. Таким образом мы получаем, что в нашем серийном номере на позициях 4, 9 и 14 должны стоять символы ‘-», т.е. наш серийный номер должен соответствовать маске «XXXX — XXXX — XXXX — XXXX», где «X» — неизвестный пока символ. Продолжим анализ кода (рисунок 116).
Рисунок 116 — Продолжение алгоритма
В этом блоке кода происходит присваивание локальной переменной var_8 (локальная переменная хранится на стеке) значения регистра RBX, зануление регистров r10d и r11d, присваивание регистру RBX адреса локальной переменной var_18 и присвоения адреса введенной строки регистру r9. Ничего интересно, поэтому продолжим анализ (рисунок 117).
Рисунок 117 — Продолжение алгоритма
Первым делом значение в регистре RCX становится равным 0. После чего символ с индексом ECX из введенной строки записывается в регистр EAX, к нему прибавляется значение 0xFFFFFFD0 (4 294 967 248) и оно сравнивается со значением 0x09 (9) и если результат сложения его превышает, то происходит переход к операциям из рисунка 118. Такая проверка проводится для первых четырех элементов серийного номера.
Рисунок 118 — Выход из функции со значением 0
Из этого блока кода мы можем сделать вывод, что коды первых четырех элементов серийного номера должны быть больше 0x2f и меньше 0x3a. Данный диапазон соответствует символам «1» — «9». Из этого мы делаем вывод, что первые четыре символа представляют из себя цифры. Продолжаем анализ (рисунок 119).
Рисунок 119 — Продолжение алгоритма
Регистру EAX присваивается значение по адресу из регистра r9 (первый символ строки), после чего к нему прибавляется значение двух последующих символов. После этого еще трижды прибавляется символ, находящийся на расстоянии 3, от того, что находится по адресу из регистра r9. Далее к регистру RBX прибавляется 4, к регистру r11d прибавляется 1, к регистру r9 прибавляется 5. В регистр ECX записывается адрес, который находится как сумма значения из регистра RAX (вышеописанная сумма), значения из регистра RCX и значения -0x150 (-336). Это значение записывается по адресу RBX-4 и прибавляется к регистру r10d. Далее значения из регистра r11d сравнивается с 4, и если оно строго меньше, то происходит переход по адресу loc_140001050.
Из этого блока мы видим, что операции на рисунков 2.16 и 2.18 выполняются 4 раза (по 1 разу для каждого блока). Каждый блок проверяется на то, чтобы он состоял только из цифр, после чего для каждого блока высчитывается сумма первых трех цифр и последней, умноженной на 3. После этого к данной сумме прибавляется еще раз значение последней цифры и вычитается 336, после чего оно запоминается отдельно на стеке, а также их общая сумма сохраняется в регистре r10d. Продолжаем анализ (рисунок 120).
Рисунок 120 — Продолжение алгоритма
Значение из регистра r10d сдвигается вправо на 2 двоичных разряда (делится на 4 нацело), значение в регистре ECX обнуляется, регистр RAX начинает указывать на массив сумм блоков серийного номера. Продолжаем анализ (рисунок 121).
Рисунок 121 — Продолжение алгоритма
Теперь мы видим, что значения, на которые указывает регистр RAX сравниваются со значение r10d, и если они не равны, то происходит переход к инструкциям из рисунка.
Таким образом сумма каждого блока должна быть равна общей сумме, деленной на 4. Это значит, что суммы всех четырех блоков должны быть равными. Продолжаем анализ (рисунок 122).
Рисунок 122 — Продолжение алгоритма
Последняя часть нашего анализа. Первым делом значение в регистре RAX становится равным 0. После этого в последующих трех блоках сравниваются значения символов в каждой группе серийного номера на позиции из регистра RAX. И есть хотя бы двое их них совпали, то функция завершается с выходным значением 0. Теперь мы знаем, что символы в каждом блоки на с одинаковым смещение не должны быть равны.
Таким образом мы разобрали алгоритм. Теперь обобщим полученные сведения о строении серийного номера:
— Правильный серийный номер состоит из 19 символов.
— Серийный номер делится на блоки по 4 символа (начиная с 0-го смещения), между которыми расположен символ ‘-».
— Каждый блок состоит из цифр.
— Суммы первых трех цифр и учетверенной последней цифры за вычетом 336 каждого блока равны между собой.
— Цифры, находящиеся на одинаковой позиции внутри каждого блока (от 0 до 3) попарно различны.
Напишем Keygen, который всегда будет генерировать правильные серийные номера. Результат работы Keygen’а представлен на рисунках 123—124.
Рисунок 123 — Результат работы Keygen. exe
Рисунок 124 — Серийный номер принят программой
Заключение
При выполнении работы на практике была произведена обратная разработка программы crackme01_x64.exe при помощи интерактивного дизассемблеро IDA Pro Freeware.
По итогам работы были выполнены следующие задания:
— Разобрался в структуре программы crackme01_x64.exe;
— Построил граф работы программы;
— Написал кейген для приложения;
— Сделал вывод по результатам проведенной работы.
ПРИЛОЖЕНИЕ А
Исходный код Keygen
Листинг 1 — Исходный код Keygen на C++
ЛАБОРАТОРНАЯ РАБОТА №6
Тема: Пароль на архив crackmes.de (ЗАДАНИЕ ПО ВАРИАНТАМ)
1. Изменить 1 байт продемонстрировать что программа приняла серийный номер.
2. Изменить ключевой условный переход
3. Изменить ключевой безусловный переход
4. Описать процесс формирования серийного номера.
5. Описать процесс распаковки серийного номера.
6. Изменить 2 байта продемонстрировать что программа приняла серийный номер
7. Построить граф работы программы
8. Исследовать и определить длины серийного номера, имени
9. Исследовать и определить адерса имени и серийного номера
10. Изменить произвольное количество байт (более 2), продемонстрировать что программа приняла серийный номер
11. Определить константы для упаковки серийного номера
12. Определить ключевые участки кода ответственные за упаковку серийного номера.
13. Определить константы для распаковки серийного номера
14. Определить константы для распаковки серийного номера
15.* Получить действительную пару имя, серийный номер (это задание может сделать любой если затрудняется сделать свой вариант)
16.* Написать патч для приложения (это задание может сделать любой если затрудняется сделать свой вариант)
17.** Написать кейген для приложения (это задание может сделать любой если затрудняется сделать свой вариант).
Задания с одной звездочкой это средний уровень.
Задание с двумя звездами это высокий уровень.
Пример выполнения ЛАБОРАТОРНАЯ РАБОТА №6
Реверс программы level_2.exe
Введение
Цель работы: произвести обратную разработку программы level_2.exe.
Для выполнения цели поставлен ряд задач:
— Разобраться в структуре программы level_2.exe;
— Построить граф работы программы;
— Написать кейген для приложения;
— Сделать вывод по результатам проведенной работы.
1 Знакомство с программой
Программа level_2.exe (в дальнейшем программа) представляет из себя консольное приложение, поэтому запустим ее через консоль (рисунок 125).
Рисунок 125 — Внешний вид программы
Как можно заметить, ничего не произошло, поэтому сразу откроем данную программу в IDA Pro.
2 Изучение программы в IDA Pro
2.1 Первый взгляд
Откроем функцию main и посмотрим, что она из себя представляет (рисунок 126).
Рисунок 126 — Граф выполнения функции main
Приступим к разбору.
2.2 Разбор алгоритма
Перейдем к началу функции (рисунок 127).
Рисунок 127 — Начало функции main
Из этого блока кода можно понять, что программа принимает на вход 3 аргумента. Нужно помнить, что первый аргумент в командной строке — название программы, поэтому при запуске программы дополнительно требуется ввести еще 2 аргумента.
Рисунок 128 — Продолжение алгоритма
После получения 3-х аргументов при помощи функции calloc на куче выделяется один блок памяти размером 0x100 (256) байт и указатель на него помещается на стек (локальная переменная) по смещению +0x34 (52). Переименуем это смещение на pArr.
Рисунок 129 — Продолжение алгоритма
Далее идет цикл по всем введенным параметрам на каждом шаге которого ищется последовательность “-f». Как только данная последовательность найдена, флаг на стеке по смещению +0x3C (60) устанавливается в 1, а в переменной по смещению +0x38 (56) хранится индекс следующего параметра командной строки.
Рисунок 130 — Продолжение алгоритма
После того, как был найден аргумент “-f», при помощи функции memset все элементы выделенного ранее массива становятся равными 0, после чего в него копируется значение параметра, указанного после “-f».
Рисунок 131 — Продолжение алгоритма
После копирования проверяется первый символ строки, и если он не равен 0, то происходит открытие файла и его handle помещается по смещению +0x30 (48). После чего производится проверка на корректность открытия файла. Если файл не открылся, то программа завершается.
Рисунок 132 — Продолжение алгоритма
После успешного открытия файла, его дескриптор передается функции _construct_key. Результат ее выполнения записывается по смещению +0x2C (44), и если он равен, нулю, то выводится сообщения об ошибке, в ином случае на консоль выведутся правильные маркеры.
Рисунок 133 — Условные переходы после работы функции _construct_key
Наша задача заключается в том, чтобы функция _construct_key вернула не 0. Исследуем как она работает.
2.3 Функция _construct_key
Рисунок 134 — Граф выполнения функции _construct_key
Рисунок 135 — Начало функции _construct_key
Первым делом вызывается функция __prepare_key, и если результат ее работы равен 0, то происходит выход из функции. Рассмотрим функцию __prepare_key.
2.4 Функция __prepare_key
Рисунок 136 — Граф работы функции __prepare_key
Рисунок 137 — Начало работы функции
Первым делом выделяется 1 блок памяти размером 8 байт на куче при помощи функции calloc и указатель на этот блок сохраняется по смещению -0x0C (-12). Причем смещение берется от начала стекового кадра, т.е. по факту, мы работаем с локальной переменной var_10 (так как дополнительные 4 байта занимает база стекового кадра) функции _construct_key.
Рисунок 138 — Продолжение алгоритма
Если выделение прошло успешно, то происходит выделение еще одного блока на куче размером 0x540 (1344) байта и указатель на этот блок записывается в предыдущий блок. Таким образом, получить доступ к большому блоку мы может только перейдя по адресу, записанному в малом блоке, адрес которого хранится на стеке по смещению -0x0C.
Далее выделяется еще один блок размером 8 байт, указатель на который сохранятся со смещением +4, от предыдущего большого блока. После этого записываем внутрь блока адрес строки «VOID», находящейся в памяти. В последующие 2 байта записываем 5, и в оставшиеся 2 байта — 4.
После этого программа работает с большим блоком. По смещению 0x00 записываем два байта со значением 0x62 (98), по смещению +0x104 (260) записываем байт 3, по смещению +0x218 (546) — байт 0x57 (87), по смещению +0x324 (804) — байт 0x70 (112), по смещению +0x10C (268) — байт 0x6C (108), по смещению +0x430 (1072) — байт 0x98 (152), по смещению +0x53C (1340) — 4 байта со значением 0x462 (1122).
После всех действий функция завершается и управление передается обратно функции _construct_key.
2.5 Возвращение в функцию _construct_key
Рисунок 139 — Продолжение функции _construct_key
После возвращения в данную функцию мы знаем, что по смещению var_10 находится адрес блока памяти, с которым мы работали в функции __prepare_key.
Первым делом считываются первые 4 байта файла по адресу var_15 при помощи функции fread (нужно помнить, что каретка внутри файла движется по мере считывания). После этого в регистр EAX записывается адрес строки «VOID» (описано в предыдущем пункте) и первые 4 байта это строки сравниваются со считанными байтами из файла. Если строки не равны, то работы функции завершается. Таким образом в указанном файле первые четыре символа, записанные в файл, должны быть равны «VOID».
Рисунок 140 — Продолжение алгоритма
Если проверка на предыдущем шаге прошла успешно, то из файла считываются следующие 2 байта и записываются сразу же после адреса «VOID», тем самым перезаписывая значение 5. После этого считываются еще 2 байта файла, которые записываются на место 4 (сразу после предыдущей записи). Далее происходит сравнения последних считанных 2-х байтов с 4 и если программа считала другое число, то происходит выход из функции.
Рисунок 141 — Продолжение алгоритма
После этого происходит проверка первого считанного байта, и если он не равен 5, то происходит выход из функции.
Рисунок 142 — Продолжение алгоритма
В локальную переменную по смещению var_2C записывается адрес начала большого блока. Теперь в локальные переменные функции записываются значение из этого блока памяти, полученные в функции __prepare_key. В переменную по смещению var_2C записывается значение из большого блока по смещению 0x00, т.е. 0x62 (98), по смещению var_28 — значение по смещению 0x10C (268), т.е. 0x6C (108), по смещению var_24 — значение по смещению 0x218 (546), т.е. 0x57 (87), по смещению var_20 — значение по смещению 0x324 (804), т.е. 0x70 (112), по смещению var_1C — значение по смещению 0x430 (1072), т.е. 0x98 (152). Переменной по смещению var_C присваиваем значение 0.
Рисунок 143 — Продолжение алгоритма
Далее идет цикл с таким предусловием, пока значение по смещению var_C меньше либо равно 4, то выполняются команды из рисунка 144.
Рисунок 144 — Цикл
Мы видим, что происходит считывание одного байта из файла и производится его сравнение с одной из локальных переменных в зависимости от счетчика цикла, т.е. либо с var_2C, либо с var_28, либо с var_24, либо с var_20, либо с var_1C. Если считанный байт не равен рассматриваемому, то программа выходит из функции, иначе цикл продолжает выполнение.
Рисунок 145 — Цикл
Считывается следующий байт файла и сравнивается с 0-м, и если он равен, то происходит выход из функции.
Рисунок 146 — Цикл
Теперь в большой блок по смещение 0x104 (260) от адрес, который получается на основе индекса массива записывается только что считанное значение. После этого из файла считывается ровно столько байт, сколько было записано по смещению 0x104 (260), причем все эти байты записываются сразу за текущим смещением на основе индекса цикла. Теперь с помощью функции strlen находится длина этой строки и сравнивается со считанным перед этим число. Если эти значения не равны, то происходит выход из функции.
Рисунок 147 — Цикл
Теперь в локальную переменную по смещению var_38 считывается еще 1 байт файла и к считанному значению прибавляется 7. После этого считывается положение указателя внутри файла при помощи функции ftell и сравнивается с предыдущим числом. Если индекс указателя внутри файла больше, чем считанный байт, то функция завершает работу.
Рисунок 148 — Цикл
Теперь значение индекса каретки, полученное раннее, записывается после считанной длины строки и при помощи функции fseek указатель внутри файла перемещается на эту позицию. После этого счетчик цикла увеличивается на 1.
Рисунок 149 — Продолжение алгоритма
После того, как цикл выполнился 5 раз, выполнение переходит к инструкциям на рисунке 149. Считываются 4 байта файла и сравниваются со значением из большого блока, находящегося по смещению 0x53C (1340), т.е. 0x463 (1122). Если эти значения равны, то функция завершается успешно.
2.6 Обобщение полученных данных
Таким образом, чтобы получить верный код необходимо создать файл с любым именем и запустить программу с аргументами “-f» ПУТЬ_ДО_ФАЙЛА.
Содержимое файла должно иметь следующую структуру:
— Первые 4 символа — слово «VOID».
— Два байта со значением 0x0005.
— Два байта со значением 0x0004.
— Пять блоков данных. Каждый блок представляет из себя:
— Байт с одним из значений в зависимости от номера цикла (0x62, 0x6C, 0x57, 0x70, 0x98);
— Ненулевой байт;
— Строка, длина которой в точности равна значению предыдущего байта;
— Байт, значение которого подобрано таким образом, что при прибавлении к нему 7, его значение будет равно его индексу внутри файла.
— Четыре байта, равные 0x00000462.
Напишем Keygen, который всегда будет генерировать правильные файлы. Результат работы Keygen’а представлен на рисунках 150—151.
Рисунок 150 — Результат работы Keygen
Рисунок 151 — Сгенерированный файл
Заключение
При выполнении работы на практике была произведена обратная разработка программы level_2.exe при помощи интерактивного дизассемблеро IDA Pro Freeware.
По итогам работы были выполнены следующие задания:
— Разобрался в структуре программы level_2.exe;
— Построил граф работы программы;
— Написал кейген для приложения;
— Сделал вывод по результатам проведенной работы.
ПРИЛОЖЕНИЕ А
Исходный код Keygen
Листинг 1 — Исходный код Keygen на C++
ЛАБОРАТОРНАЯ РАБОТА №7
При запуске программ производится запрос пароля (или организуется регистрация программы), после чего дается заключение о правильности прохода через пароль.
Ваша задача:
Знакомство с отладчиком уровня ПРИЛОЖЕНИЯ
Используя отладчик OlleDebuger пройти по программе, найти место, где происходит дешифровка пароля и расшифровать его, после чего снова запустить программу, ввести правильный пароль и получить подтверждение о правильности прохода через пароль.
Знакомство с дизассемблером
Используя дизассемблер IDA
— ознакомиться с методикой дизассемблирования Win приложений;
— дизассемблировать выданную программу;
— найти в тексте программы место проверки пароля;
— исправить ассемблерный код так, чтобы программа срабатывала при любом пароле, определить вид изменений в коде исполняемого файла;
— внести изменения в код исполняемого файла любым способом, чтобы программа срабатывала при любом введенном пароле.
Оформить электронный отчет, в котором отразить:
— титульный лист;
— тему лабораторной работы и задание на лабораторную работу;
— описание этапов дешифровки пароля на OLLEDEDUGER;
— описание использования дизассембелра IDA;
— и экранные формы из дизассемблера, использованные при дешифровке пароля;
— вид экрана после срабатывания откорректированной программы.
Пример выполнения ЛАБОРАТОРНОЙ РАБОТЫ №7
Реверс программы LAB2C_07.exe
Введение
Цель работы: произвести обратную разработку программы LAB2C_07.exe.
Для выполнения цели поставлен ряд задач:
— Разобраться в структуре программы LAB2C_07.exe;
— Построить граф работы программы;
— Сделать вывод по результатам проведенной работы.
1 Знакомство с программой
Программа LAB2C_07.exe (в дальнейшем программа) представляет из себя графическое приложение (рисунок 152).
Рисунок 152 — Внешний вид программы
Попробуем ввести пароль «123» и посмотрим на реакцию программы (рисунок 153).
Рисунок 153 — Введенный пароль «123»
Запустим данную программу в IDA Pro и посмотрим, как она работает.
2 Изучение программы в IDA Pro
2.1 Первый взгляд
Откроем программу в IDA Pro и найдем то место, где генерируется сообщение о неудаче (рисунки 154—155).
Рисунок 154 — Поиск по тексту
Рисунок 155 — Место, в котором программа проверяет правильность пароля
Посмотрим на граф работы функции (рисунок 156).
Рисунок 156 — Граф работы функции
Приступим к разбору.
2.2 Разбор алгоритма
Данная программа представляет из себя обращения к WinAPI, а потому кода, который несет смысловую нагрузку в ней довольно мало. Давайте перейдем сразу к нему (рисунок 157).
Рисунок 157 — Начало алгоритма
Каждый раз, когда пользователь вводит что-то в окно ввода, то срабатывает callback, который начинает выполнения данного кода. Здесь выполняется функции GetWindowTextLengthA для нашего поля ввода, в регистр EAX записывается длина строки, которая затем присваивается регистру ESI. Если длина не равна нулю, программа продолжает выполнение.
Рисунок 158 — Продолжение алгоритма
В этом блоке кода происходит вызов функции GetWindowTextA, который принимает дескриптор окна, указатель на буфер, в который записывается введенная строка и максимальное количество символов в строке. Функция возвращает количество считанных символов. После этого проверяется последний символ введенной строки и если он равен 0x0A (10 = ‘\n’), то алгоритм продолжает выполнение.
Рисунок 159 — Продолжение алгоритма
В данном блоке происходит проверка длины строки. Если длина строки равна 7, то выполнение продолжается. Однако нужно о том, что символы переноса тоже считаются как элементы строки, причем в системе Windows перенос занимает 2 байты, поэтому фактическая длина строки должна быть равна 5.
Рисунок 160 — Продолжение алгоритма
Здесь мы видим простой цикл, который проходит по всем пяти символам введенной строки, складывает их по модулю 2 с числом 0x25 (37) и сравнивает с какими-то локальными переменными. Если хотя бы одна сумма не совпадает с исходной, то алгоритм завершается неудачей. Давайте посмотрим на начало функции и найдем значения этих локальных переменных.
Рисунок 161 — Начало функции
Нас интересуют переменные var_14, var_10, var_C, var_8, var_4 именно в такой последовательности. Они равны 0x14 (20), 0x0F (15), 0x08 (8), 0x0F (15) и 0x14 (20) соответственно. Таким образом, сложим их по модулю 2 с числом 0x25 (37) и получим правильную строку.
— 0x14 ^ 0x25 = 0x31 (49 = «1»);
— 0x0F ^ 0x25 = 0x2A (42 = «*»);
— 0x08 ^ 0x25 = 0x2D (45 = ‘-»);
— 0x0F ^ 0x25 = 0x2A (42 = «*»);
— 0x14 ^ 0x25 = 0x31 (49 = «1»).
Таким образом входная строка должна быть равна «1*-*1». Давайте введем и проверим правильность выполненного анализа (рисунок 162).
Рисунок 162 — Ввод верной строки
Заключение
При выполнении работы на практике была произведена обратная разработка программы LAB2C_07.exe при помощи интерактивного дизассемблеро IDA Pro Freeware.
По итогам работы были выполнены следующие задания:
— Разобрался в структуре программы LAB2C_07.exe;
— Построил граф работы программы;
— Сделал вывод по результатам проведенной работы.