Hvad jeg lærte at hacke Facebook Messenger Soccer-spillet

For nylig, under sidste europæiske fodboldmesterskab, introducerede Facebook et lille spil i Messenger-appen, der får dig til at miste timer og timer på trods af sin enkelhed.

Hvis du ikke har bemærket det, skal du læse denne artikel om Mashable.

Jeg må indrømme ... Jeg suger totalt på dette spil, så min bedste score var 9 .

Men som udvikler var det bedste, jeg kunne gøre, at slå mine venner ved at hacke spillet.

Jeg troede virkelig, det ville være simpelt.

Den første måde: Lyt til HTTP (s) anmodninger

Mens du udvikler apps, indser du straks, at du har brug for et HTTP-fejlfindingsværktøj til at analysere indgående / udgående trafik til dine API'er.

Charleser det bedste værktøj, jeg har fundet til at udføre denne opgave. Det har en meget intuitiv grænseflade, og du kan nemt bruge den til debugging og reverse engineering.

Det skulle slutte på dette tidspunkt: Jeg bliver nødt til at analysere den API, som Facebook-appen brugte, og bare afspille den igen med CURL, mens jeg redigerer dataene og den score, der sendes til serveren.

Naturligvis er API-opkaldene i HTTPS, så de er krypterede .. men Charles kan bruges som en mand-i-midten HTTPS-proxy, så du kan se i almindelig tekst kommunikationen mellem webbrowser og SSL-webserver .

Perfekt! Så jeg installerede root Charles-certifikatet på iPhone, og jeg prøvede at inspicere trafikken. Men alle HTTP-opkald til Facebook-serverne blev afvist på forhånd i løbet af SSL-håndtryksfasen.

Ved at undersøge noget opdagede jeg, at nogle firma-apps som Facebook og Google bruger et ekstra lag af sikkerhed for at sikre, at certifikatet fra den eksterne server er det, der forventes. Denne teknik kaldes Certificate Pinning.

Du kan nemt gøre dette ved at inkludere den offentlige nøgle til fjernservercertifikatet i applikationen, så det er let at validere klientens identitet for hver HTTPS-anmodning.

Denne teknik ugyldiggør MIDM-angrebet.

Fantastisk job Facebook! Men ... (husk, der er altid et men) der er en måde at deaktivere fastgørelse af SSL-certifikat ved hjælp af nogle systemtilpasninger, der kun er tilgængelige på en fængselsbrudt enhed.

Den første måde (forbedret): Jailbreak en enhed og installer iOS SSL Kill Switch

Min iPhone kører i øjeblikket iOS 9.x, så i skrivende stund var det umuligt at jailbreak. Så jeg tog en gammel iPad mini, der kørte iOS 8.3.x, og fængslede den let ved hjælp af TaiG-værktøjet .

Jeg søgte på nettet og fandt SSL Kill Switch 2, et Blackbox-værktøj til at deaktivere validering af SSL-certifikater i iOS- og OS X-apps.

Når de er indlæst i en iOS- eller OS X-app, lapper SSL Kill Switch 2 specifikke SSL-lavniveaufunktioner i Secure Transport API for at tilsidesætte og deaktivere systemets standardcertifikatvalidering samt enhver form for brugerdefineret certifikatvalidering (såsom certifikatfastgørelse).

SSL Kill Switch bruger MobileSubstrate til at patch systemfunktioner som Secure Transport API. De er TLS-implementeringen på det laveste niveau på iOS.

Dette betyder, at deaktivering af SSL-certifikatvalidering i Secure Transport API bør påvirke de fleste (hvis ikke alle) de netværks-API'er, der er tilgængelige inden for iOS-rammen.

Venligst gør dig selv en tjeneste og følg denne blog, der dækker alle disse begreber.

Så jeg oprettede forbindelse til iPad ved hjælp af SSH og installerede pakken:

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

Når jeg var genstartet, forventede jeg at se den almindelige trafik, men det var en optimistisk vision: Jeg fik de samme fejl.

Jeg prøvede denne måde i endnu en time. Jeg læste et eller andet sted, at Facebook og Twitter bruger SPDY-protokollen til deres API-opkald, og dette kunne være et problem for Charles. Så jeg installerede en anden tweak, der (teoretisk) deaktiverede SPDY-protokollen, men det fungerede ikke.

Sultende.

Når jeg kiggede på projektproblemerne, bemærkede jeg, at en anden havde det samme problem (//github.com/nabla-c0d3/ssl-kill-switch2/issues/13) uden opløsning.

Pause.

Den anden måde: Simulere berøringsbegivenheder i applikationen

Jeg indså, at der er mange spilcheats, der bruger en "menneskelig" tilgang: simulere berøringshændelser (et af de mest populære spil, som mange spilcheats bruger denne strategi på, er Clash of Clans).

Gennemse internettet for et værktøj, der automatiserer disse operationer, fandt jeg denne fantastiske tweak - AutoTouch. Det kan registrere menneskelige berøringshændelser og gemme dataene i et LUA-script. Du kan derefter redigere dette producerede script og simulere hvad du vil hvor som helst på din enhed.

Når jeg var installeret med Cydia, gemte jeg et BMP-skærmbillede af Messenger-applikationen med bolden synlig og fik koordinaterne til, hvor man skulle klikke.

Hvad jeg troede var, at ved at klikke nøjagtigt i midten af ​​kuglens X-akse, måtte jeg kun simulere gentagne berøringshændelser i de samme koordinater og derefter stoppe scriptet, når jeg havde en score, som jeg var tilfreds med.

Her er hvad jeg skrev for at nå dette mål:

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

Nej, det fungerede ikke.

Sandsynligvis introducerede Facebook-udviklere en tilfældig fejl på berøringskoordinater for bedre at simulere spillet eller for at forhindre denne type scripts.

Eller måske klikkede jeg bare på den forkerte pixel.

Så for en anden chance forsøgte jeg at simulere flere klik i et større område, men uden held. Nogle gange simulerede jeg så mange berøringshændelser, at springbrættet bare styrtede ned på grund af hukommelsesfejl .

I stedet for at klikke i de samme koordinater hver gang, prøvede jeg en bedre tilgang.

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.

Jeg opdagede, at Facebook Messenger har et meget stort antal klasser.

Men til sidst fik jeg en lille liste.

Når jeg først fik klassens navne, brugte jeg et script til at udskrive alle metoderne i klassen, og ved at inspicere MNSoccerGame- klassen var de resulterende metoder:

Bemærk: Jeg forstår stadig ikke, hvad metoden wasCheatDetected er.

Nu da jeg havde en komplet liste over klassemetoderne, besluttede jeg at tilsidesætte _setScore- metoden i håb om, at andre metoder ikke bemærkede det.

For at gøre dette brugte jeg MobileSubstrate og dens MS.hookMessage- metode.

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

Nu kan du bare spille, tabe og alligevel score en ny rekord.

Hvad jeg lærte

Stop aldrig dig selv. Prøv altid at finde en ny måde at opnå det samme på. Jeg ved, det er bare et spil, men hvis du behandler det problem, du prøver at løse som en udfordring, får du meget mere end tilfredsheden med at slå dine venner.