Автоматизация игроков всегда была большой проблемой в глобальных многопользовательских онлайновых ролевых играх (MMORPG), таких как World of Warcraft и Runescape, и этот вид взлома игр значительно отличается от традиционных читов, например в стрелялках. Однажды в выходные я решил взглянуть на системы обнаружения, созданные компанией Jagex для предотвращения автоматизации игроков в Runescape и вот что из этого вышло.
Использование ботов
Последние несколько месяцев игрок с учётной записью sch0u играл в World 67 круглосуточно, выполняя обычные задачи, такие как убийство мобов или сбор ресурсов. На первый взгляд игрок с этой учётной записью выглядит так же, как и любой другой игрок, но есть одно ключевое отличие — это бот.
Я запустил этого бота ещё в октябре, чтобы протестировать возможности системы обнаружения ботов. Я попытался найти в Интернете информацию о том, как компания Jagex борется с создателями таких ботов, и нашёл только видео коммерческих ботов, создатели которых хвастались тем, что их системы перемещения мыши неотличимы от людей.
Поэтому единственный вывод, который мне удалось сделать, заключается в том, что движение мыши имеет значение.
Эвристика!
Я начал с анализа клиента Runescape, чтобы подтвердить эту теорию, и быстро заметил глобально вызываемую переменную hhk, которая задаётся вскоре после запуска.
const auto module_handle = GetModuleHandleA(0);
hhk = SetWindowsHookExA(WH_MOUSE_LL, rs::mouse_hook_handler, module_handle, 0);
В результате на мышь устанавливается низкоуровневая hook-точка, добавляя её к общесистемной цепочке hook-точек. Это позволяет приложениям в Windows перехватывать все события мыши, независимо от того, связаны они с вашим приложением или нет. Низкоуровневые hook-точки часто используются клавиатурными шпионами, однако есть и законные случаи использования, такие как эвристика, подобная вышеупомянутой hook-точке мыши.
Обработчик мыши Runescape довольно прост по своей сути (следующий псевдокод красиво переписан вручную):
LRESULT __fastcall rs::mouse_hook_handler(int code, WPARAM wParam, LPARAM lParam)
{
if ( rs::client::singleton )
{
// Call the internal logging handler
rs::mouse_hook_handler_internal(rs::client::singleton->window_ctx, wParam, lParam);
}
// Pass the information to the next hook on the system
return CallNextHookEx(hhk, code, wParam, lParam);
}
void __fastcall rs::mouse_hook_handler_internal(rs::window_ctx *window_ctx, __int64 wparam, _DWORD *lparam)
{
// If the mouse event happens outside of the Runescape window, don't log it.
if (!window_ctx->event_inside_of_window(lparam))
{
return;
}
switch (wparam)
{
case WM_MOUSEMOVE:
rs::heuristics::log_movement(lparam);
break;
case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK:
case WM_RBUTTONDOWN:
case WM_RBUTTONDBLCLK:
case WM_MBUTTONDOWN:
case WM_MBUTTONDBLCLK:
rs::heuristics::log_button(lparam);
break;
}
}
С учётом пропускной способности эти функции rs::heuristics::log_* используют простые алгоритмы для пропуска данных событий, которые похожи на предыдущие зарегистрированные события.
Эти данные события позже анализируются функцией rs::heuristics::process, которая вызывается каждым фреймом в основном цикле рендеринга.
void __fastcall rs::heuristics::process(rs::heuristic_engine *heuristic_engine)
{
// Don't process any data if the player is not in a world
auto client = heuristic_engine->client;
if (client->state != STATE_IN_GAME)
{
return;
}
// Make sure the connection object is properly initialised
auto connection = client->network->connection;
if (!connection || connection->server->mode != SERVER_INITIALISED)
{
return;
}
// The following functions parse and pack the event data, and is later sent
// by a different component related to networking that has a queue system for
// packets.
// Process data gathered by internal handlers
rs::heuristics::process_source(&heuristic_engine->event_client_source);
// Process data gathered by the low level mouse hook
rs::heuristics::process_source(&heuristic_engine->event_hook_source);
}
Вдали от клавиатуры?
Двигаясь в обратном направлении, я прилагаю усилия, чтобы узнать, насколько релевантна рассматриваемая функция, в первую очередь путём создания и применения hook-точек или патчей для рассматриваемой функции. Обычно заключение о релевантности функции можно получить, сделав её бесполезной и наблюдая за состоянием программного обеспечения. Эта методология приводит к интересному наблюдению.
Запретив игре вызывать функцию rs::heuristics::process, я сразу ничего не заметил, но ровно через пять минут вышел из игры. По-видимому, Runescape принимает решение о неактивности игрока просто по эвристическим данным, отправленным клиентом на сервер, хотя вы можете просто отлично играть в эту игру. Это породило новый вопрос: если сервер не считает, что я играю, то считает ли он, что я использую бота?
В результате я потратил несколько дней на реконструкцию сетевого слоя игры и смог использовать бота для выполнения почти всех действий при помощи только сетевых пакетов.
Чтобы доказать свою теорию, я использовал бот двадцать четыре часа в сутки, семь дней в неделю, даже не шевеля мышкой. Прошли тысячи часов, и я могу с уверенностью заявить, что обнаружение ботов компанией либо опирается на отправленные клиентом эвристические данные событий, либо запускается только тогда, когда игрок не находится в состоянии «вдали от клавиатуры». Любого игрока, которому удаётся играть, не двигая мышью, следует немедленно забанить, то есть нынешний контроль имеет смысл пересмотреть.
Уязвимостей полно не только в играх, а с ростом цифровизации различных отраслей, многие недостатки безопасности «вышли наружу» и требуют серьезного внимания, а значит, растёт востребованность специалистов в сфере информационной безопасности, для обучения которых мы сделали специальный курс Этичный хакер. Если вам по душе искать пробелы в защите и получать за это вознаграждение — добро пожаловать.Узнай, как прокачаться и в других областях работы с данными или освоить их с нуля:
Другие профессии и курсы
ПРОФЕССИИ
КУРСЫ
Узнайте, как прокачаться и в других специальностях или освоить их с нуля:
Другие профессии и курсы
ПРОФЕССИИ
КУРСЫ