1 puan yazan GN⁺ 2023-12-06 | 1 yorum | WhatsApp'ta paylaş
  • Magic: The Gathering Arena’da rakibi istenen anda teslim olmuş saydırmak mümkün olduğundan, eşleştirme oyunlarında kaybetmeyen bir durum oluşturulabiliyordu
  • Kart oyunları genelde sunucunun tüm durumu yönettiği sunucu otoriteli mimariye uygundur; ancak MTGA’daki bot rakip Sparky, yerel istemci mantığıyla uygulanmıştı
  • C# tabanlı MTGA istemcisinde reflection ile çalışma zamanındaki nesnelere ve private alanlara erişilebiliyordu; decompile edilmiş kodda JoinMatch, ConnectAndJoinMatch, HeadlessClient gibi adlar görüldü
  • Bot maçlarında aynı hesabın PersonaID değeri ve JWT ile iki koltuğa da bağlanılan bir yapı kullanılıyordu; bu genel maçlara uygulanarak rakibin koltuğuna headless istemci bağlanıp ConcedeGame() çağrılabiliyordu
  • Sunucu daha sonra eşleştirme oyunlarında iki koltuğun aynı hesabı ve JWT’yi kullanamaması için yamalandı; bu, istemci taraflı bot uygulaması ile koltuk kimlik doğrulama denetiminin sınırının gerçek güvenliği doğrudan etkilediği bir örnek oldu

Kart oyunlarını hacklemenin neden zor olduğu

  • Kart oyunları sıra tabanlıdır ve istemci ile sunucu arasında gidip gelen bilgi fazla olmadığından sunucu otoriteli mimariye iyi uyar
  • Sunucunun tüm oyun durumunu yönetip istemciye yalnızca gerekli bilgileri iletmesi yeterlidir
    • Rakibin eli veya destesi gibi açık olmayan bilgiler yerelde bulunmaz
    • Deste sırasını değiştirmek ya da çekilecek kartı manipüle etmek gibi girişimler zordur; çünkü eylemi sunucu gerçekleştirir ve yalnızca sonucu bildirir
  • Birinci şahıs nişancı oyunlarının aksine kart oyunlarında oyuncu eylemleri sınırlıdır ve belirli anlarda gerçekleşir
    • FPS’lerde düşman modeli konumu gibi bilgiler istemcide önceden cache’lenebildiği için wallhack gibi biçimler mümkün olabilir
    • Riot’un anti-wallhack blog yazısı, istemci tarafındaki oyuncu konumu verilerini azaltma yaklaşımını ele alıyor
  • Hatalı eylemleri tespit etmek de görece kolaydır
    • Elde olmayan bir kartı oynamak
    • Kendi sırası değilken eylem yapmak

Analizin başlangıç noktası: ağ ve C# istemcisi

  • Oyun hacklemenin başlangıç noktası olarak ağ iletişimini inceleme yaklaşımı seçildi
  • MMO hackleme örneklerini ele alan Manfred’in DEF CON sunumu, ağ protokolü tersine mühendisliğinin birçok hata analizinin merkezinde olduğunu gösteriyor
  • MTGA C# ile yazıldığı için, trafik gönderme/alma fonksiyonlarını hook’lamak yerine çalışma zamanında nesneler manipüle edilebiliyordu
  • Obfuscate edilmemiş .NET assembly’leri, metadata token sayesinde fonksiyon, değişken ve sınıf adlarının insan tarafından okunabilir biçimde görülmesini sağlar
    • Bu nedenle decompile sonucu fiilen kaynak kod incelemesine yakın hale gelir

