R0 CREW

CrackMe by Fereter #2[разбор и написание KeyGen]

В этой статье мы рассмотрим решение CrackMe by Fereter #2. Скачать его можно здесь.
Не беря во внимание названия файла, фактически - это КейГенМи.

Уровень: Для начинающих.

Используемые инструменты:

  • IDA Pro как дизассемблер и деббагер.
  • х64dbg
  • плагин Labeless(импортирует метки и имена с IDA Pro в х64dbg)
    Задача: найти и разобрать алгоритм валидации пары Name : Serial key и написать Генератор Ключей.

Посмотрим на сам КрекМи:

Базовый статистический анализ с помощью PEview и Peid ничего интересного не показал.
Загружаем в IDA Pro и начнем углубленный статический анализ и динамический анализ.

1. Анализируем строки

В окне программы мы видим следующие строки:
«CrackMe by Fereter #2», «Name», «Serial key», «Unregistered», «Check», «Exit»
В IDA Pro в закладке String window(View>Open subviews>Strings) видим только:
«Made in Russia»

Можно сделать предположение, что программа содержит строки GUI-окна в зашифрованном виде - в процессе работы их расшифровывает.
Если начать деббажить та увидим, что перед началом каждого WinApi вызова, который берет на вход строку как один из аргументов, вызывается sub_402590 , а после выполнения WinApi_вызова, вызывается sub_40257E, ниже на рисунке пример

Проанализируем, что это за функции.

Это функции XOR расшифровывания и зашифровывания строк, в который в качестве ключа используется байтовое значение C6h, а указатель на строку передается в функции через регистр EAX
Переименовываем эти функции соответственно какXorDecode и XorEncode.
Дальше-больше, локализуем и расшифруем строки которые использует XorDecode.
Сначала смотрим адреса, где XorDecode вызывается (IDA Pro > переходим на листинг XorDecode > Правый клик мыши > List crossreferences to…)

Смотрим адреса которые XorDecode использует в качестве аргумента передаваемого через регистр EAX - все они находятся в диапазоне 00401000 - 00401073

Посмотрим на них в HEX-редакторе

Можно наблюдать, что очень часто встречается байт C6h, который равен нашему ключу шифрования с функций XorDecode и XorEncode что говорит о том что перед нами зашифрованы массив ноль-терминированных(NULL-terminated) строк, так как C6h XOR 00h = C6h.

Теперь расшифровываем, чтобы посмотреть содержимое этого массива и сформировать массивы и присвоить им имена в IDA Pro. Для этого используем XOR idc script отсюда:

В итоге было:

То что мы сделали после расшифровки:

Теперь снова зашифруем (ведь наша цель была сформировать структуры данных(строки) и присвоить им имена отражающие их содержимое, а не изменять бинарный файл)

В итоге видим полный набор строк которые использует программа.

2. Анализируем функции

В начале недалеко от start видим RegisterClassA вызов, который берет на вход структуру WNDCLASS

Рассмотрим эту структуру:

Видим offset sub_4021B7 - это WNDPROC lpfnWndProc (см.MSDN) обработчик сообщений посылаемых окну
Благополучно переименовываем sub_4021B7 на fnWndProc.
Из оставшихся функции с наскока можно понять, что делает sub_40254A

Подсчитывает 8-битную контрольную суму строки, указатель на которую содержится в регистре EBX, и результат сохраняет в регистре DL. Переименовываем sub_40254A на ByteControlSumm.
А также sub_4025A2

Переименовываем sub_4025A2 на ClearEAX.

В итоги имеем следующее окно функций

3. Анализируем поток программы

функция start как и в любой другой GUI-программе содержит Message Loop, в который вставлены некоторые средства анти-отладки:

В 1-ом и 3-ем случае сканирование в цикле кода на наличие INT3(0xCC), во 2-ом на наличие NOP(0x90). Думаю элегантным решением будет заменить на NOP-ы инструкции условного переход jz (short)end_program
В итоге получаем:

Есть одно средство анти-деббагина, которое обходиться любым плагином типа IDAStealth, ScyllaHide

Ура, товарищи!, мы обошли средства анти-деббагинга.

4. Анализируем нашу функцию-обработчик сообщений(ивентов) fnWndProc

Первая проверка сравнивает аргумент MSG с единицей(1==WM_CREATE). Далее ветвление направо на блок создания GUI окна программы. Все что нам нужно с этого блока - это идентификатор кнопки «CHECK». А вот и он

Ветвление на лево ведет нас к блоку, где сравнивается аргумент MSG с 111h (111h==WM_COMMAND) - это то, куда мы двигаемся далее loc_4023F2

Вот тут и начинается обработка нашего нажатия на кнопку «Check»

5. Анализируем нашу обработку нажатия на кнопку «Check»

анализируем sub_402557 видим, что фактически это обертка функции SendMessageA. Переименовываем ее как SendMessageAWrapper.

Видим как извлекается ввод полей Name, Serial key.
И, внимание, проверка № 1 сравнивается длина ввода поля Serial key с числом 11.
Если не равно, то осуществляется прыжок на loc_40253А(это епилог(окончание) функции fnWndProc)

Далее идут проверки на соответствие введенного имени и серийного ключа. Рассмотрим их.

проверка № 2 - см. псевдокод на рисунке выше
проверка № 3 - см. псевдокод на рисунке выше
Следующий блок:

проверка № 4 - см. псевдокод на рисунке выше
проверка № 5 - см. псевдокод на рисунке выше

Теперь рассмотрим sub_402541 что это за зверь такой?
Это зверь в середине себя содержит две проверки.
uint8_t serialKeyControlSumm= ByteControlSumm(serialKey); # см. предпоследний рисунок
проверка № 6: # см. последний рисунок
if ( serialKeyFieldInput[6] == serialKeyControlSumm/9%9 + 30h)
проверка № 7: # см. последний рисунок
if ( serialKeyFieldInput[5] == serialKeyControlSumm%9 + 30h)

И вот финал.

Алгоритм валидации пары Name : Serial key на псевдокоде выглядит так:

var name;
var serialKey;
var nameControlSumm;
var serialKeyControlSumm;

GetInput(name);
GetInput(serialKey);

nameControlSumm = ByteControlSumm(Name);
serialKeyControlSumm = ByteControlSumm(serialKey);

if( serialKey.length == 11
[INDENT]&& serialKey[0] == NameControlSumm%9 + 30h[/INDENT]
[INDENT]&& serialKey[1] == NameControlSumm/9%9 + 30h[/INDENT]
[INDENT]&& serialKey[3] == ‘-’ [/INDENT]
[INDENT]&& serialKey[7] == ‘-’[/INDENT]
[INDENT]&& serialKey[5] == serialKeyControlSumm%9 + 30h[/INDENT]
[INDENT]&& serialKey[6] == serialKeyControlSumm/9%9 + 30h[/INDENT]
) {
[INDENT]Registered();[/INDENT]
} else {
[INDENT]Unregistered();[/INDENT]
}

P.S.: Исходники самого КейГен(уже готов) - приведу в красивый вид и выложу в ближайшее время

P.P.S.: Комментарии, замечания, вопросы, предложения приветствуются,
возможно, вы бы делали что-то иначе - в общем прошу комментировать

исходный код Генератора Серийников