Проект games.mail.ru «крышует» многие условно-бесплатные игры, работающие всего 1 час, а затем требующие денег (или расплаты натурой). Народ разрываясь бьется в истерике: платить за софт у нас не принято и унизительно, а играть-то хочется! Причем серийные номера меняются чуть ли не каждый день, и кряки, найденные в Сети, не срабатывают. Между тем существует простой, элегантный и универсальный способ взлома, доступный даже продвинутым пользователям, не разбирающимся ни в дизассемблере, ни в секретах хакерства!

Постановка задачи

Мы будем потрошить симпатичную гейму Age of Japan от компании LoLo Games. Остальные игры ломаются аналогичным образом, поскольку построены на том же самом движке. Может быть, не все игры, но подавляющее большинство точно. Я проверял «Тайны Египта», «Пузырьковое ассорти» и еще несколько других игр, взятых наугад с сайта games.mail.ru.

После Age of Japan игры вскрываются на автомате, без всяких умственных усилий, причем стратегия взлома такова, что разработчикам навряд ли удастся исправить защиту после выхода этой статьи. Даже если они перепишут ее с чистого листа, это все равно ничего не изменит. Я поставил перед собой задачу не просто хакнуть конкретно взятую игрушку, а найти универсальный способ взлома, подходящий не только для games.mail.ru, но и для многих других триальных приложений, написанных посторонними разработчиками. И, представь себе, решил!

К сожалению, по непонятным причинам Age of Japan исчезла с games.mail.ru. Более того, она исчезла и с официального сайта ее непосредственных разработчиков. Тем не менее она уже успела расползтись по интернету, но, чтобы не давать ссылки на потенциально ненадежные ресурсы, мы решили выложить установочный файл на DVD, а также на http://nezumi.org.ru/souriz/hacksetupageofjapan.exe (естественно, в оригинальном, неломанном варианте).

Кстати говоря, сам взлом не противоречит УК, так как не модифицирует ни одного байта, непосредственно относящегося к игре, поскольку хачить программы это, во-первых, нехорошо, а во-вторых, не универсально.

Первые эксперименты, или артобстрел перед боем

Запускаем setupageofjapan.exe и устанавливаем игру на свой компьютер (разумеется, это может быть не только «Век Японии», но и любая другая игра, ведь принцип взлома универсален вплоть до мельчайших деталей). Установка проходит успешно, и на рабочем столе появляется красивый красный веер, по которому требуется щелкнуть мышью. Дважды.

Сразу же после запуска на экран выпрыгивает противное диалоговое окно с неизменным логотипом «игры@mail.ru» и сообщением о том, что у нас осталось 60 минут. Внизу находятся кнопки: «Играть», «Купить», «Еще игры» и «Ввести ключ».


Нажимаем «Играть» и гоняем мышь по всему экрану пока не надоест, после чего выходим по <Esc> и видим, что количество игрового времени сократилось до 47 минут. Но мы ведь даже не начали играть!

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

Вот только никаких гарантий, что в остальных программах используется тот же самый алгоритм, у нас нет!

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

На подступах к взлому

Игре соответствует исполняемый файл showcase.exe. Загружаем его в любой hex-редактор, например, hiew или FAR) и смотрим в начало файла, где следом за магическом словом PE следуют секции с именами UPX0 и UPX1, выдающие имя упаковщика. Скачиваем UPX посвежее с upx.sourceforge.net (благо он бесплатен) и распаковываем файл с помощью самого упаковщика, запущенного с ключом ‘-d’ (сокращение от decompress).

После этого игра увеличивается в размере с 500 Кб до 3,7 Мб, и все текстовые строки, выводимые защитой на экран, становятся зрительно видимыми, в частности, нажав <ALT-F7>, мы можем найти: «У Вас осталось <…> минут игры», «Поздравляем Вас! Игра успешно зарегистрирована!», «Ошибка – неверный регистрационный ключ».


Действуем по стандартной и годами отработанной схеме. Грузим распакованный файл в IDA Pro (если она есть), находим указанные текстовые строки, по перекрестным ссылкам, сгенерированным Идой, поднимается «наверх», к тому коду, который их выводит, и анализируем его окрестности на предмет поиска условного перехода, определяющего правильность регистрации. С одной стороны к нему примыкает код валидации серийных номеров, с другой — счетчик игровых тиков, обновляемый инструкцией MOV. Очевидно, если заменить MOV (копирование данных) командой NOP (нет операции), то игровое время навсегда застынет на отметке в 60 секунд.

Однако предложенный способ страдает рядом недостатков. Прежде всего, он не универсален, и с каждой игрой приходится разбираться индивидуально, что не есть хорошо, особенно если хочется играть во все игры и сразу! Также неподготовленным пользователям очень сложно объяснить, какие именно действия они должны предпринять для достижения желаемого результата. Вид дизассемблера большинство начинающих хакеров приводит в ужас, и они предпочитают пользоваться готовыми кряками, а не писать кряки для всех игр.