JoinMatch içinde bulunan Sparky yapısı

  • Maça katılım başlatmasını bulmak için ilgili fonksiyon adları aranırken JoinMatch fonksiyonu bulundu
  • JoinMatch 200 satırı aşan uzun bir fonksiyondu ve alt kısmında ConnectAndJoinMatch çağrısı görüldü
    • Bu fonksiyon, maç ayar bilgilerini alıp oyun sunucusuna bağlanma akışı gibi görünüyordu
  • Aynı kod akışında MatchType.NPE ve MatchType.Familiar dalları vardı
    • NPE, yeni oyuncu deneyimi olduğu tahmin edilen eğitim serisi maçları
    • Familiar, standart bot maçı
  • Bu dallarda çağrılan mantık, MTGA’nın bot rakibi Sparky ile bağlantılıydı
    • Sparky, eğitimlerde ve bot karşılaşmalarında kullanılan MTGA’nın maskot benzeri rakibidir
    • Bot maçlarında bot mantığı, yerel makinedeki oyun istemcisinin içinde çalışır

Yerel bot ve HeadlessClient

  • Botun gerçek mantık işleyicisi HeadlessClient sınıfının içindeydi
  • HeadlessClient, oyun tahtasını render etmeyen bir headless istemcidir; sunucuya bağlanıp oyunu yürütür
  • Yerelde oluşturulan bot istemcisi, oyun istemcisiyle aynı kullanıcı kimlik doğrulama bilgilerini kullanır
    • Kullanıcı kimliği rolündeki PersonaID
    • Girişten sonra oyuna verilen JSON web token
  • Bot maçlarında aynı istemcinin fiilen maçın iki tarafına da bağlanmasını sunucu sorun olarak görmeyen bir yapı vardı
  • Koltuk (seat), oyunda hangi oyuncu olunduğunu ayırt etmek için kullanılır
    • Bot maçlarında aynı kimlik doğrulama bilgileriyle farklı koltukları dolduran bir yapılandırma mümkündü

Normal maçı ele geçirme yöntemi

  • Bot maçı mantığının normal maçlara uygulanıp iki koltuğa da bağlanmanın mümkün olup olmadığı test edildi
  • Gerekli bilgiler çalışma zamanındaki oyun nesnesinden alındı
    • Mevcut maç ayarları
    • Maç sunucusu host’u ve port’u
    • controllerFabricUri
    • matchId
    • PersonaID
    • Jwt
    • Kart veritabanı
    • Maç yöneticisi
    • Varlık sorgulama sistemi
  • Kendi koltuğu temel alınarak rakibin koltuğu hesaplandı
    • Kodda diğer koltuk man.LocalPlayerSeatId % 2U + 1U ile elde ediliyor
  • UnityFamiliar.SpawnFamiliar_DEBUG(...) ile rakibin koltuğuna bot bağlandı
  • Oluşturulan UnityFamiliar nesnesi bulunup cheatbot.Client.Gre.ConcedeGame() çağrılarak anında teslim olması sağlandı

Sonuç ve yama

  • Bu yöntem normal maçlarda da çalıştı
    • Rakip zaten bağlıyken ve oyun devam ederken bile çalışıyordu
    • Eşleştirme oyunu olduğu için insan rakibi yenmiş gibi ödül alındı
  • Açığın özü, normal maç sunucusunun aynı hesap ve JWT ile iki koltuğa da bağlanılan duruma izin vermesiydi
  • Sunucu daha sonra eşleştirme oyunlarında iki koltuğun aynı hesabı ve JWT’yi kullanamaması için yamalandı
  • Ekteki InstaWin kodu, Unity MonoBehaviour ile GUI düğmesi oluşturup düğmeye tıklandığında mevcut maç bilgilerini toplayarak botu rakibin koltuğuna bağlayan ve teslim ettiren akışı içeriyor

