Как взломать Among Us

Как взломать Among Us

Moody

Милые, неуклюжие персонажи в форме желейных подушечек - одно из многих забавных увлечений охвативших интернет. Являетесь ли вы поклонником игр или нет, вы, несомненно, слышали о Fall Guys и Among Us. Помимо того, что они великолепны в разрушении дружеских отношений, эти две игры не только обеспечили огромное количество фана за последние несколько месяцев, но и стали жертвой невероятного количества читеров. В этом посте я рассказываю о распространенности читерства в популярных видеоиграх на примере «Among Us» и «Fall Guys».

Fall Guys обрел невероятную популярность в первый же день релиза. Однако, через пару недель стало очевидно, что огромной проблемой игры стали читеры. Пользователи Reddit, Twitter и других платформ постоянно жаловались на то, как много было читеров, прикрепляя скринкасты. Вот несколько примеров:

В читерстве, конечно, нет ничего нового, но оно редко бывает настолько вопиющим, чтобы вызывать массовые протесты со стороны игроков и фанатов, каким мы это видели в Fall Guys. Почему читерство в Fall Guys так распространено? Что ж, на это непросто ответить объективно, но я лично считаю, что это связано с двумя основными факторами:

  1. Инструменты и ресурсы для разработки и публикации высококачественных и доступных игр никогда не отличались качеством, особенно в руках небольших независимых студий.
  2. Разработчики игр часто не имеют ресурсов - времени, денег, опыта и т. д., и часто вынуждены отдавать приоритет новому контенту, вместо того чтобы работать над невидимыми глазу функциями, одной из которых является защита от читеров.

Протесты из-за читеров в Fall Guys были настолько громкими, что разработчики сочли необходимым дать публичный отклик. В их первом ответе говорилось о том, что они усилят меры по борьбе с читерами, которые уже присутствовали в игре. Ветку в твиттере с подробным описанием можно найти здесь. К сожалению, этих усилий оказалось недостаточно.

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

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

