Stadt Land Fluss Multiplayer - Pwned

Hallo zusammen! Der Ausdruck “Pwned” findet in meinem Vokabular eigentlich keine Verwendung, doch hier ist er wirklich angebracht. Heute geht es um eine (noch) relativ unbekannte App “Stadt Land Fluss Multiplayer“, welche mit ca. 25000 Downloads nicht so bekannt wie Quizduell ist. Das Prinzip des Spiels ist einfach: Man hat 60 Sekunden Zeit, in den verschiedesten Kategorien Begriffe mit dem gleichen Anfangsbuchstaben einzutragen. Wer also die meisten Wörter weis und dabei auch noch ohne Schreibfehler tippt, schlägt den Gegner.

Screenshot_2014-07-13-18-23-33

Eine normale Modifikation könnte uns die Zeit zum Eintippen der Begriffe auf unendlich hochsetzen. Ein solcher Hack ist innerhalb von 3 Minuten geschrieben, denn die GameActivity bekommt als Parameter 60 ( = Sekunden) übergeben. Ein kleiner Smali-Patch schafft hier Abhilfe. Doch das ist kein Pwn, bei Begriffen die wir nicht wissen hilft uns auch keine längere Zeit zum überlegen. Ein anderer Ansatz muss her!

Diesen Ansatz finden wir in der API, die glücklicherweiße die Daten unverschlüsselt und per JSon überträgt. Zum Abrufen von Spieldaten senden wir folgende Request an den Server:

postData={"auth":{"password":"PASSWORDMD5Hashed","userId":"66XXX"},"clientInfo":{"appVersion":"1.0","bundleId":"de.lochmann.stadtlandfluss","os":"android"},"requests":{"getGameData":{"gameId":"1945415","userId":"X61XX","type":"getGameData"}}}

Die Antwort, welche zu Lang zum pasten ist, liefert uns diverse Strukturen mit Daten zum Spiel, dem Spieler, seiner Punktezahl und natürlich den bisher eingegeben Antworten. Ihr ahnt, worauf es hinausläuft? Daten aller Spiele grabben, eine riesige Datenbank aufbauen und pwnen! Das wäre ein Ansatz, doch bei bisher 1945415 gespielten Spielen wäre das komplette Grabben sinnlos. Zwar habe ich hier nun eine 2 GB Datenbank mit den ersten paar tausend Einträgen rumliegen, doch das filtern von richtigen Antworten macht auch nicht wirklich Spass. Man könnte daraus eine informative Statistik über Antworten und Punktezahlen erstellen, doch das nur als Randgedanke.

Die Seite json2csharp macht uns aus JSon Daten C#-Klassen, welche einfach per Deserialize gefüllt werden. So schreiben wir uns eine kleine Applikation, welche die aktuellen Spiele ausließt und schön in einer Liste darstellt:

SLF1

Auch die Struktur für Spieldaten sind dank json2csharp schnell erstellt. Wir geben uns die bisher eingetragen Antworten aus:

SLF2

Die App bietet die Möglichkeit 3 mal nach Spielende mögliche richtige Antworten anzuzeigen. Auch dieses ist eine API Request. Da weder die Request, noch die Response ewig groß ist sei sie hier abgebildet:
REQUEST:

{"auth":{"password":"MD5HashedPW","userId":"2****"},"clientInfo":{"appVersion":"1.0","bundleId":"de.lochmann.stadtlandfluss","os":"android"},"requests":{"getAdditionalData":{"requestString":"{\"category\":\"occupation\",\"letter\":\"x\",\"mode\":\"getSolution\"}","type":"getAdditionalData"}}}

RESPONSE:

{"response":{"getAdditionalData":{"answer":"{\"solution\":\"xml entwickler\"}"}},"status":{"result":"ok","message":"ich bin neu"}}

Neben XML Entwickler ist noch Xylophonspieler, sowie Xylophonbauer aufgelistet. Damit bekommen wir also auf jeden Fall richtige Ergebnisse, die vom Server-Backend als gültig gewertet werden. Und wir bekommen noch Bonuspunkte für exotische Antworten, wie zum Beispiel diese hier:

Screenshot_2014-07-13-18-25-20

