Разбор простого криптографического keygenme

в 17:25, , рубрики: keygenme, ollydbg, ассемблер, метки: , , ,

Привет, хабрахабр.

Листая одним декабрьским вечером различные хабы, я заметил, что нигде давненько не бывало статей о реверсинге. А разборов crackme/keygenme – и подавно. И вдруг меня осенило: почему бы не написать свой туториал?

Разбор простого криптографического keygenme

Тех, кого интересует разбор простенького криптографического keygenme и что же в итоге получилось, прошу под кат.

Сегодня мы будем препарировать keygenme под названием «The XOR Algorithm» авторства Ksydfius. Найти данный keygenme вы можете на сайте crackmes.de или здесь.

Дано:
-Текст, шифрованный правильным ключем.
-Тот же текст, но не зашифрованный.
-Патчинг и брутофорс запрещены и бессмысленны.

В итоге мы должны получить какое-то секретное сообщение.

Необходимый инструментарий: OllyDBG или любой другой отладчик.

Давайте же приступим непосредственно к разбору. Открываем keygenme в Олли и останавливаемся на точке входа.

Разбор простого криптографического keygenme

А сейчас необходимо немного осмотреться. Ознакомимся с импортируемыми функциями – благо, в данном файле их не так уж и много. Ставим точки останова на интересующую нас функцию, которая забирает введенный текст из поля – GetDlgItemTextA.

Разбор простого криптографического keygenme

Жмем F9 и перед нами появляется главное окошко пациента. В поле «K E Y» вбиваем все, что душе угодно (я взял слово hello) и жмем ОК.

Разбор простого криптографического keygenme

Далее сработает бряк на нужной нам функции. Нажимаем Ctrl+F9 и останавливаемся на выходе из функции. Сразу после GetDlgItemTextA, которая забирает введенный ключ, следует вызов другой функции. Нажимаем F7 и попадаем в нее.

Разбор простого криптографического keygenme

Продолжаем трассировать, пока не доходим до следующего участка:

CMP EAX,20		;20h=32d
JNZ SHORT 00401075		;RETN->ExitProcess

Несколько нажатий F8 и keygenme покидает нас. Что ж, давайте заглянем, куда ведет jnz. Сначала он ведет на команду выхода из функции (RETN), а затем происходит сравнение длины введенного ключа и числа 20h, которые в нашем случае не равны. Потом следует jnz, ведущий на функцию ExitProcess, которая и завершает процесс нашего keygenme.

Хорошо, перезапустим keygenme и введем произвольную строку из 32 символов, я взял такую — 12345678901234567890123456789012. На этот раз мы успешно проходим сравнение и входим в новую функцию.

Разбор простого криптографического keygenme

А здесь и происходит чуть ли не самые важные действия во всем keygenme. В EDI перемещается заранее приготовленный незашифрованный текст, а в ESI – введенный ключ.

Разбор простого криптографического keygenme

Затем к ESI прибавляется значение EDX. Зачем это сделано, я расскажу немного ниже. Затем один байт длинной строки xor'ится с байтом из ключа. К xor'енному значению прибавляется значение EDX, а потом все это вдобавок прибавляется к значению нижнего регистра BL.

После всех этих ивзращений вызывается функция (CALL 00401000), которая перемещает значение EBX, т.е результат работы предидущей процедуры, в EAX, регистру EBX присваивается значение 20h и EAX делится на EBX. В конце функции EBX обнуляется.

Разбор простого криптографического keygenme

Затем все то же самое происходит со последующими байтами незашифрованного текста из EDI, пока текст не зашифруется. Однако, с ключем все несколько интереснее. Помните, я обещал рассказать, почему к ESI прибавляется EDX? Дело в том, что в регистре EDX хранится остаток деления EAX и EBX из функции 00401000. Этот остаток прибавляется к регистру ESI, который содержит введенный ключ. Значит, остаток является номером байта из введенного нами ключа, который будет xor'ится со следующим байтом из EDI.

Пример-картинка, показывающая исполнение первого и второго цикла этой функции:

Разбор простого криптографического keygenme

Во время первого цикла EDX = 00000000, поэтому программа использовала первый байт ключа. Во время второго цикла EDX = 00000006, значит программа использовала 7 (1+6) байт ключа.

Ладно, едем дальше. Ставим бряк на выход из процедуры (RETN) по адресу 0x00401079 и нажимаем F9. Останавливаемся на выходе из процедуры с уже шифрованным текстом.

Далее мы видим такую картину:

Разбор простого криптографического keygenme

После выхода из главной процедуры очищаются регистры EAX, EBX, ECX и EDX. В ESI помещается строка, зашифрованная с помощью нашего неверного ключа, а в EDI помещается та же строка, только зашифрованная с правильным ключем. Затем в подрегистр AL помещается байт из ESI, в подрегистр СL соответственно помещается байт из EDI. Далее происходит сравнение байтов из CL и AL, и если они равны, то нас отправляют на процедуру расшифровки сообщения (Скажу по секрету, что там происходит то же самое, что и в главной процедуре, только xor'ятся правильный ключ и зашифрованное сообщение). Но т.к. в нашем случае данные подрегистры не равны, отлаживаемый процесс вылетает.

Теперь разберемся, как же генерируется серийник. Псевдоуравнение:

Байт правильно зашифрованного текста = (Байт незашифрованногог текста) xor ((байт ключа[предыдущий байт mod 20h]) + (предыдущий байт ключа mod 32)).

Давайте обозначим все это через переменные для лучшей читаемости и понимания:

Байт незашифрованного текста= s
Байт ключа = х
Предыдущий правильно зашифрованный байт mod 20h = y

Новое уравнение:

Байт правильно зашифрованного текста = s xor (x[y] + y)

Т.к. нас интересует x[y], давайте выразим его через другие переменные:

x[y] = s xor (Байт правильно зашифрованного текста– y)

Для примера вычислим пару первых байтов:
x[1] = 57 xor (3 — 0) = 54h. Смотрим в таблицу ASCII, это знак «T»
y = 3 mod 20 = 3
x[1+3] = 65 xor (50 – 3) = 28h. А это уже знак "(".
И так далее, пока все 32 элемента строки не будут заполнены.

Что ж, теперь можно и свой кейген написать. Предлагаю ознакомиться с моим решением (сорри за Delphi, но это было быстрее всего). Вы можете скачать исполняемый файл отсюда, а исходники посмотреть здесь.

Итак, в последний раз открываем многострадальную тушку нашего подопытного кролика, копируем ключ из кейгена, нажимаем кнопку ОК, созерцаем MessageBox с поздравлениями, радуемся.

Разбор простого криптографического keygenme

Вот и все. Спасибо за прочтение, надеюсь, это было достаточно весело и познавательно.

Автор: Bernd

Источник

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


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