Wie ich Trivia Crack geknackt habe

Trivia Crack ist ein sehr beliebtes Spiel für Web- und Mobilplattformen, das Trivial Pursuit nachempfunden ist. Es handelt sich um den neuesten Trend im Bereich Social Gaming, bei dem Benutzer gegen ihre Freunde und Fremden antreten und Fragen aus einer Reihe von Kategorien beantworten können. Obwohl ich mich nie besonders für Spiele interessiert habe, ist meine Frau seit Kurzem ein großer Fan von Trivia Crack. Nachdem ich ihr eine Weile beim Spielen zugesehen hatte, beschloss ich, es herunterzuladen und mir die Umsetzung genauer anzusehen.

Ich begann damit, die über das Netzwerk gestellten Web-API-Anfragen zu überwachen, während ich die Android-App verwendete. Sehr schnell fiel mir während des Spielbetriebs etwas Interessantes auf. Es schien, dass die App die Kategorie, Frage und Antwort von den Trivia Crack-Servern erhielt, bevor der Benutzer überhaupt anfing, am „Kategorie“-Rad zu drehen.

Nachfolgend finden Sie eine Beispielantwort, die die App abruft, bevor dieser Bildschirm angezeigt wird:

{ 

"id": 2747994099,

"opponent": {

"id": 0,

"alerts_count": 0,

"username": "smartplay(tm)"

},

"game_status": "PENDING_APPROVAL",

"language": "EN",

"created": "03/23/2015 08:58:29 EST",

"last_turn": "03/23/2015 08:58:29 EST",

"type": "NORMAL",

"expiration_date": "03/26/2015 08:58:29 EST",

"my_turn": true,

"statistics": {

"player_one_statistics": {

"category_questions": [

{

"category": "GEOGRAPHY",

"correct": 1,

"incorrect": 0,

"worst": false

}

],

"correct_answers": 1,

"incorrect_answers": 0,

"challenges_won": 0,

"questions_answered": 1,

"crowns_won": 0

},

"player_two_statistics": {

"correct_answers": 0,

"incorrect_answers": 0,

"challenges_won": 0,

"questions_answered": 0,

"crowns_won": 0

}

},

"duelGameType": false,

"normalType": true,

"spins_data": {

"spins": [

{

"type": "NORMAL",

"questions": [

{

"question": {

"id": 14996887,

"category": "SPORTS",

"text": "Who was the first woman gymnast to score a perfect ten at the Olympics?",

"answers": [

"Nadia Comaneci",

"Mo Huilan",

"Tatiana Gutsu",

"Agnes Keleti"

],

"author": {

"id": 71534267,

"name": "Florentina Ionela Gagliano",

"username": "florentina.gagliano",

"facebook_id": "100000030456122",

"facebook_name": "Florentina Ionela Gagliano",

"fb_show_picture": true,

"fb_show_name": true

},

"correct_answer": 0,

"media_type": "NORMAL"

},

"powerup_question": {

"id": 8534934,

"category": "SPORTS",

"text": "In basketball, what does it mean to \"kiss it off the glass\"?",

"answers": [

"Make both free throws",

"Pass off someone's back",

"Dribble past two people",

"Hit a shot off the backboard"

],

"author": {

"id": 41439403,

"name": "tsan.819",

"username": "tsan.819",

"fb_show_picture": false,

"fb_show_name": false

},

"correct_answer": 3,

"media_type": "NORMAL"

}

}

]

}

]

},

"available_crowns": [

"SCIENCE",

"ARTS",

"HISTORY",

"ENTERTAINMENT",

"SPORTS",

"GEOGRAPHY"

],

"my_player_number": 1,

"available_extra_shots": 1,

"player_one": {

"charges": 1

},

"player_two": {

"charges": 0

},

"round_number": 1,

"sub_status": "P1_PLAYING_FIRST_TURN",

"previous_sub_status": "P1_WAITING_FIRST_TURN",

"is_random": true,

"unread_messages": 0,

"status_version": 1,

"new_achievements": false,

"my_level_data": {

"level": 1,

"points": 1,

"progress": 33,

"goal_points": 3,

"level_up": false

}

}

Beachten Sie, dass die Kategorie, die Frage, die Antwortoptionen und die richtigen Antwortschlüssel alle in der Antwort enthalten sind. Dies bedeutet, dass es einfach wäre, die Antwort zu finden, wenn man in der App aufgefordert wird, das Spiel zu betrügen. Auch wenn es für den Einsatz in Spielen nicht gerade ethisch oder fair ist, dachte ich, es wäre eine interessante Forschung.

Mein ursprünglicher Plan bestand darin, die Android-App zurückzuentwickeln und dem Benutzer eine bereitzustellen Toast Benachrichtigung über die Antwort. Ich habe damit angefangen Dekompilieren der App und Überprüfung des Quellcodes. Ich habe grep verwendet, um die Quelle nach einigen Schlüsselwörtern zu durchsuchen, von denen ich hoffte, dass sie mir dabei helfen würden, die Fragen-/Antwortaktivitäten aufzuspüren. Als ich einige der potenziellen Ergebnisse durchsuchte, erregten einige Zeilen meine Aufmerksamkeit.

 v.setText(p); 

