El mayor portal de MU Online de Brasil — desde 2003
Tutorial Avanzado Cliente

Cómo configurar anti-tamper (protección) del cliente de MU Online

Blinda el Main.exe de tu servidor de MU Online contra edición, inyección y memory hacks combinando checksum de integridad, anti-debug, verificación de módulos y un handshake firmado con el servidor.

GA Gabriel · Actualizado el 12 jul 2025 · ⏱ 24 min de lectura
Respuesta rápida

Proteger el cliente de MU Online es una carrera armamentista permanente. Del otro lado están los editores hexadecimales, los inyectores de DLL, los trainers de memoria y los cheats de speed, wallhack y auto-combo que se aprovechan de un Main.exe desprotegido. El anti-tamper es el conjunto de defensa

Proteger el cliente de MU Online es una carrera armamentista permanente. Del otro lado están los editores hexadecimales, los inyectores de DLL, los trainers de memoria y los cheats de speed, wallhack y auto-combo que se aprovechan de un Main.exe desprotegido. El anti-tamper es el conjunto de defensas que dificulta editar el binario, adjuntar un debugger, inyectar código y alterar valores en memoria y, tan importante como eso, permite que el servidor detecte cuándo el cliente no es confiable. En este tutorial vas a montar esas capas de forma práctica: integridad por checksum, anti-debug, verificación de módulos cargados, protección de memoria y un handshake firmado con el servidor. Todos los valores concretos (offsets, puertos, nombres de sección) aparecen como ejemplo y varían por season/cliente.

Requisitos previos

Antes de blindar cualquier cosa, necesitas una base funcional. Si aún estás montando el servidor, comienza por cómo crear un servidor de MU Online y vuelve aquí cuando el cliente ya se conecte normalmente. Blindar un cliente que ni siquiera loguea solo multiplica variables cuando algo se rompa.

RequisitoDetalle (ejemplo — varía por season/cliente)
Cliente funcionalMain.exe que conecta y loguea sin protección todavía
Copia de seguridad del binarioCopia intacta Main_original.exe fuera de la carpeta del cliente
Herramientas de análisisHxD, CFF Explorer, x64dbg, Process Hacker
Launcher propioEjecutable que valida e inicia el cliente (ideal)
Acceso al ConnectServerPara agregar validación server-side
Entorno de prueba aisladoMáquina limpia, separada de la de desarrollo

El ítem menos obvio es el launcher propio. Muchas protecciones quedan mejor en un componente que controlas totalmente y puedes recompilar a voluntad, en vez de intentar remendar el Main.exe que vino en el paquete. El launcher verifica la integridad, conversa con el servidor y solo entonces dispara el cliente.

Modelo de amenazas: contra qué te estás protegiendo

Antes de elegir técnicas, define qué quiere hacer el atacante. Una protección genérica desperdicia CPU y genera falsos positivos; una protección dirigida al ataque real vale el esfuerzo.

AtaqueVector típicoDefensa principal
Editar IP/versión en el binarioHxD, patcherChecksum de integridad
Adjuntar debuggerx64dbg, Cheat EngineAnti-debug
Inyectar DLL de cheatInjector, LoadLibraryVerificación de módulos
Alterar valores en memoriaCheat Engine, trainerCifrado/ofuscación de variables + validación server-side
Speed hackAceleradores de clockVerificación de tiempo + validación server-side
Forjar paquetesProxy, botHandshake firmado + validación server-side

Fíjate en que la validación server-side aparece en casi todas las líneas. Esa es la lección central: el cliente corre en la máquina del enemigo y nunca será totalmente confiable. El anti-tamper eleva el costo del ataque y alimenta al servidor con señales; el veredicto final es del servidor.

Capa 1 — Integridad por checksum

La defensa más barata contra la edición del binario es comprobar si es bit a bit igual al que distribuiste. Genera un hash fuerte del Main.exe original y verifícalo en dos lugares: en el launcher, antes de iniciar, y en el servidor, durante el handshake.

