Hackeando el T-Rex Runner en trex-runner.com: Entendiendo y Evadiendo el Sistema Anti-Trampas
Introducción: El T-Rex Runner en trex-runner.com
¡Hola, entusiastas del hacking ético! El T-Rex Runner, conocido como el juego del dinosaurio de Google Chrome, es un Easter Egg que aparece cuando no hay conexión a internet (chrome://dino/
). Sin embargo, en trex-runner.com, puedes jugar una versión hackeada online que permite competir en tablas de clasificación globales, como se muestra en la siguiente tabla de puntuaciones diarias:
Este juego, ejecutado en JavaScript, es un excelente campo de pruebas para aprender sobre manipulación de código y seguridad web. En este post, exploraremos cómo hackear el juego para establecer puntuaciones específicas (como 10,000 puntos), entenderemos el sistema anti-trampas implementado en trex-runner.com y aprenderemos cómo evitar ser detectados como tramposos.
El Juego: T-Rex Runner Online
En trex-runner.com, el T-Rex Runner es una versión modificada del juego original de Chrome:
- Mecánica: Un dinosaurio corre automáticamente, saltando cactus y pterodáctilos con las teclas de flecha arriba (saltar) y abajo (agacharse).
- Puntuación: Basada en la distancia recorrida (
distanceRan
). - Online: Envía puntuaciones al servidor para tablas de clasificación.
- Anti-Trampas: El servidor valida los datos enviados para detectar manipulaciones.
Fórmula de Puntuación
La puntuación se calcula con: [ \text{puntuación} = \text{Math.round}(\text{Math.ceil}(\text{distanceRan}) \times 0.025) ]
distanceRan
: Distancia recorrida.Math.ceil
: Redondea hacia arriba.0.025
: Factor de conversión.Math.round
: Redondea al entero más cercano.
Para una puntuación de 10,000: [ 10,000 = \text{Math.round}(\text{Math.ceil}(\text{distanceRan}) \times 0.025) ] [ \text{Math.ceil}(\text{distanceRan}) \approx \frac{10,000}{0.025} = 400,000 ] [ \text{distanceRan} \approx 399,999.999 ]
Accediendo al Juego
Método 1: Sin Conexión (Chrome Original)
- Desconecta tu internet.
- Intenta navegar a cualquier página en Chrome.
- Presiona Espacio para empezar.
Método 2: URL Directa
chrome://dino/
Método 3: trex-runner.com
Visita trex-runner.com para jugar online y competir en tablas de clasificación.
Sistema Anti-Trampas Avanzado en trex-runner.com
La versión de trex-runner.com implementa un sistema anticheat sofisticado que va mucho más allá del simple juego de Chrome. Cuando terminas una partida, el juego envía una solicitud POST a /ajax/qufw/
con datos que el servidor valida exhaustivamente.
Request HTTP al Finalizar Partida
POST /ajax/qufw/ HTTP/2
Host: trex-runner.com
Content-Type: application/x-www-form-urlencoded
name=pikasito&points=10000&dist=400000&t=666667&token=0e5828d32be15905daad5b209d71a844796cdb8b99d35b2f962060448a0df88d
Parámetros Enviados
Parámetro | Descripción | Ejemplo |
---|---|---|
name |
Nombre del jugador | pikasito |
points |
Puntuación final calculada | 10000 |
dist |
Distancia recorrida | 400000 |
t |
Tiempo de juego (ms) | 666667 |
token |
Hash de verificación | 0e5828d32be... |
Análisis del Código Anticheat
Del código JavaScript proporcionado, el sistema anticheat funciona así:
// Fragmento del código original
if (k > A) {
var B = new XMLHttpRequest();
B.open("GET", "/ajax/qufw/?points=" + k, true);
B.onload = function() {
if (B.readyState === B.DONE) {
if (B.status === 200) {
if (B.responseText != "") {
var D = "name=" + user_name + "&points=" + k + "&dist=" + C + "&t=" + z + "&token=" + document.getElementById("token").value;
B.open("POST", "/ajax/qufw/", true);
B.send(D);
}
}
}
};
}
Variables Clave
k = Math.round(this.highestScore * 0.025)
- Puntuación calculadaC = this.distanceRan
- Distancia recorridaz = this.runningTime
- Tiempo de juego
Validaciones del Servidor
1. Fórmula Matemática
El servidor verifica que: [ \text{points} = \text{Math.round}(\text{Math.ceil}(\text{dist}) \times 0.025) ]
Ejemplo para 10,000 puntos:
dist
debe ser ~400,000Math.ceil(399,999.999) = 400,000
400,000 × 0.025 = 10,000
✅
2. Coherencia Temporal
La velocidad del T-Rex va de 6 a 13 unidades por frame (60 FPS):
[ \text{velocidad promedio} \approx 10 \text{ unidades/frame} ] [ \text{dist} \approx 10 \times \left( \frac{\text{t}}{1000} \times 60 \right) = 0.6 \times \text{t} ]
Para dist=400,000
:
[ 400,000 = 0.6 \times \text{t} ]
[ \text{t} = \frac{400,000}{0.6} = 666,667 \text{ ms} \approx 11.1 \text{ minutos} ]
3. Token de Seguridad
El token
(ejemplo: 0e5828d32be15905daad5b209d71a844796cdb8b99d35b2f962060448a0df88d
) es un hash SHA-256 generado posiblemente con:
- Valores de
points
,dist
,t
- Clave secreta del servidor
- Timestamp o session ID
Caso Real: Detección de Trampa
En un intento previo:
points=7273, dist=290907.363, t=4760.3 ms
Respuesta del servidor: "cheatin"
¿Por qué falló?
- Velocidad calculada: (\frac{290,907}{4.76} \div 60 \approx 1,018) unidades/frame
- Límite del juego: ~13 unidades/frame máximo
- Factor de error: 78x más rápido que lo físicamente posible
Técnicas de Hacking Avanzado
🚨 Hack 1: Método de Puntuación Específica (Recomendado)
Para lograr cualquier puntuación sin ser detectado:
function setScore(targetScore) {
// Calcular valores coherentes
const distance = (targetScore / 0.025) - 0.001;
const time = Math.round(distance / 0.6); // Velocidad promedio realista
// Establecer valores
Runner.instance_.distanceRan = distance;
Runner.instance_.runningTime = time;
Runner.instance_.highestScore = Math.ceil(distance);
// Finalizar juego
Runner.instance_.gameOver();
console.log(`✅ Configurado: ${targetScore} pts, dist: ${distance}, tiempo: ${time}ms`);
}
// Ejemplo: 10,000 puntos
setScore(10000);
Matemáticas del Hack
Para cualquier puntuación P
:
[ \text{distanceRan} = \frac{P}{0.025} - 0.001 ]
[ \text{runningTime} = \frac{\text{distanceRan}}{0.6} ]
Ejemplos de puntuaciones populares:
- 1,000 pts:
distanceRan=39,999.999
,time=66,667ms
(~1.1 min) - 5,000 pts:
distanceRan=199,999.999
,time=333,333ms
(~5.6 min) - 10,000 pts:
distanceRan=399,999.999
,time=666,667ms
(~11.1 min)
🚨 Hack 2: Invencibilidad + Auto-Accumulate
Para jugar “legítimamente” pero sin morir:
// Desactivar game over
Runner.prototype.gameOver = function(){};
// Auto-play inteligente
function smartAutoPlay() {
if (Runner.instance_.crashed) return;
const obstacles = Runner.instance_.horizon.obstacles;
const tRex = Runner.instance_.tRex;
if (obstacles.length > 0) {
const nextObstacle = obstacles[0];
const distance = nextObstacle.xPos - tRex.xPos;
// Saltar cuando el obstáculo esté cerca
if (distance <= 100 && distance > 50 && !tRex.jumping) {
tRex.startJump();
}
// Agacharse para pterodáctilos altos
if (nextObstacle.typeConfig && nextObstacle.typeConfig.type === 'PTERODACTYL') {
if (nextObstacle.yPos < 80 && distance <= 80 && !tRex.ducking) {
tRex.setDuck(true);
setTimeout(() => tRex.setDuck(false), 500);
}
}
}
setTimeout(smartAutoPlay, 20);
}
smartAutoPlay();
console.log("🤖 Auto-play inteligente activado");
🚨 Hack 3: Bypass Completo del Anticheat
El método más sofisticado combina timing realista con automatización:
function antiCheatBypass() {
console.log("🔓 Iniciando Bypass Anticheat...");
// Configuración realista
const targetScore = parseInt(prompt("Puntuación objetivo:", "5000"));
const baseDistance = (targetScore / 0.025) - 0.001;
const baseTime = baseDistance / 0.6;
// Agregar variabilidad realista
const variance = 1 + (Math.random() * 0.1 - 0.05); // ±5% variación
const finalDistance = baseDistance * variance;
const finalTime = baseTime * variance;
// Ejecutar hack gradual
let currentDist = Runner.instance_.distanceRan;
let currentTime = Runner.instance_.runningTime;
const interval = setInterval(() => {
if (currentDist >= finalDistance) {
Runner.instance_.distanceRan = finalDistance;
Runner.instance_.runningTime = Math.round(finalTime);
Runner.instance_.highestScore = Math.ceil(finalDistance);
Runner.instance_.gameOver();
clearInterval(interval);
console.log(`✅ Bypass completado: ${targetScore} puntos`);
return;
}
// Incremento gradual
const increment = (finalDistance - currentDist) / 100;
const timeIncrement = (finalTime - currentTime) / 100;
currentDist += increment;
currentTime += timeIncrement;
Runner.instance_.distanceRan = currentDist;
Runner.instance_.runningTime = Math.round(currentTime);
}, 50);
console.log(`🎯 Objetivo: ${targetScore} pts en ${Math.round(finalTime/1000)}s`);
}
antiCheatBypass();
🚨 Hack 4: Monitor de Sistema Anticheat
Script para monitorear las validaciones del servidor:
// Interceptar requests XMLHttpRequest
const originalXHR = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(data) {
console.log("📡 Request interceptada:", data);
// Analizar datos enviados
if (data && data.includes('points=')) {
const params = new URLSearchParams(data);
const points = params.get('points');
const dist = params.get('dist');
const time = params.get('t');
const token = params.get('token');
console.log("🔍 Análisis de coherencia:");
console.log(`Points: ${points}`);
console.log(`Distance: ${dist}`);
console.log(`Time: ${time}ms (${(time/1000/60).toFixed(2)} min)`);
console.log(`Token: ${token.substring(0,16)}...`);
// Validar fórmula
const expectedPoints = Math.round(Math.ceil(parseFloat(dist)) * 0.025);
const speedCheck = (parseFloat(dist) / (parseFloat(time) / 1000)) / 60;
console.log(`✓ Fórmula correcta: ${points == expectedPoints ? 'SÍ' : 'NO'}`);
console.log(`✓ Velocidad realista: ${speedCheck <= 13 ? 'SÍ' : 'NO'} (${speedCheck.toFixed(2)} u/f)`);
}
// Interceptar respuesta
this.addEventListener('load', function() {
if (this.responseText.includes('cheatin')) {
console.log("🚨 ANTICHEAT ACTIVADO - Trampa detectada");
} else if (this.responseText === '1') {
console.log("✅ Puntuación aceptada por el servidor");
}
});
return originalXHR.call(this, data);
};
console.log("🕵️ Monitor anticheat activado");
Script Completo: T-Rex Ultimate Hacker
Herramienta Todo-en-Uno
(function() {
const TRexHacker = {
// Configuración
config: {
minSpeed: 6,
maxSpeed: 13,
frameRate: 60,
scoreFactor: 0.025
},
// Calcular valores coherentes
calculateValues: function(targetScore) {
const distance = (targetScore / this.config.scoreFactor) - 0.001;
const avgSpeed = (this.config.minSpeed + this.config.maxSpeed) / 2;
const time = Math.round(distance / (avgSpeed * this.config.frameRate / 1000));
return {
distance: distance,
time: time,
score: targetScore,
highScore: Math.ceil(distance)
};
},
// Establecer puntuación específica
setScore: function(score) {
if (typeof Runner === 'undefined') {
alert('❌ Ve a trex-runner.com primero');
return;
}
const values = this.calculateValues(score);
Runner.instance_.distanceRan = values.distance;
Runner.instance_.runningTime = values.time;
Runner.instance_.highestScore = values.highScore;
Runner.instance_.gameOver();
console.log(`✅ Score: ${score}, Dist: ${values.distance}, Time: ${values.time}ms`);
},
// Modo invencible
godMode: function() {
Runner.prototype.gameOver = function(){};
console.log("🛡️ Invencibilidad activada");
},
// Auto-play inteligente
autoPlay: function() {
function play() {
if (Runner.instance_.crashed) return;
const obstacles = Runner.instance_.horizon.obstacles;
const tRex = Runner.instance_.tRex;
if (obstacles.length > 0) {
const obstacle = obstacles[0];
const dist = obstacle.xPos - tRex.xPos;
if (dist <= 100 && dist > 50) {
if (obstacle.typeConfig.type === 'PTERODACTYL' && obstacle.yPos > 75) {
if (!tRex.ducking) tRex.setDuck(true);
setTimeout(() => tRex.setDuck(false), 300);
} else if (!tRex.jumping) {
tRex.startJump();
}
}
}
setTimeout(play, 30);
}
play();
console.log("🤖 Auto-play activado");
},
// Monitor del sistema
monitorAntiCheat: function() {
const original = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(data) {
if (data && data.includes('points=')) {
const params = new URLSearchParams(data);
console.log("📊 Datos enviados al servidor:");
console.table({
'Points': params.get('points'),
'Distance': params.get('dist'),
'Time (ms)': params.get('t'),
'Time (min)': (params.get('t')/60000).toFixed(2),
'Token': params.get('token')?.substring(0,16) + '...'
});
}
this.addEventListener('load', function() {
if (this.responseText.includes('cheatin')) {
console.log("🚨 Servidor respondió: TRAMPA DETECTADA");
} else {
console.log("✅ Puntuación aceptada");
}
});
return original.call(this, data);
};
console.log("🕵️ Monitor anticheat iniciado");
}
};
// Menú interactivo
console.log("🦕 T-REX ULTIMATE HACKER CARGADO 🦕");
console.log("Comandos disponibles:");
console.log("TRexHacker.setScore(10000) - Establecer puntuación");
console.log("TRexHacker.godMode() - Invencibilidad");
console.log("TRexHacker.autoPlay() - Juego automático");
console.log("TRexHacker.monitorAntiCheat() - Monitor del sistema");
// Hacer global
window.TRexHacker = TRexHacker;
// Activar monitor por defecto
TRexHacker.monitorAntiCheat();
})();
Instrucciones de Uso
- Ir al juego: Abre trex-runner.com
- Abrir DevTools: Presiona
F12
>Console
- Cargar el script: Pega el código completo y presiona Enter
- Usar comandos:
TRexHacker.setScore(8500); // Puntuación específica TRexHacker.godMode(); // Invencibilidad TRexHacker.autoPlay(); // Juego automático
Análisis Profundo del Código Anticheat
Decompilación del Sistema
El código JavaScript minificado revela el mecanismo completo:
// Código original extraído
k = Math.round(this.highestScore * 0.025); // Puntuación
// Validación de nuevo récord
if (k > A) { // A = puntuación anterior
var B = new XMLHttpRequest();
B.open("GET", "/ajax/qufw/?points=" + k, true);
// Solicitud POST con datos completos
var D = "name=" + user_name + "&points=" + k + "&dist=" + C + "&t=" + z + "&token=" + document.getElementById("token").value;
B.open("POST", "/ajax/qufw/", true);
B.send(D);
}
Flujo Completo del Anticheat
- Cálculo Local:
points = Math.round(highestScore * 0.025)
- Verificación GET:
/ajax/qufw/?points=X
- Valida si es nuevo récord - Envío POST: Datos completos con token de seguridad
- Validación Servidor: Múltiples checks de coherencia
- Respuesta: “1” (éxito) o “cheatin” (trampa detectada)
Generación del Token
El token es crítico y probablemente se genera con:
// Posible algoritmo del token (especulación)
token = SHA256(points + dist + time + secretKey + sessionId)
Estrategias para evadir:
- No modificar directamente: Usar valores que generen tokens válidos
- Respetar timing: El token puede incluir timestamp
- Calcular coherentemente: Todos los valores deben ser matemáticamente consistentes
Técnicas de Evasión Avanzadas
Método 1: Slow Burn (Recomendado)
function slowBurnHack(targetScore, durationMinutes = 10) {
const values = TRexHacker.calculateValues(targetScore);
const targetTime = durationMinutes * 60 * 1000; // Convertir a ms
// Ajustar velocidad promedio para el tiempo deseado
const requiredSpeed = values.distance / (targetTime / 1000 * 60);
if (requiredSpeed > 13) {
console.log(`⚠️ Velocidad requerida (${requiredSpeed.toFixed(2)}) > límite (13)`);
console.log(`💡 Aumenta duración a ${Math.ceil(values.distance/(13*60*1000/1000)/60)} minutos`);
return;
}
console.log(`🎯 Configurando ${targetScore} pts en ${durationMinutes} min`);
console.log(`📈 Velocidad promedio: ${requiredSpeed.toFixed(2)} u/f`);
// Aplicar hack
Runner.instance_.distanceRan = values.distance;
Runner.instance_.runningTime = targetTime;
Runner.instance_.highestScore = values.highScore;
setTimeout(() => {
Runner.instance_.gameOver();
console.log("✅ Slow burn completado");
}, 1000);
}
// Ejemplo: 5000 puntos en 8 minutos
slowBurnHack(5000, 8);
Método 2: Token Preservation
function preserveTokenHack(targetScore) {
// Guardar token original
const originalToken = document.getElementById("token").value;
// Hacer pequeños ajustes que no afecten dramáticamente el token
const originalDist = Runner.instance_.distanceRan;
const originalTime = Runner.instance_.runningTime;
const values = TRexHacker.calculateValues(targetScore);
// Aplicar cambios gradualmente
const steps = 20;
const distStep = (values.distance - originalDist) / steps;
const timeStep = (values.time - originalTime) / steps;
let step = 0;
const interval = setInterval(() => {
if (step >= steps) {
clearInterval(interval);
Runner.instance_.gameOver();
return;
}
Runner.instance_.distanceRan += distStep;
Runner.instance_.runningTime += timeStep;
step++;
}, 100);
console.log("🔐 Hack con preservación de token iniciado");
}
Consideraciones Éticas
⚠️ Notas Importantes
- Solo propósito educativo - No hagas trampa en leaderboards reales
- Respeta términos de servicio - Úsalo responsablemente
- Testing local recomendado - chrome://dino/ es más seguro
Para Desarrolladores
Validaciones clave del servidor: consistencia de fórmulas, límites de velocidad y verificación de tokens.
Conclusiones
🎓 Lecciones Clave
Esta aventura de hackear el T-Rex nos enseñó principios fundamentales de ciberseguridad:
“Nunca Confíes en el Cliente”
- Validación del cliente = teatro de seguridad
- Validación del servidor = seguridad real
- Todo lo enviado desde navegadores puede ser manipulado
Las Matemáticas Derrotan los Hacks
- Velocidad = Distancia ÷ Tiempo (¡la física se aplica al hacking!)
- La consistencia en números es clave tanto para saltarse COMO para detectar
- Los servidores nos pillaron con velocidades sobrehumanas imposibles
Aplicaciones del Mundo Real
Estos no son solo trucos de juegos - se aplican a:
- Apps bancarias (mismos problemas de confianza)
- Comercio electrónico (prevención de manipulación de precios)
- APIs (rate limiting, validación)
- Sistemas de autenticación (validación de tokens)
🔬 Habilidades Técnicas Adquiridas
- Competencia en JavaScript (manipulación DOM, debugging)
- Análisis de redes (peticiones HTTP, manejo de respuestas)
- Ingeniería inversa (análisis de código, comprensión de sistemas)
- Mentalidad de seguridad (pensar como atacante Y defensor)
🎯 Reflexiones Finales
Google intencionalmente mantiene chrome://dino/ hackeable por valor educativo. La verdadera victoria no fue conseguir puntuaciones altas - fue entender cómo funcionan los sistemas por dentro.
Recuerda: Todo experto comenzó como un principiante curioso. La diferencia entre sombrero blanco y negro no es la habilidad - es cómo eliges usar ese conocimiento.
Este análisis se publica con fines educativos para enseñar conceptos de seguridad web y programación en JavaScript.