. _ . _ -|-------------------------/-//--|- // / _______________ | __ _____ | \_ _/_ \_____·/ \/ \ | / / / /_ / _ / t e a m | -/-----/\________/ \__\___/--/- 5 3 | /____/\____\ --- | . | wPx _ | _ | \ \\ -|--\\-\-------------------------|- Tutorials . Pack . Number . #13 ЭЛЕМЕНТАРНЫЙ ВЗЛОМ CRAZY MINESWEEPER v.1.2. (для начинающих) Поводом для написания настоящей статьи стала моя любовь к бессмертной игре "Сапер" и ее клонам, которые слишком часто требуют регистрации (читай - суммы в пределах от 10 рублей до ?). Одной из таких игр и является Crazy Minesweeper (текущая версия 2.4.). Клон достаточно неплохой, однако ограничения условно-бесплатной версии довольны существенны: - недоступны уровни "Эксперт" и "Другой"; - периодически выскакивает надпись, напоминающая о регистрации; - не сохраняется таблица рекордов; - в окошке About красуется надпись UNREGISTERED -)). Так как ни один серийник из Serials 2000 к проге не подошел (что мне показалось достаточно странным), вывод был один - надо ломать. Итак, инструменты: - PEiDentifier v.0.8 - WKT_tElock_Dumper v.1.2 - W32Dasm v.9.00 - SoftIce v.4.05 Первым делом обнаруживаем, что прога не хочет запускаться под SoftIce'ом (который на моей машине всегда активен), FrogsIce тоже не помогает. Что-ж, не иначе фокусы какого-то пакера-криптора-протектора. Запускаем PEiDentifier и видим, что прога упакована tElock 0.90. Для распаковки воспользуемся WKT_tElock_Dumper v.1.2. Распаковка проходит успешно, теперь перед нами файл unpacked.exe, который прекрасно работает и под SoftIce. Заходим в менюшку регистрации, и вводим в поля что-нибудь вроде: Имя: Hacker, E-mail: Hacker@net, регистрационный код: 2389456712345678. Нажимаем OK, и получаем сообщение "You must restart application to finish registration.". Понятно, значит прога кладет регистрационные данные в реестр или файл, и проверка происходит при запуске экзешника. Конечно, можно поставить брейкпоинт на вызов API функции regqueryvalueexa, с помощью которой считываются значения из реестра, но…..дадим потрудиться дизассемблеру. Однако W32Dasm v.8.93 здесь не поможет, этот замечательный дизассемблер вообще частенько не "срабатывается" с распакованными прогами. В то же время не хочется прибегать и к услугам IDA - для этого, без преувеличения, лучшего дизассемблера найдутся задачи и посерьезнее. Получить ассемблерный листинг 400 Kb экзешника мы сможем с помощью W32Dasm v.9.00 от J.Ping. Идем в раздел строк Refs>String Data References и находим интересующую нас строку: You must restart application to…… , ее вызов идет после прыжка с адреса 0043881F. Посмотрим код чуть выше: * Possible StringData Ref from Code Obj ->"Software\PR0GRAmmIZER\Crazy Minesweeper " ->"Rus" | ………………………………… :0043881D 84C0 test al, al :0043881F 744A je 0043886B ………………………………… * Possible StringData Ref from Code Obj ->"Name" | :00438832 BAF4884300 mov edx, 004388F4 :00438837 8BC3 mov eax, ebx …………………………………….. * Possible StringData Ref from Code Obj ->"Code" | :0043885F BA04894300 mov edx, 00438904 …………………………………….. Итак, как видно из этого куска кода, введенные нами имя и код заносятся в реестр в секцию HKCU\Software\PR0GRAmmIZER\Crazy Minesweeper, причем названия параметров - Name и Code соответственно. Запустим RegEdit и убедимся, что это так, отметив две особенности: первое - в реестре отсутствует в явном виде введенный адрес электронной почты, и второе - код хранится в зашифрованном виде. Однако к указанным параметрам прога должна обращаться как минимум еще один раз - для проверки регистрационных данных, поэтому теперь поищем в листинге строку "Code". Она встретится нам всего в двух местах: по уже знакомому адресу 0043885F и в следующем интересном фрагменте кода: * Possible StringData Ref from Code Obj ->"Code" | :0043B27F BAC0B84300 mov edx, 0043B8C0 :0043B284 8BC3 mov eax, ebx :0043B286 E8C9B9FFFF call 00436C54 :0043B28B 8B45F0 mov eax, dword ptr [ebp-10] ………………………………………….. Вероятно, именно здесь и происходит считывание из реестра нашего номера и дальнейшие манипуляции с ним. Ставим в SoftIce'е точку останова: bpx 0043B27F и запускаем нашего сапера. Сразу же вываливаемся в Sice. Начинаем трассировать прогу, отмечая следующие моменты: :0043B27F BAC0B84300 mov edx, 0043B8C0 :0043B284 8BC3 mov eax, ebx :0043B286 E8C9B9FFFF call 00436C54 < в этой процедуре параметр "Code" считывается из реестра :0043B28B 8B45F0 mov eax, dword ptr [ebp-10] :0043B28E 8D55F4 lea edx, dword ptr [ebp-0C] :0043B291 E85ED4FFFF call 004386F4 < в этой процедуре считанное значение преобразовывается в номер, который мы вводили + адрес e-mail :0043B296 8B55F4 mov edx, dword ptr [ebp-0C] :0043B299 A1C8EF4300 mov eax, dword ptr [0043EFC8] :0043B29E E86984FCFF call 0040370C :0043B2A3 8D45F8 lea eax, dword ptr [ebp-08] ………………………………………………. :0043B2D8 8D45F4 lea eax, dword ptr [ebp-0C] :0043B2DB E868D2FFFF call 00438548 < после этой процедуры в EAX ложится адрес, по которому в памяти лежит какой-то номер :0043B2E0 8B45F4 mov eax, dword ptr [ebp-0C] :0043B2E3 50 push eax …………………………………………………. :0043B2F2 8B45F8 mov eax, dword ptr [ebp-08] :0043B2F5 E83E88FCFF call 00403B38 < а после этой - в EDX адрес, по которому в памяти лежит введенный нами номер, только немного "урезанный" :0043B2FA 8B55F0 mov edx, dword ptr [ebp-10] :0043B2FD 58 pop eax :0043B2FE E84187FCFF call 00403A44 < очень интересная подпрограмма :0043B303 7509 jne 0043B30E :0043B305 833D4C15440000 cmp dword ptr [0044154C], 00000000 :0043B30C 7504 jne 0043B312 :0043B30E 33C0 xor eax, eax :0043B310 EB02 jmp 0043B314 В вышеприведенном куске кода происходит следующее. В процедуре по адресу 0043B286 из реестра считывается значение параметра Code - DHPHFJNFCGKCGKOGZv{zw‡X}w‰. Call по адресу 0043B291 преобразовывает эту строку в то, чем она и является на самом деле: регистрационный номер, соединенный с адресом e-mail - 2389456712345678Hacker@net. Теперь понятно, почему в реестре мы не увидели параметра "E-mail"……. Далее, по адресу 0043B2DB генерируется какой-то номер. Манипуляции же с нашими регистрационными данными производятся еще ниже, в call'е по адресу 0042B2F5. После выполнения этого вызова в памяти оказывается такая строка символов: 3894567123. Как видите, это введенное нами значение серийного номера, урезанное до 11 символов и с отброшенным первым символом. А теперь посмотрите на код по адресам 0043B2FE - 0043B303: здесь осуществляется вызов подпрограммы, сразу же после которого стоит команда условного перехода. Очень похоже, что в подпрограмме происходит сравнение "истины и лжи". Ну что ж, это не сложно проверить, зайдя внутрь процедуры и трассируя код: :00403A6D 8B0E mov ecx, dword ptr [esi] :00403A6F 8B1F mov ebx, dword ptr [edi] :00403A71 39D9 cmp ecx, ebx < сравнение первых 4 цифр серийников :00403A73 7558 jne 00403ACD < прыгать, если не равны :00403A75 4A dec edx :00403A76 7415 je 00403A8D :00403A78 8B4E04 mov ecx, dword ptr [esi+04] :00403A7B 8B5F04 mov ebx, dword ptr [edi+04] :00403A7E 39D9 cmp ecx, ebx < вторые четыре цифры :00403A80 754B jne 00403ACD < опять прыжок …………………………… :00403A99 8B0E mov ecx, dword ptr [esi] :00403A9B 8B1F mov ebx, dword ptr [edi] :00403A9D 38D9 cmp cl, bl < еще одна цифра :00403A9F 7541 jne 00403AE2 < снова прыжок :00403AA1 4A dec edx :00403AA2 7417 je 00403ABB :00403AA4 38FD cmp ch, bh < проверка последнего 10 символа :00403AA6 753A jne 00403AE2 < последний бастион защиты… Наши предположения оказались верны. По адресам 00403А71, 00403А7Е, 00403A9D, 00403AA4 проверяются соответственно все 10 цифр серийного номера. Итак, вводим серийный номер: любой 1-й символ, далее основная часть 5957930451, и хвост 45678. Получаем что-то вроде 1595793045145678. Цифры "45678", также как и адрес e-mail, служат для генерации первой части номера, и поэтому должны быть обязательно введены. Вот и все. Как видите все элементарно просто, и подобный взлом не занимает более 5 минут. KViNTO P/S/ Данная статья предназначена только для ознакомительных целей и автор не несет ответственности за противозаконное использование приведенного материала.