Как взломать вампира или История одного нубохака
Пролог
Пару лет назад на просторах интернета столкнулся с многообещающей игрой с фурри-проном в вампирской тематике. Игра называлась (и называется) “Vampire Life”. Вампирскую тематику я люблю, рпг уважаю, название намекает на некий симулятор, что тоже неплохо, а вот фурри прон мне заходит ситуативно, т.к многие автора плохо видят границу с зооеблей. Пожалуй, решающим аргументом в пользу скачивания стала необычная рисовка: мультяшная, будто рисовали кисточкой, без нарочитого нарушения пропорций тел и черт лица, чем нынче грешат (грешили и будут грешить) многие ленивые художники называя это “авторским стилем”. В описании на торрентах создатель честно предупредил что в игре присутствует гринд… нет, не так - много гринда, и это несколько настораживало, но я все же решил рискнуть, в конце концов - гринд гринду рознь, и как показало время страхи были не беспочвенными.
Часть 1: Суть игры и мотивация к взлому
Пару лет назад на просторах интернета столкнулся с многообещающей игрой с фурри-проном в вампирской тематике. Игра называлась (и называется) “Vampire Life”. Вампирскую тематику я люблю, рпг уважаю, название намекает на некий симулятор, что тоже неплохо, а вот фурри прон мне заходит ситуативно, т.к многие автора плохо видят границу с зооеблей. Пожалуй, решающим аргументом в пользу скачивания стала необычная рисовка: мультяшная, будто рисовали кисточкой, без нарочитого нарушения пропорций тел и черт лица, чем нынче грешат (грешили и будут грешить) многие ленивые художники называя это “авторским стилем”. В описании на торрентах создатель честно предупредил что в игре присутствует гринд… нет, не так - много гринда, и это несколько настораживало, но я все же решил рискнуть, в конце концов - гринд гринду рознь, и как показало время страхи были не беспочвенными.
Часть 1: Суть игры и мотивация к взлому
Сама игра выполнена на (в?) рпгмэйкере, управление интуитивное, уже в то время (пару лет назад) в игре большинство стоковых ассетов было заменено, что делало визуал более свежим, приятным и приближало его к сеттингу. Сам протагонист - вампир, который проснулся в своем “логове” (на деле - грязной пещере), будучи голым, нищим и потерявшим всю свою силу, навыки и память (если таковые были) за время сна. Клише конечно, но, будем откровенны, большинство сюжетных ходов было изобретено еще в античные времена, так что на данный момент все зависит главным образом от авторской подачи. Вампир знакомится со своей верной, но бестолковой слугой, с жителями поселения которое находится на выходе из логова и решает зарабатывать на жизнь отловом и продажей в рабство/на опыты фурри-розбійників (называемых в игре морфами), что в обилии обитают в тамошних местах, параллельно поебывая тех самых фурри, по возможности не обходя стороной и обычных неписей.Игра обладает множеством механик: потребности (еда, вода, сон, иммунитет), шмотки и оружие, их заточка, крафт, отстройка логова, отношение с неписями, прокачка навыков, зелья, артефакты и т.д., что, хоть и может крепко увлечь на первых порах, в дальнейшем становится рутиной и источником необходимости гриндить для получения новых элементов прогрессии все больше и больше (в оффлайн игре!).С первых секунд игры появляется ощущения что тебя троллят.., нет - откровенно издеваются. Причем не как над персонажем, а как над игроком, и в дальнейшем эти ощущения только усиливаются. Регулярно возникают игровые ситуации, которые требуют значительной прокачки (явно больше чем может иметь игрок попавший в них на старте) или метаинформации, и в случае провала значительно тормозят прогресс игры (еще больше гринда). Самого гринда много: мало лута, мобы имеют рандомные статы, требования по ресурсам для прогрессии значительные. И по мере самой прогрессии только растут. При таких вводных очевидно, что накрутить себе нужных параметров условным артмани становится удобным решением для пропуска дрочи (в плохом смысле), и переходу непосредственно к новой порции контента. И тут меня ждал сюрприз: разработчик озаботился защитой от желающих срезать углы.
Часть 2: Взлом начинается
Так как никакие попытки найти нужные мне значения с использованием тулзов проде читэнжина или артмани не увенчались успехом (и я позже поясню почему), была предпринята попытка модификации сейв файла. Благо что движок популярный - онлайн эдиторы присутствуют, а сам сейв должен являть собой сырой JSON (в теории). В реальности, меня в этот раз постигла неудача - онлайн тулза для модификации сохранений упорно рапортовала об ошибке чтения. Решил заглянуть в сам файл и поглядеть что там не так, и таки что я там вижу? Строка из букв разных кейсов, крайне похожая на нечто заэнкоженное в Base64. Но увы, походить не значит являться (АУФ!) - снова неудача. К тому моменту мной уже плотно овладел азарт, мне было пофиг на геймплей, я хотел решить этот пазл, и очевидно низкий технический уровень разработчика, который просматривался сквозь декорации игры давал надежду что у меня получится. Не можем прочитать сейв? Тогда бы почему не открыть сам проект?Ищу в стиме Rpgmaker MZ, смотрю на цену, вспоминаю что я далеко не самый состоятельный человек в нищей восточноевропейской стране, и отправляюсь в зеленый стим. Ставлю и вылечиваю Мэйкер, создаю новый проект и копирую в него ресурсы из игры. Чуда не произошло - ресурсы не читаются. Открываю файлы ресурсов - там те же закодированные строки заместо джейсонов, как и в сейвах. Т.к чудес очевидно не бывает, и игра все-же должна как-то уметь читать свои же ресурсы, то она явно хранит в себе некий декриптор или декодер который превращает буквенное месиво в джейсон. Пришла пора лезть в код.
Как выглядели ресурсы игры |
Часть 3: Пора кодить
Как в любом приличном проекте на рпгмэйкере , в файлах игры лежит движок, написанный на JS, и который, как я подозревал, был модифицирован автором игры для защиты от взлома и модификации. Хоть я и большую часть времени я пишу на Java, в моей жизни было два года, когда я работал на проекте где приходилось совмещать 50/50 джаву с Node JS. Научившись в свое время отличать асинк от авэйта, промис от колбэка, и запомнив все 6 (или 7?) типов которые существуют в JS я подходил к разбору кода со сдержанным оптимизмом. Который чуть было не иссяк стоило мне увидеть код. ВСЕ было написано на прототипах, на которых писал еще мой прадед в перерывах между охотой на мамонтовую фауну и наскальной живописью. Было ли то результатом некой компиляции из typescript либо невозможностью (или нежеланием, что по сути одно и то же) разработчиков движка добавить в него поддержку es6 я не знал, да и к сути задачи оно не относилось. Через непродолжительное время копания в коде, мною было обнаружено что весь кастомный код содержится в папке /plugins, что весьма логично, в коде есть захардкоженный список ресурсов которые енкриптятся особо, а искомый декриптор, очевидно кастомный, созданный автором игры, хранится в PKD_Protector.js.
Фрагмент того самого обфусцированного протектора |
К слову, в процессе перебора исходников пришло понимание почему в артмани не работает поиск: каждая переменная в памяти игры хранится в двух полях. Условно А и Б. Истинное_значение = A - Б, где Б генерируется случайно при каждом изменении переменной. Таким образом, для поиска условного артмани обе цифры в памяти меняются как-бы случайным образом. Или не меняются, т.к рандом может и совпасть.
И как всегда ложка дегтя: код декриптора был обфусцирован (переписан с сохранением синтаксиса языка, но в нечитабельной для человека форме). Это уже успех - запустив этот скрипт можно получить чистые исходники ресурсов для последующего их открытия в Rpgmaker MZ. В теории. Но на практике посмотреть и изменить ресурсы и скрипты игрового процесса мало - нужно еще вложить их на старое место предварительно зашифровав обратно. А для этого нужен был алгоритм шифрования. Обфусцированного кода всего 300 строк, что очень немного. Расставляю брейкпоинты, запускаю дебаггер помечаю используемые строчки кода и значения. Спустя полчаса алгоритм дешифрования найден и переписан в явном виде (всего в 20 строк). Еще 3 минуты на написание и проверку обратного алгоритма. Запустил сразу на все содержимое папки /data, и получил исходники ресурсов. Теперь (наконец-то!) можно переходить в Rpgmaker MZ и насладится творчеством разработчика.
Как было оно было задумано разработчиком (логика сохранен) |
Часть 4: Глубже в кроличью нору
Еще на этапе игры меня не покидало чувство, что игру делал человек с сильным желанием, хорошей фантазией, большими амбициями но малым опытом в разработке. когда я увидел ресурсы игры мое мнение превратилось в твердую уверенность, с чувством легкого уважения к человеку, который не умея толком кодить, не зная английского языка и изобретая велосипеды по пути, смог сделать (и заставить работать) потенциально многообещающий продукт. Далее просто приведу перлы которые я успел найти в коде:
Естественно, что обладая буквально авторскими возможностями в игре сложно сохранить интерес к геймплею, так что я выдав персонажу все нужное для завершения прохождения текущего билда быстро просмотрел оставшийся в игре контент и отчалил.
Часть 5: Выводы
Мне очень понравилась концепция заложенная в игру “Vampire Life”, у проекта хорошие интенции, и мне жаль что местами проект портит неуместный йумор и баланс настроенный на гринд. Сам проект висит на патроне уже б-г знает сколько и как по мне, разработчику пока остановится с новым контентом, потратить время на починку старого, выправить баланс и релизится с чистой совестью. На полноценную игру контента хватит с головой, хватит сосать из патронов шекели. Удачи разрабу во всем, надеюсь мой пост будет компенсацией за то, что поиграл в версию с разблокированными возможностями так и не занеся ему денег
P.S. Этот пост должен был выйти в день моей днюхи, но слегка запоздал. Не являясь активным участником срачей или контентмейкером реактора я посчитал нужным вместо фотки кота, торта и монитора (у меня и кота то нет), что было бы крайне неуместно и нагло с моей стороны, угостить честной люд вкусным контентом - так будет правильно
P.S. Этот пост должен был выйти в день моей днюхи, но слегка запоздал. Не являясь активным участником срачей или контентмейкером реактора я посчитал нужным вместо фотки кота, торта и монитора (у меня и кота то нет), что было бы крайне неуместно и нагло с моей стороны, угостить честной люд вкусным контентом - так будет правильно