- Magic: The Gathering Arena में प्रतिद्वंद्वी को मनचाहे समय पर हार मानने के लिए मजबूर किया जा सकता था, जिससे matchmaking गेम में कभी न हारने की स्थिति बनाई जा सकती थी
- कार्ड गेम आमतौर पर उस server-authoritative architecture के लिए उपयुक्त होते हैं जिसमें पूरा state server संभालता है, लेकिन MTGA का bot opponent Sparky local client logic के रूप में implement किया गया था
- C# आधारित MTGA client में reflection के जरिए runtime objects और private fields तक पहुँचा जा सकता था, और decompiled code में
JoinMatch,ConnectAndJoinMatch,HeadlessClientजैसे नाम दिखे - bot match में एक ही account के
PersonaIDऔर JWT से दोनों seats पर connect होने वाली संरचना इस्तेमाल होती थी, और इसे सामान्य match पर लागू कर opponent seat पर headless client जोड़ने के बादConcedeGame()कॉल किया जा सकता था - बाद में server पर patch किया गया ताकि matchmaking गेम में दोनों seats एक ही account और JWT का उपयोग न कर सकें, और यह client-side bot implementation तथा seat authentication validation की सीमा का व्यावहारिक security पर सीधे असर दिखाने वाला उदाहरण बना
कार्ड गेम को हैक करना कठिन क्यों है
- कार्ड गेम turn-based होते हैं और client तथा server के बीच बहुत अधिक जानकारी का आदान-प्रदान नहीं होता, इसलिए वे server-authoritative architecture के लिए अच्छी तरह उपयुक्त हैं
- server पूरा game state संभालता है और client को केवल ज़रूरी जानकारी भेजता है
- प्रतिद्वंद्वी के hand या deck जैसी सार्वजनिक न होने वाली जानकारी local में मौजूद नहीं होती
- deck क्रम बदलने या अगला card manipulate करने जैसी कोशिशें कठिन होती हैं, क्योंकि server कार्रवाई चलाता है और केवल परिणाम बताता है
- first-person shooter से अलग, कार्ड गेम में player actions सीमित होते हैं और तय समय पर होते हैं
- FPS में enemy model location जैसी जानकारी client में पहले से cache हो सकती है, इसलिए wallhack जैसी तकनीकें संभव होती हैं
- Riot का anti-wallhack ब्लॉग client-side player location data घटाने के दृष्टिकोण पर चर्चा करता है
- गलत व्यवहार का पता लगाना भी तुलनात्मक रूप से आसान है
- हाथ में न होने वाला card खेलना
- अपनी turn न होने पर action करना
विश्लेषण की शुरुआत: नेटवर्क और C# client
- game hacking की शुरुआत के लिए network communication देखने का तरीका चुना गया
- MMO hacking के मामलों पर Manfred की DEF CON प्रस्तुति दिखाती है कि network protocol reverse engineering कई bugs के विश्लेषण में अहम होती है
- MTGA, C# में लिखा गया है, इसलिए traffic send/receive functions को hook करने के बजाय runtime में objects को manipulate किया जा सकता था
- .NET reflection से private fields और methods तक भी पहुँचना संभव है
- संबंधित बुनियादी उदाहरण के रूप में Unity game reflection hacking tutorial जुड़ा है
- obfuscate न किए गए .NET assemblies में metadata token की वजह से functions, variables और classes के नाम मानव-पठनीय रूप में देखे जा सकते हैं
- इसी कारण decompiled output लगभग source code review जैसा बन जाता है
JoinMatch में मिली Sparky की संरचना
- match join initialization खोजने के लिए संबंधित function names ढूँढते हुए
JoinMatchfunction मिला JoinMatch200 से अधिक lines वाला लंबा function था, और नीचेConnectAndJoinMatchकॉल दिखाई दी- यह function match configuration information लेकर game server से connect होने वाला flow लगता था
- उसी code flow में
MatchType.NPEऔरMatchType.Familiarbranches थींNPEसंभवतः नए खिलाड़ियों के experience वाली tutorial match श्रेणी थीFamiliarstandard bot match था
- इस branch में कॉल होने वाला logic MTGA के bot opponent Sparky से जुड़ा था
- Sparky tutorial और bot battles में इस्तेमाल होने वाला MTGA का mascot-जैसा opponent है
- bot matches में bot logic local machine के game client के भीतर चलता था
local bot और HeadlessClient
- bot का वास्तविक logic handler
HeadlessClientclass के भीतर था HeadlessClientएक headless client है जो game board render नहीं करता, बल्कि server से connect होकर game चलाता है- local में बनाए गए bot client ने game client जैसी ही user authentication information का उपयोग किया
- user ID की भूमिका वाला
PersonaID - login के बाद game को दिया जाने वाला JSON web token
- user ID की भूमिका वाला
- bot matches में server इसे समस्या नहीं मानता था कि मूल रूप से एक ही client match की दोनों sides से connect हो जाए
- seat का उपयोग game में यह अलग करने के लिए होता है कि कौन-सा player कौन है
- bot match में एक ही authentication information से अलग-अलग seats भरना संभव था
सामान्य match पर कब्ज़ा करने का तरीका
- bot match logic को सामान्य matches पर लागू कर यह जाँचा गया कि क्या दोनों seats से connect हुआ जा सकता है
- ज़रूरी जानकारी runtime के game objects से ली गई
- वर्तमान match configuration
- match server host और port
controllerFabricUrimatchIdPersonaIDJwt- card database
- match manager
- asset lookup system
- अपनी seat के आधार पर opponent seat की गणना की गई
- code में
man.LocalPlayerSeatId % 2U + 1Uसे दूसरी seat निकाली गई
- code में
UnityFamiliar.SpawnFamiliar_DEBUG(...)से opponent seat पर bot connect कराया गया- बने हुए
UnityFamiliarobject को ढूँढकरcheatbot.Client.Gre.ConcedeGame()कॉल किया गया, जिससे तुरंत हार मान ली गई
परिणाम और patch
- यह तरीका सामान्य matches में भी काम करता था
- प्रतिद्वंद्वी पहले से connected हो और game चल रहा हो, तब भी यह काम करता था
- क्योंकि यह matchmaking game था, इसलिए इंसानी opponent को हराने जैसा reward मिलता था
- vulnerability का मूल यह था कि सामान्य match server एक ही account और JWT से दोनों seats पर connection की अनुमति दे रहा था
- बाद में server पर patch किया गया ताकि matchmaking गेम में दोनों seats एक ही account और JWT का उपयोग न कर सकें
- परिशिष्ट में दिया गया
InstaWincode एक UnityMonoBehaviourहै, जो GUI button बनाता है, और button click पर मौजूदा match information इकट्ठा कर bot को opponent seat पर जोड़कर उससे हार मँगा देता है
1 टिप्पणियां
Hacker News की राय
Linux को पहली बार सच में गहराई से समझने की शुरुआत EverQuest के लिए ShowEQ से network traffic देखने से हुई थी
उस समय traffic encrypted नहीं था और उसमें बहुत-सी उपयोगी जानकारी होती थी। Hub के ज़रिए traffic को Linux machine पर mirror करके zone का real-time map बनाया जाता था, और monster·NPC·user की locations दिखाई जाती थीं, यहाँ तक कि monster के loot भी दिखते थे, इसलिए सिर्फ़ चुने हुए monster को target किया जा सकता था। इसका फ़ायदा यह था कि यह manual तरीका था, इसलिए detect करना संभव नहीं था, और आख़िरकार SOE को इसका पता चल गया और उसने traffic encryption शुरू कर दी
फिर दूसरी तरफ़ key-based signing लाई जाती है, उसके बाद फिर client से key चुराने की कोशिश होती है, encryption तोड़ी जाती है, और फिर anti-cheat system आने के साथ बिल्ली-चूहे का खेल शुरू हो जाता है
क्या यह game में फ़ायदा लेने लायक था? नहीं। मैं इतना serious player नहीं था, इसलिए setup पर 2 हफ़्ते लगाए और लगभग 1 हफ़्ता इस्तेमाल किया, बस, लेकिन learning experience के रूप में यह शानदार था
उदाहरण के लिए hell level का अस्तित्व, यह कि इंसानों को नहीं बल्कि halfling को experience bonus मिलता था और सचमुच race/class के हिसाब से experience में फ़र्क था, शुरुआती Shaman alchemy वास्तव में टूटी हुई थी, आदि। और शायद यही आगे चलकर eqemulator.org तक पहुँचा, अगर मैं सही याद कर रहा हूँ
लगता है कि EQ के मौजूदा मालिक को इसकी ज़्यादा परवाह नहीं है, इसलिए इसे इस्तेमाल करना काफ़ी हद तक ठीक माना जाता है। हालाँकि दोनों apps ने visible gear को छोड़कर कभी monster के loot नहीं दिखाए। समय के साथ कुछ data भी बदल गया है; पहले monster की सटीक health भेजी जाती थी, अब सिर्फ़ percentage भेजी जाती है
“Magic: The Gathering का कोई भी arbitrary game खेलने वाला लगभग पूर्ण bot इतना छोटा है कि local machine पर चल सके” — यह हिस्सा ठीक से समझ नहीं आया
अगर MTG AI इतना भारी होता कि उसे customer machine पर चलाना मुश्किल हो, तो शायद उसे server पर भी नहीं चलाया जाता। Card game bot match आम तौर पर per-match billing वाले नहीं होते, इसलिए cost बड़ी हो जाती है। Server भी कोई जादू नहीं हैं; ज़्यादातर local machine जैसे ही x86 CPU इस्तेमाल करते हैं, और कई बार desktop से कम clock speed पर। अगर local से कम bot turn time चाहिए, तो customer की तुलना में कहीं ज़्यादा cores लगाने पड़ेंगे, और अगर player per 8~16 allocated cores जैसी बात हो, तो peak concurrency पर यह डरावना सपना लगेगा। अगर CPU player multi-core support नहीं करता, तो local execution को किसी भी हाल में ज़्यादा तेज़ होना चाहिए
मतलब यह कि bot का rules engine इतना छोटा है कि पुराने iPhone या Android device की memory में समा सके। Server पर state machine या rules engine की कई copies memory में रखी जा सकती हैं, और किसी specific request को execute करने में शायद processing performance लगभग लगे ही नहीं
Daniel, एक बार फिर front page पर आने की बधाई। यह पोस्ट आने के बाद मैंने भी MTGA को hack करके देखा और GitHub पर थोड़ा लिखा भी [0]
दिलचस्पी रखने वालों के लिए, मैं इस समय लगभग बिना features वाले एक unofficial MTGA client पर निष्क्रिय रूप से काम कर रहा हूँ। लक्ष्य ranked game play का automation और ज़्यादा मजबूत bot opponent देना है। हाल में यह दूसरे कामों के कारण पीछे चला गया है, और साफ़-सुथरा, समझ में आने वाला अच्छा UI कैसे बनाया जाए, इस पर भी अभी तक स्पष्टता नहीं है, इसलिए यह न्यूनतम रूप से उपयोगी कब बनेगा, इसका अंदाज़ा लगाना भी मुश्किल है। इसके अलावा Daniel या दूसरों की game hacking कहानियाँ सुनने में भी दिलचस्पी है। ऐसे bugs कैसे ढूँढे जाते हैं, hack करने के बाद ban की चिंता कैसे नहीं की जाती, @aethros की तरह bugs को public कैसे किया जाता है, unofficial card game client को कैसे structure किया जाता है — इन सब पर और सुनना चाहूँगा
[0] https://github.com/MayerDaniel/mayerdaniel.github.io/issues/...
MTG जैसे जटिल game में AI opponent बनाने के लिए overhead बड़ा होगा, यह कहना काफ़ी बड़ा understatement है
यह game लगभग Turing complete है, और infinite loops को छोड़ भी दें तो लोग उससे बहुत खेलते हैं। फिर भी AI strategy पर काफ़ी research पहले से हुई होगी, ऐसा लगता है। और चूँकि यह पोस्ट लेखक ने ख़ुद डाली है, इसलिए title में “Show HN:” भी होना चाहिए था
bot बनाने वाले के लिए मुश्किल दूसरी वाली बात लगती है
उदाहरण के लिए enter/leave/untap effects के ज़रिए token creature बनाना और मारना। ऐसे loops में हमेशा किसी एक पक्ष को damage हो, यह ज़रूरी नहीं
मैंने MTG खेला नहीं है, लेकिन यह दावा जीतने के उद्देश्य से ज़्यादा, जानबूझकर stateful structure बनाने पर तकनीकी रूप से संभव होने जैसा लगता है
बेटे के साथ old-school Magic 93/94 को फिजिकल कार्ड्स से खेलना सचमुच बहुत मज़ेदार है
हम हर साल Madrid जाते हैं और 7pts Singleton विश्व चैम्पियनशिप में भाग लेते हैं। इस गर्मियों में मेरा बेटा 9वें स्थान पर आया, जिस पर मुझे बहुत गर्व है। 7pts Singleton एक शानदार फ़ॉर्मैट है, जिसमें डेक बनाने की बहुत विविधता मिलती है और अपेक्षाकृत कम लागत पर संतुलित gameplay देता है (https://7pts-singleton.com)
भले ही 7pts Singleton में इन सबको एक साथ इस्तेमाल न किया जा सके, इनमें से सिर्फ़ एक की कीमत भी हज़ारों से लेकर दसियों हज़ार डॉलर तक होती है। फिर भी, बेटे के साथ गेम का आनंद लेना अच्छी बात है, और रैंक में आने पर बधाई
पूरी तरह client-side game logic? जब मैंने पहले छोटे गेम बनाए थे, तब responsiveness के लिए कभी-कभी client में game logic डालना पड़ता था, लेकिन ऐसा कोई नियम नहीं था कि server उसी logic को दोबारा execute न करे, इसलिए हमने ऐसा किया
FPS या RTS जैसे real-time games में यह मुश्किल हो सकता है, लेकिन card games में इसका कोई बहाना नहीं है। ऐसे card game में client को खिलाड़ियों की वास्तव में दिखने वाली जानकारी से ज़्यादा कुछ नहीं भेजना चाहिए। उदाहरण के लिए, opponent के hand की card contents भेजने के बजाय सिर्फ़ cards की संख्या भेजनी चाहिए। server को भेजे जाने वाले actions भी सिर्फ़ अपने बारे में होने चाहिए, इसलिए opponent की surrender घोषित करने की अनुमति नहीं होनी चाहिए। अगर मैं “surrender!” कहूँ, तो server को उसे मेरी surrender के रूप में समझना चाहिए
कमजोरी यह थी कि दूसरा client चलाकर चल रहे गेम में opponent की seat के रूप में connect किया जा सकता था। एक बार ऐसा हो जाने पर, surrender सहित opponent के actions भेजे जा सकते थे
लेखक ने client-side game logic का नहीं, बल्कि authorization और game access code की समस्या का फ़ायदा उठाया था। “opponent की ओर से surrender घोषित नहीं कर पाना चाहिए” कहना बस वही दोहराना है कि लेखक द्वारा खोजा गया exploit कैसे काम करता था
League of Legends में एक ख़ास champion और item combination के साथ divide-by-zero bug हुआ करता था, जिससे server crash होने से पहले सभी खिलाड़ियों को बाहर निकाल देता था
क्योंकि exploiter सबसे आख़िर में निकाला जाता था, उसकी team को जीत मिलती थी, और दूसरी team को सामान्य result की जगह Loss Prevented मिलता था
इस लेख में आसान भाषा और insightful details का अच्छा संतुलन है
लेकिन मुझे यह समझ नहीं आता कि असली मैच के दौरान bot को connect कैसे किया जा सकता है। गेम बीच मैच में join करने की अनुमति क्यों देता है, और bot के surrender करने पर उसे opponent की surrender क्यों माना जाता है? अगर यह 3-player game बन भी रहा हो, तो player 3 के surrender करने से player 2 की भी surrender नहीं मानी जानी चाहिए
code मेरे account की seat index पता करता है, फिर bot को दूसरी seat index के रूप में join करवाता है। समस्या यह है कि join करने वाला user उस seat पर होने वाला सही user है या नहीं, इसकी जाँच नहीं होती। यह भी कहा जा सकता है कि पहले से connected seat पर दोबारा connection की अनुमति नहीं होनी चाहिए, लेकिन अगर गेम mobile भी support करता हो, तो आप disconnect timeout काफ़ी लंबा रखना चाहेंगे। क्योंकि आप उस player को रोकना नहीं चाहेंगे जो थोड़ी देर के लिए disconnect हुआ और timeout के पुराने connection को dead मानने से पहले ही reconnect करना चाहता है। दूसरे गेमों में भी मैंने देखा है कि reconnect करने पर लगभग 10 सेकंड तक “चल रहे गेम में शामिल नहीं हो सकते” दिखता है, और बाद में ही reconnect होता है। एक तुलना करें तो जैसे आप स्थानीय card shop के MTG tournament में पहुँचें, किसी को उसकी कुर्सी से हटाकर खुद बैठ जाएँ और चिल्लाएँ “मैं surrender करता हूँ!”, और judge यह मान ले कि उस कुर्सी पर बैठे व्यक्ति ने घोषणा की है, इसलिए player B ने concede कर दिया
शायद इसी वजह से वह opponent की ओर से surrender कर सका। हो सकता है developers ने सोचा ही न हो कि कोई जानबूझकर ऐसा करने की कोशिश करेगा, इसलिए उन्होंने वह check नहीं लगाया
Diablo 2 के दिनों की याद आ गई, जब उसी login packet को दोबारा इस्तेमाल करके open server characters (LAN) को आधिकारिक bnet internet servers पर connect किया जा सकता था
open server data पूरा का पूरा local में stored होता था, इसलिए आप हर तरह के ऐसे items बना सकते थे जो मूल रूप से मौजूद ही नहीं होने चाहिए थे, और official server भी उन्हें स्वीकार कर लेता था
मैंने हाल ही में MTGA के ज़रिए फिर से MTG खेलना शुरू किया। यह Unity game है और il2cpp नहीं है, इसलिए मैंने इसे जल्दी decompile करके देखा; और भले ही यह il2cpp होता, मुझे नहीं लगता कि वह बहुत सुरक्षा देता। कुछ काफ़ी दिलचस्प चीज़ें मिलीं
जैसे Epic Launcher build के लिए keys और undocumented APIs। मेरा cheating में इस्तेमाल करने का इरादा नहीं है, बस काश combat log जैसी कोई चीज़ होती। जैसे कौन-सा match जीता या हारा, या खत्म हुए गेम का battlefield state फिर से देखने की सुविधा। मैं इस लेख को भी देखूँगा, और उम्मीद है इसे जल्दी patch कर दिया जाएगा
अगर आप records देखना चाहते हैं, तो https://untapped.gg/en देख सकते हैं। मैंने वहाँ के लोगों से थोड़ा बात की है, और वह लगभग वही करता है जो आप चाहते हैं। ज़्यादातर जानकारी MTGA application directory में मौजूद MTG debug logs से ली जाती है, इसलिए चाहें तो आप अपना tracker भी बना सकते हैं। साइट पर यह भी समझाया गया है: https://help.hearthsim.net/en/articles/3620440-how-do-i-supp...
मुझे याद है कि उस log का इस्तेमाल करके track करने वाले काफ़ी apps थे