Як я зламав Trivia Crack

Trivia Crack — це дуже популярна гра як для веб-, так і для мобільних платформ, дещо створена за моделлю Trivial Pursuit. Це остання мода в соціальних іграх, що дозволяє користувачам змагатися зі своїми друзями та незнайомими людьми у відповідях на запитання з низки категорій. Хоча я ніколи не дуже цікавився іграми, моя дружина нещодавно стала великим фанатом Trivia Crack. Поспостерігавши за її грою деякий час, я вирішив завантажити його та ближче розглянути, як це реалізовано.

Я почав із моніторингу запитів веб-API, зроблених через мережу під час використання програми Android. Дуже швидко я помітив дещо цікаве під час роботи гри. Здавалося, що програма отримувала категорію, запитання та відповідь із серверів Trivia Crack ще до того, як користувач навіть почав крутити колесо «категорій».

Нижче наведено приклад відповіді, яку програма отримує перед показом цього екрана:

{ 

"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

}

}

Зверніть увагу, що категорія, питання, варіанти відповідей і ключі правильних відповідей включені у відповідь. Це означає, що буде легко визначити відповідь, коли в програмі буде запропоновано обдурити гру. Хоча це не зовсім етично чи справедливо для використання в іграх, я подумав, що це буде цікаве дослідження.

Моїм початковим планом було переробити програму Android і надати користувачеві Тост повідомлення про відповідь. Я почав з декомпіляція програми і перегляд вихідного коду. Я використовував grep для пошуку в джерелі деяких ключових слів, які, як я сподівався, допоможуть мені відстежити діяльність у питаннях/відповідях. Під час пошуку деяких потенційних результатів мою увагу привернули кілька рядків.

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

Після коду "ANSWERS_CHEAT" посилається на прихований режим читів у грі. Замість того, щоб заново винаходити велосипед, я вирішив дізнатися, як це працює. За допомогою grep я знайшов усі посилання на "ANSWERS_CHEAT" рядок і швидко виявлено посилання на приховане меню на головній панелі операцій.

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

}

}

Здавалося, цей код керує налаштуванням режиму читів, але я все ще не міг отримати доступ до самого меню. У межах тієї ж дії я переглянув метод OnCreateOptionsMenu нижче:

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

}

}

Більшість функціональних можливостей чіт-режиму, включаючи приховане меню, виглядало так, ніби воно залежало від повернутого значення com.etermax.tools.f.a.a(). Код для цього класу наведено нижче:

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;

}

}

Здавалося, це була точка прийняття рішення, яку я шукав. Зміна призначення a = false; до правда треба було ввімкнути приховане меню. Я відкрив smali представлення класу та знайшов призначення логічного члена.

# 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

Я змінив рядок 29 (рядок №7 фрагмента вище) на const/4 v0, 1, що встановлює значення true. Потім я перекомпілував програму та встановив її. Потім кнопка меню успішно показала приховані параметри нижче:

«Відповідь на обман» тепер, здається, увімкнено за замовчуванням, тому я запустив нову гру, щоб перевірити. Як і очікувалося, ігри тепер додають число після запитань, що вказує на нульовий індекс правильної відповіді.

Завантажте виправлений APK тут. Зауважте, що це лише для дослідницьких цілей; Я не несу відповідальності за аморальний геймплей!

РЕДАГУВАТИ:Дзеркало APK

Це має служити хорошим прикладом того, що конфіденційність клієнтських програм не може бути гарантована, і розробникам слід бути обережними щодо того, що включено до їхніх скомпільованих випусків.