Найти тему

Райтап на таск «Крестики» с Codeby Games | CTF, реверс-инжиниринг

Оглавление

Хотели порешать эти ваши реверс-инжиниринги на CTF? Да ещё и на C++ с Windows Forms? К тому же чтобы он был не сложным и в райтапе были объяснения? Тогда вам сюда 😉

Ссылка на задание (файлы): нажми на меня :)

-2

В архиве будет лежать cross_cr.exe. Флаг должен быть формата CODEBY{FLAG}.

План статьи

1. Статический анализ файла
1. Detect It Easy
- Карта памяти
- Энтропия
- Строки
- Импорты
- Анализ заголовков
- Виртуализация
- Ресурсы
2. Resource Hacker
3. Hex-редактор
2. Динамический анализ
3. Анализ в IDA
1. Поиск сообщения о неправильном флаге
2. Анализ функции и начало сбора флага
3. Составляем "тело флага"

-3

1. Статический анализ файла

1.1 Detect It Easy

Начнём анализ исполняемого файла с помощью утилиты Detect It Easy (далее DIE).

-4
-5

DIE не обнаружил никаких упаковщиков/протекторов и прочих средств защиты. Сам таск свежий, если верить отметки времени. Кроме того он с графическим интерфейсом.

Посмотрим информацию о файле через продвинутый анализ.

Карта памяти

-6

В карте памяти аномалий не выявлено.

Энтропия

-7

Файл кажется сжатым, но если смотреть по секциям, то наиболее сжатый по энтропии - это секция ресурсов (.rsrc). Пока что просто запомним это. Возможно, далее нам это пригодится.

Строки

-8

Поиск по строкам дал нам возможные ориентиры, на места в коде с выводом сообщение о флаге и о проигрыше. Также названия некоторых функций и пока что непонятное MASTER_OF_CODEBY.

Импорты

-9

Из импортов чего-то "слишком криминального" не выявлено. Но есть IsDebuggerPresent.

Примечание: Хоть функция IsDebuggerPresent и есть в программе, но она не используется в основном коде для изменения поведения таска во время отладки. Поэтому нам будет проще.

Анализ заголовков

-10
-11

По заголовкам всё выглядит нормально для EXE-файла.

Виртуализация

-12

Бывает полезно посмотреть таким образом на файл. По графическому представлению видно, что ресурсы занимают больше всего места в этом исполняемом файле.

Ресурсы

-13

Теперь понятно, откуда такой размер. Это PNG-файл. Посмотрим более детально в Resource Hacker.

1.2 Resource Hacker

-14

Это иконка. Если смотреть на неё в Hexdump'е (Binary View) ничего странного не видно.

1.3 Hex-редактор

-15

Иногда в конце исполняемых файлов некоторых тасков что-то можно найти. Но тут ничего странного нет.

-16

2. Динамический анализ

-17
-18

Динамический анализ в Autoruns, Process Monitor, Process Hacker и Wireshark не показал ничего необычного.

3. Анализ в IDA

Примечание: далее будет использована IDA Freeware 8.4. Её хватит с головой :)
Но вы также можете использовать Ghidra, Cutter (Radare2) или любой другой отладчик, который вам нравится. Код в декомпиляторах будет +- похожим.

3.1 Поиск сообщения о неправильном флаге

Попробовав запустить файл и ввести что-то в поля для ввода, мы наблюдаем вызов функции MessageBox с текстом о неправильном флаге.

-19

Запустим IDA и попробуем найти код, что вызывает этот MessageBox. Перейдём в окно Strings (Shift + F12).

-20

Русские символы по умолчанию не отображаются. Для этого нужно нажать правую кнопку мыши (далее ПКМ), затем Setup и выбрать такие пункты меню.

-21
-22

Опция Unicode нужна, чтобы нормально отображались символы из 16-битных кодировок в стандарте Unicode. Строки в 16-битной кодировке активно используются в WinAPI.
Галочку со Strict ASCII мы убираем для поиска русских символов (в том числе для опции Unicode). Но для нормального отображения нам нужно зайти ещё сюда.

-23
-24

Затем тут выставляем cp1251. Это стандартная 8-битная кодировка для русских символов в Windows.
Далее нажимаем Rebuild и видим русские символы.

-25
-26

Первых символов не видно, но понять можно. Жмём на "хх..." (от Эхх...).

-27
-28

Нужно представить эти байты как строку. Жмём ALT+A, затем сюда.

-29
-30

