Знакомство с инструкциями (командами, мнемониками) ассемблера
и поиск путей взлома

В прошлых уроках мы узнали о существовании 32- и 64-битных исполняемых файлах, научились бегло анализировать файл для определения языка программирования, на котором он написан, а также возможной защиты. Кроме того, немного познакомились с виртуальными адресами, опкодами и ассемблерными мнемониками (они же - инструкции или команды ассемблера).

Напомню из прошлого урока, что инструкции ассемблера (мнемоники) это машинный код в удобочитаемом для человека виде, который выполняется микропроцессором. Т.е. каждая строчка с инструкцией ассемблера выполняет какую-то задачу. Для начала откроем в отладчике FaNt0m's Crackme #1 из урока №2 (ссылка на crackme) и посмотрим на третью колонку слева.



Как понять, где находятся инструкции ассемблера? На каждой строчке они всегда идут первыми. На снимке ниже инструкции ассемблера это ADD, CALL, CMP (на снимке она не видна, находится ниже), JE (также не видна), JMP (также не видна), LEA (также не видна), MOV, POP, PUSH.



Что же именно выполняют таинственные инструкции ассемблера? Каждая из инструкций специализируется на выполнении одной конкретной задачи. В пояснениях ниже будут появляться незнакомые слова и наборы символов. В этом уроке достаточно запомнить лишь то, что ниже выделено жирным шрифтом. Итак...

Инструкция ADD (пример: ADD ESP, -50) --- добавляет одно значение к другому.
Инструкция CALL (пример: CALL JMP.&KERNEL32.lstrcmpA) - сначала вызывает какую-либо функцию, а после её выполнения возвращается к следующей инструкции.
Инструкция CMP (пример: CMP EAX, 0) - сравнивает два значения (в данном случае "0" и "EAX").
Инструкция JE (пример: JE SHORT 0040110B) - инструкция-прыжок "Jump if Equal".
Инструкция JMP (пример: JMP SHORT 004010E3) - безусловная инструкция-прыжок. Безусловная, потому что выполняется при любых условиях.
Инструкция LEA (пример: LEA EAX,[EBP-4C]) - выполняет вычисления, связанные с адресацией памяти.
Инструкция MOV (пример: MOV DWORD PTR DS:[403094],EAX) - перемещает информацию из одного источника в другой. В качестве источника может выступать какое-либо значение, регистр или адрес памяти.
Инструкция POP (пример: POP DWORD PTR SS:[EBP-1C]) - инструкция берёт из стека 32-битное значение, чтобы сохранить его в регистре или памяти.
Инструкция PUSH (пример: PUSH EAX) - инструкция добавляет определённое значение к вершине стека.

Для того, чтобы лучше понять роль инструкций ассемблера, необходимо несколько слов сказать о том, что происходит после запуска любой программы. В упрощённом виде этот процесс выглядит так:

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

Платные программы при запуске проверяют наличие лицензии, поэтому изучение выполняемых инструкций помогает понять механизм проверки лицензии, а значит и обойти этот механизм. На снимке ниже представлено окошко программы FolderSizes c информацией о том, что она не зарегистрирована. И более того - в неактивированном режиме она будет работать ещё 8 дней. Делаем вывод, что программа где-то сохранила день своей установки, на этом основана работа таймера обратного отсчёта до окончания испытательного времени. Обратим внимание на строчку "You have 8 day(s) left in your evaluation". За исключением цифры 8, поскольку это переменная, которая каждый день будет меняться.



Попробуем зарегистрировать программу, нажав на "Enter License Code". Появится окошко с текстовым полем для ввода информации.



Код мы не знаем, попробуем просто нажать "ОК". В ответ программа сообщает, что поле для ввода кода не может быть пустым.



Давайте введём 123. Вдруг повезёт? На этот раз программа пишет, что код неверный.



Не будем отчаиваться, а подведём итог нашего небольшого исследования:
- программа некоторое время работает в испытательном режиме, отсчитывая время с даты установки (= проверка даты)
- при попытке регистрации пустым кодом появляется окошко с соответствующим уведомлением (= проверка заполнения текстового поля для ввода информации)
- при вводе неправильного кода появляется окошко с соответствующим уведомлением (= проверка кода лицензии).
- если в испытательном режиме не вводить код, тогда программа успешно запускается (= сначала идёт проверка даты, код лицензии проверяется только после истечения испытательного режима или по желанию пользователя в испытательном режиме).

Мы пока не можем взломать программу, но можем предположить, что есть три варианта решения проблемы:
1) найти код
2) обойти механизм проверки кода
3) обойти механизм проверки даты, сделав т.н. вечный испытательный режим (в этом режиме каких-то явных ограничений в работе программы нет, поэтому достаточно продлить работу программу не на традиционные 14 или 30 дней, а навсегда).

Механизм проверки кода и даты можно определить после изучения инструкций ассемблера, т.к. они показывают буквально всё - когда происходит вызов окошек (включая те, в которых требует ввести код лицензии), когда происходит проверка кода... Всё так легко? Не совсем. Мы уже бегло познакомились с инструкциями. Но как применить наши знания к проверке кода? Об этом в следующих уроках.

            

Страница обновлена 3 апреля 2022 года.