Paso 1 — Generar el hash de referencia

En Windows, con el binario final ya listo (ya parcheado con IP y versión correctas):

certutil -hashfile Main.exe SHA256

Guarda ese hash. Es la "verdad" contra la cual se comparará todo cliente. Cada vez que reedites el Main.exe, el hash cambia: automatiza la regeneración para no distribuir un cliente con un hash desactualizado.

Paso 2 — Verificar en el launcher

El launcher calcula el SHA-256 del Main.exe en disco y lo compara con el valor esperado antes de ejecutar. Ejemplo en C++ (esbozo):

// Pseudocódigo — varía por season/cliente y por cómo incrustas el hash
bool VerificarIntegridade(const wchar_t* caminho, const std::string& hashEsperado) {
    std::string hashAtual = CalcularSHA256(caminho); // via CryptoAPI / bcrypt
    if (hashAtual != hashEsperado) {
        MostrarErro(L"Cliente adulterado. Descárgalo nuevamente desde el launcher.");
        return false;
    }
    return true;
}

> No incrustes el hash esperado como una cadena en texto plano fácil de encontrar. Ofúscalo, divídelo en partes o derívalo de otra cosa. Un atacante que localiza la cadena simplemente la cambia por el hash de su binario editado.

Paso 3 — Checksum de sección en runtime (self-check)

Además del check en disco, el propio cliente puede comprobar la suma de su sección de código (.text) en memoria mientras corre. Esto atrapa parches aplicados después de la carga (inyección de código). La idea: en el build, calcula el CRC/hash de la sección .text y, en runtime, recalcúlalo periódicamente comparándolo con el valor grabado. Si diverge, repórtalo al servidor.

Como el .text se mapea con relocations y el valor esperado debe coincidir, este check normalmente exige control del proceso de build o un protector que ya lo haga por ti (ver Capa 6).

Capa 2 — Anti-debug

Cheat Engine y x64dbg dependen de adjuntar un debugger al proceso. Detectar esa presencia encarece el análisis dinámico.

Paso 4 — Verificaciones básicas

// Ejemplos clásicos — combina varios, nunca confíes en uno solo
bool DebuggerPresente() {
    if (IsDebuggerPresent()) return true;

    BOOL remoto = FALSE;
    CheckRemoteDebuggerPresent(GetCurrentProcess(), &remoto);
    if (remoto) return true;

    // PEB->BeingDebugged y NtGlobalFlag también los verifican las protecciones más profundas
    return false;
}

Paso 5 — Detectar herramientas por ventana/proceso

Barre ventanas y procesos en busca de firmas conocidas (nombres de clase y títulos de Cheat Engine, x64dbg, OllyDbg, Process Hacker). Mantén la lista externa y actualizable, porque los nombres cambian.

> No cierres el cliente al detectar. Los overlays de grabación, las herramientas de accesibilidad e incluso algunos antivirus disparan estos checks. El patrón seguro es reportar al servidor con la señal y dejar el ban para el análisis humano o la heurística acumulada. Matar el proceso al instante es la receta para un foro lleno de quejas de jugadores legítimos.

Capa 3 — Verificación de módulos cargados

Los cheats frecuentemente entran como DLL inyectada. Enumerar los módulos del proceso y compararlos con una allowlist detecta inyecciones obvias.

Paso 6 — Enumerar y clasificar módulos

// Esbozo — la allowlist varía MUCHO por season/cliente y por los drivers del usuario
void VarrerModulos() {
    // EnumProcessModules -> para cada módulo, GetModuleFileName
    // Clasifica: sistema (system32), del propio cliente, y "desconocido"
    // Módulos desconocidos y no firmados -> señal para el servidor
}

Cuidado con los falsos positivos: los overlays (Discord, Steam, GPU), los IME y el software de audio inyectan DLLs legítimas. Por eso la salida ideal es un reporte al servidor con los módulos sospechosos, no un bloqueo local ciego. Firmar digitalmente y comprobar la firma (Authenticode) reduce mucho el ruido.

