Ломаем с IDA PRO #1

Сегодня мы сконцентрируемся на возможностях IdaPython, плагина ставшего штатной частью современной Иды и позволяющего делать с ней нечто невероятное!

Для того чтобы достойно оценить IdaPython нам потребуется свежий CrackMeByFereter#2 не использующий сложных трюков, но затрудняющий статический анализ.

Познакомиться с основами IdaPython можно в старом руководстве от Ero Carrera или этой статье. Современная документация располагается здесь. Примеры скриптов есть на github. Кроме того много полезных примеров можно найти в блоге Ильфака.

Обход защиты

Первое на что мы натыкаемся – это шифрованные строки

str_1

Легко заметить процедуру шифрования, ксорящую каждую строку на 0xC6:

str_3

Ида позволяет нам загружать свои скрипты, для этого нажмём alt+f9 и выберем ‘insert’, указав путь до скрипта. Давайте посмотрим на код скрипта:

Скрипт получает виртуальный адрес на который мы последним кликнули мышкой и дешифрует строку во внутренний буфер. Недопустимые символы заменяются на нижнее подчеркивание.  Полученное имя назначается адресу начала строки:

str_2

Дешифровать непосредственно байты мне кажется плохим тоном

По началу и стилю кода можно понять что CrackMe писался на ассемблере. В коде присутствует динамическое вычисление адреса перехода и защита от отладки.

Начнём с IsDebuggerPresent. Для красоты решения, мы не будем патчить код CrakMe, а напишем скрипт, убирающий флаг IsDebugged из PEB, посмотрим на код:

Первая проблема с которой столкнуться обладатели x64 системы (при работе с x32 кодом), это подсистема WoW64. В адресном пространстве таких процессов существует две копии PEB в 32 и 64-битной версии. Мы перечисляем сегменты памяти в поисках TEB текущего потока. Если это x64 система, то и TEB будет иметь ссылки этой разрядности. Из TEB мы получаем ссылку на PEB.

И здесь будет немного магии. В адресном пространстве PEB64 всегда находится на расстоянии 0x1000 от PEB32. У меня нет внятного объяснения как это работает, но я нашел множество исходников подразумевающих это как данность.

Пора проверить скрипт в деле, кликаем в начало программы, нажимаем f4 и запускаем наш скрипт:

patched

Теперь отладчик стал чуть менее заметен.

Следующим рубежом обороны является встроенная в цикл обработки сообщений окна, проверка кода на наличие байт 0x90 = NOP и 0xCC = INT3:

msg

После установки бряка выбираем Edit BreakPoint -> Hardware и код приложения останется без изменений.

Защита повержена, но это далеко не конец, дальше нас ждёт:

Подбор ключа

Полистав оконную функцию находим место обработки сообщения WM_COMMAND:

button

Отсюда только трассировать, так что вбиваем произвольные данные и смотрим куда это приведёт. Ага, текст полей запрашивается через SendMessage(WM_GETTEXT). Функция возвращает длину текста и нам явно дают понять что ключ имеет 11 символов.

Имя юзера суммируется в один байт, и 2 раза делится на 9, к остаткам от деления прибавляется 0x30. Эти цифры должны быть в конкретном месте ключа. Это даёт нам две первые цифры.

summ

С паролем немного сложнее, по сходному алгоритму хешируется сам пароль, после чего два остатка от деления + 0x30 должны совпадать с цифрами в середине ключа.

Не знаю решается ли это математически, но хеширование в 1 символ даёт невероятно много коллизий, так что мы легко подберем пароль:

Как всё это работает? Что такое AppCall? Свежая IDA позволяет (во время отладки) вызывать ассемблерные функции из нашего скрипта! Нужно лишь задать правильный прототип, щёлкаем на функцию хеширования, нажимаем Y и вводим:

Теперь мы можем вызвать хеш-функцию прямо из скрипта! В силу слабого хеша, можно взять любые последние символы. Запускаем скрипт и вуаля:

cracked

FIN

Это было интересно! Спасибо автору CrackMe. Надеюсь пример работы с IdaPython получился достаточно познавательным. Возможно в следующем выпуске с IdaPython мы ещё встретимся =)

Добавить комментарий