Как известно, важной частью борьбы с киберугрозами является исследование вредоносных файлов, чем у нас занимаются вирусные аналитики — отважные парни (и девушки!) из Anti-Malware Team. На основании своего опыта они регулярно создают специальные тренажеры, CrackMe, которые начинающие аналитики могут использовать для проверки своих знаний.
Не так давно, мы анонсировали конкурс CrackMe, проходивший в рамках event-платформы CoLaboratory. Теперь, когда конкурс завершился и все решения приняты, мы можем рассмотреть задачи подробнее.
ВНИМАНИЕ: Если вы не успели поучаствовать в конкурсе, но тем не менее хотите попробовать свои силы — не читайте информацию под катом. Там мы описываем алгоритм решения задания. Скачать свежие задачи CrackMe можно здесь.
Решение CRACKME#1
Итак, зимний CRACKME#1 от Лаборатории Касперского. При запуске файла нас приветствует вот такое незамысловатое окошко с требованием ввести данные для решения.
Требуется ввести e-mail, под которым вы регистрировались на сайте и подобрать для него ключ. При вводе неверного значения окошко ругается – придется решать.
Для нашего увлекательного исследования мы будем использовать (барабанная дробь!) всего лишь IDA Pro, вот настолько все просто.
В итоге мы видим вполне стандартную картину для оконного приложения. Перед нами фрагмент WinMain, который и делает всю магию. Функция DialogBoxParamW принимает в качестве входных параметров бла-бла-бла. Думаю излишне повторять документацию, поэтому просто переходим на адрес, по которому содержится функция, которая будет что-то делать, если мы нажмем кнопку «Check».
Чтобы понять, насколько все просто, посмотрите на рисунок выше, где отображена та самая магическая функция. На самом деле это просто нагромождение кода, который показывает нам сообщение «Serial is invalid», если мы вводим некорректные данные. Изобилие же стандартных названий различных структур, к примеру «ms_exc.registration.TryLevel» наталкивает на мысль, что Crackme написан на C++, именно так с изнанки выглядит конструкция (try-catch) и скорее всего именно обращениями к этой структуре будет окружен код, который производит манипуляции с входными данными.
Если параллельно с чтением, вы следили за ходом мысли в окне IDA, то, вероятно, вы уже нашли нужное нам место.
Переходим на единственную функцию между обращениями к «ms_exc.registration.TryLevel» и вуаля — мы на главной функции, которая определяет, верно или не верно мы нашли ключ для нашей почты.
Для концентрации внимания и красивого отображения вершины графа сгруппированы на рисунке выше, чтобы было видно какая часть за что отвечает. Обычная конструкция if-else.
Сосредоточимся на вершине графа «GetText And Check». Единственное, на что мы обратим внимание из этого сгруппированного блока, это вот этот кусочек листинга.
Если внимательно посмотреть на команды, которые есть выше, то мы увидим, что полученные поля EMail и Serial сохраняются в памяти. На картинке же выше приведены команды, которые заносят адреса полученных данных в регистры ECX и EDX соответственно. А дальше начинается проверка, собственно, это ее граф и изображен ниже.
Впечатляет, но огромный размер графа с многочисленными ветвлениями может быть просто способом запутать код мусорными командами. Поэтому не расстраиваемся, берем лопату и идем искать клад.
Начинаем просеивать «грунт». Сразу бросается в глаза большое количество команд от адреса 0040DC00 до 0040DC86, которые, на первый взгляд делают что-то математически важное для проверки нашего ключа. Однако, если присмотреться пристальнее, то можно понять, что это пары команд, которые компенсируют действия друг друга. Весь диапазон можно представить, как одну большую nop-команду, пропускаем её. Берем следующий наполненный смыслом модуль. Код, который содержится в этом модуле, не распознался как стандартный, но все операции, проводимые им, просто переводят строки между Wide string в просто string.
Для удобства переименуем вызываемые функции, а разбор внутренностей оставим для особенно любознательных читателей. Особое внимание обратим только на функцию с условным названием «Md5». Почему мы так ее назвали? Заглянем внутрь и, чтобы не перегружать статью картинками и объяснениями каждой строчки листинга, посмотрим только на нужный кусок.
Код достаточно прямолинеен, поэтому, чтобы понять, что происходит, достаточно просто прочитать названия WinApi функций. На картинке вы видите блок, из которого мы можем определить, ЧТО за алгоритм вообще реализован этой функцией. Порывшись в официальной документации, находим значение 8003h для константы «CALG_MD5». Комментарии излишни.
Обратимся к следующему модулю.
Он содержит в себе цикл. Из него видно, что цикл итерирует над последовательностью данных в памяти при помощи двух переменных, значения которых имеют отступ друг от друга в 16 позиций. Над каждым элементом последовательности производится операция XOR с элементом, отстоящим от него на 16 символов. От полученного результата вычисляется MD5 сумма.
Следующий модуль для рассмотрения выглядит так:
Модуль производит сравнение двух переменных, замусорен командами, в конце сравнивает значения переменной и значение регистра ebx (условие сравнения длин последовательностей?). В итоге производится переход на цикл, который представлен в модуле на картинке ниже. Он на последовательности из 16 символов производит сравнение, увеличивая счетчик на единицу при совпадении и уменьшая на единицу в противном случае. (Это операция сравнения полученного Serial с исходным, который был вычислен и хранился в памяти).
После Этого цикла происходит инициализация, и мы видим зеркальный цикл, который начинается не с нуля, а с 16-го символа. Рисунок представлен ниже.
После обработки в цикле последовательности, среди замусоренного кода и стандартных процедур, есть модуль, который принимает решение, на основании сравнения двух переменных. Не стоит даже сильно вчитываться в дизассемблированный код. Это сравнение совпадений двух строк Serial и вычисленного значения на основании введенной почты. Рисунок модуля представлен ниже.
Чтобы проверить результаты нашего исследования, попробуем провести сами манипуляции над введенным адресом электронной почты:
1. получим Md5 сумму от адреса;
2. разделим пополам полученную сумму и произведем операцию xor,
3. снова вычислим Md5 от результата.
В качестве подопытной почты была использована: sam@kakoitodomen.com
В качестве Serial была использована: BB23F6DFA9375ED119237AAC4DE31BCD
Результат на картинке ниже
Вот такой простой CRACKME.
Решение CRACKME#2
Во втором крекми нам дан бинарный файл (PE 32-bit). И снова требуется подобрать корректный Serial под EMail.
Для начала открываем этот файл в вышеупомянутой IDA. Также полезно при анализе пользоваться Hex-Rays (удобный декомпилятор, который поддерживает множество архитектур).
Мы можем найти место, в котором происходит проверка серийника.
По адресу 40E960 (не учитывая ASLR) находится проверочная функция.
В начале можно увидеть, что e-mail сжимается до размера 22 байта путём xor всех символов, чьи позиции равны по модулю 22. В случае нехватки расширяется нулевыми байтами.
Затем проверяется, что серийник находится в шестнадцатеричной системе счисления, он переводится в байты и над ним также проводится операция xor с адресом почты.
Дальше происходит проверка, что получившаяся xor-сумма удовлетворяет СЛАУ, в которой используются ASCII коды символов некоторого внутреннего секретного значения.
Уравнений в СЛАУ много, поэтому необходимо рассмотреть некоторый способ автоматического решения. Для этого можно воспользоваться системой компьютерной математики (например NumPy), либо так называемым SMT-решателем z3, который мгновенно находит решение. Также СЛАУ можно попробовать решать с помощью фреймворка angr, который уже содержит внутри себя z3.
В авторском решении используется z3. Но не стоит забывать, что любую СЛАУ можно решить на бумажке методом Гаусса, надо просто постараться.
Решив СЛАУ, мы получаем секретное значение «KL_F4n7a5tiC_chAl1eN63», которому и должен быть равен данный xor всего со всем.
Пример:
EMail: sample@kaspersky.com
Serial: 382d3236580b770a540719262d10033842520a233633
Ну вот и всё. Мы с вами разобрали две из трех CrackMe зимнего сезона от «Лаборатории Касперского». Но всех секретов раскрывать не будем. Вполне вероятно что третьий CrackMe мы будем использовать в качестве тестовой задачи и дальше. Так что, если захотите сделать карьеру вирусного аналитика — попробуйте решить его самостоятельно.
Больше CrackMe, вечерних встреч, хакатонов и других событий уже скоро на нашем сайте. Присоединяйтесь!
Автор: «Лаборатория Касперского»