Capa 4 — Protección de valores en memoria

Los trainers editan HP, zen, coordenadas y velocidad directo en la RAM con Cheat Engine. No impides la lectura, pero dificultas la escritura útil.

  • No guardes valores sensibles en texto plano. Almacena HP, zen y velocidad cifrados/ofuscados y descífralos solo al usarlos. Cheat Engine encuentra el valor 1000 fácil; encontrar el valor cifrado que cambia de representación, no tanto.
  • Guarda una copia sombra. Mantén un segundo valor derivado (suma de verificación) y, periódicamente, comprueba si coinciden. Divergencia = alguien escribió directamente.
  • Valida en el servidor. El HP, el zen, la posición y la velocidad que solo existen en el cliente son inútiles: el servidor debe ser la autoridad. Si el cliente dice que caminó 50 celdas en 100 ms, el servidor lo rechaza, independientemente de cualquier protección local.

Capa 5 — Handshake firmado con el servidor

Esta es la capa que el atacante no controla, y por eso la más valiosa. En vez de confiar en que el cliente es íntegro, el servidor exige una prueba en cada sesión.

Paso 7 — Desafío-respuesta en la conexión

  1. Al conectar, el ConnectServer/GameServer envía un nonce aleatorio (valor de uso único).
  2. El cliente combina ese nonce con el hash de su propio binario y con un secreto incrustado, y responde con un HMAC.
  3. El servidor recalcula el HMAC con el hash esperado y el mismo secreto. Si no coincide, rechaza la sesión.
Servidor -> Cliente : nonce = 0x9F3A...   (aleatorio por sesión)
Cliente  -> Servidor: resp = HMAC_SHA256(secreto, nonce || hashBinario)
Servidor            : recalcula y compara. Diferente => tumba la conexión.

Como el nonce cambia cada sesión, un atacante no puede grabar una respuesta válida y reproducirla después (anti-replay). Y como el servidor conoce el hashBinario esperado, un Main.exe editado produce un HMAC diferente y queda bloqueado, incluso si el atacante neutralizó el check local.

> El secreto incrustado en el cliente es el eslabón débil: quien haga ingeniería inversa del binario puede extraerlo. Rota el secreto en cada actualización de cliente, combínalo con datos de build y trátalo como algo que eventualmente se filtra. La fuerza real viene de sumar esto a la validación de comportamiento en el servidor.

Capa 6 — Packers y protectores comerciales

Si no tienes el código fuente del cliente, los protectores aplicados al binario ya listo entregan gran parte de las capas 1, 2 y parte de la 4 de una sola vez.

HerramientaEnfoqueContrapartida (ejemplo)
ThemidaAnti-debug, virtualización, integridadPesado; falsos positivos de AV; inicio lento
VMProtectVirtualización de tramos críticosPérdida de FPS si virtualizas código caliente
Enigma ProtectorIntegridad, licenciamiento, anti-dumpConfiguración extensa

Reglas de oro al usar un protector: virtualiza solo las rutinas críticas (handshake, checks), nunca el loop de render, o los FPS se desploman en máquinas débiles; mantén una build interna sin protección para depurar; y prueba los antivirus antes de lanzar, porque los packers disparan heurística y necesitarás whitelist/reputación.

Errores comunes y soluciones

SíntomaCausa probableSolución
El cliente se cierra al abrir para muchos jugadoresAnti-debug agresivo atrapando overlay/AVCambiar el bloqueo por reporte; refinar la allowlist
El antivirus borra el Main.exePacker sin reputaciónFirmar el binario; enviarlo a whitelist; reputación en VirusTotal
El hash siempre es inválido en el launcherHash de referencia desactualizado tras reediciónAutomatizar la regeneración del hash en el build
Los FPS cayeron mucho tras protegerVirtualización del loop de renderVirtualizar solo las rutinas críticas
El handshake rechaza clientes legítimosReloj/nonce desincronizado o versión equivocadaVerificar la tolerancia de tiempo y AcceptVersion
Falso positivo con Discord/SteamVerificación de módulos ciegaFirmar/allowlist de módulos firmados conocidos
El secreto del handshake se filtróCadena en texto plano en el binarioOfuscar/rotar el secreto en cada update

