Trivia Crack ir ļoti populāra spēle gan tīmekļa, gan mobilajām platformām, kas ir nedaudz veidota pēc Trivial Pursuit parauga. Tas ir jaunākais sociālo spēļu trakums, kas ļauj lietotājiem sacensties ar saviem draugiem un svešiniekiem, atbildot uz jautājumiem no dažādām kategorijām. Lai gan es nekad neesmu ļoti interesējies par spēlēm, mana sieva nesen ir kļuvusi par lielu Trivia Crack fanu. Kad kādu laiku skatījos viņas spēli, es nolēmu to lejupielādēt un sīkāk izpētīt, kā tas tika īstenots.
Es sāku, pārraugot tīmekļa API pieprasījumus, kas tika veikti tīklā, izmantojot Android lietotni. Ļoti ātri es pamanīju kaut ko interesantu spēles darbības laikā. Šķita, ka lietotne saņēma kategoriju, jautājumu un atbildi no Trivia Crack serveriem, pirms lietotājs pat sāka griezt "kategorijas" riteni.
Tālāk ir sniegts atbildes piemērs, ko lietotne ienes pirms šī ekrāna parādīšanas:
{"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
}
}
Ņemiet vērā, ka atbildē ir iekļauta kategorija, jautājums, atbilžu iespējas un pareizo atbilžu taustiņi. Tas nozīmē, ka būtu vienkārši noteikt atbildi, ja lietotnē tiek prasīts apkrāpt spēli. Lai gan tas nav gluži ētisks vai godīgs spēļu lietošanai, es domāju, ka tas būtu interesants pētījums.
Mans sākotnējais plāns bija Android lietotnes apgrieztā inženierija un nodrošināt lietotājam a Tosts paziņojums par atbildi. Es sāku ar lietotnes dekompilēšana un avota koda pārskatīšanu. Es izmantoju grep, lai meklētu avotā dažus atslēgvārdus, kas, es cerēju, palīdzētu man izsekot jautājumu/atbilžu darbībai. Meklējot dažus iespējamos rezultātus, manu uzmanību piesaistīja dažas rindiņas.
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();
Pēc koda "ANSWERS_CHEAT" norādīja uz slēpto krāpšanās režīmu spēlē. Tā vietā, lai no jauna izgudrotu riteni, es nolēmu noskaidrot, kā tas darbojas. Izmantojot grep, es atradu visas atsauces uz "ANSWERS_CHEAT" virkne un ātri atklāja a atsauce uz slēpto izvēlni galvenajā informācijas paneļa darbībā.
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);
}
}
Šķita, ka šis kods apstrādā krāpšanās režīma opcijas iestatīšanu, taču es joprojām nevarēju piekļūt pašai izvēlnei. Tās pašas darbības ietvaros es pārskatīju tālāk norādīto OnCreateOptionsMenu metodi.
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);
}
}
Lielākā daļa krāpšanās režīma funkcionalitātes, tostarp slēptā izvēlne, izskatījās tā, it kā tā būtu atkarīga no atgrieztās vērtības com.etermax.tools.f.a.a(). Šīs klases kods ir zemāk:
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;
}
}
Šķita, ka tas bija lēmuma punkts, ko es meklēju. Uzdevuma maiņa a = nepatiess; uz taisnība vajadzēja iespējot slēpto izvēlni. Es atvēru klases smali attēlojumu un atradu Būla dalībnieka uzdevumu.
# 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
Es nomainīju 29. rindiņu (fragmenta rindiņa Nr. 7 iepriekš) uz const/4 v0, 1, kas iestatīja vērtību uz patiesu. Pēc tam es pārkompilēju lietotni un instalēju to. Pēc tam izvēlnes poga veiksmīgi atklāja tālāk norādītās slēptās opcijas:
Šķita, ka pēc noklusējuma ir iespējota "Atbildes apkrāpšana", tāpēc es sāku jaunu spēli, lai pārbaudītu. Kā gaidīts, spēles tagad aiz jautājumiem pievienoja skaitli, kas norāda uz nulles bāzes indeksu pareizajai atbildei.
Lejupielādējiet laboto APK šeit. Ņemiet vērā, ka tas ir paredzēts tikai pētniecības nolūkiem; Es neesmu atbildīgs par amorālu spēli!
EDIT:APK spogulis
Tam vajadzētu kalpot par labu piemēru, ka nevar garantēt klienta lietojumprogrammu konfidencialitāti, un izstrādātājiem jābūt uzmanīgiem attiecībā uz to, kas ir iekļauts viņu apkopotajos laidienos.