Загрузка...

Не могу до конца понять работу обхода античита в простой игре

Тема в разделе Реверсинг / Assembler создана пользователем Wayner 2 июн 2025 в 23:38. 83 просмотра

Загрузка...
  1. Wayner
    Wayner Автор темы 2 июн 2025 в 23:38 576 18 май 2019
    Имеется веб-приложение с играми (@g_amee) в тг. Напримере этой статьи , попытался отправить фейковый запрос в игре. Но сам код не работает, из-за проблемы с библиотекой. (Не удалось получить токены авторизации. Прерываю выполнение.)
    Код
    // gamee_score_sender.ts

    // --- 1. Импорты (необходимые для MD5 и работы с датами) ---
    import { md5 } from "@takker/md5";
    import dayjs from "https://cdn.skypack.dev/dayjs";
    import utc from "https://cdn.skypack.dev/dayjs/plugin/utc";
    import timezone from "https://cdn.skypack.dev/dayjs/plugin/timezone";
    dayjs.extend(utc);
    dayjs.extend(timezone);

    // --- 2. Ваши основные данные ---
    // ВНИМАНИЕ: gameAuthUrlPath НУЖНО ЗАМЕНИТЬ НА СВОЙ АКТУАЛЬНЫЙ URL ИЗ ПРИГЛАШЕНИЯ В ИГРУ!
    // Пример: "/game-bot/astrocat-c6d185e817410ccca2fe1d3a8fa929403e1c68ac"
    const gameAuthUrlPath = "/game-bot/***"; // <--- замена

    // Секретный ключ для checksum
    const checksumSecretSuffix = "crmjbjm3lczhlgnek9uaxz2l9svlfjw14npauhen";

    // --- 3. Функции для выполнения действий ---

    // Функция для получения токенов авторизации
    async function getAuthTokens(): Promise<{ authToken: string; installUuid: string } | null> {
    console.log("1. Пытаюсь авторизоваться и получить токены...");
    try {
    const authRes = await fetch("https://api.gamee.com/", {
    method: "post",
    body: JSON.stringify({
    jsonrpc: "2.0",
    id: "oauth.token",
    method: "oauth.token",
    params: {
    gameUrl: gameAuthUrlPath,
    // UUID устройства. Можно использовать `crypto.randomUUID()` для нового,
    // или тот, что был в твоем "слизанном" запросе авторизации.
    uuid: crypto.randomUUID(), // генерация нового
    },
    }),
    headers: {
    "Content-Type": "text/plain;charset=UTF-8",
    "Origin": "https://prizes.gamee.com",
    },
    });
    const authData = await authRes.json();

    if (authData.error) {
    console.error("Ошибка авторизации:", authData.error.message, authData.error.data);
    return null;
    }

    console.log("Авторизация прошла успешно!");
    return {
    authToken: authData.result.accessToken.token,
    installUuid: authData.result.installUuid,
    };

    } catch (error) {
    console.error("Произошла ошибка при запросе авторизации:", error);
    return null;
    }
    }

    // Функция для отправки игровых данных
    async function sendGameplayData(tokens: { authToken: string; installUuid: string }) {
    console.log("\n2. Готовлю данные для отправки игрового раунда...");

    // --- ВАЖНО: Эти значения ты можешь менять для каждого нового раунда ---
    const gameId = 125; // ID игры
    const scoreToSend = 5000; // ТВОЙ ЖЕЛАЕМЫЙ СЧЕТ! Укажи здесь сколько хочешь очков.
    const playTimeToSend = 180; // Время игры в секундах.
    const gameUrl = "/game-bot/***"; // URL конкретной игры
    const releaseNumber = 6;
    const gameStateData = null; // Если есть состояние игры, оно пойдет сюда (может быть JSON-строкой)
    const gameplayId = 129; // Этот ID может быть статичным или должен увеличиваться (проверь)

    // Генерируем новый UUID для каждого раунда, чтобы избежать ошибки "Gameplay already exists"
    const roundUuid = crypto.randomUUID();

    // Форматируем текущее время в нужный формат "YYYY-MM-DDTHH:mm:ss+**:mm"
    const currentCreatedTime = dayjs().format("YYYY-MM-DDTHH:mm:ssZ");

    // Вычисляем checksum по сложной формуле, которую мы нашли
    const calculatedChecksum = md5(
    `<span class="math-inline">\{scoreToSend ?? 0\}\:</span>{playTimeToSend ?? 0}:<span class="math-inline">\{gameUrl\}\:</span>{
    gameStateData ?? ""
    }:<span class="math-inline">\{roundUuid\}\:</span>{checksumSecretSuffix}`,
    );
    console.log("Вычисленный checksum:", calculatedChecksum);

    console.log("\n3. Отправляю данные игрового раунда...");
    try {
    const res = await fetch("https://api.gamee.com/", {
    method: "post",
    body: JSON.stringify({
    jsonrpc: "2.0",
    id: "game.saveWebGameplay",
    method: "game.saveWebGameplay",
    params: {
    gameplayData: {
    gameId: gameId,
    score: scoreToSend,
    playTime: playTimeToSend,
    gameUrl: gameUrl,
    releaseNumber: releaseNumber,
    createdTime: currentCreatedTime,
    metadata: {
    gameplayId: gameplayId,
    },
    isSaveState: false,
    gameStateData: gameStateData,
    gameplayOrigin: "game",
    replayData: null,
    replayVariant: null,
    replayDataChecksum: null,
    uuid: roundUuid,
    checksum: calculatedChecksum,
    },
    },
    }),
    headers: {
    "Authorization": `Bearer ${tokens.authToken}`, // Используем полученный токен
    "Content-Type": "text/plain;charset=UTF-8",
    "Origin": "https://prizes.gamee.com",
    "Accept": "*/*",
    "Referer": "https://prizes.gamee.com/",
    "User-Agent":
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15",
    "Accept-Language": "en-US",
    "Sec-Fetch-Dest": "empty",
    "Sec-Fetch-Mode": "cors",
    "Sec-Fetch-Site": "same-site",
    "client-language": "en",
    "x-install-uuid": tokens.installUuid, // Используем полученный installUuid
    },
    });

    const data = await res.json();
    console.log("\n--- Ответ сервера после сохранения геймплея ---");
    console.log(data);

    if (data.error) {
    console.error("\n!!! Ошибка при сохранении геймплея:", data.error.message);
    if (data.error.data && data.error.data.reason) {
    console.error("Причина ошибки:", data.error.data.reason);
    }
    } else {
    console.log("\n Геймплей успешно сохранен!");
    }

    } catch (error) {
    console.error("\n Произошла ошибка при выполнении запроса сохранения геймплея:", error);
    }
    }

    // --- 4. Запускаем все действия по порядку ---
    async function main() {
    // Сначала получаем токены
    const tokens = await getAuthTokens();

    // Если токены получены успешно, отправляем данные геймплея
    if (tokens) {
    await sendGameplayData(tokens);
    } else {
    console.error("Не удалось получить токены авторизации. Прерываю выполнение.");
    }
    }

    // Вызываем основную функцию
    main();
    Очень прошу совета опытного реверсера .
     
Top