В принципе возможно расшифровать алгоритм генерации серийных номеров, который должен быть общим для всех игр, но никаких гарантий тут у нас нет, тем более что изменить алгоритм (имея исходные тексты игры на руках) – минутное дело, и хакерские генераторы тут же откажут в работе, а постоянно дорабатывать их ни у кого желания нет.

Начинаем ломать

Очевидно, чтобы знать, сколько осталось времени, защита должна где-то в той или иной форме хранить это значение. Начнем с простого. Копируем игру в другой каталог, запускаем, играем. Возвращаемся к оригиналу. И что же мы видим! Оригинал прекрасно осведомлен, сколько времени мы играли! Следовательно, игровое время внутри каталога Age of Japan не хранится, и его нужно искать совершенно в другом месте (что, кстати сказать, вполне логично, иначе бы игру уже давно сломали).

Для сужения района поиска проведем следующий эксперимент: запустим штатную утилиту MS Backup (вызываемую из командной строки по ntbackup.exe) и сохраним образ операционной системы в bkf-файл, затем поиграем (хоть до полного истечения игрового времени), после чего выполним процедуру восстановления из bkf-файла.

Ну и что? Время «волшебным образом» возвращается назад! Эту операцию можно проделывать сколько угодно раз (пока не надоест), она вполне легальна, но архивация и восстановление выполняются достаточно медленно и к тому же требуют прав администратора и перезагрузки. Кроме того, образ системы должен быть создан до окончания триала, а не после него.

Хорошо, предположим, что данные о времени хранятся в реестре (действительно, прятать их в файлах было бы неразумно и слишком заметно). Берем бесплатный Registry Monitor от Марка Руссиновича и смотрим, к каким ветвям реестра обращается программа.

Таких ветвей на самом деле очень много, но при тщательном разборе лога обращают на себя внимание два ключа, названия которых говорят сами за себя: HKCUSoftwareITTGames58RemainTime и HKCUSoftwareITTGames58TotalTime, то есть сколько времени осталось и сколько его всего соответственно.

Попробуем их изменить? От предвкушения близкой победы у нас пересыхает во рту и мы едва попадаем по клавишам. Однако все наши действия дают нулевой эффект, воздействующий только на «градусник» (линейку прогресса), но игра все равно завершается в положенный срок, несмотря на захаченный реестр.

Собственно, этого и следовало ожидать. MS Backup не сохраняет HKEY_CURRENT_USER, следовательно, значения, содержащиеся в этой ветви, используются защитой исключительно в качестве вспомогательных данных (например, для быстрой отрисовки «градусника» без актуального запуска защитного механизма). Впрочем, такой трюк ничуть не усложняет взлом (во всяком случае, для тех, кто помимо монитора реестра владеет техникой отладки и знает ассемблер как свой хвост родной).

Но, прежде чем бросаться в объятия дизассемблера, нелишне запустить API-шпион, чтобы узнать, с какими системными функциями работает защита и в каком направлении нам вообще копать. API-шпионов много. Лично я предпочитаю бесплатный Kerberos от Рустема Фасихова.

Однако, если просто скормить ему имя исполняемого файла (в данном случае showcase.exe), ничего хорошего не получится и программа завершится, не успев еще начаться, с сообщением о неправильной установке. Создается такое впечатление, что она содержит мощные антиотладочные приемы, сопротивляющиеся шпионажу, но на самом деле все гораздо проще!

В командной строке игра ожидает получения определенного параметра, равного (в случае Age of Japan) числу 97, что легко выяснить, щелкнув правой клавишей мыши по ярлыку с веером и как следует изучив его свойства. От глаз опытного хакера ничто не скроется!

Запускаем Kerberos еще раз, явным образом прописав аргумент 97 в параметрах командой строки (разумеется, в твоем случае это значение может быть другим), жмем на Inject и даем ему поработать до появления основного игрового поля на экране. После этого выходим из программы и приступаем к анализу отчета, сохраненного в файле showcase.rep и содержащего сотни тысяч строк, преимущественно состоящих из повторяющихся функций, так что пара банок пива нам не помешает.

Подавляющее большинство API-функций совершенно обычны по своей природе и сохранять значение в реестре (или за его пределами) не могут. Однако наше внимание привлекает серия функций с префиксом LSA (Local Security Authority), использующихся для хранения секретных криптографических ключей (и другой конфиденциальной информации) в Защищенном хранилище, доступа к которому не имеет даже администратор!

Так-так-так! Уже тепло, если не сказать жарко! Пахнет чем-то паленым, наверное, защита горит, точнее, догорает. Еще немного – и мы ее взломаем!

Битва за LSA

По замыслу разработчиков NT, доступ к секретной информации должна получать только та программа, которая ее туда положила. Между тем функции LsaRetrievePrivateData/LsaStorePrivateData, дающие доступ ко всем секретным данным, существуют еще со времен NT 4.0, хоть и остаются недокументированными (типа для внутренних нужд системы). Однако сейчас о них знает каждый (или практически каждый) хакер. Физически они сосредоточены в файле WINNTsystem32configSAM, монтируемом на ветвь системного реестра HKLMSECURITYPolicySecrets, доступ к которому имеет только System, но, увы, не администратор!

Тем не менее мы можем написать несложную утилиту, читающую и записывающую секретные данные с помощью API-функций LsaRetrievePrivateData/LsaStorePrivateData, что позволит нам получить неограниченный триал. Вся проблема в том, что мы не знаем, в какой именно слот игра записывает свои данные. Более того, прежде чем править эти данные (а они зашифрованы), в них как минимум следует разобраться, анализируя мегабайты дизассемблерного текста, что утомительно, непродуктивно и опять-таки не универсально (а ведь наша цель — универсальный взлом!).

К счастью, существует множество бесплатных LSA-шпионов, например «Каин и Авель» (Cain-n-Abel), услугами которого мы и воспользуемся. Запускаем его на стерильной машине (то есть до установки любой из тех игр, что представлены на games.mail.ru), переходим в раздел LSA Secrets, нажимаем кнопку «+» на панели инструментов и получаем дамп секретов в шестнадцатеричной форме.

Затем устанавливаем Age of Japan (или любую другую игрушку), повторяем сканирование вновь и… ага! В дампе появляется пара слотов вида L$DTnn, L$DTnn_, где nn – некоторое число, например, равное 22. Поиграем немного и повторим сканирование LSA еще один раз. Слоты L$DTnn, L$DTnn_ изменились, в то время как остальные остались без изменений.

Таким образом, мы нашли, где защита прячет свои данные, и теперь остается придумать, как уговорить ее продолжить работу даже после истечения триала.

Техника взлома

Мы находимся на финальной стадии взлома, но от самого взлома нас отделяет выбор из множества путей. Можно, например, написать перехватчик, подменяющий вызовы LSA-функций своими собственными процедурами, лишь имитирующими запись в Защищенное хранилище, но не осуществляющими ее физически. Это довольно универсальный способ, работающий со множеством триальных программ (а не только с теми, что с games.mail.ru), но ему присущи по меньшей мере два серьезных недостатка. Во-первых, это же сидеть и писать надо, то есть тратить время, шевелить мозгом и стучать по клавиатуре :). Во-вторых, некоторые программы действительно нуждаются в LSA и с подобным перехватчиком работать не будут, поэтому нам придется изобретать сложный эвристический механизм, позволяющий отличить «защитные данные» от честных криптографических ключей. LSA интенсивно используется системой (особенно Server 2003), и потому автоматический перехват приводит к развалу Windows, в чем я уже успел убедиться.

На самом деле для взлома ничего своего писать не нужно — вполне хватит и штатных средств в виде редактора реестра. Вот только заглянуть в нужную ветвь, даже с правами администратора, никак не получится. Нас просто туда не пустят! Ведь это все-таки Защищенное хранилище, а не проходной двор! Но ведь не писать же из-за этого целый драйвер?

Разумеется, нет! Достаточно воспользоваться штатным планировщиком, запускающим приложения с привилегиями System, позволяя нам просматривать и модифицировать все ветви реестра без исключения (в том числе и защищенные).

Запускаем regedit32 (полноценный 32-битный редактор реестра), указав время, на минуту или две опережающее текущее, и терпеливо ждем. Если редактор на экране не появится, значит мы забыли задать ключ /interactive» или служба планировщика отключена. Зайди в раздел «Службы» и включи.

Идея – экспортируем пару ветвей L$DTnn/L$DTnn_ в reg-файлы, а когда игровое время закончится, просто импортируем их оттуда (внимание: просто навести курсор на reg-файл и нажать на <ENTER> явно недостаточно — у нас просто не хватит прав, и потому необходимо запустить редактор реестра через команду at.exe и выполнить импорт уже в нем с привилегиями System).

Действуя таким образом, мы можем продлевать игровое время бесконечное количество раз (как вручную, так и по расписанию, благо планировщик под рукой, а редактор реестра еще не разучился понимать ключи командной строки). Этот трюк особенно полезен для игр типа «бродилка», которые не позволяют сохранять состояние игрока, а бродить по ним можно часами, и так обидно, когда отпущенное время заканчивается на самом интересном месте, буквально в двух шагах от победы! Так что планировщик рулит!

А как быть, если мы спохватились слишком поздно и отпущенное нам игровое время уже истекло? Экспорт и импорт в этом случае ничего не дадут, но! Если набраться смелости и удалить пару ветвей L$DTnn/L$DTnn_, при следующем запуске игра сообщит, что она неправильно установлена и потребует переустановки, после которой… Правильно! Мы получим целый час законного игрового времени!

Заключение

Вот мы и поломали Age of Japan, а вместе с ней и все остальные игры с games.mail.ru, включая многочисленные триальные защиты, скрывающие данные в LSA. При этом назвать эти действия «взломом» язык не поворачивается! Ведь код и данные игры остаются нетронутыми, ну а из своего собственного защищенного хранилища мы вправе выкидывать всякий мусор, который туда записывается без нашего ведома.

By Ruslan Novikov

Интернет-предприниматель. Фулстек разработчик. Маркетолог. Наставник.