ट्रिविया क्रैक वेब और मोबाइल दोनों प्लेटफार्मों के लिए एक अत्यधिक लोकप्रिय गेम है जो कुछ हद तक ट्रिवियल परस्यूट के आधार पर बनाया गया है। यह सोशल गेमिंग में नवीनतम सनक है, जो उपयोगकर्ताओं को विभिन्न श्रेणियों के प्रश्नों का उत्तर देने में अपने दोस्तों और अजनबियों के खिलाफ प्रतिस्पर्धा करने की अनुमति देता है। हालाँकि मुझे कभी भी गेमिंग में बहुत दिलचस्पी नहीं रही, मेरी पत्नी हाल ही में ट्रिविया क्रैक की बहुत बड़ी प्रशंसक बन गई है। कुछ देर तक उसका खेल देखने के बाद, मैंने इसे डाउनलोड करने और इसे कैसे लागू किया गया, इस पर करीब से नज़र डालने का फैसला किया।
मैंने एंड्रॉइड ऐप का उपयोग करते समय नेटवर्क पर किए गए वेब एपीआई अनुरोधों की निगरानी करके शुरुआत की। बहुत जल्द, मुझे गेम के संचालन के दौरान कुछ दिलचस्प चीज़ नज़र आई। ऐसा लगता है कि उपयोगकर्ता द्वारा "श्रेणी" चक्र घुमाना शुरू करने से पहले ही ऐप को ट्रिविया क्रैक सर्वर से श्रेणी, प्रश्न और उत्तर प्राप्त हो रहे थे।
नीचे एक उदाहरण प्रतिक्रिया दी गई है जिसे ऐप इस स्क्रीन को दिखाने से पहले प्राप्त करता है:
{"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
}
}
ध्यान दें कि प्रतिक्रिया में श्रेणी, प्रश्न, उत्तर विकल्प और सही उत्तर कुंजी सभी शामिल हैं। इसका मतलब यह है कि गेम को धोखा देने के लिए ऐप के भीतर पूछे जाने पर उत्तर की पहचान करना आसान होगा। हालाँकि यह गेमिंग के उपयोग के लिए बिल्कुल नैतिक या उचित नहीं है, फिर भी मैंने सोचा कि यह दिलचस्प शोध होगा।
मेरी प्रारंभिक योजना एंड्रॉइड ऐप को रिवर्स इंजीनियर करने और उपयोगकर्ता को एक प्रदान करने की थी सेंकना उत्तर की अधिसूचना. मैंने शुरुआत की ऐप को डीकंपाइल करना और स्रोत कोड की समीक्षा कर रहे हैं। मैंने कुछ कीवर्ड के स्रोत को खोजने के लिए 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" गेम में एक छिपे हुए चीट मोड की ओर इशारा करता है। पहिये का पुनः आविष्कार करने के बजाय, मैंने यह पता लगाने का निर्णय लिया कि यह कैसे काम करता है। ग्रेप का उपयोग करते हुए, मुझे "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;
}
}
ऐसा प्रतीत होता है कि यही वह निर्णय बिंदु है जिसकी मैं तलाश कर रहा था। असाइनमेंट बदलना ए = झूठा; को सत्य छिपे हुए मेनू को सक्षम करना चाहिए था। मैंने कक्षा का स्माली प्रतिनिधित्व खोला और बूलियन सदस्य का असाइनमेंट पाया।
# 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) को बदल दिया स्थिरांक/4 वि0, 1, जो मान को सत्य पर सेट करता है। फिर मैंने ऐप को दोबारा संकलित किया और इसे इंस्टॉल किया। इसके बाद मेनू बटन ने नीचे छिपे विकल्पों को सफलतापूर्वक उजागर कर दिया:
"उत्तर धोखा" अब डिफ़ॉल्ट रूप से सक्षम लग रहा था, इसलिए मैंने परीक्षण के लिए एक नया गेम शुरू किया। जैसा कि अपेक्षित था, गेम में अब प्रश्नों के बाद एक नंबर जोड़ा गया है, जो सही उत्तर के शून्य-आधारित सूचकांक को दर्शाता है।
पैच किया गया एपीके डाउनलोड करें यहाँ. ध्यान दें कि यह केवल शोध उद्देश्यों के लिए है; मैं किसी भी अनैतिक गेमप्ले के लिए ज़िम्मेदार नहीं हूँ!
संपादन करना:एपीके मिरर
इसे एक अच्छे उदाहरण के रूप में काम करना चाहिए कि क्लाइंट एप्लिकेशन गोपनीयता की गारंटी नहीं दी जा सकती है और डेवलपर्स को इस बात से सावधान रहना चाहिए कि उनके संकलित रिलीज़ में क्या शामिल है।