Das ist ein richtiger Pwn, wir lesen die richtigen Antworten direkt vom Server und erhalten sogar noch Extrapunkte, da niemand der 25000 Spieler biser “Seppioline mit gedünsteter Ananas in Kurkuma-Kokosmilch” verwendet hat :D

Dabei gestaltet sich das Abrufen von richtigen Antworten, sowie das Abschicken von “gegebenen Antworten” richtig einfach. Hier ein bisschen Code zum Verständnis:

SendMoveRequest.MoveStringData moveStringData = new SendMoveRequest.MoveStringData();
moveStringData.gameId = gameData.response.getGameData.gameId.ToString();
moveStringData.state = "WaitingForUser";
moveStringData.letter = gameData.response.getGameData.letter;
moveStringData.answers = new List();
 
foreach (var t in gameData.response.getGameData.answers)
{
    GetAdditionalDataRequest request = new GetAdditionalDataRequest(t.category, gameData.response.getGameData.letter);
    GetAdditionalDataResponse response = ApiManager.SendAPIRequest(request);
    string solution = response.GetSolution();
 
    moveStringData.answers.Add(new SendMoveRequest.Answer() { answerOpponent = t.answerOpponent, answerUser = solution, category = t.category, categoryLocalized = t.categoryLocalized, explanationLabelOpponent = t.explanationLabelOpponent, explanationLabelUser = t.explanationLabelUser, explanationOpponent = t.explanationOpponent, explanationUser = t.explanationUser, scoreOpponent = t.scoreOpponent.ToString(), scoreUser = t.scoreUser.ToString()});
}
 
SendMoveRequest requ = new SendMoveRequest(moveStringData, gameData.response.getGameData.gameId.ToString());
string resp = ApiManager.SendAPIRequest(requ);

Der Bot kann bisher nur gegen Herrausforderungen spielen, also selbst keine Spiele gegen zufällige Leute initieren. Wer dies implementieren will, schnappt sich das Projekt sowie ein Android Handy und arbeitet sich auf Platz 1 der Liste vor. Gibt sogar ein extra Achievement :D

Download: Stadt Land Fluss Bot (109)

Wenns noch Fragen gibt, immer her damit!

9 people like this post.
    • Christian
    • 14. Jul. 2014 1:19pm

    Schönes Ding!

  1. Hallo,

    danke für den Artikel, wir fühlen uns geehrt! ;-)
    Interessanter Ansatz mit dem getGameData-Call, an den Ansatz hatten wir nicht gedacht.

    Wir haben diese Lücke soeben umgehend geschlossen.

    Viele Grüße!
    Benjamin Lochmann

      • Easysurfer
      • 20. Jul. 2014 3:04pm

      Hallo,
      es ist immer etwas komisch, wenn die Entwickler der jeweiligen Apps sich zu einem solchen Artikel äußern, da diese Einträge doch realtiv provokant geschrieben sind ;) Wie seid Ihr denn darauf gestossen?

      Um es Reversern im generellen schwerer zu machen, rate ich im übrigen zu einer verschlüsselten Datenübertragung und HTTPS, damit man die Daten nicht einfach mitschneiden und rekonstruieren kann.
      Grüße Easy

  2. Hallo Easy,

    wir haben Stadt Land Fluss letzte Woche etwas beworben. Nach einer Promotion checken wir immer via Google, wie das Feedback auf die App ist, um eventuell Verbesserungen vorzunehmen.

    @https:
    Thx für den Hinweis!
    Wir haben bei dieser App der Einfachheit halber darauf verzichtet, da wir das Gefahrenpotential für eher gering halten. Letztendlich ist es bei Stadt Land Fluss ja ohnehin recht einfach zu bescheißen, indem man einfach parallel am Rechner via Google passende Begriffe sucht. Die persönlichen Daten, die wir speichern, beschränken sich auf die User-Id. Einen Facebook Login, Login via E-Mail-Adresse oder Ähnliches haben wir bewusst nicht integriert.

    Viele Grüße!
    Benjamin Lochmann

    • pr0st
    • 21. Jul. 2014 5:55pm

    I <3 YOU! EASY

  1. Noch keine TrackBacks.