Lo que aprendí pirateando el juego Facebook Messenger Soccer

Recientemente, durante el último Campeonato de Europa de Fútbol, ​​Facebook introdujo un pequeño juego en la aplicación Messenger que te hace perder horas y horas a pesar de su sencillez.

Si no lo notó, lea este artículo sobre Mashable.

Tengo que admitir ... Soy un desastre en este juego, así que mi mejor puntuación fue 9 .

Pero, como desarrollador, lo mejor que podía hacer era vencer a mis amigos pirateando el juego.

Realmente pensé que esto sería simple.

La primera forma: escuchar las solicitudes HTTP (s)

Mientras desarrolla aplicaciones, inmediatamente se da cuenta de que necesita una herramienta de depuración HTTP para analizar el tráfico entrante / saliente para sus API.

Charleses la mejor herramienta que he encontrado para realizar esta tarea. Tiene una interfaz muy intuitiva y puede usarla fácilmente para fines de depuración e ingeniería inversa.

Se suponía que terminaría en este punto: tendría que analizar la API que usaba la aplicación de Facebook y simplemente reproducirla con CURL mientras editaba los datos y la puntuación enviada al servidor.

Por supuesto, las llamadas a la API están en HTTPS, por lo que están encriptadas ... pero Charles puede usarse como un proxy HTTPS de intermediario, lo que le permite ver en texto sin formato la comunicación entre el navegador web y el servidor web SSL. .

¡Perfecto! Así que instalé el certificado raíz de Charles en el iPhone e intenté inspeccionar el tráfico. Pero todas las llamadas HTTP a los servidores de Facebook fueron denegadas por adelantado durante la fase de protocolo de enlace SSL.

Investigando un poco, descubrí que algunas aplicaciones de empresas como Facebook y Google utilizan una capa adicional de seguridad para garantizar que el certificado proporcionado por el servidor remoto sea el que se espera. Esta técnica se llama Fijación de certificados.

Puede hacer esto fácilmente incluyendo la clave pública del certificado del servidor remoto dentro de la aplicación, de modo que sea fácil validar la identidad del cliente para cada solicitud HTTPS.

Esta técnica invalida el ataque del hombre en el medio (MITM).

¡Buen trabajo Facebook! Pero ... (recuerde, siempre hay un pero) hay una manera de deshabilitar la fijación del certificado SSL mediante algunos ajustes del sistema que solo están disponibles en un dispositivo con jailbreak.

La primera forma (mejorada): hacer Jailbreak a un dispositivo e instalar iOS SSL Kill Switch

Mi iPhone ejecuta actualmente iOS 9.x, por lo que en el momento de escribir este artículo era imposible hacer jailbreak. Así que tomé un viejo iPad mini con iOS 8.3.xy fácilmente lo hice con la herramienta TaiG .

Buscando en la web, encontré SSL Kill Switch 2, una herramienta Blackbox para deshabilitar la validación del certificado SSL dentro de las aplicaciones iOS y OS X.

Una vez cargado en una aplicación iOS u OS X, SSL Kill Switch 2 parchea funciones específicas de SSL de bajo nivel dentro de la API de transporte seguro para anular y deshabilitar la validación de certificado predeterminada del sistema, así como cualquier tipo de validación de certificado personalizado (como fijación de certificado).

SSL Kill Switch utiliza MobileSubstrate para parchear funciones del sistema como la API de transporte seguro. Son la implementación de TLS de nivel más bajo en iOS.

Esto significa que la desactivación de la validación del certificado SSL en la API de transporte seguro debería afectar a la mayoría (si no a todas) de las API de red disponibles en el marco de iOS.

Por favor, hazte un favor y sigue este blog que cubre todos estos conceptos.

Entonces, me conecté al iPad usando SSH e instalé el paquete:

wget //github.com/nabla-c0d3/ssl-kill-switch2/releases/download/0.10/com.nablac0d3.SSLKillSwitch2_0.10.deb --no-check-certificatedpkg -i com.nablac0d3.SSLKillSwitch2_0.10.debkillall -HUP SpringBoard

Una vez reiniciado, esperaba ver el tráfico normal, pero era una visión optimista: obtuve los mismos errores.

Intenté de esta manera durante otra hora. Leí en algún lugar que Facebook y Twitter usan el protocolo SPDY para sus llamadas API, y esto podría ser un problema para Charles. Así que instalé otro ajuste que (teóricamente) deshabilitó el protocolo SPDY, pero no funcionó.

Muriendo de hambre.