String s1 = "";

if (com.etermax.tools.f.a.a() && h.a("ANSWERS_CHEAT", true))

{

s1 = (new StringBuilder()).append(" (").append(r.getCorrectAnswer()).append(")").toString();

}

B.setText((new StringBuilder()).append(r.getText()).append(s1).toString());

A.setContentDescription(r.getText());

a(B);

u.setVisibility(0);

C.startAnimation(com.etermax.preguntados.ui.a.c.b());

x.setImageResource(com.etermax.preguntados.ui.game.duelmode.h.a(m).a(g, r.getCategory()));

LayoutInflater layoutinflater;

List list;

if (l != null && l == GameType.DUEL_GAME)

{

y.setVisibility(0);

y.setText(c(c.x().h()));

} else

{

y.setVisibility(8);

}

H.setEnabled(false);

layoutinflater = getLayoutInflater(getArguments());

d.a(e.d);

list = r.getAnswers();

Im Anschluss an den Code spielte „ANSWERS_CHEAT“ auf einen versteckten Cheat-Modus im Spiel an. Anstatt das Rad neu zu erfinden, beschloss ich, herauszufinden, wie es funktioniert. Mit grep habe ich alle Verweise auf „ANSWERS_CHEAT“ gefunden. Zeichenfolge und schnell entdeckt Verweis auf ein verstecktes Menü in der Hauptaktivität des Dashboards.

 public boolean onOptionsItemSelected(MenuItem menuitem) 

{

if (com.etermax.tools.f.a.a() && menuitem.getItemId() == com.etermax.i.cheat)

{

if (j.a("ANSWERS_CHEAT", true))

{

j.b("ANSWERS_CHEAT", false);

menuitem.setTitle("Enable Answer Cheat");

return true;

} else

{

j.b("ANSWERS_CHEAT", true);

menuitem.setTitle("Disable Answer Cheat");

return true;

}

} else

{

return super.onOptionsItemSelected(menuitem);

}

}

Dieser Code schien die Einstellung der Cheat-Modus-Option zu handhaben, aber ich konnte immer noch nicht auf das Menü selbst zugreifen. Im Rahmen derselben Aktivität habe ich die OnCreateOptionsMenu-Methode unten überprüft:

 public boolean onCreateOptionsMenu(Menu menu) 

{

if (com.etermax.tools.f.a.a())

{

getMenuInflater().inflate(com.etermax.l.preguntados_debug_menu, menu);

return true;

} else

{

return super.onCreateOptionsMenu(menu);

}

}

Die meisten Funktionen des Cheat-Modus, einschließlich des versteckten Menüs, schienen vom zurückgegebenen Wert von abzuhängen com.etermax.tools.f.a.a(). Der Code für diese Klasse ist unten:

public class a. 

{

private static boolean a;

private static String b;

public static void a(ApplicationInfo applicationinfo)

{

a = false;

}

public static void a(String s)

{

b = s;

}

public static boolean a()

{

return a;

}

public static String b()

{

return b;

}

public static boolean c()

{

return b != null;

}

}

Dies schien der Entscheidungspunkt zu sein, den ich suchte. Ändern der Zuordnung a = falsch; Zu WAHR hätte das versteckte Menü aktivieren sollen. Ich habe die Smali-Darstellung der Klasse geöffnet und die Zuweisung des booleschen Elements gefunden.

# direct methods. 

.method public static a(Landroid/content/pm/ApplicationInfo;)V

.locals 1

.prologue

.line 29

const/4 v0, 0x0

sput-boolean v0, Lcom/etermax/tools/f/a;->a: Z

.line 30

return-void

.end method

Ich habe Zeile 29 (Zeile Nr. 7 oben) geändert in const/4 v0, 1, wodurch der Wert auf true gesetzt wird. Anschließend habe ich die App neu kompiliert und installiert. Die Menüschaltfläche hat dann die folgenden versteckten Optionen erfolgreich angezeigt:

„Antwort-Cheat“ schien jetzt standardmäßig aktiviert zu sein, also habe ich ein neues Spiel zum Testen gestartet. Wie erwartet haben die Spiele nun nach den Fragen eine Zahl angehängt, die den nullbasierten Index der richtigen Antwort angibt.

Laden Sie die gepatchte APK herunter Hier. Beachten Sie, dass dies nur zu Forschungszwecken dient. Ich bin nicht verantwortlich für unmoralisches Gameplay!

BEARBEITEN:APK-Spiegel

Dies sollte als gutes Beispiel dafür dienen, dass der Datenschutz von Clientanwendungen nicht garantiert werden kann und Entwickler vorsichtig sein sollten, was in ihren kompilierten Versionen enthalten ist.