Обратная разработка коммерческой программы: кейген для Zuma Deluxe




Вступление

Здравствуйте, Хабралюди.
Судя по последним статьям в блоге Assembler, тема кейгенов становится здесь весьма популярной. Что ж, внесу и я свои пять копеек.
Наш сегодняшний подопытный — игра Zuma Deluxe, на которую я никак не мог отгуглить себе кейген (не подумайте, что я игроман: на всё данное исследование меня вдохновил тов. k_d с его самоиграйкой для Zuma). И сразу дисклеймер: данный взлом от начала и до конца проделан в образовательных целях и не имеет целью нести убытки компании PopCap Games.
Итак, гуглим дистрибутив Зумы, скачиваем его, приводим в боеготовность OllyDBG, и начинаем разбор.
Да, заранее оговорюсь — я с некоторых пор заделался линуксоидом, поэтому запускаться вся эта радость будет из-под WINE. Впрочем, забегая вперёд, отмечу, что для данной задачи в этом есть свои плюсы, такие как, например, простота редактирования записей и отслеживания изменений в WINE`овском реестре, в силу его хранения в обычном текстовом файле.


Часть 1: коварный Flash

В общем, запускаем игру, играем дольше положенного (или сразу же лезем в ветку реестра HKLM/Software/PopCap/Zuma и выставляем нули в ключах TimesExecuted и TimesPlayed) — и вуаля:



Отлично, выбираем «Buy Now», закрываем вылезшее окошко браузера с предложением купить такую-то игру за жалкие 16.99 евро, и жмём «Enter the Registration Key Manually».



Так-с, поле ввода. Уже от чего-то можно плясать. Пробуем ввести какую-нибудь абракадабру, ожидаемо получаем «Please enter a valid key», и идём разбираться, что к чему. Первое, что настораживает при вдумчивом осмотре — наличие в папке, прямо рядом с бинарём игры, двух файлов, намекающих на использование в программе технологии Flash: собственно, Flash.ocx и drm.swf… Видимо, с закрытием браузера можно было повременить. Ладно, открываем этот самый drm.swf — и что же мы видим:



Вся гламурненькая оболочка для регистрации ключа, как оказалось, выполнена в том самом .SWF-файле. Может быть, и сам код проверки находится там же? Давайте посмотрим. Берём любой декомпилятор ActionScript (я, например, использовал Flare) и вынимаем из drm.swf исходный код.
Смотрим, что же у нас там надекомпилировалось. Рано ли, поздно ли натыкаемся на вот такую интересную строчку:

    gFrameLabels[4] = 'RegFailed';

Ищем по «RegFailed» и выходим на вот этот блок кода:

    if (_root.RegCodeEdit.text.length >= 23 && _root.validate_regkey(_root.RegCodeEdit.text)) {
        _root.APError.text = '';
        gRegFailedHeader = gHeader_RegFail;
        gRegFailedMessage = gMessage_RegFail;
        gRegFailedRetryLocation = 'APScreen';
        fscommand('Register', _root.RegCodeEdit.text);
    }

Вот оно. Правильный ключ имеет в длину 23 символа (больше просто не позволяет ввести само текстовое поле) и заставляет validate_regkey() возвращать True. На то, что в этом же блоке кода происходит инициализация таких «страшных» значений как gRegFailedMessage, можно не обращать внимания, т.к. здесь, вне зависимости от них, из флэш-объекта посредством fscommand() происходит передача данных в родительский процесс.
Теперь пора заняться самой функцией validate_regkey(). Вот она целиком:

    function validate_regkey(string) {
      if (string.substr(5, 1) == '-' && string.substr(11, 1) == '-' && string.substr(17, 1) == '-') {
        char = new Array();
        k = 0;
        while (k <= string.length - 1) {
          char = string.slice(k, k + 1);
          if (char == '0' || char == '1' || char == '2' || char == '3' || char == '4' || char == '5' || char == '6' || char == '7' || char == '8' || char == '9' || char == 'A' || char == 'B' || char == 'C' || char == 'D' || char == 'E' || char == 'F' || char == 'G' || char == 'H' || char == 'I' || char == 'J' || char == 'K' || char == 'L' || char == 'M' || char == 'N' || char == 'O' || char == 'P' || char == 'Q' || char == 'R' || char == 'S' || char == 'T' || char == 'U' || char == 'V' || char == 'W' || char == 'X' || char == 'Y' || char == 'Z' || char == 'a' || char == 'b' || char == 'c' || char == 'd' || char == 'e' || char == 'f' || char == 'g' || char == 'h' || char == 'i' || char == 'j' || char == 'k' || char == 'l' || char == 'm' || char == 'n' || char == 'o' || char == 'p' || char == 'q' || char == 'r' || char == 's' || char == 't' || char == 'u' || char == 'v' || char == 'w' || char == 'x' || char == 'y' || char == 'z' || char == '-' || char == ' ') {
            if (k == string.length - 1) {
              result = 'Thank you for submitting !';
              return true;
            }
          } else {
            result = 'Unauthorized character ' + char;
            return false;
          }
          ++k;
        }
      } else {
        result = 'Error in delimiters';
        return false;
      }
    }

Что ж, центральная проверка — однозначный шедевр. Надо, наверное, запостить это на govnokod.ru, ну да ладно, мы сюда не позубоскалить собрались. Главное, что эта функция дала нам структуру лицензионного ключа:

#####-#####-#####-#####
где # — символ из алфавита «0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz- ».
Ровно 23 символа.

Опять забегая вперёд, скажу что набор верных символов внутри самой программы будет несколько сокращён. Но пока что нам без разницы. Запускаем OllyDBG и загружаем в него нашу подопытную. Запускаем на выполнение (F9) и дожидаемся момента прорисовки главного окна.
Куда копать дальше?
А помните найденный нами вызов fscommand() с первым параметром, равным строке «Register»?
Поэтому открываем Memory Map (Alt+M) и ищем вхождение этой строки (Ctrl+B). А вот и она, лежит себе по адресу 0x4417D0:



Ставим на неё точку останова по чтению (выделение → Shift+F3). Далее, в окне проверки, идём по ссылке внизу «Already purchased this game?» → «Enter the Registration Key Manually», и вводим в поле для ключа любую алфавитно-цифровую белиберду, разделённую дефисами на 4 блока по 5 символов. Жмём «Register».


Часть 2: we need to go deeper

Вот мы и попали, наконец, внутрь алгоритма проверки. Идём в список контрольных точек на память и удаляем 0x4417D0 (Alt+Y → Del), выполняемся (Ctrl+F9) до конца функции, т.к. там ничего интересного для нас нет, только цикл сравнения, далее возвращаемся в вызывавшую функцию (F8), и видим там проверку возвращённого результата. Опять пропускаем всё до конца функции и возвращаемся в вызывавшую:



Ага! А вот теперь мы в сердце анализатора лицензионного ключа. Чтобы не забыть это место, поставим (F2) контрольную точку на 0x04066CA и осмотримся вокруг. Чуть ниже (0x406757 и 0x4067A8) видны вызовы функций с очень интересными строковыми параметрами «RegSucceeded» и «RegFailed». А повыше (0x406748) находится ветвление, которое передаёт управление в нужную функцию. Это ветвление завязано на сравнение (0x40672D) регистров AL и BL. Похоже, что функция 0x404260, вызываемая ещё двумя командами ранее — это как раз то, что мы искали, т.е. Самая Важная Функция Проверки.

Сначала, проверим свою догадку: изменим сравнение так, чтобы оно оказывалось верным при некорректных исходных данных. Наведём выделение на 0x406748 и нажмём пробел. Откроется окно «Assemble». Заменим переход по равенству, JE, на переход по неравенству — JNE. Запустим на выполнение (F9)…



Ура, первый бастион взят!
Но мы сейчас пишем не просто кряк, а очень даже кейген. А это значит, что на достигнутом останавливаться рано, и придётся перезапустить программу (Ctrl+F2) и углубиться в недра функции 0x404260.

Сейчас наша задача — понять, как себя ведут внутри этой функции регистры AL и BL, и где именно расположен кусок кода, ответственный за их равенство либо неравенство.
Перейдём в «хвост» функции, поближе к точке выхода, RETN, и включим подсветку регистра BL (контекстное меню → Highlight register → EBX).



Как видите, содержимое регистра AL на протяжении практически всего «хвоста» хранится в BL, и только перед самым выходом копируется обратно, с дальнейшим восстановлением исходного значения EBX из стэка.
При том, само значение AL берётся из функции, на картинке вверху помеченной выделением.
Переходим внутрь этой функции — и что же мы видим:



У этой функции всего два возможных выходных значения — 0 и 1. Первое генерируется, когда строка байт, указатель на структуру с которой передан как параметр функции, не совпадает со строкой, чей указатель лежит по адресу [ECX + 8]. Второе же (то самое, которое нам нужно) — при обратной ситуации, т.е. когда строки идентичны.


Часть 3: MD5, RSA и все-все-все

Вернёмся в родительскую функцию и взглянем, откуда берутся значения из [ECX + 8] и [ARG.1 + 8].
Для этого поставим (выделение → Shift+F5) «аппаратные» точки контрольного останова на два адреса в стэке, в которые должны быть помещены эти строки. Для разных конфигураций машин и операционных систем данные адреса, скорее всего, будут различаться. Так, в моём случае это 0x33E624 и 0x33E660 (вообще, рекомендую завести себе сбоку дополнительное окно, показывающее состояние стэка, независимое от положения его вершины, ESP, как на картинке).
Аппаратными эти контрольные точки быть обязаны, т.к. другие типы контрольных точек, будучи поставленными на стэк, либо приведут к «обвалу» программы, либо не будут сохраняться между запусками. Пока что эти точки нужно сделать неактивными (контекстное меню → Breakpoint → Hardware disable).

Теперь перезапустим программу и остановимся на входе в нашу главную функцию проверки (0x404260). Поставим туда контрольную точку и начнём трассировать функцию построчно (F8), следя за состоянием двух наших аппаратных точек останова. Трассировка показывает, что до строки 0x404546 оба значения остаются неизменными. А вот дальше уже любопытнее.

Функция, непосредственно вызываемая из 0x404546, является «трамплином» для запуска функции 0x41E320, так что в ней нет ничего интересного. Ставим точку останова на 0x41E320 и жмём F9.
На данный момент, в стэке можно заметить строку, состоящую из странных, но тем не менее печатных символов (к примеру, у меня это A.....6..O6NBBO....E4GXF3O0..), символа перевода строки и постфикса ZUMA. Трассируем далее, и набредаем на 0x41E37F:



Так-так-так… да это же векторы инициализации для алгоритма MD5!
MD5. Так-то лучше. Теперь анализ остального кода функции проходит легко и беззаботно:
  • 0x41E3200x41E397: инициализация данных и выделение памяти под результат
  • 0x41E39B0x41E3C3: вычисление MD5-хэша от вышеупомянутой строки и подготовка структуры (далее по тексту я буду называть её «фреймом»), которая будет содержать в себе ссылку на результат
  • 0x41E3C50x41E408: цикл, перестраивающий байты в результате задом наперёд
  • 0x41E40A0x41E424: проверка, которая в силу фиксированности четвёртого параметра функции (0x5E) всегда оказывается истинной
  • 0x41E4260x41E474: код, который, в силу предыдущей проверки, никогда не исполняется
  • 0x41E4760x41E4B5: функции «обрезки» 128-битного MD5-хэша до 96 бит; выход из функции

Теперь давайте посмотрим на первую из наших аппаратных контрольных точек:



Такая структура из пяти значений, как я уже говорил, впоследствии будет называться «фрейм».
  • Первый DWORD никогда не изменяется, и всегда равен 0x44543C
  • Второй DWORD имеет неясное назначение (да в общем-то и не особо важен, как далее покажет практика)
  • Третий DWORD равен адресу в памяти, где хранится строка байт
  • Четвёртый DWORD задаёт её «эффективную» длину в WORD`ах (т.е. сколько WORD`ов из строки будет использоваться в дальнейших вычислениях)
  • Пятый DWORD задаёт её «суммарную» длину в WORD`ах (т.е. сколько WORD`ов было изначально выделено для размещения строки)

Так вот, после выполнения только что протрассированной нами процедуры, первый из фреймов уже заполнен. Т.е., у нас уже есть одна из строк, назовём её условно «эталонной», которая подвергнется сравнению с той, которую нам ещё только предстоит вычислить в 0x40454F0x40458C.

Теперь взглянем попристальнее на строку 0x404560, откуда вызывается функция 0x41E5A0.
Функция очень длинная и очень страшная, однако мы для того и здесь, чтобы сделать длинное и страшное простым и понятным. Эта функция обрабатывает введённую нами строку регистрационного ключа, и пересчитывает её в число.
  • 0x41E5A00x41E608: инициализация, выделение памяти, установка обработчика исключений
  • 0x41E60B0x41E6EF: цикл, преобразующий буквы строки в верхний регистр, и заменяющий символы «1» на «L», а «O» и «0» — на «Q»
  • 0x41E6F50x41E70A: подготовка ко второму циклу
  • 0x41E7100x41E7E4: второй цикл, строящий из строки число по принципу преобразования его из 28-ичной системы счисления (первый символ — младший разряд, последний — старший), с набором знаков «234679ACDEFGHJKLMNPQRTUVWXYZ», игнорируя дефисы, и выдающий ошибку при отсутствии текущего символа в наборе
  • 0x41E7EA0x41E844: копирование результата, освобождение временных буферов, выход
  • 0x41E8450x41E874: «хвост», выполняющийся, если второй цикл выдал ошибку

Отлично, строка пересчитана в число, и теперь мы что-то с нею делаем.

До заветного момента, когда можно сказать, что реверс произведён, осталась одна функция, 0x41E100 (вызов из 0x40458C).

Ну тут уж я не буду вас мучать прочтением и расшифровкой ассемблерных листингов, поскольку один хороший товарищ, к тому моменту как я только начал её разбирать, подкинул мне очень вовремя утёкший в Сеть кусок исходника PopCap`овского фреймворка, содержащий в себе пусть не реализацию указанной функции, но хотя бы её название. В общем, барабанная дробь… та функция, на которую мы сейчас собираемся пойти в лобовую атаку, называется aSignature.ModPow(e, n).
Интересующиеся могут проследовать к строке 00069 и обнаружить поразительное сходство функции bool SexyApp::Validate() (SexyApp — во назвали-то; я хренею без баяна, милостивые господа) с нашей, ставшей уже такой родной, 0x404260.

Также, рекомендую обратить внимание на сами e и n:

    BigInt n("42BF94023BBA6D040C8B81D9");
    BigInt e("11");

или, в ассемблерном представлении,



Как можно догадаться из названия, ModPow() означает возведение в степень по модулю.
А комментарий на строке 00478

    // Public RSA stuff
    BigInt n("D99BC76AB7B2578738E606F7");
    BigInt e("11");

    BigInt aHash = HashData(aFileData, aFileDataPos, 94);
    delete aFileData;

    BigInt aSignature(aSigStr);
    BigInt aHashTest = aSignature.ModPow(e, n);

окончательно проясняет ситуацию: алгоритм, с которым мы имеем дело — это RSA.


Часть 4: генератор ключей

Что ж, у нас есть практически все исходные данные, чтобы начать писать кейген. Единственное, что осталось сделать — это факторизовать публичный модуль 0x42BF94023BBA6D040C8B81D9 и вычислить приватную экспоненту. Ну что ж, берём в руки MSieve + TMG RSA Tool, и получаем на выходе 0x03AE5465C52D0C4C0A8FE303D.
Всё, осталось написать (или спереть готовую, хе-хе) реализацию длинной арифметики. Сам же алгоритм для генерации ключа у нас есть:
  1. посчитать MD5 от строки ИМЯПОЛЬЗОВАТЕЛЯ,0Ah,ZUMA
  2. выкинуть последний DWORD, и записать оставшееся в обратном порядке байтов
  3. по-WORD-ово пройтись по результату, и применить (чит.: скопипастить в кейген) сдвиг; см. 0x41D280
  4. снова поменять порядок байтов
  5. вычислить от полученного функцию ModPow(D, N), где D = 0x3AE5465C52D0C4C0A8FE303D, N = 0x42BF94023BBA6D040C8B81D9, E = 0x11
  6. последовательным делением на 28, подставляя остатки по таблице «234679ACDEFGHJKLMNPQRTUVWXYZ», раскрыть из вычисленного лицензионный ключ

Здесь я намеренно опустил несколько часов изысканий по поводу того, чем является та самая заветная строка «A.....6..O6NBBO....E4GXF3O0..», которую я по мере разбора принял как данность, а в вышеизложенном алгоритме обозначил как ИМЯПОЛЬЗОВАТЕЛЯ. Оказывается, она генерируется на основе железа компьютера, в частности количество сетевых адаптеров на компьютере отвечает за её длину.
Сам код этой генерации, на мой взгляд, писали какие-то параноики-наркоманы. Вот, например, реальная ситуация: в моём компьютере в каждый момент времени может находиться три или четыре сетевых адаптера (возвратник lo, Ethernet-интерфейс eth0, WiFi-интерфейс wlan0, а также мобильник, подключаемый через USB-порт и играющий роль GPRS-модема, ppp0). Как только я подключаю мобильник, их становится 4. Как отключаю — 3. Этим двум состояниям, по мнению генератора, соответствуют разные строки. Следовательно, в одном из них регистрация Zuma, купленная за, простите, €16.99, просто слетит.

В общем, исходя из вышесказанного, код, генерирующий эту пакость, я решил в кейген не копипастить, а банально красть уже готовую строку из памяти игры посредством ReadProcessMemory(). В качестве небольшого хулиганства, также я добавил возможность записывать в строку имени что-то своё (с помощью WriteProcessMemory(), как несложно догадаться). Но, к сожалению, работает (т.е. сохраняет валидность регистрации) такой трюк только на WINE, но не на «реальной» Windows.

В остальном — прошу любить и жаловать: Zuma keygen, proof-of-concept.
Язык написания — ассемблер. Алгоритм MD5 скопипащен из бинаря игры, и слегка доработан напильником. 96-битная арифметика — аутентична =)

Кейген проверялся не только на той версии Zuma, про которую идёт речь в статье, но также ещё и на других, более ранних или поздних (я не разбирался). Несмотря на то, что адреса с именем пользователя разнились, сам лицензионный ключ подходил к ним всем, что свидетельствует о неизменности алгоритма аж с 2003 года.


Послесловие и использованные ссылки

Эта статья была бы невозможна без помощи нескольких грамотных ребят с WASM.RU Ѳорум, наставивших меня на путь истинный вот в этой теме.
Также мне сильно помогла утилита RSA Tool от хакерской команды TMG, и онлайновый RSA-калькулятор http://nmichaels.org/rsa.py.
Статьи в Википедии по RSA и MD5 также много мне дали для понимания сути происходящего в недрах игры.
Если кто-то заинтересовался — до кучи выкладываю .UDD-файл для OllyDBG со всеми комментариями и контрольными точками.

P.S. Если кто-то может посоветовать более надёжный файлообменник, с которого файлы не удаляются через 30 дней простоя — буду крайне признателен.

P.P.S. Каково же было моё удивление, когда уже после взлома я обнаружил, что Zuma.exe из обсуждаемого пакета — это просто обёртка, архив, который по лицензионному ключу разархивирует в свою же папку реальный бинарь с Zuma, названный popcapgame1.exe

[UPDATE:] перенёс картинки на Habrastorage.
Share post

Comments 72

    +85
    Хотел намекнуть на то, что текст статьи попадает под наше законодательство, посмотрел на ник… задумался.
    • UFO just landed and posted this here
        +13
        А пока никто и не собирался, слава Лейн. В конце концов, холиворы оставим на потом, а почитать хорошую статью про исследование систем защиты приложений всегда приятно (^_^)
        +9
        Было время, когда я только искал свой профиль в сфере IT, я любил всяческие крякмиксы и т.п. Но именно из-за нелегальности данного направления долго не задержался в этой сфере. Теперь же, читая подобные топики многое конечно-же не допонимается, но тем не менее, вызывает состояние некоторой эйфории и ностальгии.
          +1
          Последний раз открывал олли наверно год назад, а раньше это было моей главной работой, но прекратил также как и Вы из-за незаконности хакинга и того, что это дело тянет на себя просто уйму времени к сожалению. А вообще есть в скринах отладчика и всех хакерских тулзах, что-то магическое.)
            +2
            Отлаживать чужое может и не легально. Но крякмисы не защищенны какой-либо лицензией, и собственно сделаны для того, чтобы их анализировали. В этом плане все чисто.
            Да и интерес у органов Вы не будете вызывать до тех пор, пока не начнете выкладывать кряки на право и на лево, или пока не перейдете этим дорогу софтверным компаниям из черного списка.
            Ну или реверс будет предлогом взять Вас за что-то другое.
            –35
            Отличная статья, я раньше играл в эту версии игры, очень занятная времяубивалка. Сейчас играю в неё же только на фейсбуке — флеш версия.
              +25
              а нам вы это зачем сообщили?
              0
              Сделайте свои скрины в jpg, ибо 400кБайтная картинка в краткой новости в png — это жестоко…
                +4
                Преобразовал в .JPG, подсчитал размеры.
                Те файлы, где .PNG-версии были объёмнее (в частности, титульную картинку) заменил.
                +4
                Бедная Зума, как же над ней только не издевались =) Из лучшей классической игры в своем жанре превратилась в подопытного кролика :)
                  +9
                  >> превратилась в подопытного кролика
                  Скорее в лягушку для препарирования.
                    +1
                    А почему бедная? Своего рода «уважуха» игре.
                      –24
                      Уважаемую игру(программу) не ломают. Это понимают не сразу, это приходит со временем.
                        +9
                        А можно пример уважаемой программы, к которой нет кряка по «этическим соображениям»?
                          –1
                          Avid ProTools 9/10 win, mac поломали через дикие костыли. ни к одной версии PT нет ни одного нормального кряка от уважаемой группы.
                          Steinberg Cubase 6 под обе платформы, поломана только обрезанная версия под mac
                          Steinberg Cubase 5 под win — полтора года не ломали, mac вроде так и никто и не делал.

                          это только популярное.
                            +3
                            Cubase группа H2O перестала ломать из-за слишком больших трудозатрат, если мне не изменяет память. Они как эмулятор аппаратного ключа написали, так сразу в ридми указали, что больше их на такие подвиги не тянет.
                              0
                              я бы не сказал, что сложные системы для обработки звука популярны. Это же не фотошоп какой, которым можно фотографии урезать совсем без навыков.
                                0
                                можете считать эти программы фотошопом для аудио, если вам нравится такое сравнение.

                                практически каждая уважающая себя аудио или музыкальная студия имеет либо cubase, либо PT в наличии, потому что это стандарт.
                                  +1
                                  это я к тому, что у среднего юзера задача обработки изображений куда актуальнее обработки звука. А студии — это совсем не средний юзер.
                                  Поэтому та же уважаемая группа лучше напишет таблетку для популярного в массах PS, чем кряк для PT, которым воспользуются 3.5 человека.
                                    –2
                                    вы сильно недооцениваете этот рынок.
                                      0
                                      почему? Зашел в гугле на первый сайт по запросу software popularity, software.informer.com. Среди их пользователей Photoshop стоит у 932 781 пользователя, Steinberg Cubase — у 5 471.
                                      По оборотам рынки, возможно, и одинаковы, но по количеству пользователей и, соответственно, популярности кряков, емкость совершенно разная.
                                        +1
                                        Может быть. Но уж эти-то 5471 пользователя без Cubase не могут совершенно никак. Как минимум потому, что и альтернатив-то нет, по сути (как, например, Gimp в случае в Photoshop)
                                          –1
                                          И что? Спасибо за сравнение ложки с саперной лопатой, в этом вы преуспеваете.

                                          Зайдите уже на какой-нибудь популярный русский торрент-трекер и гляньте количество скачиваний, у пятой версии оно стремится к 100 000. Вот это — показатель популярности работы варез-групп, а какой-то сайт, занимающийся индексированием непонятно как — нет.
                                  +2
                                  Как выше упомянул braintorch, Cubase не ломали не по этическим соображением, а совсем по-другим причинам. После того как Steinberg выпустили версию с защитой от Syncrosoft, h2o (команда, которая обычно занималась взломом профессионального аудио-софта), смогли выпустить крек только через 9 месяцев после выхода Cubase. В .nfo файле к креку было сказано, что взлом этой защиты был для них делом принципа, но из-за чудовизных трудозатрат (речь шла о паре человеко-лет), больше они эту защиту ломать не будут. Как-то так всё было.
                                  +2
                                  Я за других не в ответе, я имел ввиду конкретно отдельных личностей. Пусть кто хочет тот и ломает, но если кому-то нравится какая-то программа (игра) с правильной ценой, которая отвечает требованиям цена/качество, то ее не грех купить, отдав некую дань разработчикам. Я знаю тех кто ломал, но при этом некоторые программы легально покупал для себя. Я себе лично купил Skyrim, т.к. мне нравится этот цикл игр и я долго ждал продолжения.
                                  Ну а вы минусуйте дальше.
                                  0
                                  Не занудничайте, ломают всё. Мне вот интересно стало, почему такое убожество стоит 16 евро, я в него и бесплатно играть не стану.

                                  Так для сравнения — на Маке игры подобного уровня имеют ценовую категорию около 5$ (специально только что полез посмотреть как дела у маководов с мелкими играми).
                                  Под Линуксами вообще фришные игры такого рода, пусть они может и не такие разукрашенные.
                                  А здесь же имеем случай, когда игра для секретарши продается по цене, приближающейся к квейкам, скайримам, варкрафтам при распродаже на Стиме.

                                  Я предлагаю вообще ни покупать ни взламывать такое.
                                    +1
                                    Уважаемую игру как раз и ломают. Кому нахрен надо тратить время на взлом никому не нужного говна.

                                    Если ломают, значит кому-то это нужно (с) кто-то сказал.
                                +11
                                > Что ж, центральная проверка — однозначный шедевр. Надо, наверное, запостить это на govnokod.ru, ну да ладно, мы сюда не позубоскалить собрались.


                                Не может ли быть так, что эта центральная проверка — результат работы декомпилятора?
                                  +1
                                  А ведь действительно. Как-то не подумал об этом с самого начала…
                                  0
                                  Получается, от кряка\кейгена спасьтись можно только онлайн-верификацией? Хотя и тут можно хосты закрыть :(
                                    +2
                                    От кейгена помогает длинный RSA.
                                      +9
                                      От длинного RSA помогает короткий патч.
                                        0
                                        до следующего апдейта+фикзна что патч с компом делает
                                          0
                                          А вы не пользуйтесь чужим, делайте свои. :)
                                          А откуда у вас уверенность в том, что кейген не делает ничего лишнего.
                                          Хочете достать сыр с мышеловки, будьте готовы попасться. Пусть как вы не будете его доставать (патч, кейген, етс.).
                                            0
                                            >Хочете достать сыр с мышеловки, будьте готовы попасться. Пусть как вы не будете его доставать
                                            золотом на крак-сайты :)
                                              +1
                                              А откуда у вас уверенность в том, что кейген не делает ничего лишнего.
                                              Верно, но когда он сидит в песочнице, пусть творит что́ хочет, главное — ключ бы давал.
                                                0

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

                                      +1
                                      А взяли бы они RSA ключ побольше и уже keygen было бы не сделать, да? Интересно почему они такой небольшой ключ выбрали…
                                        0
                                        Вот как раз для того, чтобы ключ был короткий. Типа удобство пользователя без скила копипаст.
                                          +21
                                          О, меня в своё время Acronis порадовал. У них ключ был — 128 бит, из них 64 бита — данные ключа, еще 64 бита — эти же данные зашифрованные по RSA.
                                          В общем, универсальный кейген я помнится тогда сделал для всех продуктов Acronis. Ключ просто брутфорсом брался за несколько секунд на тогда еще слабом железе.
                                          Потом они усложнили задачу. RSA стало 128 бит. Правда, я интерес уже потерял к тому моменту.

                                          Самое ржачное было — находить копии своих кейгенов с перебитыми в нём «by ...» :)))
                                          +1
                                          Зума с мясом. Спасибо!
                                            0
                                            Надо было использовать 1024-битый ключ, а не 96, тогда и кейгена бы не было.
                                              0
                                              тогда мне кажется был бы аккуратный патчик заменяющий JE на JNE :)
                                                +1
                                                Ошибка большинства. Это не совсем корректный патч. Нужно патчить или нопами или на безусловный переход, но не менять условие на противоположное.
                                                  0
                                                  Ну, справедливости ради, там и не самое удачное место было для патча. Лучше было внутри самой сравнивающей функции перекинуть все ветвления на уже готовый MOV AL, 1 (а то и просто заменить XOR AL, AL на такой же MOV AL, 1).
                                                    0
                                                    Ну, да. Но тут сейчас речь больше об общей технике патчей переходов.
                                                      0
                                                      Я ведь тоже написал образно. Наверное придется вычислить куда надо перейти и вписать jmp. Это как-то надежнее что ли. А вот насчет nop я не уверен, разве не может переход вести выше того места, где идет проверка? Как тогда nop'ами туда добраться?
                                                        0
                                                        Где не нужно чтобы переход сработал заполняем нопами, а где нужно чтобы сработал меняем на jmp.
                                              +6
                                              Никогда бы не подумал, что моя недописанная может вдохновить кого-то на такой интересный разбор.
                                                0
                                                Да, блин, локальная проверка введенного лицензионного ключа — это эпик фейл.

                                                Не зря всё же в моем мозге живет уверенность в том, что все дыры, благодаря которым «рутуются» и «джейлбрейкаются» современные смартфоны — это фича, а не баг. Ну то есть — часть игры, в которую мы с вами играем.

                                                Точнее можем поиграть, если захотим…
                                                  +1
                                                  Вообще да, зачастую производители намеренно не заморачиваются над защитой, т.к. было бы желание — всё равно сломают. А те кто хотят взять лицензионку — возьмут её и так.
                                                  А насчёт локальной проверки лицензионного ключа в зуме — это вполне не эпик фейл. Ну проверялся бы ключ через сервер, что толку если поправив 1 байт в ехе-шнике игра игнорировала бы ответ от сервера «неверный ключ».
                                                    0
                                                    В крайнем случае — эмулятор сервера можно написать. Который будет отвечать, что ключ верный.
                                                  +2
                                                  И только мне название "обратная разработка" кажется издевательством над читателем? (да, я в курсе, что так reverse engineering переведена на википедии).
                                                  Последнее время на Хабре пошла какая-то волна насильственных переводов терминов.
                                                  +3
                                                  … это просто обёртка, архив, который по лицензионному ключу разархивирует в свою же папку реальный бинарь с Zuma, названный popcapgame1.exe…
                                                  Тогда получается, что лицензия после изменения количества сетевых адаптеров не слетит.
                                                    +8
                                                    Аж чем-то ностальгическим от поста повеяло. Ловите +. За то, что при виде скринов Olly я вспоминаю себя лет 10 назад.

                                                    Если кому-то интересно — давным-давно, курсе на 2-м пробовал ломать (и изучать ASM по ходу пьесы) Хрумер (по-моему 5-й). До кровавых мозолей зеленых соплей и красных глаз. До бессвязного бормотания «MOV EAX, EDX; XOR EDX, EDX;» и поднимаемого абсолютно пустого взгляда в ответ на попытку человеков отвлечь мое внимание от экрана. До ненавистных ассемблерных снов. Программирование на ASM — это что-то как наркота! Слава Программерскому Богу, я спрыгнул. Держусь уже года 4 (было парочка халтур, но небольшие).

                                                    Но думается мне, что после этого поста я смахну пыль со своих старых добрых Olly, SoftIce и IDA, восстановлю пароль с cracklab и опять посмотрю на какой-нибудь код с другой стороны компилятора. И сейчас я говорю за это спасибо. Надеюсь опять спрыгнуть получится.
                                                      +1
                                                      Есть такое: после нескольких часов, проведенных в IDA, наступает состояние какого-то просветления.
                                                      0
                                                      Читая в последнее время хабр, все больше хочется создать тему, в которой люди будут пытаться взломать алгоритм написанный другим хаброюзером.
                                                      Вообще интересно, но, к сожалению, ассемблер знаю довольно поверхностно и постоянно нахожу что то не до конца понятное.
                                                        0
                                                        Что ж, центральная проверка — однозначный шедевр

                                                        Я извиняюсь, а разве не так разворачивается в ассемблер выражение вида isigit(a) или ishex(a)?
                                                          0
                                                          Это не ассемблер в общем-то. Это результат декомпиляция байткода ActionScript.
                                                          Вариантов два:
                                                          1) был говнокод
                                                          2) так отработал декомпилятор на оптимизированном байткоде.
                                                          Можно проверить при желании.
                                                            0
                                                            Транслятор ActionScript никогда не делал inlining и, насколько я знаю, не умеет его делать до сих пор.
                                                            Тем более, что судя по использованию для декомпиляции Flare, этот код был написан на AS1/AS2 который стар как бивни мамонта.
                                                            +9
                                                            данный взлом от начала и до конца проделан в образовательных целях и не имеет целью нести убытки компании PopCap Games

                                                            Просто на будущее, лучше не употреблять слово «взлом». Это все же тянет попасть под законодательство. Лучше говорить «анализ ПО». Суть действий не меняется, а цель с которой эти действия совершаются звучит благороднее.
                                                            А за статью большое спасибо.
                                                              +6
                                                              Ну как дети, ей-богу! Как не формулируй, законодательству всё равно как вы взлом называете :)
                                                              +2
                                                              Ностальгия. Занимался «исследованием» лет в 15… пока не поймали… пришлось завязать.

                                                              Когда не встаешь с компа всю ночь и под утро наконец находишь нужный ключ к программе или тот адрес где нужно поставить магические jz или jnz, было сравнимо с оргазмом и душевным удовлетворением =))

                                                              Но а про сам НЕ взлом…

                                                              Вы можете «взлом» называть как хотите и представлять как хотите, но судье будет глубоко все равно почему и зачем вы это делали, даже если это для образовательных целей вашей бабушки.

                                                              Другое дело, как себя поведет правообладатель. Ему главное захотеть — и будете всю жизнь работать на выплачивание штрафа. Мне повезло, в 15 лет в тюрьму не посадиш и штраф не выпишешь — простили…

                                                              А так — я лично за «исследования». Это даже интереснее чем само программирование.
                                                                0
                                                                Я скучаю по этой штуке…

                                                                image
                                                                  0
                                                                  image
                                                                    +1
                                                                    А я сколько не пытался привыкнуть к этой штуке, а Олька всё равно роднее, но да, ностальгия =)
                                                                      +1
                                                                      Да, TRW2000 был однозначно лучшим из лучших, но, к сожалению, для W98 максимум. Я даже какое-то время не выбрасывал старенький ноут с 98, для таких случаев)
                                                                      Было исключительно удобно запускать дебаггер уже _после_ прохождения всех антиотладочных защит, и оказываться хоть в ring0 сразу)
                                                                        0
                                                                        Гыгы, вы в теме (:
                                                                    0
                                                                    К слову о Zuma.
                                                                    В Steam все игры Popcap защищены весьма просто. Нужно просто в исполняемом файле удалить всё, грубо говоря, до второго MZ(executable header).

                                                                    Only users with full accounts can post comments. Log in, please.