Al observar los problemas del proyecto, noté que alguien más tenía el mismo problema (//github.com/nabla-c0d3/ssl-kill-switch2/issues/13), sin resolución.

Pausa.

La segunda forma: simular eventos táctiles dentro de la aplicación

Me di cuenta de que hay muchos trucos de juegos que utilizan un enfoque "humano": simular eventos táctiles (uno de los juegos más populares en el que muchos trucos utilizan esta estrategia es Clash of Clans).

Al buscar en la web una herramienta que automatice estas operaciones, encontré este increíble ajuste: AutoTouch. Puede registrar eventos de toque humano y almacenar los datos en un script LUA. A continuación, puede editar este script producido y simular lo que desee en cualquier lugar de su dispositivo.

Una vez instalado con Cydia, guardé una captura de pantalla BMP de la aplicación Messenger con la bola visible y obtuve las coordenadas de dónde hacer clic.

Lo que pensé es que, al hacer clic exactamente en el centro del eje X de la pelota, solo tenía que simular eventos táctiles repetitivos en las mismas coordenadas y luego detener el guión cuando tenía una puntuación con la que estaba satisfecho.

Esto es lo que escribí para lograr este objetivo:

adaptResolution(768, 1024);adaptOrientation(ORIENTATION_TYPE.PORTRAIT);
for i=1,2000 do
 touchDown(1, 544, 954); usleep(66000); touchUp(1, 544, 954);
 usleep(10000);
end

No, no funcionó.

Probablemente, los desarrolladores de Facebook introdujeron un error aleatorio en las coordenadas táctiles para simular mejor el juego o para evitar este tipo de scripts.

O tal vez simplemente hice clic en el píxel incorrecto.

Entonces, para tener una segunda oportunidad, intenté simular varios clics en un área más grande, pero sin suerte. A veces, simulé tantos eventos táctiles que el Springboard se bloqueó debido a errores de memoria .

En lugar de hacer clic en las mismas coordenadas cada vez, probé un enfoque mejor.

Reading the AutoTouch documentation, I found the following two methods:

  • findColor (color, count, region) - Search the coordinates of the pixel points matching the specified color on the current screen.
  • getColor (x, y) - Get the color value of the pixel point of the specified coordinate on the current screen.

The idea was to find a unique color inside the ball, and use the findColor method to get the coordinates of the ball in that moment, to simulate a touch event.

adaptResolution(768, 1024);adaptOrientation(ORIENTATION_TYPE.PORTRAIT);
local c = getColor(544, 954);
for i=1,2000 do local r = findColor(c, 0, {400, 500, 768, 1024});
 for i, v in pairs(r) do touchDown(1, v[1], v[2]); usleep(66000); touchUp(1, v[1], v[2]); usleep(10000); end
end

I don’t know why, but it simply didn’t work. Maybe the findColor is too slow to intercept the ball, which then makes the script useless.

The third way: Reverse engineer the app

I don’t have good native skills in Objective C, but I remember (when I played with the jailbreak ~4 years ago) that there was a tool by Saurik that could inject itself into iOS processes.

It is released along with Cydia and was called Cycript.It allowed developers to explore and modify running applications on iOS, by injecting code at run time.

I read some basic tutorials on how to use it, and after a few struggles, I decided to follow this (another) way.

Once you login via SSH into your iOS device, you can easily attach to a process just by typing:

cycript -p Messenger

I tried to inspect some basic UI classes like UIApp, but didn’t find anything interesting. Then I made a complete class dump, filtering it for the keyword soccer.

var C = Object.keys(ObjectiveC.classes);var soccer_classes = []; for (var i = 0; i < C.length; i++) C[i].match(/soccer/i) && soccer_classes.push( C[i] );

It was a slow process.

Descubrí que Facebook Messenger tiene una gran cantidad de clases.

Pero, al final, obtuve una pequeña lista.

Una vez que obtuve los nombres de las clases, usé un script para imprimir todos los métodos de la clase y, al inspeccionar la clase MNSoccerGame , los métodos resultantes fueron:

Nota: todavía no entiendo cuál es el método wasCheatDetected.

Ahora que tenía una lista completa de los métodos de la clase, decidí anular el método _setScore , esperando que otros métodos no se dieran cuenta de eso.

Para hacer esto, utilicé MobileSubstrate y su método MS.hookMessage .

@import com.saurik.substrate.MS; 
var _setScore_pointer = {}; MS.hookMessage(MNSoccerGame, @selector(_setScore:), function(arg0) { return _setScore_pointer->call(this, 9999); }, _setScore_pointer);

Ahora puedes jugar, perder y, de todos modos, conseguir un nuevo récord.

Que aprendí

Never stop yourself. Always try and discover new way to accomplish the same thing. I know, it’s just a game, but if you treat the problem you’re trying to solve like a challenge, you’ll get much more than the satisfaction of beating your friends.