• XSS.stack #1 – первый литературный журнал от юзеров форума

Реверс мини-игры в хомяке

exx1v

floppy-диск
Пользователь
Регистрация
22.08.2024
Сообщения
2
Реакции
3
Привет.
Я пытаюсь разгадать, как получить монеты в хомяке, не играя в мини-игру Hexa Puzzle (в исходниках она называется Tiles, поэтому дальше буду называть её так).
Эта мини-игра написана на движке Defold, язык Lua и скомпилирована в wasm модуль (на самом деле там несколько игр, все в одном модуле).
Суть игры - собирать пазлы и доходить до как можно большего уровня, чтобы получить больше монет.

    • DefoldGames_wasm.js
    • DefoldGames.wasm
    • archive/archive_files.json
    • archive/game0.arcd
    • archive/game0.arci
    • archive/game0.dmanifest
    • archive/game0.projectc
    • archive/game0.public.der
При запуске игры в неё передаются следующие параметры:
JavaScript:
{
    method: 'StartGame',
    level: '', // не используется, всегда пустая строка
    number: 1725188400, // дата обнуления результатов (ежедневно в 11:00 UTC)
    score_coef: 9072, // коэффициент
    start_timestamp: 1725203396 // дата запуска игры
}

Дальше, во время игрового процесса никакие важные данные не передаются.

При завершении игры на выходе получаются такие данные:
JavaScript:
{
    method: "OnGameFinished",
    cipher: e, // число. в моих результатах всегда начиналось с 0
    game_id: n, // название игры
    score: a, // счёт. В самой игре считаются уровни, а на выход отдаётся счёт. score = number + level * 2 (number это дата обнуления результатов (ежедневно в 11:00 UTC))
    sig: s // подпись в base64. Если декодировать его, получаются непонятные данные, всегда одинаковой длины.
}

Вот примеры выходных данных для уровня 13 и уровня 10
JavaScript:
{
    method: "OnGameFinished",
    cipher: 0260232939,
    game_id: "Tiles",
    score: 3450376826, // уровень 13
    sig: "28/PujisAwETtmHNLzB856lu6crK1CJ9g1ZeXYxyXBw="
}
{
    method: "OnGameFinished",
    cipher: 0180064280,
    game_id: "Tiles",
    score: 3450376826, // еще раз уровень 13
    sig: "oRs1rXAC6ZGrq5HVLLukt8W40VCs2ydWTnJ1NcmY0Aw="
}
{
    method: "OnGameFinished",
    cipher: 0260232939,
    game_id: "Tiles",
    score: 3450376826, // еще раз уровень 10
    sig: "HqY+rcoS/MLndiAsG8Sv6s9aOAGi6DKpvmFyOia0NgY="
}
{
    method: "OnGameFinished",
    cipher: 0330928596,
    game_id: "Tiles",
    score: 3450376826, // еще раз уровень 10
    sig: "YHSsQzexicUQb+a/3caxeZjbUTCld995J+DGbiwZLU4="
}

Нужно разгадать, как получается подпись sig.
Данные, содержащиеся в подписи на скриншотах:
1725208868703.png
1725208846986.png



В файле archive/game0.public.der содержится публичнй ключ RSA, нужен он или нет, не понятно.
Для подписи нужен приватный ключ, его я не нашёл.
Если шифровать данные, то даже для самой короткой строки получается слишком длинный шифр.

Подумал, может быть приватный ключ лежит прямо в коде.
Дизассемблировал wasm с помощью Ghidra, искал только строки, но не нашёл ничего интересного.
Пробовал делать дамп памяти в браузере, тоже самое.

Подскажите куда двигаться дальше? Каким алгоритмом может быть сделана такая подпись?
 
В бинарнике васма искал по названию полей в json'e? "method", "sig", "score" и т.д. Потом оттуда смотришь xref кто дергает функцию генерации и на каком то из этапов находишь функцию генерации sig для того чтобы собрать json. Еще важно понимать специфику того из чего компилили васм, то есть это go/rust/C?
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх