Trivia Crack on erittäin suosittu peli sekä verkko- että mobiilialustoille, joka on jossain määrin mallinnettu Trivial Pursuitin mukaan. Se on sosiaalisen pelaamisen viimeisin villitys, jonka avulla käyttäjät voivat kilpailla ystäviensä ja tuntemattomien kanssa vastaamalla useiden kategorioiden kysymyksiin. Vaikka en ole koskaan ollut kovin kiinnostunut pelaamisesta, vaimostani on hiljattain tullut valtava Trivia Crackin fani. Katsettuani hänen peliä jonkin aikaa, päätin ladata sen ja tutkia tarkemmin, miten se toteutettiin.
Aloitin seuraamalla verkon kautta tehtyjä web-sovellusliittymäpyyntöjä käyttäessäni Android-sovellusta. Hyvin nopeasti huomasin jotain mielenkiintoista pelin toiminnan aikana. Näytti siltä, että sovellus sai luokan, kysymyksen ja vastauksen Trivia Crackin palvelimilta ennen kuin käyttäjä edes alkoi pyörittää "luokkapyörää".
Alla on esimerkkivastaus, jonka sovellus hakee ennen tämän näytön näyttämistä:
{"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
}
}
Huomaa, että luokka, kysymys, vastausvaihtoehdot ja oikeat vastausavaimet sisältyvät vastaukseen. Tämä tarkoittaa, että olisi yksinkertaista tunnistaa vastaus, kun sovelluksessa pyydetään huijaamaan peliä. Vaikka se ei ollutkaan aivan eettistä tai oikeudenmukaista pelikäytön kannalta, ajattelin sen olevan mielenkiintoinen tutkimus.
Alkuperäinen suunnitelmani oli palauttaa Android-sovellus ja tarjota käyttäjälle a Paahtoleipä ilmoitus vastauksesta. Aloitin siitä sovelluksen purkaminen ja lähdekoodin tarkistaminen. Käytin grep-hakua joidenkin avainsanojen lähteestä, joiden toivoin auttavan minua jäljittämään kysymysten/vastausten tekemisen. Kun etsin joitakin mahdollisia tuloksia, muutama rivi kiinnitti huomioni.
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();
Koodia seurannut "ANSWERS_CHEAT" viittasi pelin piilotettuun huijaustilaan. Pyörän uudelleen keksimisen sijaan päätin selvittää, miten se toimii. Käyttämällä grepiä löysin kaikki viittaukset "ANSWERS_CHEAT" merkkijono ja nopeasti löydetty a viittaus piilotettuun valikkoon kojelaudan päätoiminnossa.
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);
}
}
Tämä koodi näytti käsittelevän huijaustilan asettamisen, mutta en silti päässyt itse valikkoon. Saman toiminnon puitteissa tarkastelin alla olevaa OnCreateOptionsMenu-menetelmää:
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);
}
}
Suurin osa huijaustilan toiminnoista, mukaan lukien piilotettu valikko, näytti siltä, että se riippui palautetusta arvosta com.etermax.tools.f.a.a(). Tämän luokan koodi on alla:
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;
}
}
Tämä näytti olevan se päätöskohta, jota etsin. Tehtävän muuttaminen a = epätosi; to totta Piilotettu valikko olisi pitänyt ottaa käyttöön. Avasin luokan smali-esityksen ja löysin loogisen jäsenen tehtävän.
# 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
Muutin rivin 29 (katkelma rivi #7 yllä) muotoon const/4 v0, 1, joka asetti arvon tosi. Käänsin sitten sovelluksen uudelleen ja asensin sen. Valikkopainike paljasti sitten onnistuneesti alla olevat piilotetut vaihtoehdot:
"Answer Cheat" näytti nyt olevan oletusarvoisesti käytössä, joten käynnistin uuden pelin testattavaksi. Kuten odotettiin, pelit lisäsivät nyt kysymysten perään numeron, joka osoittaa oikean vastauksen nollaperusteisen indeksin.
Lataa korjattu APK tässä. Huomaa, että tämä on vain tutkimustarkoituksiin; En ole vastuussa mistään moraalittomasta pelistä!
MUOKATA:APK peili
Tämän pitäisi toimia hyvänä esimerkkinä siitä, että asiakassovellusten yksityisyyttä ei voida taata, ja kehittäjien tulee olla varovaisia koottujen julkaisujensa suhteen.