Как стать автором
Обновить

Врайтап осеннего crackme от «Лаборатории Касперского»

Время на прочтение 3 мин
Количество просмотров 4.2K
Всем привет. Название говорит само за себя. Эвент был мало освещен и я лишь каким-то чудом сумел в нем поучаствовать. В результате, успел выхватить одиннадцатое место и получить право на обещанные дивиденды. Перейдем к делу.

Крякми. Или тут (привет из 2к17 если ссылка затерлась)

Инструменты: IDA, HxD, CFF Explorer, DbgView, PEChecksum, KmdManager
Последние три инструмента довольно специфичны, многие крекеры уже поняли в чем вся соль крякми.

После скачивания файла оказалось, что он не имеет расширения. В мою голову начали лезть пакостные мысли про то, что это очередная ctf чушь а-ля найди как меня использовать. Хекс листинг вернул меня в состояние атараксии:

Убрано под спойлер
image

Заветные сигнатуры Марка Збиковски оказались на месте, продолжаем анализ:

Убрано под спойлер
image

Вот это поворот — перед нами драйвер. Смело переименовываем крякми в crackme.sys. На сей раз в голову пришел вполне обоснованный вопрос: а где лоадер? Где гуй(graphical user interface, не подумайте ничего плохого)? Их нет. Буквально. Считаю это второй по значимости (хе-хе, до первой доберемся еще) нелогичностью крякми: так не бывает. Продолжаем анализ.

Вот так выглядит в драйвере ImageBase:

Убрано под спойлер
image

А вот так и настоящий DriverEntry:

Убрано под спойлер
image

Здесь стоит запомнить имя девайса и обратить внимание на то, что наш драйвер любезно обрабатывает юзермодный DeviceIoControl.

Вот так обработчик выглядит до ручной корректировки:

Убрано под спойлер
image

А вот так после сопоставления с асм листингом:

Убрано под спойлер
image

Что здесь происходит? Функция получает на вход некий буфер (я кст так и не разобрался, как его передать средством DeviceIoControl, пишите в комментарии) и некий контрольный код. Буфер, в зависимости от ControlCode, копируется в поле мейла или серийника (классная эмуляция гуя, че сказать). После заполнения этих полей мы в третий раз должны послать ControlCode и в результате запустится некая функция Validate, на основании которой выведется то или иное сообщение.

Бывалый крякер пропатчил бы это дело и запустил в релиз, да только нам необходимо найти серийник к нашему мейлу. Готовимся к самому худшему и переходим к заветной функции Validate:

Убрано под спойлер
image

Асм листинг ее самого интимного момента:

Убрано под спойлер
image

После валидации полученных параметров она высчитывает хеш от некой строки-константы, хеш от входного buf1 (нашего мейла, это очевидно) и общий хеш от этих двух строк.

Как выглядит функция func1? Страшно и ужасно (на самом деле не очень). Внутри нее находится еще функции 4, которые что-то делают со входящей строкой: заполняют, копируют, модифицируют и тд.

Стоит вспомнить, что в func1 мы не передаем ничего, что было бы связано с buf2 (очевидно, это наш серийник). А что делает крякер, когда видит некую хеш функцию от мейла, в которую не передается ничего связанного с серийником, а прямо после этого прелестное сочетание:

xor eax, eax
repe cmpsb
setz al
ret

Конечно! Он летит как кама пуля идет ставить бряк после вызова этой функции, тк возвращаемая строка и есть наш серийник (самая большая проблема любого крякми — банальный strcmp). Но тут есть пару но:

  1. Нам необходимо правильно инициализировать вызов функции Validate через серию обращений к драйверу (ну или ручками вызвать + пропатчить память)
  2. Обычный отладчик архетипа «Оля» для ring0 не подходит — необходимо использовать инструменты помощнее

Как бы я ни старался, но мой VirtualBox с накатанной сверху xp sp3 отказался принимать Syser/SoftICE/WinDbg. Появилась идея: почему бы не заставить драйвер любезно сообщать нам серийник? Как это можно сделать?

Для начала патчим проверки на валидность входящих данных внутри Validate:

Убрано под спойлер
image

Просто затираем их nop`ами.

Затем необходимо вручную заполнить буфер с мылом (он выделяется динамически), делаем это, скажем, в самом начале функции Validate. Было так:

Убрано под спойлер
image

Стало так:

Убрано под спойлер
image

Те был выпилен динамический подсчет длины мейла и все, что связано с buf2.

Теперь пропатчим самый конец функции и вместо исполнения repe cmpsb впихнем вызов DbgPrint:

Убрано под спойлер
image

После патчинга необходимо пересчитать поле CheckSum драйвера — для этого используем утилиту PEChecksum. Затем загружаем драйвер с помощью KmdManager (для загрузки x32 драйвера вы обязаны иметь x32 систему, желательно, xp), открываем DebugView. Далее осталось написать небольшую программу для вызова драйвера:

char tmp[0x100];

HANDLE handle = CreateFile(L"\\\\.\\crackme", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
DeviceIoControl(handle, 0x222408, 0, 0, &tmp, 0x100, &tmp, 0);
CloseHandle(handle);

Компилируем, запускаем:

Убрано под спойлер
image

Первая строка является искомым серийником. На этом прощаюсь.
NOTE: Решение опубликовал сразу после того, как задание выполнили первые пятнадцать участников конкурса. Необходимо уважать честную конкуренцию.
Теги:
Хабы:
+4
Комментарии 5
Комментарии Комментарии 5

Публикации

Истории

Работа

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн