Крякаем программу без лёгких путей (ну, почти)
Сегодня мы в образовательных целях обойдём проверку лицензии в программе [УДАЛЕНО].
Эта статья не является руководством к действию, автор всячески осуждает использование нелицензионных копий программ, все описанные действия производятся с целью понять идеи и принципы, лежащие в основе ПО, и прочая, и прочая.
…более того, кряки описываемой здесь неназванной программы широко доступны в Интернете, поэтому сведения из этой статьи никакой ценности, кроме образовательной, не несут.
Покончив с (само)успокоительными увещеваниями, приступим к сути.
У нас есть программа, которая даёт пробный период в 100 дней, после чего выводит в интерфейсе грустную рожицу. Нам необходимо как-то убедить её в том, что мы обладаем лицензией.
Сразу становится ясно, что проверка лицензии происходит онлайн - тому свидетельствуют опция “Activate via web browser”, а также ошибка, возникающая при неверном ключе активации: “Server says error; ERROR: INCORRECT LICENSE KEY”.
В WinAPI за взаимодействие с Интернет-ресурсами отвечают функции из
wininet.dll, такие как InternetOpenW,
InternetOpenUrlW и InternetReadFile.
Действительно, такие импорты в программе присутствуют, и, поставив на
них бряки, мы видим рутину, совершенно явным образом обращающуюся к
серверу за подтверждением лицензии:
URL составляется из частей и выглядит так:
https://[УДАЛЕНО]/activate.php?a=38c6cbd28bf16507[...]cb4b439f1046c193&b=1&all=1
Очевидно, параметр a здесь - это некий хэш нашего
ключа.
В ответ на заведомо неверный ключ сервер отвечает сообщением об ошибке:
Чуть далее по коду идёт проверка длины возвращённого сервером
значения - если оно меньше 128, то интерпретируется, как ошибка и
выводится практически в неизменённом виде в месседжбоксе. Если же оно
равно 128, то записываем его в реестр в
HKLM\SOFTWARE\[УДАЛЕНО]\License 1, в
параметр ActivationData.
Итак, очевидно, что значение длиной 128 символов, полученное от сервера и записанное в реестр, каким-то образом удостоверяет наличие у нас лицензии. Нам необходимо найти код, который читает это значение, и либо пропатчить его, либо разгадать логику его проверки.
Используя Process Monitor, отфильтруем события реестра,
сгенерированные [УДАЛЕНО]Cfg.exe, и найдём среди них чтение
значения ActivationData. Procmon также способен показать
стек вызовов на тот момент:
Видим, что значение реестра читается функцией
Ordinal_102 динамической библиотеки
[УДАЛЕНО]X64.dll. Вот как она выглядит:
Видим, что прочитанное значение передаётся на вход другой функции (я
подписал её activationCheck). Внутри неё оно шифруется
функциями из bcrypt.dll и сравнивается с другим значением,
каким-то образом вычисляемым из другого значения реестра,
LicenseHash. Нам, впрочем, не очень интересен конкретный
алгоритм проверки, так как всё, что необходимо для её обхода - это
ненулевое значение на выходе Ordinal_102:

Ленивый способ кряка - это пропатчить либо
[УДАЛЕНО]X64!Ordinal_102, либо вызывающую его функцию. Но я
не ищу лёгких путей, а поэтому сначала попытался решить проблему
хукингом.
Я написал свою DLL-библиотеку, которая перенаправляет все вызовы, кроме Ordinal_102, в оригинальную библиотеку, загружаемую динамически. Что касается Ordinal_102 - во всех случаях, где она используется, идёт проверка двух вещей - возвращаемого значения и значения указателя, который ей передаётся при вызове; для успешного прохождения проверки эти значения должны быть ненулевыми:
Впрочем, подменив таким образом оригинальную библиотеку, мы
добиваемся лишь частичного успеха - меню настроек действительно
показывает активированную лицензию, но после перезагрузки системы
explorer.exe просто… не загружается.
Так как подменяемая библиотека отвечает не только за проверку
лицензии, но и за непосредственный функционал программы (она инжектится
в процесс explorer.exe при загрузке), скорее всего, наша
прокси-DLL не делает чего-то, что делает оригинальная. У меня есть
некоторые соображения на этот счёт, но они требуют проверки.
После этого я пошёл ленивым путём и просто пропатчил функцию проверки
лицензии, а также функцию Ordinal_102, чтобы они возвращал успех при
любом раскладе. Еле-еле впихнув наш ассемблер, мы получаем заветное
сообщение об активной лицензии, при этом explorer.exe
спокойно загружается, ибо остальную библиотеку мы не трогали.
Теги: reverse-engineering
на деле данный ключ присутствует как в HKEY_LOCAL_MACHINE, так и в HKEY_CURRENT_USER, причём их назначение, по-видимому, несколько разнится.↩︎



