Решение задач зимнего CrackMe

в 15:39, , рубрики: information security, kaspersky lab, reverse engineering, Блог компании «Лаборатория Касперского», для начинающих, информационная безопасность, реверс-инжиниринг

Как известно, важной частью борьбы с киберугрозами является исследование вредоносных файлов, чем у нас занимаются вирусные аналитики — отважные парни (и девушки!) из Anti-Malware Team. На основании своего опыта они регулярно создают специальные тренажеры, CrackMe, которые начинающие аналитики могут использовать для проверки своих знаний.

Не так давно, мы анонсировали конкурс CrackMe, проходивший в рамках event-платформы CoLaboratory. Теперь, когда конкурс завершился и все решения приняты, мы можем рассмотреть задачи подробнее.

image

ВНИМАНИЕ: Если вы не успели поучаствовать в конкурсе, но тем не менее хотите попробовать свои силы — не читайте информацию под катом. Там мы описываем алгоритм решения задания. Скачать свежие задачи CrackMe можно здесь.

Решение CRACKME#1

Итак, зимний CRACKME#1 от Лаборатории Касперского. При запуске файла нас приветствует вот такое незамысловатое окошко с требованием ввести данные для решения.

image

Требуется ввести e-mail, под которым вы регистрировались на сайте и подобрать для него ключ. При вводе неверного значения окошко ругается – придется решать.

image

Для нашего увлекательного исследования мы будем использовать (барабанная дробь!) всего лишь IDA Pro, вот настолько все просто.

image

В итоге мы видим вполне стандартную картину для оконного приложения. Перед нами фрагмент WinMain, который и делает всю магию. Функция DialogBoxParamW принимает в качестве входных параметров бла-бла-бла. Думаю излишне повторять документацию, поэтому просто переходим на адрес, по которому содержится функция, которая будет что-то делать, если мы нажмем кнопку «Check».

image

Чтобы понять, насколько все просто, посмотрите на рисунок выше, где отображена та самая магическая функция. На самом деле это просто нагромождение кода, который показывает нам сообщение «Serial is invalid», если мы вводим некорректные данные. Изобилие же стандартных названий различных структур, к примеру «ms_exc.registration.TryLevel» наталкивает на мысль, что Crackme написан на C++, именно так с изнанки выглядит конструкция (try-catch) и скорее всего именно обращениями к этой структуре будет окружен код, который производит манипуляции с входными данными.

Если параллельно с чтением, вы следили за ходом мысли в окне IDA, то, вероятно, вы уже нашли нужное нам место.

image

Переходим на единственную функцию между обращениями к «ms_exc.registration.TryLevel» и вуаля — мы на главной функции, которая определяет, верно или не верно мы нашли ключ для нашей почты.

image

Для концентрации внимания и красивого отображения вершины графа сгруппированы на рисунке выше, чтобы было видно какая часть за что отвечает. Обычная конструкция if-else.

Сосредоточимся на вершине графа «GetText And Check». Единственное, на что мы обратим внимание из этого сгруппированного блока, это вот этот кусочек листинга.

image

Если внимательно посмотреть на команды, которые есть выше, то мы увидим, что полученные поля EMail и Serial сохраняются в памяти. На картинке же выше приведены команды, которые заносят адреса полученных данных в регистры ECX и EDX соответственно. А дальше начинается проверка, собственно, это ее граф и изображен ниже.

image

Впечатляет, но огромный размер графа с многочисленными ветвлениями может быть просто способом запутать код мусорными командами. Поэтому не расстраиваемся, берем лопату и идем искать клад.

Начинаем просеивать «грунт». Сразу бросается в глаза большое количество команд от адреса 0040DC00 до 0040DC86, которые, на первый взгляд делают что-то математически важное для проверки нашего ключа. Однако, если присмотреться пристальнее, то можно понять, что это пары команд, которые компенсируют действия друг друга. Весь диапазон можно представить, как одну большую nop-команду, пропускаем её. Берем следующий наполненный смыслом модуль. Код, который содержится в этом модуле, не распознался как стандартный, но все операции, проводимые им, просто переводят строки между Wide string в просто string.

image

Для удобства переименуем вызываемые функции, а разбор внутренностей оставим для особенно любознательных читателей. Особое внимание обратим только на функцию с условным названием «Md5». Почему мы так ее назвали? Заглянем внутрь и, чтобы не перегружать статью картинками и объяснениями каждой строчки листинга, посмотрим только на нужный кусок.