Байты представились как текст в кодировке UTF-16LE (UTF-16 Little Endian). Наводим курсор на название строки (aE) И нажимаем X, чтобы IDA показала нам, где используется эта строка. Жмём левой кнопкой мыши (далее ЛКМ) на пункт меню со скрина.

-31

Видим 2 блока, ведущих к MessageBoxW. Обычно это блоки о неправильном/правильном флаге. Переменные unk на скриншотах - это русские строки. Их тоже можно представить в нормальном виде.

-32

Через клавишу N можно поменять название ноды графа, наведя курсор на его первую инструкцию. Кроме этого можно задать цвет через ПКМ или специальную иконку.

-33
-34

Более того мы сразу попали на функцию проверки ввода.

-35
-36

3.2 Анализ функции и начало сбора флага

Составим краткий "скелет" функции через декомпилятор - клавиша F5. В IDA Freeware онлайн-декомпилятор, поэтому иногда он может быть недоступен. Учтите это, если будете пробовать сами.

-37

Через клавишу N можно менять названия объектов.

Убедиться, что эта функция используется для проверки нашего ввода можно, если навести курсор на её название и нажать X. А далее посмотреть, где вызывается.

-38
-39
-40

Эту функцию можно назвать так. Она обрабатывает сообщения от GUI-окна. По коду 0x111 (WM_COMMAND) вызывается наша функция проверки ввода.

-41

На check_input и сосредоточим внимание. Вывод декомпилятора:

-42

Самые первые инструкции получают данные из полей с вводом имени и флага:

-43

В дизассемблированном виде код выглядит так (вывод декомпилятора полезно проверять на листинге дизассемблера):

-44

Сразу дадим нормальные имена, чтобы повысить читаемость. Через отладку можно понять, где будет что.

-45

В данном случае в поле имени было введено "qwe".

-46

Следующая часть кода выполняет подсчёт длины строки с флагом:

-47

Листинг дизассемблера:

-48

Флаг должен быть длиною в 27 символов.

Следующий кусок кода:

-49

Первое условие из выделения со скрина проверяет, что начальные 7 символов флага - это CODEBY{. Второе условие из выделения проверяет, что код символа с индексом 26 (по счёту 27-ой) равен 125. В таблице ASCII это символ }.

-50

Листинг дизассемблера:

-51

Таким образом сейчас у нас есть следующее представление флага:

-52

Следующий блок кода:

-53

Листинг дизассемблера:

-54

Данный блок кода проверяет часть флага между фигурными скобками {}. Она должна быть такого вида:

-XXXX-XXXX-XXXX

Где X - это цифра в 10-ой системе.

Немного странно, что в этой проверке упущена часть перед первым -, это мы поймём далее.

Затем идёт такой блок:

-55

Он преобразует строку с числом между символами - в число.

Листинг дизассемблера:

-56

Следующий блок кода сравнивает введённое имя со строкой MASTER_OF_CODEBY. Это будет правильным именем для дальнейшего решения таска.

-57
-58

Листинг дизассемблера:

-59

3.3 Составляем "тело флага"

Посмотрим на следующий блок:

-60

Он выполняет шифрование чисел через простые операции и сравнивает их с нужными.

-61

Листинг дизассемблера:

-62

Перепишем это в более понятном виде:

-63

Для удобства я не использовал копии чисел, как показал декомпилятор.

Теперь останется просто применить противоположные операции в обратном порядке к нужным значениям.

  • Для операции + обратная операция -.
  • Для операции - обратная операция +.
  • Для операции xor обратная операция xor.
-64

Итого наши части флага:

9312-8831-4294972108-1221

Общий флаг:

CODEBY{9312-8831-4294972108-1221}

Третья часть очень выделяется. И проверку не пройдёт. Если посмотреть листинг дизассемблера для функции шифрования, то данные там хранятся в 4-байтовых регистрах.

-65

Представим число 4294972108 в 16-ом виде:

0x1000012CC
0x01 00 00 12 CC (по байтам)

Это 5-байтовое число. А регистры 4-байтовые. 5-байтовое число в 4-байтовый регистр никак не влезает. Поэтому в процессе шифрования первые лишние байты просто отсекаются. В данном случае это байт 0x01 в самом начале:

0x00 00 12 CC (по байтам)

Получили 0x000012CC. Незначащие байты (0x0000) можно убрать и получить 16-ое число. Это 16-ое число переводим в 10-е. Далее оформляем флаг и сдаём.

Делиться открытым флагом не буду, дальше вы сами добьёте таск! :)

-66

Спасибо за прочтение статьи! 😉