Come ho risolto Trivia Crack

Trivia Crack è un gioco molto popolare sia per piattaforme web che mobili, che è in qualche modo modellato su Trivial Pursuit. È l'ultima mania dei giochi sociali, che consente agli utenti di competere contro i propri amici e sconosciuti rispondendo a domande di una serie di categorie. Anche se non sono mai stato molto interessato ai giochi, mia moglie è recentemente diventata una grande fan di Trivia Crack. Dopo averla guardata giocare per un po', ho deciso di scaricarlo e dare un'occhiata più da vicino a come è stato implementato.

Ho iniziato monitorando le richieste API Web effettuate sulla rete durante l'utilizzo dell'app Android. Molto presto ho notato qualcosa di interessante durante il funzionamento del gioco. Sembrava che l'app ricevesse la categoria, la domanda e la risposta dai server Trivia Crack prima ancora che l'utente iniziasse a girare la ruota della "categoria".

Di seguito è riportata una risposta di esempio che l'app recupera prima di visualizzare questa schermata:

{ 

"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

}

}

Tieni presente che la categoria, la domanda, le opzioni di risposta e le chiavi di risposta corrette sono tutte incluse nella risposta. Ciò significa che sarebbe semplice identificare la risposta quando viene chiesto all'interno dell'app di imbrogliare il gioco. Sebbene non sia esattamente etico o giusto per l'uso dei giochi, ho pensato che sarebbe stata una ricerca interessante.

Il mio piano iniziale era di decodificare l'app Android e fornire all'utente un file Pane abbrustolito notifica della risposta. Ho iniziato da decompilando l'app e rivedere il codice sorgente. Ho usato grep per cercare nella fonte alcune parole chiave che speravo mi aiutassero a rintracciare l'attività di domande/risposte. Durante la ricerca tra alcuni dei potenziali risultati, alcune righe hanno attirato la mia attenzione.

 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();

Dopo il codice, "ANSWERS_CHEAT" alludeva a una modalità cheat nascosta nel gioco. Piuttosto che reinventare la ruota, ho deciso di scoprire come funzionava. Usando grep, ho trovato tutti i riferimenti a "ANSWERS_CHEAT" corda e rapidamente scoperto UN riferimento a un menu nascosto nell'attività della dashboard principale.

 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);

}

}

Questo codice sembrava gestire l'impostazione dell'opzione della modalità cheat, ma non ero ancora in grado di accedere al menu stesso. All'interno della stessa attività, ho esaminato il metodo OnCreateOptionsMenu di seguito:

 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);

}

}

La maggior parte delle funzionalità della modalità cheat, incluso il menu nascosto, sembrava dipendessero dal valore restituito di com.etermax.tools.f.a.a(). Il codice per quella classe è seguente:

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;

}

}

Questo sembrava essere il punto decisionale che stavo cercando. Modifica dell'incarico a = falso;VERO avrei dovuto abilitare il menu nascosto. Ho aperto la piccola rappresentazione della classe e ho trovato l'assegnazione del membro booleano.

# 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

Ho cambiato la riga 29 (riga dello snippet n. 7 sopra) in cost/4 v0, 1, che imposta il valore su true. Ho quindi ricompilato l'app e l'ho installata. Il pulsante del menu ha quindi esposto con successo le opzioni nascoste di seguito:

"Answer Cheat" ora sembrava abilitato per impostazione predefinita, quindi ho avviato un nuovo gioco da testare. Come previsto, i giochi ora aggiungevano un numero dopo le domande, indicando l'indice in base zero della risposta corretta.

Scarica l'APK con patch Qui. Tieni presente che questo è solo a scopo di ricerca; Non sono responsabile di alcun gameplay immorale!

MODIFICARE:Specchio APK

Ciò dovrebbe servire da buon esempio del fatto che la privacy dell'applicazione client non può essere garantita e gli sviluppatori dovrebbero prestare attenzione a ciò che è incluso nelle loro versioni compilate.