Kako sam krekirao Trivia Crack

click fraud protection

Trivia Crack vrlo je popularna igra za web i mobilne platforme koja je donekle oblikovana po uzoru na Trivial Pursuit. To je najnovija ludnica u društvenim igrama, koja korisnicima omogućuje da se natječu protiv svojih prijatelja i stranaca u odgovaranju na pitanja iz niza kategorija. Iako me igranje nikad nije jako zanimalo, moja žena je nedavno postala velika obožavateljica Trivia Cracka. Nakon što sam je neko vrijeme gledao kako igra, odlučio sam je preuzeti i pobliže pogledati kako je implementirana.

Počeo sam s nadgledanjem zahtjeva za web API koji se šalju preko mreže tijekom korištenja Android aplikacije. Vrlo brzo sam primijetio nešto zanimljivo tijekom rada igrice. Činilo se da je aplikacija primala kategoriju, pitanje i odgovor od poslužitelja Trivia Crack prije nego što je korisnik uopće počeo okretati kotačić "kategorije".

Ispod je primjer odgovora koji aplikacija dohvaća prije prikazivanja ovog zaslona:

{ 

"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

}

}

Imajte na umu da su kategorija, pitanje, opcije odgovora i ključevi točnog odgovora uključeni u odgovor. To znači da bi bilo jednostavno identificirati odgovor kada se unutar aplikacije zatraži varanje igre. Iako nije baš etično ili pošteno za korištenje u igricama, mislio sam da bi to bilo zanimljivo istraživanje.

Moj početni plan bio je obrnuti inženjering Android aplikacije i pružiti korisniku Tost obavijest o odgovoru. Počeo sam od dekompiliranje aplikacije i pregled izvornog koda. Koristio sam grep da pretražim izvor za neke ključne riječi za koje sam se nadao da će mi pomoći u praćenju aktivnosti pitanja/odgovora. Dok sam pretraživao neke od mogućih rezultata, nekoliko mi je redaka privuklo pozornost.

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

Nakon koda, "ANSWERS_CHEAT" aludira na skriveni način varanja u igri. Umjesto da ponovno izmišljam kotač, odlučio sam saznati kako funkcionira. Koristeći grep, pronašao sam sve reference na "ANSWERS_CHEAT" niz i to brzo otkrio referenca na skriveni izbornik na glavnoj aktivnosti nadzorne ploče.

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

}

}

Čini se da ovaj kod upravlja postavljanjem opcije načina varanja, ali još uvijek nisam mogao pristupiti samom izborniku. U okviru iste aktivnosti pregledao sam metodu OnCreateOptionsMenu u nastavku:

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

}

}

Većina funkcionalnosti načina varanja, uključujući skriveni izbornik, izgledala je kao da ovisi o vraćenoj vrijednosti com.etermax.tools.f.a.a(). Kod za tu klasu je ispod:

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;

}

}

Činilo se da je ovo točka odluke koju sam tražio. Mijenjanje zadatka a = lažno; do pravi trebao je omogućiti skriveni izbornik. Otvorio sam mali prikaz klase i pronašao dodjelu booleovog člana.

# 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

Promijenio sam redak 29 (isječak retka #7 iznad) u const/4 v0, 1, koji je vrijednost postavio na istinito. Zatim sam ponovno kompajlirao aplikaciju i instalirao je. Gumb izbornika zatim je uspješno otkrio skrivene opcije u nastavku:

Čini se da je "Answer Cheat" sada omogućen prema zadanim postavkama, pa sam pokrenuo novu igru ​​za testiranje. Kao što se i očekivalo, igre su sada dodale broj nakon pitanja, označavajući indeks točnog odgovora temeljen na nuli.

Preuzmite zakrpani APK ovdje. Imajte na umu da je ovo samo u istraživačke svrhe; Ne odgovaram za nemoralno igranje!

UREDI:APK Mirror

Ovo bi trebalo poslužiti kao dobar primjer da se ne može jamčiti privatnost klijentske aplikacije i da bi programeri trebali paziti što je uključeno u njihova kompilirana izdanja.