Что нужно?
Как не странно - нам понадобится apk нашего приложения
Так же для автоматизации процесса понадобится немного собственного софта. Я предпочитаю использовать питон
Среда для разработки, у меня это vs-code
Любой 16-ричный редактор, у меня это расширение для vs code
Let`s start!
Для начала посмотрим что мы вообще имеем
APK файлы представляют из себя самый обычный zip архив, который можно открыть любым архиватором. Распакуем файлы в какую нибудь папку
Бегло пробежав по файлам можно обнаружить файлы с кодом на lua
Открыть эти файлы просто так не получится - они зашифрованы. Но все эти файлы объеденяет одно - слово signatr в самом начале. Пока что отложим эту информацию и пойдем дальше
Зайдем в папку lib и перейдем к нужной архитектуре - я обнаружил один единственный .so файл
Попробуем просмотреть его через hex-редактор
Много непонятного текста, но если полистать ниже - можно найти читаемые строки!
Введем в поиск слово которое получили ранее - signatr
Слева от этого результата есть непримечательное слово. Чтож, это слово - это наш ключ шифрования. Давайте попробуем им воспользоваться
Напишу простой скрипт на питоне для дешифровки методом xxtea
import xxtea # pip install xxtea
file = 'client.luac'
sign = 'signatr'
key = 'anyxteakey'
with open(file, 'rb') as f:
filedata = f.read()
filedata = filedata[len(sign):] # обрежем начало файла чтоб убрать 'signatr'
data = xxtea.decrypt(filedata, key) # Дешифруем ключом
with open('test.lua', 'wb') as f:
f.write(data)
Запустим скрипт и получим файл test.lua
Все сработало! Мы получили расшифрованный файл
Осталось только сделать обертку для скрипта декодирования и реализовать рекурсивное декодирование в папках
import os
import xxtea
sign = 'signatr'
key = 'anyxteakey'
def recursive_decrypt(directory):
files = os.listdir(directory)
for f in files:
if os.path.isdir(directory + "/" + f):
recursive_decrypt(directory + "/" + f)
else:
if f.endswith(".luac"):
print("Decrypting", f)
data = b""
with open(directory + "/" + f, "rb") as file:
data = file.read()[len(sign):]
decrypted = xxtea.decrypt(data, key)
if decrypted:
with open(directory + "/" + f[:-1], "wb") as file:
file.write(decrypted)
os.remove(directory + "/" + f)
else:
print("Failed to decrypt", f)
От себя я так же добавил функцию очистки, что бы убрать пустые папки и не lua файлы
import shutil
def post_clean(directory):
# delete all not lua files
ls = os.listdir(directory)
if not ls:
shutil.rmtree(directory)
print("Removed", directory)
return
for file in os.listdir(directory):
if os.path.isdir(directory + "/" + file):
post_clean(directory + "/" + file)
elif not file.endswith(".lua"):
os.remove(os.path.join(directory, file))
print("Removed", file)
if not os.listdir(directory):
shutil.rmtree(directory)
print("Removed", directory)
Вот и все.
Спасибо за внимание :)
dimitrii_z
Плохая защита продукта.. С одной стороны, мало кто до этого додумается, с другой теперь статья будет гуглиться. Это opensource продукт, а думали придумать как улучшить защиту, и/или обсудить это с основными участниками проекта https://github.com/cocos2d/cocos2d-x ?
guhbap Автор
Как говорится - кто ищет, тот найдет. Я был бы рад помочь продукту, но мне недостаточно знаний в области безопасности и шифрования в частности. В своей статье я лишь привел способ, к которому пришел после поиска и анализа десятков тредов по реверсу с различных форумов и статей. Описанная проблема в шифровании файлов существует уже не первый год и была описана например тут.
domix32
Некоторые студии делят основную игру и загружаемый бандл, который подтягивается отдельно. Раньше это делалось для того чтобы пройти в лимиты сторов (когда-то можно было быть не тяжелее 50 мб в гуглсторе, например), теперь фактически используется для обновлений и защиты - зашивается сертификат к родным серверам и качается через HTTPS - возись теперь с MITM. Обычно заморачиваться с бОльшей защитой скриптов смысла нет. Альтернативный вариант - пережимать все скрипты и распаковывать их при запуске, но опять же - защита скриптов особо не нужна.
Экономический эффект для игровой кампании от этого примерно никакой и даже если кому-то и удастся их выковырнуть - что он с ними делать будет?
В качестве кода использовать не сможет - сторы могут и забанить за такое, если апроприация чужого кода будет обнаружена
сварганить на основе этого свою игру - да ради бога, код не самое ценное в данной ситуации с учётом предыдущего пункта
соберёт кастомный бандл и выложит на какой-нибудь 4pda - опять же особых проблем с этим нет, т.к. экономический эффект для игровой кампании обычно достаточно низкий. В случае чего задетектить и прописать бан игроку с палёным клиентом будет достаточно просто, но обычно никто с этим не заморачиается, т.к. большинство мобильных игр и без того f2p.
Вся финансовая логика (вроде внутренней валюты) обычно зашита в компилируемой части приложения и не страдает от вскрытия бандлов.