- Di Magic: The Gathering Arena, lawan bisa dipaksa menyerah pada waktu yang diinginkan, sehingga memungkinkan kondisi tidak pernah kalah dalam game matchmaking
- Game kartu biasanya cocok dengan arsitektur server-authoritative yang mengelola seluruh state di server, tetapi lawan bot MTGA, Sparky, diimplementasikan dengan logika klien lokal
- Klien MTGA berbasis C# dapat mengakses objek runtime dan field private lewat refleksi, dan nama seperti
JoinMatch,ConnectAndJoinMatch, danHeadlessClientditemukan dalam kode yang didekompilasi - Dalam match bot, struktur yang digunakan memungkinkan koneksi ke kedua seat dengan
PersonaIDdan JWT dari akun yang sama; ini lalu diterapkan ke match biasa dengan menempelkan headless client ke seat lawan dan memanggilConcedeGame() - Server kemudian ditambal agar dalam game matchmaking kedua seat tidak bisa memakai akun dan JWT yang sama, menjadikannya contoh bagaimana batas antara implementasi bot sisi klien dan verifikasi autentikasi seat berdampak langsung pada keamanan nyata
Mengapa meretas game kartu itu sulit
- Game kartu berbasis giliran dan tidak banyak informasi yang bolak-balik antara klien dan server, sehingga sangat cocok untuk arsitektur server-authoritative
- Server mengelola seluruh state permainan dan hanya mengirim informasi yang diperlukan ke klien
- Informasi yang tidak dibuka, seperti kartu di tangan lawan atau isi deck, tidak ada di lokal
- Upaya seperti mengubah urutan deck atau memanipulasi kartu yang akan diambil sulit dilakukan karena server yang mengeksekusi tindakan dan hanya memberi tahu hasilnya
- Berbeda dengan first-person shooter, tindakan pemain dalam game kartu terbatas dan terjadi pada momen yang sudah ditentukan
- Di FPS, informasi seperti posisi model musuh bisa lebih dulu di-cache di klien sehingga memungkinkan bentuk cheat seperti wallhack
- Blog Riot tentang anti-wallhack membahas pendekatan untuk mengurangi data posisi pemain di sisi klien
- Mendeteksi tindakan yang salah juga relatif lebih mudah
- Memainkan kartu yang tidak ada di tangan
- Bertindak saat bukan gilirannya
Titik awal analisis: jaringan dan klien C#
- Sebagai titik awal peretasan game, dipilih pendekatan untuk melihat komunikasi jaringan
- Presentasi DEF CON oleh Manfred yang membahas kasus peretasan MMO menunjukkan bahwa rekayasa balik protokol jaringan adalah inti dari analisis banyak bug
- Karena MTGA ditulis dalam C#, objek bisa dimanipulasi saat runtime alih-alih meng-hook fungsi kirim-terima trafik
- Refleksi .NET memungkinkan akses bahkan ke field dan method private
- Sebagai contoh dasar terkait, ditautkan tutorial meretas game Unity dengan refleksi
- Assembly .NET yang tidak diobfuscate memungkinkan nama fungsi, variabel, dan kelas dilihat dalam bentuk yang bisa dibaca manusia berkat metadata token
- Karena itu, hasil dekompilasinya nyaris setara dengan review source code
Struktur Sparky yang ditemukan dari JoinMatch
- Saat mencari inisialisasi masuk match, ditemukan fungsi
JoinMatchsetelah menelusuri nama fungsi terkait JoinMatchadalah fungsi panjang lebih dari 200 baris, dan di bagian bawah terlihat pemanggilanConnectAndJoinMatch- Fungsi ini tampak sebagai alur yang menerima informasi konfigurasi match lalu terhubung ke server game
- Dalam alur kode yang sama juga ada percabangan
MatchType.NPEdanMatchType.FamiliarNPEdiduga merupakan match tutorial untuk pengalaman pemain baruFamiliaradalah match bot standar
- Logika yang dipanggil dalam percabangan ini terhubung ke lawan bot MTGA, Sparky
- Sparky adalah lawan bergaya maskot MTGA yang digunakan dalam tutorial dan pertandingan melawan bot
- Dalam match bot, logika bot berjalan di dalam klien game pada mesin lokal
Bot lokal dan HeadlessClient
- Handler logika inti bot berada di dalam kelas
HeadlessClient HeadlessClientadalah headless client yang tidak merender game board, tetapi tetap terhubung ke server dan memainkan game- Klien bot yang dibuat secara lokal menggunakan informasi autentikasi pengguna yang sama dengan klien game
PersonaIDyang berperan sebagai ID pengguna- JSON web token yang diberikan ke game setelah login
- Dalam match bot, strukturnya membuat server tidak menganggap bermasalah jika klien yang sama pada dasarnya terhubung ke kedua sisi match
- Seat digunakan untuk membedakan siapa pemainnya di dalam game
- Dalam match bot, dimungkinkan mengisi seat yang berbeda dengan informasi autentikasi yang sama
Cara mengambil alih match biasa
- Logika match bot diterapkan ke match biasa untuk menguji apakah bisa terhubung ke kedua seat
- Informasi yang diperlukan diambil dari objek game saat runtime
- konfigurasi match saat ini
- host dan port server match
controllerFabricUrimatchIdPersonaIDJwt- database kartu
- manajer match
- sistem pencarian aset
- Seat lawan dihitung berdasarkan seat milik sendiri
- Dalam kode, seat lainnya didapatkan dengan
man.LocalPlayerSeatId % 2U + 1U
- Dalam kode, seat lainnya didapatkan dengan
UnityFamiliar.SpawnFamiliar_DEBUG(...)digunakan untuk menghubungkan bot ke seat lawan- Setelah menemukan objek
UnityFamiliaryang dibuat, dipanggilcheatbot.Client.Gre.ConcedeGame()agar langsung menyerah
Hasil dan patch
- Cara ini juga bekerja dalam match biasa
- Bahkan tetap berfungsi saat lawan sudah terhubung dan game sedang berlangsung
- Karena ini adalah game matchmaking, hadiah tetap diberikan seolah-olah mengalahkan lawan manusia
- Inti kerentanannya adalah server match biasa mengizinkan koneksi ke kedua seat dengan akun dan JWT yang sama
- Server kemudian ditambal agar dalam game matchmaking kedua seat tidak bisa menggunakan akun dan JWT yang sama
- Kode
InstaWindi lampiran adalahMonoBehaviourUnity yang membuat tombol GUI; saat tombol diklik, ia mengumpulkan informasi match saat ini, menempelkan bot ke seat lawan, lalu memaksanya menyerah
1 komentar
Komentar Hacker News
Hal yang pertama kali membuat saya benar-benar mendalami Linux adalah memakai ShowEQ untuk EverQuest guna mengintip traffic jaringan
Saat itu traffic belum dienkripsi dan berisi banyak informasi berguna. Dengan hub, traffic diduplikasi ke mesin Linux untuk menggambar peta zona secara real-time, menampilkan posisi monster, NPC, dan pengguna, bahkan menunjukkan loot yang dibawa monster sehingga bisa memilih monster tertentu saja untuk diburu. Kelebihannya, karena caranya pasif, tidak bisa dideteksi; pada akhirnya SOE mengetahuinya dan mulai mengenkripsi traffic
Lalu pihak lawan memperkenalkan tanda tangan berbasis kunci, orang kembali mencoba mencuri kunci dari klien dan memecahkan enkripsi, dan setelah sistem anti-cheat masuk, dimulailah permainan kucing dan tikus
Apakah itu cukup bernilai untuk mendapat keuntungan dalam game? Tidak. Saya tidak bermain dengan serius, jadi saya menghabiskan 2 minggu untuk instalasi dan hanya memakainya sekitar 1 minggu, tetapi sebagai pengalaman belajar itu luar biasa
Contohnya keberadaan hell level, fakta bahwa bukan manusia melainkan halfling yang mendapat bonus pengalaman dan bahwa memang ada perbedaan pengalaman berdasarkan ras/kelas, serta fakta bahwa alchemy Shaman awal benar-benar rusak. Dan saya rasa ini kemudian mengarah ke eqemulator.org
Pemilik EQ saat ini tampaknya tidak terlalu peduli, jadi relatif aman untuk dipakai. Namun, kecuali perlengkapan yang terlihat, kedua aplikasi itu tidak pernah menampilkan loot yang dibawa monster. Seiring waktu sebagian data juga berubah; dulu health monster yang akurat dikirim, tetapi sekarang hanya persentasenya
Saya kurang memahami bagian “bot yang hampir lengkap dan bisa memainkan game arbitrer Magic: The Gathering cukup kecil untuk berjalan di mesin lokal”
Kalau AI MTG terlalu berat untuk dijalankan di mesin pelanggan, saya rasa mereka juga tidak akan menjalankannya di server. Pertandingan bot dalam game kartu biasanya tidak ditagih per partai, jadi biayanya bisa besar. Server juga bukan sihir; kebanyakan memakai CPU x86 yang sama seperti mesin lokal, dan clock-nya sering kali lebih rendah daripada desktop. Untuk mengurangi waktu giliran bot dibanding lokal, mereka harus memakai jauh lebih banyak core daripada pelanggan; kalau 8–16 core teralokasi per pemain, itu terdengar seperti mimpi buruk saat puncak pengguna bersamaan. Kalau pemain CPU tidak mendukung multicore, eksekusi lokal bagaimanapun seharusnya lebih cepat
Maksudnya, rules engine bot cukup kecil untuk muat di memori iPhone atau perangkat Android lama. Di server, mereka bisa menaruh banyak state machine atau rules engine di memori, dan mungkin hampir tidak memakai performa pemrosesan untuk menjalankan permintaan tertentu
Daniel, sekali lagi selamat karena tulisannya masuk peringkat atas. Setelah tulisan ini muncul, saya mencoba meretas MTGA dan sedikit berdiskusi juga di GitHub [0]
Untuk yang tertarik, saat ini saya sedang mengerjakan secara tidak aktif klien MTGA tidak resmi yang hampir belum punya fitur. Tujuannya adalah mengotomatiskan permainan ranked dan menyediakan lawan bot yang lebih kuat. Belakangan tersisih oleh pekerjaan lain, dan saya juga masih belum punya gambaran bagaimana membuat UI yang bagus dan mudah dilihat, jadi sulit menebak kapan bahkan versi minimal yang berguna akan tersedia. Selain itu, saya tetap ingin mendengar lebih banyak cerita Daniel atau orang lain tentang hacking game. Saya ingin mendengar lebih banyak tentang bagaimana bug seperti ini ditemukan, bagaimana tidak khawatir kena ban setelah hacking, cara mengungkap bug seperti yang disebut @aethros, dan bagaimana menyusun klien game kartu tidak resmi
[0] https://github.com/MayerDaniel/mayerdaniel.github.io/issues/...
Mengatakan bahwa perkiraan overhead untuk membuat lawan AI di game sekompleks MTG akan besar itu cukup meremehkan
Game ini hampir Turing-complete, dan bahkan jika loop tak terbatas dikecualikan, orang-orang banyak bermain-main dengannya. Meski begitu, riset di sisi strategi AI sepertinya sudah banyak dilakukan. Dan karena ini tulisan yang diunggah langsung oleh penulisnya, sepertinya judulnya boleh diberi “Show HN:”
Yang sulit bagi penulis bot tampaknya adalah yang kedua
Misalnya membuat dan membunuh creature token dengan efek masuk/keluar/untap. Loop seperti ini juga tidak selalu merugikan salah satu pihak
Saya belum pernah memainkan MTG, tetapi klaim ini terdengar seperti secara teknis mungkin jika sengaja membuat struktur yang memiliki state, bukan untuk tujuan menang
Bermain Old School Magic 93/94 dengan kartu fisik bersama anak saya benar-benar menyenangkan
Setiap tahun kami pergi ke Madrid untuk ikut Kejuaraan Dunia 7pts Singleton. Musim panas ini anak saya menempati peringkat ke-9, dan saya sangat bangga. 7pts Singleton adalah format yang bagus karena memungkinkan beragam susunan deck dan menawarkan gameplay yang seimbang dengan biaya yang relatif tidak membebani (https://7pts-singleton.com)
Meski di 7pts Singleton tidak bisa memakai semuanya, satu saja harganya bisa ribuan hingga puluhan ribu dolar. Tapi tetap menyenangkan bisa menikmati game bersama anak, dan selamat juga karena masuk peringkat atas
Logika game murni di sisi klien, ya. Dulu saat membuat game kecil, ada kalanya saya harus menaruh logika game di klien demi responsivitas, tetapi tidak ada larangan untuk menjalankan ulang logika yang sama di server, jadi itulah yang saya lakukan
Untuk game real-time seperti FPS atau RTS mungkin sulit, tetapi untuk game kartu tidak ada alasan. Untuk game kartu seperti ini, semestinya klien tidak dikirimi informasi di luar yang benar-benar bisa dilihat pemain. Misalnya, jangan kirim isi kartu di tangan lawan, cukup jumlah kartunya saja. Aksi yang dikirim ke server juga seharusnya hanya tentang diri sendiri, jadi tidak boleh bisa mendeklarasikan lawan menyerah. Kalau saya berkata “menyerah!”, server harus menafsirkannya sebagai saya yang menyerah
Celahnya adalah bisa menjalankan klien kedua dan masuk ke game yang sedang berlangsung sebagai kursi lawan. Setelah itu, aksi lawan, termasuk menyerah, bisa dikirim
Yang dimanfaatkan penulis bukanlah logika game di sisi klien, melainkan masalah pada otorisasi dan kode untuk bergabung ke game. Pernyataan “seharusnya tidak bisa mendeklarasikan menyerah atas nama lawan” pada dasarnya hanya mengulang persis bagaimana exploit yang ditemukan penulis bekerja
Di League of Legends pernah ada bug pembagian dengan nol pada kombinasi champion dan item tertentu, yang membuat server mengeluarkan semua pemain lalu crash
Karena pelaku exploit dikeluarkan paling akhir, timnya dihitung menang, sementara tim lawan mendapat Loss Prevented alih-alih hasil normal
Artikel ini enak diikuti dan punya detail yang bernas
Namun saya tidak paham soal menghubungkan bot saat pertandingan berlangsung. Mengapa game mengizinkan masuk di tengah pertandingan, dan mengapa ketika bot menyerah itu diproses sebagai lawan yang menyerah? Kalau yang dibuat adalah game 3 pemain, pemain ke-3 yang menyerah seharusnya tidak membuat pemain ke-2 ikut menyerah
Kodenya mencari tahu indeks kursi akun saya, lalu memasukkan bot ke indeks kursi yang lain. Masalahnya adalah tidak ada verifikasi bahwa pengguna yang bergabung memang pengguna yang benar untuk kursi tersebut. Bisa saja terpikir bahwa kursi yang sudah terhubung tidak boleh diakses lagi, tetapi untuk game yang juga mendukung mobile, Anda mungkin ingin timeout putus koneksi cukup panjang. Sebab Anda tidak ingin memblokir pemain yang sempat terputus lalu menyambung kembali sebelum timeout menyadari koneksi sebelumnya sudah mati. Saya juga pernah melihat di game lain, saat mencoba reconnect muncul pesan “tidak bisa bergabung ke game yang sedang berlangsung” sekitar 10 detik, baru kemudian bisa reconnect. Analogi kasarnya, seseorang datang ke turnamen MTG di toko kartu lokal, mendorong orang lain dari kursinya, duduk, lalu berteriak “Saya menyerah!”, dan juri mengakui pemain B drop karena orang yang duduk di kursi itu yang menyatakan demikian
Karena itu tampaknya ia bisa menyerah atas nama lawan. Para developer mungkin tidak membayangkan ada orang yang punya alasan untuk mencoba hal seperti itu, sehingga tidak menambahkan pemeriksaan
Ini mengingatkan saya pada masa Diablo 2, ketika paket koneksi yang sama bisa digunakan ulang untuk menghubungkan karakter server terbuka (LAN) ke server internet bnet resmi
Karena seluruh data server terbuka disimpan lokal, kita bisa membuat segala macam item yang seharusnya tidak ada, dan server resmi pun menerimanya
Baru-baru ini saya kembali masuk ke MTG lewat MTGA. Karena ini game Unity dan bukan il2cpp, saya cepat-cepat mendekompilasinya; sekalipun il2cpp, sepertinya itu juga bukan perlindungan besar, dan saya menemukan beberapa hal yang cukup menarik
Ada hal-hal seperti key untuk build Epic Launcher dan API yang tidak terdokumentasi. Saya tidak ingin memakainya untuk curang; saya hanya ingin ada riwayat pertandingan. Misalnya fitur untuk melihat match mana yang menang atau kalah, serta meninjau kembali keadaan board pada game yang sudah selesai. Saya juga akan mengecek artikel ini, dan semoga cepat ditambal
Kalau ingin melihat riwayat, coba cek https://untapped.gg/en. Saya sempat sedikit berbicara dengan mereka, dan pada dasarnya layanan itu melakukan hal yang Anda inginkan. Sebagian besar informasinya diambil dari log debug MTG yang ada di direktori aplikasi MTGA, jadi jika mau Anda juga bisa membuat tracker sendiri. Situsnya juga menjelaskan ini: https://help.hearthsim.net/en/articles/3620440-how-do-i-supp...
Saya ingat ada cukup banyak aplikasi yang memakai log itu untuk pelacakan