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

- такой же как Forbes, только лучше.

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

Крякми. Или тут (привет из 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: Решение опубликовал сразу после того, как задание выполнили первые пятнадцать участников конкурса. Необходимо уважать честную конкуренцию.

Вы можете помочь и перевести немного средств на развитие сайта



Комментарии (5):

  1. REPISOT
    /#10471808 / +1

    Что такое врайтап? Имелось в виду write-up? там нет буквы «В» (Write брит. |r??t|)
    Тут недавно была статья с подборкой ресурсов для изучения английского. Вам бы не помешало.

    • unc1e
      /#10471816

      Наверняка вы правы, спасибо

  2. fryday
    /#10472850

    Очень сложно =)
    Как решал я:
    1) Находим в хэш функции константы
    2) Гуглим. Узнаем, что это md5
    3)

    Заголовок спойлера
    serial = md5(md5(email) || md5(const_str))

    • unc1e
      /#10472868

      Если не секрет, откуда вы узнали про крякми? Я пытался найти зимний крякми от лк, перешел по ссылке, а там проводится новый эвент уже.

      • fryday
        /#10473244

        Попал на Kaspersky Open Day -> заполнил опросник на SurveyMonkey -> в нем была ссылка на кряку