Ревёрс-инжиниринг: что это такое и зачем нужно
Загадочная история Бенджамина Баттона, который решил стать программистом.
Кадр: фильм «Игра в имитацию» / The Weinstein Company
Если вы в детстве любили разбирать игрушки, возможно, вы прирождённый специалист по ревёрс-инжинирингу, но пока не знаете об этом. Ведь занимаются они примерно тем же самым, только вместо игрушек у них программы и техника, а вместо молотка и отвёртки — специальные приложения.
Рассказываем об основах ревёрс-инжиниринга и показываем, как специалисты по кибербезопасности анализируют вирусы. А в конце статьи попробуем разобрать на винтики простенькую программу на C++, чтобы вы смогли понять, как этот процесс выглядит изнутри.
Предупреждаем: то, о чём вы сейчас узнаете, может вызвать соблазн перейти на тёмную сторону. Не надо так: лучше становитесь белым хакером и помогайте компаниям бороться с киберпреступностью.
Что такое ревёрс-инжиниринг
Представьте, что вы работаете программистом в компании по производству беспилотных автомобилей. К вам приходит руководитель отдела разработки и говорит: «Мы получили прототип программы нашего главного конкурента. Вот тебе файл в формате EXE. Сможешь разобраться, как она работает?» Что будете делать?
Решить задачу не так-то просто, если размышлять в парадигме обычной (прямой) разработки. А состоит она в следующем:
- программист пишет код на понятном для него языке — например, Java, Python или C++;
- затем он отдаёт файл компилятору, который превращает код из понятного для человека в бинарный файл — чтобы его мог прочитать компьютер;
- Пользователь скачивает скомпилированную программу — например, в вышеупомянутом формате EXE и запускает её на компьютере.
Бинарный файл, или, как его ещё называют, исполняемый файл, — это набор нулей и единиц, машинный код. Простой человек со стороны не сможет прочитать его, а значит, и разобраться в устройстве программы.
Чтобы не попасть в тупик в таких ситуациях, придумали ревёрс-инжиниринг. Слово «ревёрс» означает, что процесс разработки идёт в обратную сторону — то есть бинарный файл переводят обратно в человекочитаемый формат. Вот как это выглядит:
- разработчик получает бинарный файл, который понимает только компьютер;
- затем он прогоняет этот файл через специальную программу и превращает в код на знакомом ему языке программирования;
- дальше программист изучает этот файл и пытается разобраться во внутреннем устройстве программы.
Процесс ревёрс-инжиринига может показаться простым — но это иллюзия. Даже опытные специалисты по обратной разработке могут анализировать одну и ту же программу месяцами. И не факт, что её удастся расшифровать полностью.
Зачем нужно обратное проектирование
С помощью ревёрс-инжиниринга мы можем понять, как работает программа, какие данные использует, куда и что отправляет, а также какие в ней есть слабые места и как она реагирует на аварийные ситуации. Это всё поможет нам сделать свой продукт лучше и переиграть конкурентов.
Дисклеймер: здесь стоит оговориться, что почти все разработчики запрещают расшифровывать код своих программ в лицензионном соглашении. А значит, применять ревёрс-инжиниринг стоит либо на свой страх и риск, либо предварительно согласовав с компаниями-поставщиками.
Давайте приведём ещё пару примеров областей, в которых полезна обратная разработка.
🔵 Анализ вирусов и поиск уязвимостей. Специалисты по кибербезопасности уже давно применяют методы ревёрс-инжиниринга, чтобы анализировать вредоносное ПО. Например, они могут специально скачивать вирусы, заражать ими свои компьютеры и выяснять, как те устроены, чтобы потом разработать средства защиты.
🔵 Разработка модов для игр. В геймдеве обратная разработка позволяет создавать модификации для игр и изменять игровой процесс: добавлять новые функции и контент. Например, таким образом создавались моды для игр The Elder Scrolls V: Skyrim и Grand Theft Auto 5.
🔵 Изучение старых технологий. Бывает, что оригинальная документация для приложений утеряна или что программа написана для старых компьютеров, которые больше не производятся. Поэтому разработчикам приходится с нуля воссоздавать код приложений.
Способы и этапы обратного проектирования: как взломать программу
Хорошо, ревёрс-инжиниринг — это наука о том, как машинный код превратить в понятный для человека язык. С этим разобрались. Но как именно происходит обратная разработка? Есть три способа.
1️⃣ Перевести бинарный файл в код на языке высокого уровня. Для этого существуют специальные программы — дизассемблеры. Они понимают, как устроен машинный код, и без проблем могут перевести его на удобный для нас язык программирования — например, C++.
Единственный минус работы дизассемблера в том, что в готовом коде часто нет названий переменных и комментариев, поэтому после процедуры разработчику нужно будет довольно долго разбираться, за что отвечают отдельные блоки кода.
2️⃣ Перевести бинарный файл в код на языке ассемблера. Ассемблер — язык чуть более высокого уровня, чем машинный код, но гораздо более низкого, чем привычные нам JavaScript и Python. Любой процессор умеет работать с ассемблером, поэтому для компьютера этот способ расшифровки бинарного файла — самый простой.
Чтобы прочитать код, написанный на ассемблере, нужно разбираться в том, как устроен процессор, какие команды он использует и как вообще работает. Поэтому без подготовки проанализировать программу будет сложно.
Читайте также:
3️⃣ Изучить, какие данные программа пересылает по Сети или внутри компьютера. Обычно программы обмениваются данными по интернету или внутри операционной системы. Поэтому, чтобы понять, как устроена программа, ревёрс-инженеры используют специальные сетевые анализаторы.
Например, существует сетевой анализатор, встроенный прямо в Google Chrome. Чтобы его открыть, нужно зайти в инструменты разработчика (клавиша F12) и перейти на вкладку «Network».
Теперь, когда мы знаем основные способы обратной разработки, давайте перейдём к самому процессу — этапам ревёрс-инжиниринга. Всего их четыре.
- Провести предварительное исследование. Сначала нужно внимательно изучить программу: понажимать все кнопки, попользоваться всеми функциями. Это поможет составить цельную картину того, как работает приложение.
- Начать разборку, или демонтаж. Теперь мы должны заглянуть внутрь программы и посмотреть, как она устроена. Для этого как раз применяем один из способов обратной разработки, а затем изучаем полученный код.
- Провести анализ. Когда мы разобрались, какие в программе есть алгоритмы и структуры данных, пора собирать всё воедино. Мы изучаем все части и пытаемся понять, как они работают вместе. Например, смотрим, в какой последовательности выполняются методы в коде и как приложение взаимодействует с внешней средой.
- Создать документацию. После того как мы со всем разобрались, пора документировать функциональность. Нужно записать, что делают функции, какие переменные они принимают и куда отправляют данные. А потом всё это тщательно задокументировать, чтобы не возникало вопросов о том, что делают отдельные части кода.
Ещё раз напомним, что процесс может занять много времени. А чтобы понять, как работает программа, нужно иметь опыт программирования — иначе будет сложно. Хотя попробовать всё равно стоит.
Как освоить ревёрс-инжиниринг: первые шаги
Допустим, вы решили попробовать себя на нелёгкой стезе ревёрс-инжиниринга. Куда идти, что нажимать?
❗️ Хотим напомнить, что пиратство в России незаконно. За него суд может назначить штраф до 200 тысяч рублей, до двух лет исправительных работ или лишить свободы на срок до двух лет. А за распространение, использование и создание вредоносного ПО — до семи лет. Поэтому не занимайтесь взломом — занимайтесь кибербезопасностью.
Лучше всего изучить обратную разработку на своих проектах или решать задачи на специальных сайтах — например, на Crackmes. Так вы сможете вполне легально прокачать свои навыки.
Программ для ревёрс-инжиниринга достаточно. Некоторые из них могут быть вам знакомы — например, Cheat Engine. Вообще, это программа для обратной разработки, но она также позволяет накрутить игровой валюты где-нибудь в Sims или GTA.
Вот ещё список программ:
Давайте в качестве примера покажем, как выглядит обратная разработка в программе IDA Pro. Напишем код «Hello, World» на C++, скомпилируем его и попробуем расшифровать с помощью приложения.
Открываем программу IDA Pro и видим первый экран. Здесь нажимаем кнопку «New», чтобы начать процесс дизассемблирования:
Дальше нам нужно загрузить файл в программу. На выбор есть два варианта — формат DLL или бинарный файл. Нам нужен первый:
Готово — вот как выглядит наш дизассемблированный файл. Можно поизучать его и понять, из каких элементов он вообще состоит.
Сначала мы попадаем на вкладку «IDA View-A». Это место, где находится код языка ассемблера нашей переведённой программы. Если приглядеться, то можно увидеть строчку lea rdx, _Val ; "Hello, World". Она показывает, что мы что-то делаем со строкой «Hello, World» — а точнее, пытаемся вывести её в консоль. Но это очевидно для нас, потому что программа простая. Если бы тут был, скажем, код операционной системы Windows, то мы бы думали очень долго.
Давайте посмотрим, что находится в других вкладках 👇
Это вкладка «Hex View 1». Тут дизассемблированный код представлен в виде шестнадцатеричных — то есть понятных для компьютера — символов. Если понимать язык нулей и единиц, отсюда можно достать полезную информацию — например, найти повторяющиеся команды или какие-нибудь интересные данные.
Кстати, обратите внимание на функции слева. Они тоже могут дать много полезной информации:
Например, по этим функциям можно понять, какие системные вызовы делает программа. Правда, имена этих вызовов не вполне очевидны, поэтому часто приходится гуглить, зачем они нужны.
Переходим на следующую вкладку — «Structures».
Здесь можно подробнее исследовать, как устроены структуры данных в программе. Например, тут показано, какие классы вызываются, какие типы переменных они используют и какие исключения обрабатывают. Сложно, зато познавательно.
👉 Подведём итоги: с помощью всех этих данных инженеры по обратному проектированию изучают, как работает программа. Они запускают дебагеры и тыкают везде, где можно потыкать, чтобы собрать максимум информации об архитектуре. Работа непростая — но невероятно полезная. А ещё за это платят неплохие деньги — какие именно зарплатные вилки у разработчиков, владеющих языком ассемблера, мы рассказывали в отдельной статье.
Больше интересного про код — в нашем телеграм-канале. Подписывайтесь!