Distribución y rotación

La protección no es "configura y olvida". Cada nueva versión del cliente debe generar un nuevo hash, un nuevo secreto de handshake y, de ser posible, pequeñas variaciones en las rutinas de check para evitar que una solución pública de bypass valga para siempre. Distribuye siempre por el launcher (que valida antes de correr), publica el hash junto a la descarga y escanea el binario final antes de subirlo. Trata cada bypass reportado en tu Discord como un bug de prioridad alta.

Lista de verificación de lanzamiento

  • Copia de seguridad Main_original.exe guardada fuera de la carpeta del cliente
  • Hash SHA-256 de referencia generado a partir del binario final
  • Verificación de integridad activa en el launcher (hash ofuscado)
  • Anti-debug en modo reporte, no en modo kill
  • Verificación de módulos con allowlist de firmados conocidos
  • Valores sensibles (HP/zen/velocidad) cifrados en el cliente
  • Validación server-side de HP, posición, velocidad y paquetes
  • Handshake nonce + HMAC activo en el ConnectServer/GameServer
  • Secreto del handshake rotable y ofuscado
  • Protector aplicado solo en rutinas críticas (FPS probado en PC débil)
  • Binario firmado y enviado para reputación de antivirus
  • Probado en máquina limpia, separada de la de desarrollo
  • Build de debug interna sin protección guardada para depurar
  • Plan de rotación de hash/secreto en cada actualización documentado

Preguntas frecuentes

¿El anti-tamper reemplaza al anticheat del servidor?

No. El anti-tamper protege el binario del cliente y la memoria local, mientras que la validación server-side comprueba si las acciones y valores recibidos tienen sentido. Son capas complementarias: un cliente blindado con un servidor ingenuo aún cae por paquetes forjados, y viceversa. Siempre valida en el servidor además de proteger el cliente.

¿Puedo usar Themida o VMProtect en el Main.exe?

Sí, los packers comerciales como Themida, VMProtect y Enigma se usan bastante para dificultar la ingeniería inversa y el debugging. El costo es un mayor consumo de CPU/RAM, un tiempo de inicio más lento y falsos positivos en algunos antivirus. Prueba el rendimiento en máquinas débiles antes de lanzar y mantén una build de debug sin packer para depurar tú mismo.

¿El checksum del cliente puede burlarse?

Un atacante determinado siempre puede neutralizar un check local, porque el código que verifica corre en su máquina. El objetivo del anti-tamper no es ser irrompible, sino elevar el costo del ataque y permitir que el servidor detecte inconsistencias. Por eso el handshake firmado con el servidor, que el atacante no controla, es la parte más valiosa.

¿El anti-debug molestará a los jugadores legítimos?

Puede, si es demasiado agresivo. Técnicas como IsDebuggerPresent y la verificación de ventanas de herramientas raramente afectan a los jugadores, pero cerrar el proceso al detectar cualquier cosa sospechosa genera falsos positivos con overlays, grabadores de pantalla y software de accesibilidad. Prefiere reportar al servidor y dejar la decisión de ban para el análisis, en vez de matar el cliente al instante.

¿Necesito recompilar el Main.exe para agregar protección?

Depende. Si tienes el código fuente del cliente (algo raro), compilas la protección junto. Sin fuente, el camino es aplicar un packer/protector externo al binario y, si hay soporte vía loader o DLL inyectada por tu launcher, agregar checks en ese componente. La verificación de integridad y el handshake pueden vivir en el launcher y en el ConnectServer sin tocar el Main.exe.

GA
Editor de guías y builds

Gabriel cubre gameplay, builds de clases, PvP y progresión. Prueba cada estrategia en un servidor antes de publicar.

Sigue leyendo

Artículos relacionados