Cómo Runescape atrapa a los bots y por qué ella no me atrapó a mí



La automatización de las acciones de los jugadores siempre ha sido un problema importante en MMORPG como World of Warcraft y Runescape . Este tipo de pirateo de juegos es muy diferente de los trucos tradicionales, por ejemplo, en los shooters.



Un fin de semana decidí echar un vistazo a los sistemas de detección que utiliza Jagex para evitar que Runescape automatice las acciones de los jugadores.



Botanicultura



Durante los últimos meses, la cuenta ha estado sch0u



jugando las 24 horas del día en el servidor del mundo 67, realizando tareas monótonas como matar mobs y recolectar recursos. A primera vista, esta cuenta se parece a cualquier otro jugador, pero hay una diferencia importante: es un bot .





Lancé este bot en octubre para probar las capacidades del sistema de reconocimiento de bots. Después de intentar encontrar información sobre cómo Jagex lucha contra bots bots, solo encontré videos de bots pagos, cuyos desarrolladores se jactaban de que sus sistemas de movimiento del mouse eran indistinguibles de las acciones humanas.



Por lo tanto, lo único que pude entender fue la importancia de los movimientos del mouse , pero ¿es así realmente?



¡Heurística!



Para confirmar esta teoría, comencé examinando el cliente de Runescape y casi de inmediato noté que se establecía una variable global hhk



poco después del lanzamiento.



const auto module_handle = GetModuleHandleA(0);
hhk = SetWindowsHookExA(WH_MOUSE_LL, rs::mouse_hook_handler, module_handle, 0);
      
      





Este código instala un interceptor de bajo nivel en el mouse que está conectado a la cadena del interceptor del sistema . Esto permite que las aplicaciones de Windows intercepten todos los eventos del mouse, incluso si no están asociados con una aplicación específica. Los keyloggers suelen utilizar interceptores de bajo nivel (ganchos) , pero también pueden utilizarse con fines pacíficos, por ejemplo, en heurística, como el interceptor de ratón antes mencionado.



De hecho, el controlador del mouse de Runescape es bastante simple (el pseudocódigo se modificó para la belleza a mano):



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;
  }
}
      
      





Para reducir la carga en el enlace, estas funciones rs::heuristics::log_*



utilizan algoritmos simples para omitir datos de eventos que se asemejan a eventos registrados previamente.



Posteriormente, estos datos de eventos se analizan mediante una función rs::heuristics::process



que se llama a cada fotograma del bucle de renderizado principal.



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);
}
      
      





¿Lejos del teclado?



Durante el proceso de ingeniería inversa, traté de descubrir la importancia para mí de cada función que aprendí, generalmente creando ganchos o parches para esas funciones. Por lo general, puede saber si una función es relevante haciéndola inútil y controlando el estado del software. Esta metodología de investigación dio lugar a una observación interesante.



Habiendo prohibido al juego llamar a la función rs::heuristics::process



, al principio no noté nada, pero después de exactamente cinco minutos el servidor me desconectó. Obviamente, Runescape determina la inactividad del jugador únicamente por los datos heurísticos transmitidos por el cliente al servidor, incluso si puedes jugar con bastante normalidad. Esto planteó una nueva pregunta: si el servidor piensa que no estoy jugando, ¿cree que estoy jugando como un bot? ...



Después de eso, pasé unos días más aplicando ingeniería inversa a la capa de red del juego, de modo que mi bot ahora puede hacer casi cualquier cosa usando solo paquetes de red .



Para probar mi teoría, me molestaban las veinticuatro horas del día, siete días a la semana, sin siquiera mover el mouse. Habiendo pasado miles de horas así, puedo decir con confianza que el sistema de detección de bots usa solo los datos de eventos heurísticos enviados al servidor por el cliente, o solo funciona cuando el jugador no está "afk". Cualquier jugador que logre jugar sin mover el cursor debe ser baneado de inmediato, es decir, los desarrolladores deben prestar atención a esta falla.






All Articles