Skip to main content

Реверс инжиниринг

Как делать такие задачи и готовить реверс-инженеров в школе

Зачем вообще учить reverse в школе

Reverse полезен не только для CTF.

Он учит:

  1. аккуратно думать;
  2. работать с неполной информацией;
  3. не верить внешнему виду объектов;
  4. читать технические артефакты как следы логики;
  5. спокойно разбирать сложные системы по кускам.

Проще говоря, reverse делает из ученика не просто пользователя инструментов, а исследователя.

Кого и как учить

Школьников нельзя сразу бросать в IDA, VMProtect и запутанные crackme.

Так они быстро устанут.

Нужна лестница сложности.

Уровень 1. Видеть артефакт

Цель:

  1. научить, что файл это объект исследования;
  2. научить первым проверкам;
  3. развить привычку не гадать по названию.

Навыки:

  1. file
  2. strings
  3. xxd
  4. размеры файлов
  5. сравнение файлов
  6. базовые кодировки

Примеры задач:

  1. текст в base64;
  2. xor с коротким ключом;
  3. флаг в хвосте файла;
  4. строка в hex, которую надо собрать;
  5. картинка с повреждённым заголовком.

Уровень 2. Скрипт как инструмент

Цель:

  1. научить автоматизировать рутину;
  2. писать маленькие анализаторы;
  3. не делать руками то, что легко делается кодом.

Навыки:

  1. Python для парсинга байт;
  2. bytes, bytearray, ord, chr;
  3. циклы по файлу;
  4. простые преобразования;
  5. проверка гипотез через код.

Примеры задач:

  1. xor bruteforce;
  2. перестановка байтов;
  3. nibble swap;
  4. reversing toy-checker;
  5. поиск сигнатур в бинарных данных.

Уровень 3. Чужой код как артефакт

Цель:

  1. научить читать код, который писал не ты;
  2. видеть, где логика, а где шум;
  3. замечать обфускацию.

Навыки:

  1. читать Python/C/C++/JavaScript по смыслу;
  2. убирать мусорные слои;
  3. выносить полезную логику в псевдокод;
  4. различать данные и выполнение.

Примеры задач:

  1. eval(base64(...));
  2. marshal/pickle/zlib loader;
  3. простые crackme на сравнение по символам;
  4. проверка через xor или rotate.

Уровень 4. Bytecode и низкий уровень

Цель:

  1. научить, что код бывает не только исходным;
  2. показать bytecode, VM, dead code, self-reference;
  3. дать вкус настоящего реверса.

Навыки:

  1. opcodes;
  2. disassembly;
  3. ручной разбор инструкций;
  4. анализ unreachable bytes;
  5. понимание control flow.

Примеры задач:

  1. скрытый флаг в co_code;
  2. флаг в jump table;
  3. флаг в dead branch;
  4. кусок данных в секции, которая кажется кодом.

Как строить хорошую учебную reverse-задачу

Хорошая задача должна быть:

  1. решаемой;
  2. поучительной;
  3. честной;
  4. с одной главной идеей;
  5. с проверяемыми шагами, а не с гаданием.

Формула хорошей задачи

  1. есть внешний шум;
  2. есть один реальный трюк;
  3. есть следы, по которым до трюка можно дойти;
  4. после решения ученик понимает, чему именно научился.

Формула плохой задачи

  1. сто случайных слоёв без логики;
  2. ответ держится на угадывании;
  3. нет проверяемых промежуточных этапов;
  4. флаг можно найти только по авторской магии;
  5. сложность держится не на идее, а на боли.

Как придумать задачу типа этой

Берём понятную основу и добавляем ровно один красивый трюк.

Каркас

  1. пишем простую функцию check_flag;
  2. делаем ей необычный источник данных;
  3. прячем флаг не в строке, а в кодовом объекте;
  4. сверху добавляем безопасный слой обфускации.

Рабочая схема

  1. написать проверяющую функцию;
  2. убедиться, что её можно разобрать вручную;
  3. вставить флаг в unreachable tail или constants;
  4. сверху завернуть в base64;
  5. сверху при желании завернуть в marshal;
  6. проверить, что задача решается без магии автора.

Главное правило автора задач

Автор обязан решить свою задачу как минимум тремя способами:

  1. как новичок;
  2. как нормальный участник;
  3. как параноик с ручным разбором.

Если задача решается только при знании авторского секрета, задача плохая.

Как добавлять заподлянки честно

Заподлянка должна учить, а не ломать мотивацию.

Хорошие заподлянки:

  1. ложный printable input вместо настоящего флага;
  2. dead code с полезными данными;
  3. loader, который кажется главным, но это только внешний слой;
  4. валидный decoy-результат, после которого надо задать ещё один вопрос.

Плохие заподлянки:

  1. битый файл без намёков;
  2. зависимость от одной редкой версии тулзы;
  3. нестабильное поведение на разных машинах;
  4. шифрование без следов, что именно применено.

Как объяснять школьникам мышление реверсера

Им нужна не куча инструментов, а порядок вопросов.

Вот базовый шаблон мышления.

Вопрос 1. Что это за объект

  1. текст;
  2. архив;
  3. картинка;
  4. исполняемый файл;
  5. скрипт;
  6. байткод;
  7. контейнер с вложенным форматом.

Вопрос 2. Из чего он состоит

  1. заголовок;
  2. полезная нагрузка;
  3. хвост;
  4. метаданные;
  5. строки;
  6. сигнатуры;
  7. повторяющиеся блоки.

Вопрос 3. Что здесь реально исполняется

  1. все байты или только часть;
  2. есть ли unreachable branch;
  3. есть ли данные внутри кода;
  4. есть ли код внутри данных.

Вопрос 4. Как это автоматизировать

  1. что можно распарсить скриптом;
  2. что можно перебрать;
  3. что можно проверить без догадок.

Учебная программа на 12 недель

Недели 1-2

Тема: файл как артефакт.

Учить:

  1. file
  2. strings
  3. xxd
  4. сигнатуры форматов
  5. base16/base32/base64

Недели 3-4

Тема: простые преобразования.

Учить:

  1. xor;
  2. rot;
  3. caesar;
  4. nibble swap;
  5. bitwise операции.

Недели 5-6

Тема: Python как средство анализа.

Учить:

  1. чтение файлов;
  2. работа с байтами;
  3. маленькие bruteforce-скрипты;
  4. print-debugging;
  5. сравнение гипотез.

Недели 7-8

Тема: код как цель анализа.

Учить:

  1. обфусцированный Python;
  2. eval/exec;
  3. marshal/zlib/base64;
  4. как безопасно снимать слои.

Недели 9-10

Тема: bytecode и disassembly.

Учить:

  1. что такое opcode;
  2. как читать дизасм;
  3. что такое control flow;
  4. зачем смотреть на raw bytes.

Недели 11-12

Тема: мини-проект.

Каждый ученик должен:

  1. сделать свою задачу;
  2. решить задачу друга;
  3. написать writeup;
  4. объяснить, где была главная идея.

Как проверять прогресс ученика

Надо смотреть не только на найден ли флаг.

Надо смотреть:

  1. умеет ли он формулировать гипотезу;
  2. делает ли базовые проверки;
  3. автоматизирует ли рутину;
  4. записывает ли промежуточные выводы;
  5. может ли объяснить решение другому человеку.

Какие привычки нужно вбивать с первого дня

  1. сначала структура, потом догадки;
  2. сначала артефакт, потом запуск;
  3. сначала маленький скрипт, потом ручной ад;
  4. каждый странный байт может быть подсказкой;
  5. упавший декомпилятор это тоже сигнал.

Минимальный стек школьного реверсера

  1. Python;
  2. shell;
  3. file;
  4. strings;
  5. xxd;
  6. binwalk;
  7. exiftool;
  8. ghidra или хотя бы objdump;
  9. xdis/uncompyle6 для Python-задач;
  10. блокнот для заметок.

Как проводить занятие по этой конкретной задаче

Часть 1. Разогрев

Спросить у детей:

  1. что показывает file;
  2. что видно в strings;
  3. почему нельзя сразу запускать task.py.

Часть 2. Снятие слоя

Пусть сами достанут:

  1. base64;
  2. Python 2 код;
  3. marshal payload.

Часть 3. Поломка инструмента

Специально показать, что декомпилятор падает.

Объяснить:

  1. это нормально;
  2. дальше начинается настоящий reverse;
  3. когда автоматика ломается, включается понимание.

Часть 4. Ручной разбор

Разобрать:

  1. co_consts;
  2. co_names;
  3. co_code;
  4. почему co_code используется как источник данных.

Часть 5. Финальный инсайт

Показать детям:

  1. первые 96 байт дают валидный ввод;
  2. но настоящий флаг спрятан в хвосте;
  3. хороший реверсер всегда проверяет хвосты, dead code и unreachable data.

Как делать выпускников сильными, а не просто натасканными

Нужно развивать 4 вещи одновременно.

1. Техника

  1. команды;
  2. байты;
  3. скрипты;
  4. форматы;
  5. дизасм.

2. Метод

  1. гипотеза;
  2. проверка;
  3. фиксация результата;
  4. следующая гипотеза.

3. Терпение

  1. не паниковать, если не красиво;
  2. не сдаваться, если вывод странный;
  3. не перескакивать через базовые проверки.

4. Коммуникация

  1. писать writeup;
  2. объяснять решение товарищу;
  3. уметь сказать, что именно ты проверил и чего не хватает.

Рецепт хорошего школьного reverse-кружка

  1. короткие задачи;
  2. одна идея на задачу;
  3. обязательный writeup;
  4. ученики сами делают задачи друг другу;
  5. каждая задача заканчивается разбором не только ответа, но и маршрута мысли.

Итог

Если учить reverse правильно, школьник постепенно начинает:

  1. видеть структуру вместо хаоса;
  2. любить проверяемые гипотезы;
  3. не бояться бинарных данных;
  4. читать код и байткод как рассказ о том, что хотел сделать автор;
  5. становиться не пользователем тулз, а инженером.

Именно это и есть цель.

Не просто найти один флаг.

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