Jak jsem prolomil Trivia Crack

Trivia Crack je velmi oblíbená hra pro webové i mobilní platformy, která je do jisté míry po vzoru Trivial Pursuit. Je to nejnovější výstřelek v sociálních hrách, který uživatelům umožňuje soutěžit se svými přáteli a neznámými lidmi v odpovídání na otázky z řady kategorií. I když jsem se o hraní nikdy moc nezajímal, moje žena se nedávno stala velkým fanouškem Trivia Crack. Po chvíli sledování její hry jsem se rozhodl si ji stáhnout a podívat se blíže na to, jak byla implementována.

Začal jsem tím, že jsem sledoval požadavky webového rozhraní API ze sítě při používání aplikace pro Android. Velmi rychle jsem si během fungování hry všiml něčeho zajímavého. Zdálo se, že aplikace přijímala kategorii, otázku a odpověď ze serverů Trivia Crack ještě předtím, než uživatel vůbec začal točit kolečkem „kategorie“.

Níže je uveden příklad odpovědi, kterou aplikace načte před zobrazením této obrazovky:

{ 

"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

}

}

Všimněte si, že v odpovědi jsou zahrnuty kategorie, otázky, možnosti odpovědí a klíče správné odpovědi. To znamená, že by bylo snadné identifikovat odpověď, když budete v aplikaci požádáni o podvádění hry. I když to není úplně etické nebo spravedlivé pro herní použití, myslel jsem si, že by to byl zajímavý výzkum.

Mým původním plánem bylo provést zpětnou analýzu aplikace pro Android a poskytnout uživateli a Přípitek oznámení o odpovědi. Začal jsem tím dekompilaci aplikace a kontrolu zdrojového kódu. Použil jsem grep k vyhledání zdroje pro některá klíčová slova, o kterých jsem doufal, že mi pomohou vysledovat aktivitu otázek/odpovědí. Při prohledávání některých potenciálních výsledků mě upoutalo několik řádků.

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

Po kódu „ANSWERS_CHEAT“ odkazovalo na skrytý cheat mód ve hře. Spíše než znovu vynalézat kolo jsem se rozhodl zjistit, jak to funguje. Pomocí grep jsem našel všechny odkazy na "ANSWERS_CHEAT" tětiva a rychle objevil odkaz na skrytou nabídku na hlavní činnosti řídicího panelu.

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

}

}

Zdá se, že tento kód zvládá nastavení možnosti cheat módu, ale stále jsem nebyl schopen přistupovat k samotné nabídce. V rámci stejné aktivity jsem zkontroloval metodu OnCreateOptionsMenu níže:

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

}

}

Většina funkcí cheat módu, včetně skryté nabídky, vypadala, že závisí na vrácené hodnotě com.etermax.tools.f.a.a(). Kód pro tuto třídu je níže:

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;

}

}

Zdálo se, že toto je bod rozhodnutí, který jsem hledal. Změna zadání a = nepravda; na skutečný měl povolit skryté menu. Otevřel jsem malou reprezentaci třídy a našel přiřazení booleovského člena.

# 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

Změnil jsem řádek 29 (úryvek řádek #7 výše) na const/4 v0, 1, který nastaví hodnotu na true. Poté jsem aplikaci znovu zkompiloval a nainstaloval. Tlačítko nabídky poté úspěšně odhalilo skryté možnosti níže:

"Answer Cheat" se nyní zdál být ve výchozím nastavení povolen, takže jsem spustil novou hru na testování. Jak se očekávalo, hry nyní za otázky přidaly číslo, které označovalo index správné odpovědi založený na nule.

Stáhněte si opravený soubor APK tady. Upozorňujeme, že toto je pouze pro výzkumné účely; Nejsem odpovědný za jakoukoli nemorální hru!

UPRAVIT:APK Mirror

To by mělo sloužit jako dobrý příklad toho, že nelze zaručit soukromí klientských aplikací a vývojáři by si měli dávat pozor na to, co je zahrnuto v jejich zkompilovaných vydáních.