image

Код достаточно прямолинеен, поэтому, чтобы понять, что происходит, достаточно просто прочитать названия WinApi функций. На картинке вы видите блок, из которого мы можем определить, ЧТО за алгоритм вообще реализован этой функцией. Порывшись в официальной документации, находим значение 8003h для константы «CALG_MD5». Комментарии излишни.
Обратимся к следующему модулю.

image

Он содержит в себе цикл. Из него видно, что цикл итерирует над последовательностью данных в памяти при помощи двух переменных, значения которых имеют отступ друг от друга в 16 позиций. Над каждым элементом последовательности производится операция XOR с элементом, отстоящим от него на 16 символов. От полученного результата вычисляется MD5 сумма.

Следующий модуль для рассмотрения выглядит так:

image

Модуль производит сравнение двух переменных, замусорен командами, в конце сравнивает значения переменной и значение регистра ebx (условие сравнения длин последовательностей?). В итоге производится переход на цикл, который представлен в модуле на картинке ниже. Он на последовательности из 16 символов производит сравнение, увеличивая счетчик на единицу при совпадении и уменьшая на единицу в противном случае. (Это операция сравнения полученного Serial с исходным, который был вычислен и хранился в памяти).

image

После Этого цикла происходит инициализация, и мы видим зеркальный цикл, который начинается не с нуля, а с 16-го символа. Рисунок представлен ниже.

image

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

image

Чтобы проверить результаты нашего исследования, попробуем провести сами манипуляции над введенным адресом электронной почты:

1. получим Md5 сумму от адреса;
2. разделим пополам полученную сумму и произведем операцию xor,
3. снова вычислим Md5 от результата.

В качестве подопытной почты была использована: sam@kakoitodomen.com
В качестве Serial была использована: BB23F6DFA9375ED119237AAC4DE31BCD

Результат на картинке ниже

image

Вот такой простой CRACKME.

Решение CRACKME#2

Во втором крекми нам дан бинарный файл (PE 32-bit). И снова требуется подобрать корректный Serial под EMail.

image

Для начала открываем этот файл в вышеупомянутой IDA. Также полезно при анализе пользоваться Hex-Rays (удобный декомпилятор, который поддерживает множество архитектур).

Мы можем найти место, в котором происходит проверка серийника.

image

По адресу 40E960 (не учитывая ASLR) находится проверочная функция.

image

В начале можно увидеть, что e-mail сжимается до размера 22 байта путём xor всех символов, чьи позиции равны по модулю 22. В случае нехватки расширяется нулевыми байтами.

image

Затем проверяется, что серийник находится в шестнадцатеричной системе счисления, он переводится в байты и над ним также проводится операция xor с адресом почты.

image

image

image

Дальше происходит проверка, что получившаяся xor-сумма удовлетворяет СЛАУ, в которой используются ASCII коды символов некоторого внутреннего секретного значения.

image

image

Уравнений в СЛАУ много, поэтому необходимо рассмотреть некоторый способ автоматического решения. Для этого можно воспользоваться системой компьютерной математики (например NumPy), либо так называемым SMT-решателем z3, который мгновенно находит решение. Также СЛАУ можно попробовать решать с помощью фреймворка angr, который уже содержит внутри себя z3.

В авторском решении используется z3. Но не стоит забывать, что любую СЛАУ можно решить на бумажке методом Гаусса, надо просто постараться.

Решив СЛАУ, мы получаем секретное значение «KL_F4n7a5tiC_chAl1eN63», которому и должен быть равен данный xor всего со всем.

Пример:

EMail: sample@kaspersky.com
Serial: 382d3236580b770a540719262d10033842520a233633

image

Ну вот и всё. Мы с вами разобрали две из трех CrackMe зимнего сезона от «Лаборатории Касперского». Но всех секретов раскрывать не будем. Вполне вероятно что третьий CrackMe мы будем использовать в качестве тестовой задачи и дальше. Так что, если захотите сделать карьеру вирусного аналитика — попробуйте решить его самостоятельно.

Больше CrackMe, вечерних встреч, хакатонов и других событий уже скоро на нашем сайте. Присоединяйтесь!

Автор: «Лаборатория Касперского»

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js