Fall Guys - не единственная игра, в которой есть недостатки. Это просто последняя известная игра, которая разработана без строгих мер безопасности или защиты от читерства, принятая во внимание огромным количеством игроков с первого дня своего существования. Вот пара ссылок о других недавних недостатках в видеоиграх. Каждое из следующих видео представляет собой выступление на ежегодной хакерской конференции DEF CON:

  • В 2020 году Джек Бейкер рассказал о ряде недостатков Unity и Unreal Engine. В настоящее время это два самых популярных движка для разработки игр. Fall Guys и Among Us были разработаны с помощью Unity.(https://www.youtube.com/watch?v=4weoWSzuCxs)
  • На DEF CON 25 Манфред рассказал о своей истории взломов различных MMO за последние 20 лет. По сути, игры стали более проработанными, но лазейки остались прежними. (https://www.youtube.com/watch?v=ZAUf_ygqsDo)
  • На DEF CON 23 Тамас говорил о возможности удаленного выполнения кода на компьютерах других игроков с помощью пользовательских карт в таких играх, как DotA 2 и Garry’s Mod. (https://www.youtube.com/watch?v=XxyRDkmNMHg)

Читы среди нас

Наконец, давайте заострим внимание на «Among Us». Не смотря на то, что игра была выпущена несколько лет назад, ее популярность резко выросла когда в нее начали играть популярные стримеры на Twitch. Фактически, она стала настолько популярной, что даже конгрессмен AOC появилась на Twitch, чтобы провести мероприятие «Выйди на голосование» во время игры: https://www.theverge.com/2020/10/20/21526164/aoc-among-us-twitch-debut-top-concurrent-viewers.

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

Проводя исследования за игрой в Fall Guys, я наткнулся на множество используемых читов. От игроков, рассылающих политический спам (https://kotaku.com/mass-among-us-hack-forces-players-to-advertise-hackers-1845464612) или каналах массовой рекламы на YouTube, до тех, кто просто хочет испортить всем удовольствие. Кроме того, стало ясно, что читерство в этой игре со временем только увеличилось, так как она стала чрезмерно популярной.

Вот неполный список возможностей читов, с которыми я столкнулся когда играл в Fall Guys:

  • Выявление предателя
  • Выдача себя за других игроков
  • Отправка сообщений в чате от имени других игроков
  • Изменение цвета своего персонажа или персонажей других игроков
  • Смена имен игроков
  • Проход сквозь стены
  • Удаление тумана войны
  • Убийство предателя
  • Возможность убивать других игроков, будучи не предателем
  • Удаление кулдаунов для задач, убийств, звонков на собрания и т. д.
  • Контроль над другими игроками
  • Возможность кикать и блокировать игроков, не являясь админом
  • Вторжение в приватные сессии
  • Доступ к платному контенту без оплаты (например, питомцы из DLC, головные уборы и другие косметические предметы)
  • Возрождение себя или других игроков
  • Повышение скорости персонажа
  • Телепортация игроков
  • Снятие банов (если вас кикнули с сервера, вы можете сами снять бан и снова присоединиться)
  • Возможность отмечать задачи как выполненные, но не выполнять их
  • И многое другое...

Как это возможно? Дело в том, что на стороне сервера отсутствует валидация действий и взаимодействий игроков. Это означает то, что, манипулируя игровым клиентом, игроки могут изменять определенные значения, которые влияют на игровой процесс. Существуют механизмы, которые можно использовать для предотвращения многих из этих читов (например, проверка совпадения идентификаторов игрока и клиента при обмене данными с сервером), но в этой игре их просто нет.

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

Прежде чем я углублюсь в технические подробности, хотелось бы сформулировать несколько вещей:

  1. Моя статья не предназначена для того, чтобы критиковать разработчиков или говорить о них плохо. Это совершенно фантастическая игра. Она создана компанией, в которой всего три сотрудника, среди которых только один программист.
  2. Мое исследование возможностей обхода средств защиты завершилось в середине октября 2020 года. С тех пор я не возвращался к теме читов в этой игре. Я не могу комментировать дальнейшие улучшения безопасности, которые имели место быть или были устранены с тех пор.
  3. Как упоминалось ранее, в ходе исследования я не обнаружил никаких проблем, связанных с безопасностью, помимо недостатков, вроде уязвимости к DOS. Мои попытки связаться с Innersloth остались без ответа. Судя по их активности в социальных сетях, похоже, что они полностью осведомлены о многих из этих проблем, и прилагают все усилия, чтобы найти решения.

Препарирование Among Us

Давайте же, наконец, рассмотрим технические детали того, как хакеры могут создавать читы. Игра Among Us была разработана с использованием игрового движка Unity. Об этом свидетельствуют файлы из каталога с игрой:

К счастью для нас, Unity упрощает изучение логики игрового процесса. Это позволяет программистам использовать различные языки программирования для разработки игр. Один из наиболее распространенных вариантов - C#. Во многих играх, которые разрабатываются для Windows, посмотреть исходный код абсурдно просто.

Давайте возьмем в качестве примера другую популярную сейчас игру, In Silence. При компиляции релизной версии игры Unity поместит всю пользовательскую логику игрового процесса в одну отдельную DLL. Ее имя по-умолчанию Assembly-CSharp.dll, однако оно может отличаться от игры к игре. Используя такие инструменты, как dotPeek или dnSpy, которые предназначены для декомпиляции бинарных .Net файлов и исследования кода, мы можем точно увидеть, как работает игра. Эти инструменты также позволяют нам изменять код и вносить изменения по своему усмотрению. Если на стороне сервера отсутствуют проверки того, вносились ли изменения в игровой клиент, игроки могут свободно использовать свои собственные модифицированные клиенты с читами.

Для «Among Us» защита достаточно тривиальна, поскольку игра также распространяется и на мобильных устройствах. Для реализации кроссплатформенной поддержки Unity использует нечто под названием IL2CPP (https://docs.unity3d.com/Manual/IL2CPP.html). Это делает код более громоздким. Тем не менее, существуют инструменты, позволяющие уменьшить головную боль. Например, IL2cppdumper сделает за нас большую часть тяжелой работы.

Выходные данные этого инструмента дают нам все необходимое для исследования игровых dll при помощи dnSpy, как в примере с InSilence выше. Главный нюанс здесь в том, что сама игровая логика во многом обрывчива. Это означает, что нам нужно прибегнуть к более традиционным методам реверс-инжиниринга с использованием Ghidra или другого подобного инструмента. К счастью, IL2CPPdumper может помочь нам, создав скрипт, который переименует и исправит дизассемблированный код.

Тут у нас есть несколько вариантов. Зная, что в игре отсутствует мощный античит-движок для обнаружения модификации клиента, мы можем его запросто изменить без последствий. Это не лучшая тактика, потому что всякий раз, когда разработчики выпускают обновления или патчи, ваш пользовательский клиент может перестать работать. На мой взгляд, следующий вариант, которым стоит воспользоваться - создать вредоносную DLL, которая будет перехватывает логику игру. Это не только делает читы более мобильными, но и более устойчивыми.

Я не собираюсь вдаваться в подробности о том, как выполнить DLL-инжект в этой статье. Вы можете взять готовый код для создания пользовательской DLL под игру из сниппета ниже.

Сначала запустим Visual Studio или любую другую, удобную вам, среду разработки, и создадим новый проект, в котором реализуем собственную динамическую библиотеку. Затем мы добавим еще немного кода, который сообщит нам, что DLL-инжект работает должным образом.

#include "pch.h"
#include <stdio.h>void insertConsole()
{
    // Spawn the console
    AllocConsole();// Set up the console for logging output and accepting input
    FILE* f = new FILE();
    freopen_s(&f, "CONOUT$", "w", stdout);
    freopen_s(&f, "CONIN$", "r", stdin);printf("[*] Injected...\n");
}BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    {
        DisableThreadLibraryCalls(hModule);// Spawn a new thread for our console/cheats when we attach to the process
        HANDLE hThread = CreateThread(nullptr, 0,
            (LPTHREAD_START_ROUTINE)insertConsole, hModule, 0, 0);
        if (hThread != nullptr)
            CloseHandle(hThread);
        break;
    }
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

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

Во-первых, немного потыкаем dnSpy, чтобы увидеть, не всплывает ли что-нибудь, явно связанное со скоростью игрока.

Затем укажем оффсеты в нашей чит-библиотеке. Если вы хотите, чтобы чит работал во всех патчах, можно создать сигнатуры для соответствующих функций, но сегодня не об этом. В большинстве случаев из-за вложенных свойств будет приличное количество беспорядочного разыменования. В Интернете есть множество сниппетов и библиотек, которые помогут с решением этой проблемы, но сегодня мы сделаем все быстро и грязно. Обратите внимание, что представленный код и оффсеты на скриншотах могут незначительно отличаться из-за того, что вы увидете у себя.

void commandLoop()
{
    // Create a reference to the library we plan on using
    auto hLib = LoadLibraryA("GameAssembly.dll");
    printf("[*] GameAssembly.dll located at: %x\n", hLib);// Working backwards from the speed variable found in dnSpy,
    // create references to all the necessary pieces to the puzzle
    uintptr_t* player_typeinfo = (uintptr_t*)((uintptr_t)hLib + 0x1468910);
    printf("[*] Player TypeInfo located at: %x\n", player_typeinfo);uintptr_t* physics = (uintptr_t*)(*player_typeinfo + 0x5c);
    printf("[*] Player Physics located at: %x\n", physics);uintptr_t* properties = (uintptr_t*)(*physics + 4);uintptr_t* speed = (uintptr_t*)(*stuff + 0x14);
    printf("[*] Speed located at: %x\n", speed);// Get command inputs from the user
    int command = 0;
    while (true)
    {
        command = 0;
        printf("Available commands:\n  1 - change speed\n\n");
        printf("Enter a command: ");
        cin >> command;
        if (command != 0)
        {
            switch (command)
            {
                case 1: // Change speed
                {
                    printf("Your current speed is: %f\n", *(float*)speed);
                    int new_speed;
                    printf("Enter new speed: ");
                    scanf("%d", &new_speed);// We know from dnSpy that this variable is a float. Make it so.
                    *(float*)speed = (float)new_speed;
                    break;
                }
                default:
                    printf("Invalid command\n");
                    break;
                }
            }
        }
    }
}void insertConsole()
{
    AllocConsole();
    FILE* f = new FILE();
    freopen_s(&f, "CONOUT$", "w", stdout);
    freopen_s(&f, "CONIN$", "r", stdin);printf("[*] Injected...\n");
    commandLoop();
}

Наконец, запустите игру, инжектните библеотеку и проверьте, как работает чит.

Может, что-нибудь посложнее? Попробуем изменить цвет персонажа.

 ...
    // Again, work backwards from function calls to get the information needed
    uintptr_t* gamedata = (uintptr_t*)((uintptr_t)hLib + 0x1468864);
    uintptr_t* gamedataSession_ptr = (uintptr_t*)((uintptr_t)*gamedata + 0x5c);
    uintptr_t* gamedataSession = (uintptr_t*)*gamedataSession_ptr;// Create references to the functions needed
    uintptr_t* (*getPlayerByID)(uintptr_t, char) = (uintptr_t * (*)(uintptr_t, char))((uintptr_t)hLib + 0xB027B0);
    uintptr_t* (__cdecl * rpcSetColor)(uintptr_t * player, char color) = (uintptr_t * (__cdecl*)(uintptr_t*, char))((uintptr_t)hLib + 0x88AFA0);int command = 0;
    while (true)
    {
            command = 0;
            printf("Available commands:\n  1 - change speed\n  2 - send chat\n  3 - set name\n\n");
            printf("Enter a command: ");
            cin >> command;if (command != 0)
            {switch (command)
                {
                case 1: // Change speed
                {
                    ...
                }
                case 2: // Change color
                {
                    uintptr_t* player;// Using a player ID of 0 for demo purposes
                    player = getPlayerByID(*gamedataSession, 0);
                    player = (uintptr_t*)((uintptr_t)player + 0x2c);int color;
                    printf("Enter new color: ");
                    wcin >> color;rpcSetColor((uintptr_t*)*player, (char)color);
                    break;
                }
                default:
                    printf("Invalid command\n");
                    break;
                }
            }
        }
    }

Я осознаю, что в этой статье отсутствует большое количество деталей, а некоторые объяснения были упрощены, но это сделано намеренно, чтобы сделать эту статью краткой. Надеюсь, я смог продемонстрировать, насколько просто взломать или обмануть многие современные игры, к которым мы привыкли за эти годы, и которые поставляются без средств защиты. Тем не менее, с увеличением видимости этих проблем я надеюсь, что многие популярные движки, предназначенные для небольших команд разработчиков, начнут предоставлять функции для предотвращения многих из этих видов читов в будущем.


Прочитать оригинал этого материала на английском можно здесь.

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

Report Page