Реверс инжиниринг
Как делать такие задачи и готовить реверс-инженеров в школе
Зачем вообще учить reverse в школе
Reverse полезен не только для CTF.
Он учит:
- аккуратно думать;
- работать с неполной информацией;
- не верить внешнему виду объектов;
- читать технические артефакты как следы логики;
- спокойно разбирать сложные системы по кускам.
Проще говоря, reverse делает из ученика не просто пользователя инструментов, а исследователя.
Кого и как учить
Школьников нельзя сразу бросать в IDA, VMProtect и запутанные crackme.
Так они быстро устанут.
Нужна лестница сложности.
Уровень 1. Видеть артефакт
Цель:
- научить, что файл это объект исследования;
- научить первым проверкам;
- развить привычку не гадать по названию.
Навыки:
filestringsxxd- размеры файлов
- сравнение файлов
- базовые кодировки
Примеры задач:
- текст в base64;
- xor с коротким ключом;
- флаг в хвосте файла;
- строка в hex, которую надо собрать;
- картинка с повреждённым заголовком.
Уровень 2. Скрипт как инструмент
Цель:
- научить автоматизировать рутину;
- писать маленькие анализаторы;
- не делать руками то, что легко делается кодом.
Навыки:
- Python для парсинга байт;
bytes,bytearray,ord,chr;- циклы по файлу;
- простые преобразования;
- проверка гипотез через код.
Примеры задач:
- xor bruteforce;
- перестановка байтов;
- nibble swap;
- reversing toy-checker;
- поиск сигнатур в бинарных данных.
Уровень 3. Чужой код как артефакт
Цель:
- научить читать код, который писал не ты;
- видеть, где логика, а где шум;
- замечать обфускацию.
Навыки:
- читать Python/C/C++/JavaScript по смыслу;
- убирать мусорные слои;
- выносить полезную логику в псевдокод;
- различать данные и выполнение.
Примеры задач:
eval(base64(...));marshal/pickle/zlibloader;- простые crackme на сравнение по символам;
- проверка через xor или rotate.
Уровень 4. Bytecode и низкий уровень
Цель:
- научить, что код бывает не только исходным;
- показать bytecode, VM, dead code, self-reference;
- дать вкус настоящего реверса.
Навыки:
- opcodes;
- disassembly;
- ручной разбор инструкций;
- анализ unreachable bytes;
- понимание control flow.
Примеры задач:
- скрытый флаг в
co_code; - флаг в jump table;
- флаг в dead branch;
- кусок данных в секции, которая кажется кодом.
Как строить хорошую учебную reverse-задачу
Хорошая задача должна быть:
- решаемой;
- поучительной;
- честной;
- с одной главной идеей;
- с проверяемыми шагами, а не с гаданием.
Формула хорошей задачи
- есть внешний шум;
- есть один реальный трюк;
- есть следы, по которым до трюка можно дойти;
- после решения ученик понимает, чему именно научился.
Формула плохой задачи
- сто случайных слоёв без логики;
- ответ держится на угадывании;
- нет проверяемых промежуточных этапов;
- флаг можно найти только по авторской магии;
- сложность держится не на идее, а на боли.
Как придумать задачу типа этой
Берём понятную основу и добавляем ровно один красивый трюк.
Каркас
- пишем простую функцию
check_flag; - делаем ей необычный источник данных;
- прячем флаг не в строке, а в кодовом объекте;
- сверху добавляем безопасный слой обфускации.
Рабочая схема
- написать проверяющую функцию;
- убедиться, что её можно разобрать вручную;
- вставить флаг в unreachable tail или constants;
- сверху завернуть в
base64; - сверху при желании завернуть в
marshal; - проверить, что задача решается без магии автора.
Главное правило автора задач
Автор обязан решить свою задачу как минимум тремя способами:
- как новичок;
- как нормальный участник;
- как параноик с ручным разбором.
Если задача решается только при знании авторского секрета, задача плохая.
Как добавлять заподлянки честно
Заподлянка должна учить, а не ломать мотивацию.
Хорошие заподлянки:
- ложный printable input вместо настоящего флага;
- dead code с полезными данными;
- loader, который кажется главным, но это только внешний слой;
- валидный decoy-результат, после которого надо задать ещё один вопрос.
Плохие заподлянки:
- битый файл без намёков;
- зависимость от одной редкой версии тулзы;
- нестабильное поведение на разных машинах;
- шифрование без следов, что именно применено.
Как объяснять школьникам мышление реверсера
Им нужна не куча инструментов, а порядок вопросов.
Вот базовый шаблон мышления.
Вопрос 1. Что это за объект
- текст;
- архив;
- картинка;
- исполняемый файл;
- скрипт;
- байткод;
- контейнер с вложенным форматом.
Вопрос 2. Из чего он состоит
- заголовок;
- полезная нагрузка;
- хвост;
- метаданные;
- строки;
- сигнатуры;
- повторяющиеся блоки.
Вопрос 3. Что здесь реально исполняется
- все байты или только часть;
- есть ли unreachable branch;
- есть ли данные внутри кода;
- есть ли код внутри данных.
Вопрос 4. Как это автоматизировать
- что можно распарсить скриптом;
- что можно перебрать;
- что можно проверить без догадок.
Учебная программа на 12 недель
Недели 1-2
Тема: файл как артефакт.
Учить:
filestringsxxd- сигнатуры форматов
- base16/base32/base64
Недели 3-4
Тема: простые преобразования.
Учить:
- xor;
- rot;
- caesar;
- nibble swap;
- bitwise операции.
Недели 5-6
Тема: Python как средство анализа.
Учить:
- чтение файлов;
- работа с байтами;
- маленькие bruteforce-скрипты;
- print-debugging;
- сравнение гипотез.
Недели 7-8
Тема: код как цель анализа.
Учить:
- обфусцированный Python;
- eval/exec;
- marshal/zlib/base64;
- как безопасно снимать слои.
Недели 9-10
Тема: bytecode и disassembly.
Учить:
- что такое opcode;
- как читать дизасм;
- что такое control flow;
- зачем смотреть на raw bytes.
Недели 11-12
Тема: мини-проект.
Каждый ученик должен:
- сделать свою задачу;
- решить задачу друга;
- написать writeup;
- объяснить, где была главная идея.
Как проверять прогресс ученика
Надо смотреть не только на найден ли флаг.
Надо смотреть:
- умеет ли он формулировать гипотезу;
- делает ли базовые проверки;
- автоматизирует ли рутину;
- записывает ли промежуточные выводы;
- может ли объяснить решение другому человеку.
Какие привычки нужно вбивать с первого дня
- сначала структура, потом догадки;
- сначала артефакт, потом запуск;
- сначала маленький скрипт, потом ручной ад;
- каждый странный байт может быть подсказкой;
- упавший декомпилятор это тоже сигнал.
Минимальный стек школьного реверсера
- Python;
- shell;
file;strings;xxd;binwalk;exiftool;ghidraили хотя быobjdump;xdis/uncompyle6для Python-задач;- блокнот для заметок.
Как проводить занятие по этой конкретной задаче
Часть 1. Разогрев
Спросить у детей:
- что показывает
file; - что видно в
strings; - почему нельзя сразу запускать
task.py.
Часть 2. Снятие слоя
Пусть сами достанут:
- base64;
- Python 2 код;
marshalpayload.
Часть 3. Поломка инструмента
Специально показать, что декомпилятор падает.
Объяснить:
- это нормально;
- дальше начинается настоящий reverse;
- когда автоматика ломается, включается понимание.
Часть 4. Ручной разбор
Разобрать:
co_consts;co_names;co_code;- почему
co_codeиспользуется как источник данных.
Часть 5. Финальный инсайт
Показать детям:
- первые 96 байт дают валидный ввод;
- но настоящий флаг спрятан в хвосте;
- хороший реверсер всегда проверяет хвосты, dead code и unreachable data.
Как делать выпускников сильными, а не просто натасканными
Нужно развивать 4 вещи одновременно.
1. Техника
- команды;
- байты;
- скрипты;
- форматы;
- дизасм.
2. Метод
- гипотеза;
- проверка;
- фиксация результата;
- следующая гипотеза.
3. Терпение
- не паниковать, если не красиво;
- не сдаваться, если вывод странный;
- не перескакивать через базовые проверки.
4. Коммуникация
- писать writeup;
- объяснять решение товарищу;
- уметь сказать, что именно ты проверил и чего не хватает.
Рецепт хорошего школьного reverse-кружка
- короткие задачи;
- одна идея на задачу;
- обязательный writeup;
- ученики сами делают задачи друг другу;
- каждая задача заканчивается разбором не только ответа, но и маршрута мысли.
Итог
Если учить reverse правильно, школьник постепенно начинает:
- видеть структуру вместо хаоса;
- любить проверяемые гипотезы;
- не бояться бинарных данных;
- читать код и байткод как рассказ о том, что хотел сделать автор;
- становиться не пользователем тулз, а инженером.
Именно это и есть цель.
Не просто найти один флаг.
А научиться вскрывать систему так, чтобы понять её глубже, чем она хотела показаться снаружи.