1 yorum

 
GN⁺ 2023-12-06
Hacker News görüşleri
  • Linux’u ilk kez gerçekten derinlemesine kurcalamama vesile olan şey, EverQuest için ShowEQ ile ağ trafiğini incelemekti
    O dönemde trafik şifrelenmemişti ve içinde çok faydalı bilgiler vardı. Trafiği bir hub üzerinden Linux makinesine kopyalayıp bölgenin gerçek zamanlı haritasını çiziyor, canavarların, NPC’lerin ve oyuncuların konumlarını gösteriyor, hatta canavarların taşıdığı ganimetleri bile göstererek sadece belirli canavarları hedeflemeyi mümkün kılıyordu. Elle yapılan bir yöntem olduğu için tespit edilememesi avantajdı; sonunda SOE bunu fark edip trafiği şifrelemeye başladı

    • Sonuçta verinin çözülüp okunması gerekiyor, bu yüzden istemciyi tersine mühendislikle inceleyip gerçek zamanlı çözme yöntemini buluyorsunuz
      Sonra karşı taraf anahtar tabanlı imza ekliyor, siz yeniden istemciden anahtarı çalmaya çalışıyor, şifrelemeyi kırıyor ve ardından hile önleme sistemleri devreye girince kedi-fare oyunu başlıyor
    • Bunu gençken Dark Age of Camelot’ta da benzer şekilde denemiştim; ağ koklama, hub ile switch arasındaki fark ve Linux öğrenmek açısından çok faydalıydı
      Oyunda avantaj sağlamak açısından değdi mi? Hayır. Zaten ciddi oynamıyordum; kuruluma 2 hafta harcayıp yaklaşık 1 hafta kullanmıştım, ama öğrenme deneyimi olarak harikaydı
    • ShowEQ’nun, Verant/Sony’nin sürekli inkâr ettiği çeşitli teorileri ve bug’ları kanıtlamak için kullanıldığını hatırlıyorum
      Örneğin hell level’ın varlığı, deneyim bonusunu insanların değil halfling’lerin aldığı ve gerçekten ırk/sınıf bazlı deneyim farkları olduğu, ilk dönem Shaman alchemy sisteminin gerçekten bozuk olduğu gibi şeyler. Ve sanırım bu iş sonradan eqemulator.org’a da uzanmıştı
    • Şifrelemenin burada nasıl yardımcı olduğunu merak ediyorum. Nasıl olsa istemcinin bunu çözmesi gerekmiyor mu; o noktaya eklemlenmek yeterli değil mi?
    • ShowEQ hâlâ çalışıyor, ayrıca Windows tabanlı bellek okuyan MySEQ de var
      Mevcut EQ sahibinin buna pek aldırmadığı anlaşılıyor, bu yüzden kullanmak genelde sorun olmuyor. Yine de iki uygulama da, görünen ekipman dışında, canavarların taşıdığı ganimetleri hiç göstermedi. Zamanla bazı veriler de değişti; eskiden tam canavar canı gönderilirken artık sadece yüzde bilgisi gönderiliyor
  • “Magic: The Gathering için rastgele oyunları oynayabilen neredeyse tam bir botun yerel makinede çalışabilecek kadar küçük olması” kısmını pek anlamadım
    Eğer MTG yapay zekası istemci makinesinde çalıştırılamayacak kadar ağırsa, sunucuda da çalıştırılmaz gibi geliyor. Kart oyunu bot maçları genelde maç başına ücretlendirilen bir şey değil, dolayısıyla maliyet büyür. Sunucular da sihirli değil; çoğu, yerel makineyle aynı x86 CPU’ları kullanıyor ve çoğu zaman masaüstünden daha düşük saat hızına sahip oluyor. Yerele göre bot tur süresini düşürmek istiyorsanız, oyuncunun makinesinden çok daha fazla çekirdek kullanmanız gerekir; oyuncu başına 8–16 ayrılmış çekirdek, eşzamanlı oyuncu zirvesinde kabus gibi olurdu. CPU oyuncusu çok çekirdeği desteklemiyorsa, yerelde çalışması zaten daha hızlı olmalı

    • Burada kastedilen işlem gücü değil, bellek kullanımı
      Yani botun kural motorunun eski iPhone veya Android cihazların belleğine sığabilecek kadar küçük olması. Sunucuda ise durum makinelerini veya kural motorlarını bellekte bolca tutabilirsiniz; hatta belirli bir isteği çalıştırmak için neredeyse hiç işlem gücü gerekmeyebilir
    • Masaüstü için doğru olabilir ama MTGA’nin telefonda da çalıştığını unutmamak lazım
    • MTG, çok karmaşık bir kural sistemine sahip bir oyun
  • Daniel, bir kez daha ana sayfa gönderin için tebrikler. Bu yazı çıktıktan sonra ben de MTGA’yı hacklemeyi denedim ve GitHub’da biraz bahsettim [0]
    İlgilenenler için söyleyeyim, şu anda neredeyse işlevsiz bir MTGA gayriresmî istemcisi üzerinde düşük tempoda çalışıyorum. Amaç, sıralamalı oyun oynamayı otomatikleştirmek ve daha güçlü bir bot rakip sunmak. Son zamanlarda başka işler yüzünden geri planda kaldı; ayrıca net görülebilen iyi bir UI’ı nasıl yapacağım konusunda da hâlâ kafam karışık, bu yüzden en azından işe yarar hâle ne zaman geleceğini tahmin etmek bile zor. Bunun dışında Daniel’in ya da başkalarının oyun hackleme hikâyelerini duymaya devam etmek isterim. Bu tür bug’ları nasıl buldukları, hackledikten sonra ban konusunda neden kaygılanmadıkları, @aethros’un söylediği gibi bug’ları açıklama yöntemleri ve gayriresmî kart oyunu istemcilerini nasıl yapılandırdıkları gibi şeyleri daha çok duymak isterim
    [0] https://github.com/MayerDaniel/mayerdaniel.github.io/issues/...

  • MTG gibi karmaşık bir oyunda yapay zeka rakip yapmanın ek yükünün büyük olacağını düşünmek bile aslında epey büyük bir küçümseme
    Çünkü oyun neredeyse Turing-complete ve insanlar, sonsuz döngüler hariç tutulsa bile, bununla çok eğleniyor. Yine de yapay zeka stratejisi tarafında muhtemelen zaten çok çalışma yapılmıştır. Ayrıca bu gönderi doğrudan yazarın kendi yazısı olduğuna göre, başlıkta “Show HN:” olması da makul görünüyor

    • Show HN, blog yazıları için değil; insanların bizzat deneyebileceği projeler içindir: https://news.ycombinator.com/showhn.html
    • “Bir oyuna Turing makinesi kodlayabilirsin” demekle “her durumda yasal hamle yapabilen bir program yazmak zordur” demek aynı şey değil
      Botu yazan kişi için zor olanın ikincisi olduğu anlaşılıyor
    • Gerçekten Turing-complete: https://arxiv.org/abs/1904.09828
    • Yeni setler döndükçe oyun sürekli değişiyor, ama belirli etkileşimlerde sonsuz döngüler kurulabildiğini ya da çeşitli dönemlerde bunun mümkün olduğunu biliyorum
      Örneğin oyuna giriş/çıkış/untap etkileriyle token yaratık üretip öldürmek gibi. Bu tür döngüler her zaman taraflardan birine hasar vermek zorunda da değil
    • Gerçek stratejiler arasında buna yakın bir karmaşıklık olup olmadığını merak ediyorum
      MTG’yi hiç oynamadım ama bu iddia, kazanma amacıyla değil de özellikle durum taşıyan bir yapı kurarsanız teknik olarak mümkün olduğu anlamına geliyor gibi görünüyor
  • Oğlumla birlikte fiziksel kartlarla old-school Magic 93/94 oynamaktan gerçekten keyif alıyorum
    Her yıl Madrid'e gidip 7pts Singleton dünya şampiyonasına katılıyoruz. Bu yaz oğlum 9. oldu ve bununla çok gurur duyuyorum. 7pts Singleton, çok çeşitli deste kurulumlarına izin veren ve nispeten makul bir maliyetle dengeli bir oynanış sunan harika bir format (https://7pts-singleton.com)

    • Black Lotus, Ancestral Recall ve Moxen'in legal olduğu bir formata ucuz demek zor
      7pts Singleton'da hepsini kullanamasanız bile bunlardan tek biri bile birkaç bin ila on binlerce dolara mal oluyor. Yine de oğlunuzla oyunun keyfini çıkarmanız güzel, dereceye girmesini de tebrik ederim
  • Oyun mantığının tamamen istemci tarafında olması şaşırtıcı. Eskiden küçük oyunlar yaparken tepkisellik için oyun mantığını istemciye koymam gereken zamanlar olmuştu, ama sunucuda aynı mantığı tekrar çalıştırmamak için hiçbir sebep yoktu, ben de öyle yapmıştım
    FPS ya da RTS gibi gerçek zamanlı oyunlarda bu zor olabilir ama kart oyunlarında bunun bahanesi yok. Böyle bir kart oyununda istemciye gerçek oyuncunun görebileceğinden fazlasını göndermemek gerekir. Örneğin rakibin elindeki kartların içeriğini göndermek yerine sadece kart sayısını göndermelisiniz. Sunucuya gönderilen eylemler de yalnızca kişinin kendisiyle ilgili olmalı; dolayısıyla rakibin teslim olduğunu ilan edebilmeniz mümkün olmamalı. “Teslim oluyorum!” derseniz, sunucu bunu benim teslim oluşum olarak yorumlamalı

    • Yazıdan anladığım kadarıyla oyun zaten tam da bu şekilde yazılmış. Gereken anda sadece gereken bilgiyi alıyor ve yalnızca kendi eylemlerini gönderiyorsunuz
      Açık, ikinci bir istemci başlatıp o an devam eden oyuna rakip koltuğundan bağlanabilmenizdi. Bunu yaptıktan sonra teslim olma dahil rakibin eylemlerini gönderebiliyordunuz
    • Yazıda açıkça belirtildiği gibi, oynanışın tamamı sunucu tarafında işleniyor
      Yazarın istismar ettiği şey istemci tarafı oyun mantığı değil, yetkilendirme ve oyuna bağlanma kodundaki bir sorundu. “Rakip adına teslimiyet ilan edememelisiniz” demek, yazarın bulduğu açığın nasıl çalıştığını sadece tekrar etmekten ibaret
    • Yazının ilk üçte birlik kısmında oyunun bu şekilde uygulandığı açıkça söyleniyor
  • League of Legends'ta belirli şampiyon ve eşya kombinasyonlarında bir sıfıra bölme hatası vardı; bu da sunucunun tüm oyuncuları oyundan atıp çökmesine yol açıyordu
    Kötüye kullanan oyuncu en son atıldığı için onun takımı galibiyet alıyor, karşı takım ise normal sonuç yerine Loss Prevented alıyordu

    • Rakip normal bir sonuç yerine yenilgi almıyorsa, kazanan takım da galibiyet almamalı
  • Bu yazı hem kolay okunuyor hem de içgörülü ayrıntılar içeriyor
    Yine de gerçek bir maç sırasında bota bağlanılması kısmını anlamıyorum. Oyun neden maç ortasında katılıma izin veriyor ve bot teslim olduğunda bu neden rakibin teslim olması olarak işleniyor? 3 oyunculu bir oyun yapsanız bile 3. oyuncu teslim olunca 2. oyuncu da teslim olmuş sayılmamalı

    • Oyun 3 oyunculu hale gelmiyor, 2 oyunculu oyun olarak kalıyor
      Kod, hesabımın koltuk indeksini öğrenip botu diğer koltuk indeksine katıyor. Sorun, katılan kullanıcının o koltukta bulunması gereken doğru kullanıcı olup olmadığının doğrulanmaması. Zaten bağlı olan bir koltuğa tekrar bağlanılmasına izin verilmemesi gerektiği düşünülebilir, ama oyun mobil de destekliyorsa bağlantı kopması zaman aşımını epey uzun tutmak isteyebilirsiniz. Kısa süreliğine kopup zaman aşımı önceki bağlantının öldüğünü anlamadan yeniden bağlanan oyuncuyu engellemek istemezsiniz. Başka oyunlarda da yeniden bağlanmaya çalışınca yaklaşık 10 saniye boyunca “devam eden oyuna katılamaz” yazdığını, sonra ancak yeniden bağlandığını gördüm. Benzetmek gerekirse, mahalledeki kart dükkânındaki bir MTG turnuvasına gidip birini sandalyesinden iterek oturuyor ve “Teslim oluyorum!” diye bağırıyorsunuz; hakem de sandalyede oturan kişi bunu ilan ettiğine göre oyuncu B çekildi diye kabul ediyor
      1. Büyük olasılıkla bağlantı kesildikten sonra yeniden bağlanmayı ele alma şekli buydu. Eski bağlantıyı sonlandırıyor olabilir
      2. Bot, oyuncu 2'nin yerini alıyor, ardından teslimiyet gönderiyor ve sunucu bunu oyuncu 2'nin teslimiyeti olarak kaydediyor
    • MTG: Arena 3 oyunculu oyuna izin vermediği için bot rakibin koltuğuna zorla giriyor
      Bu yüzden rakip adına teslim olabiliyordu gibi görünüyor. Geliştiriciler muhtemelen kimsenin özellikle böyle bir şey deneyeceğini düşünmediği için bunu kontrol etmedi
  • Diablo 2 döneminde, aynı giriş paketini yeniden kullanarak open server karakterlerini (LAN) resmi bnet internet sunucularına bağlamanın mümkün olduğu zamanları hatırlattı
    Open server verileri tamamen yerelde tutulduğu için normalde var olmaması gereken her türlü eşyayı oluşturabiliyor ve resmi sunucu da bunları kabul ediyordu

  • Kısa süre önce MTGA sayesinde MTG'ye geri döndüm. Unity oyunu ve il2cpp değil, bu yüzden hızlıca decompile ettim; il2cpp olsaydı bile pek koruma sağlayacağını sanmıyorum ve oldukça ilginç şeyler buldum
    Epic Launcher derlemesi için anahtarlar ve belgelenmemiş API'ler gibi şeyler vardı. Hile yapmak istemiyorum, sadece bir savaş günlüğü olmasını isterdim. Hangi maçları kazanıp kaybettiğimi ve bitmiş oyunların masa durumunu tekrar görme gibi şeyler. Bu yazıya da bakacağım, umarım çabuk yamalanır

    • Bu açık yazı yayımlanmadan önce zaten yamalandı ve MTG'ye bildirildi
      Kayıtlara bakmak istiyorsanız https://untapped.gg/en adresine göz atabilirsiniz. Onlarla biraz konuşmuştum; pratikte istediğiniz şeyi yapıyor. Bilgilerin çoğunu MTGA uygulama dizinindeki MTG debug log'undan alıyorlar, dolayısıyla isterseniz kendi takip aracınızı da yapabilirsiniz. Sitede de bu anlatılıyor: https://help.hearthsim.net/en/articles/3620440-how-do-i-supp...
    • https://www.17lands.com/ limited oyunlar için kazanma/kaybetme istatistikleri topluyor ve hem limited hem de constructed için tur bazlı oyun kayıtlarını saklıyor. Katkıda bulunanlardan biriyim
    • Oyun verisi toplama için https://mtgaassistant.net/ en yaygın olanlardan biri diye biliyorum
    • Bildiğim kadarıyla bu özellik zaten vardı. Muhtemelen oyuncu logundan bahsediyorsunuz
      O logu kullanarak takip yapan epey uygulama olduğunu hatırlıyorum