Всем привет! Хочу запустить небольшой курс, как можно ревёрсить программы, в конце курса дойдём до самых сложных примеров, которые накрыты VMP и множеством других протекторов. Весь курс предназначен на нативные приложения, курс будет для "чайников" в плане ревёрс-инженерии, без знаний C/C++ будет очень тяжело для понимания Ну что же, начнём! Все программы взяты с crackmes.one (Не реклама) План в основном такой: Узнать с чем имеем дело Для таких целей я использую ExeInfoPE Отсюда мы можем узнать: EP(точку входа - адрес, откуда начинаются выполняться инструкции исполняемого файла) Разрядность программы Общие сведения(Язык, пакеры, протекторы и прочее...) Анализ инструкций Загружаю программу в IDA Pro В основном для более точного анализа всегда оставляем такие настройки, позже расскажу что за что влияет Жмём ОК, далее везде жмём ок, кроме диалогового окна - загрузить отладочный .pdb файл? Тут жмём нет, ведь у нас нет этого файла, сгенерированного компилятором среды IDA показывает нам входной адрес исполняемых инструкций Что за программа? Программа обычный, простенький CrackME, просит пароль, в случае правильного пароля пишет "Congrats! The correct key was ключ", в обратном же пишет "Wrong key!" Логика, думаем., размышляем... В графе видим разветвление на 2 исхода Получается, что программа сверяет введённый ключ с уже имеющимся и на основе ответа инструкции jnz выполняет нужную часть Что такое вообще за команда jnz? JNZ - это команда, которая сверяет 2 значения и проверяет не равно ли одно из них нулю В коде бы это выглядело что то типо такого: if (var == var1 && var != NULL){ } else{ { Код if (var == var1 && var != NULL){ } else{ { Получается, что у нас несколько вариантов исхода: 1.Узнать пароль 2.Изменить проверку в обратную сторону(если пароль не равен правильному) 3.Сразу выполнять код с положительным исходом Разберём 1 вариант: Мы видим инструкцию CMP CMP - это команда сверки 2 числовых значений, которая выносит в стек флаг ответа(что то типо bool, но не он, но так понятнее) В коде что то типо такого: bool aIF = var == var1; Код bool aIF = var == var1; В данном варианте у нас выглядит так: cmp [ebp+var_8], 11CA423Eh [ebp+var_8]: ebp - это регистр, где хранится адрес текущего кадра(сегмента так сказать) var_8 - это локальный адрес того, что мы ввели в консоль(наш ключ) При сложении получается адрес нашего текста, иначе адрес точки входа + адрес в памяти нашего ключа 11CA423Eh - это пароль в бинарном виде Выделив 11CA423Eh и нажав h на клавиатуре, мы переведём в числовой формат, это и есть наш пароль - 298467902 Проверяем: Разберём 2 вариант: Нам надо изменить логику так, чтобы при неправильном пароле нас пускало в положительный исход, в обратном случае - выводило, что неправильный пароль За ветвление отвечает инструкция jnz если наш оператор CMP сохранил положительный флаг, то jnz переместит на "правильный" путь Обратная инструкция команде jnz - jz Патчим jnz на jz и смотрим результат Всем удачи в начинаниях! Всем пока!
JNZ - это инструкция, которая смотрит, устанавливается ли 6 бит(ZF) в регистре флагов(FLAGS) после выполнения инструкции CMP R, R/I, которая просто вычитает значение операнда1 из операнда2 без изменениях самих значений операндов, чтобы посмотреть, равны они или нет. Также не понял про "выносит в стек флаг ответа". Да, есть такое, загружает на стек значение, но это делает инструкция PUSH (или MOV в редких случаях).