visilii's blog

Инфобез и malware analysis
Гостевая книга | Ссылки

Крякаем программу без лёгких путей (ну, почти)

November 04, 2025 — visilii

Сегодня мы в образовательных целях обойдём проверку лицензии в программе [УДАЛЕНО].

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

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


Покончив с (само)успокоительными увещеваниями, приступим к сути.

У нас есть программа, которая даёт пробный период в 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 также способен показать стек вызовов на тот момент:

Событие чтения ActivationData
Стек вызовов

Видим, что значение реестра читается функцией Ordinal_102 динамической библиотеки [УДАЛЕНО]X64.dll. Вот как она выглядит:

Ordinal 102

Видим, что прочитанное значение передаётся на вход другой функции (я подписал её activationCheck). Внутри неё оно шифруется функциями из bcrypt.dll и сравнивается с другим значением, каким-то образом вычисляемым из другого значения реестра, LicenseHash. Нам, впрочем, не очень интересен конкретный алгоритм проверки, так как всё, что необходимо для её обхода - это ненулевое значение на выходе Ordinal_102:

Ленивый способ кряка - это пропатчить либо [УДАЛЕНО]X64!Ordinal_102, либо вызывающую его функцию. Но я не ищу лёгких путей, а поэтому сначала попытался решить проблему хукингом.

Я написал свою DLL-библиотеку, которая перенаправляет все вызовы, кроме Ordinal_102, в оригинальную библиотеку, загружаемую динамически. Что касается Ordinal_102 - во всех случаях, где она используется, идёт проверка двух вещей - возвращаемого значения и значения указателя, который ей передаётся при вызове; для успешного прохождения проверки эти значения должны быть ненулевыми:

Прокси-DLL

Впрочем, подменив таким образом оригинальную библиотеку, мы добиваемся лишь частичного успеха - меню настроек действительно показывает активированную лицензию, но после перезагрузки системы explorer.exe просто… не загружается.

Так как подменяемая библиотека отвечает не только за проверку лицензии, но и за непосредственный функционал программы (она инжектится в процесс explorer.exe при загрузке), скорее всего, наша прокси-DLL не делает чего-то, что делает оригинальная. У меня есть некоторые соображения на этот счёт, но они требуют проверки.

После этого я пошёл ленивым путём и просто пропатчил функцию проверки лицензии, а также функцию Ordinal_102, чтобы они возвращал успех при любом раскладе. Еле-еле впихнув наш ассемблер, мы получаем заветное сообщение об активной лицензии, при этом explorer.exe спокойно загружается, ибо остальную библиотеку мы не трогали.

Ассемблер до…
…и ассемблер после

Теги: reverse-engineering


  1. на деле данный ключ присутствует как в HKEY_LOCAL_MACHINE, так и в HKEY_CURRENT_USER, причём их назначение, по-видимому, несколько разнится.↩︎

badge: proud member of the darktheme.club
previous no ai webring siteno ai webringrandom no ai webring sitenext no ai webring site

Don't feed the AI! uBlock Origin Now! Edited with Vim I miss XP!
Piracy Now! Best viewed with Open Eyes built listening to Winamp CSS is difficult
badge: proud member of the 250KB Club

Домен предоставлен FreeDNS