- World of Warcraft'ın Lua eklenti ortamı, kullanıcı arayüzünü kolayca değiştirmeyi mümkün kılıyordu; ancak oyun davranışlarının otomasyonunu engellemek için bilgiye erişim ile yürütme yetkisi ayrılmıştı
- Blizzard'ın güvenlik modeli, çok fazla bilgi okuyabilen güvenli olmayan ortam ile eylem gerçekleştiren güvenli ortamı ayırıyordu ve bu sınır otomasyon önlemenin kilit noktasıydı
- Güvenli ortamda izin verilen
random, MSVC C rand için ince bir sarmalayıcıydı ve genel durumu paylaşan zayıf bir doğrusal eşlenik üreteç olduğundan bilgi aktarma kanalı olabiliyordu
- İki RNG çıktısıyla iç durum adayları en fazla 8'e indirilebiliyor, ek çıktılarla tek aday seçildikten sonra istenen eylem indeksi gelene kadar RNG ilerletilebiliyordu
- Dışarıdan rastgele eylem seçimi gibi görünse de gerçekte istenen büyü gibi bir eylemin seçilmesi sağlanabiliyordu; Blizzard'ın bunu daha sonra tam olarak nasıl düzelttiği ise bilinmiyor
World of Warcraft eklentileri programlamaya giriş noktası oldu
- World of Warcraft eklentileri, Lua ile yazılmış birkaç
.lua kaynak dosyasını bir klasöre koyduğunuzda oyunun bunları doğrudan yüklediği bir yapıya sahipti
- Dosyaları değiştirip kaydettikten sonra arayüzü yeniden yüklemek, sonucu hemen görmeyi sağlıyordu; bu da giriş eşiğini çok düşürüyordu
- Başlangıçta, başkalarının kodunu kopyalayıp refactor ederek veya yeniden birleştirerek istenen işlevi oluşturan çeşitli eklentiler yapılıyordu
- Zamanla, gerçek oyun oynamaktan çok eklenti yazmaya daha fazla vakit ayrıldı ve World of Warcraft ciddi anlamda programlamaya başlamanın vesilesi oldu
Blizzard'ın eklenti güvenlik modeli
- Kullanıcılar tamamen programlanabilir eklentiler yapabilseydi bot sorunu ortaya çıkabilirdi; bu yüzden Blizzard, sıradan oyuncuların yapabileceği otomasyonu sınırlayan bir yapı kurdu
- Kullanıcı arayüzü öğelerinin çoğu ve bilgi toplama API'leri kısıtlama olmadan kullanılabiliyordu
- Örneğin, karakterin canını okuyup ön plan çerçevesinin boyutunu ayarlayan bir can çubuğu yapılabiliyordu
- Karakter hareketi, büyü yapma ve eşya kullanma gibi gerçek oyun eylemlerini gerçekleştiren API'ler korunuyordu ve yalnızca resmi Blizzard kodu tarafından çağrılabiliyordu
- Kesin dünya konumu ve kamera yönünü veren API'ler de bir noktadan sonra koruma kapsamına alındı
- Bu, boss savaşlarını kolaylaştırmak için oyun dünyasının üzerine 3D öğeler çizen eklentilere karşı alınmış bir önlemdi
Güvenli ortam ile güvenli olmayan ortamın ayrılması
- Bazı kullanıcı arayüzü öğeleri gerçek oyun eylemleriyle etkileşmek zorunda olduğundan, tıklandığında güvenli ortamda kod çalıştıran özel düğmeler oluşturulabiliyordu
- Bu düğmeler savaş sırasında oluşturulamıyor, silinemiyor veya taşınamıyordu
- Böylece savaş sırasında imlecin altına koşullu olarak düğme yerleştirip eylemleri otomatikleştirme yöntemi engellenmiş oluyordu
- Güvenli ortam, hangi büyünün yapılacağını programatik olarak ayarlayabiliyordu; ancak keyfi otomasyon için gereken dış durum erişimi engellenmişti
- Yalnızca makro sistemi düzeyindeki bazı bilgi toplama API'lerine izin veriliyordu; skill cooldown'ları veya birimin canı gibi en iyi büyüyü seçmek için gerekli bilgiler verilmemişti
- Sonuç olarak iki ortam farklı yetkilere sahipti
- Güvenli olmayan ortam: çok bilgi alabilir ama eylem gerçekleştiremez
- Güvenli ortam: eylem gerçekleştirebilir ama otomasyon için gereken bilgiyi alamaz
random bir arka kapı kanalı oldu
- Amaç, güvenlik kısıtlarını üçüncü taraf yazılımla kapatmak değil, teknik olarak izin verilen araçlarla güvenli ortamın aşılıp aşılamayacağını görmekti
- Güvenli ortamda izin verilen işlevler listesine bakarken
random fark edildi
- Bilgisayardaki rastgele sayı üreteçlerinin çoğu iç duruma sahip sözde rastgele sayı üreteçleri olduğundan, bu durum manipüle edilebilirse dış bilginin güvenli ortama aktarılabileceği düşünüldü
- Gerçekte
random, C'nin rand işlevini saran küçük bir sarmalayıcıydı
- World of Warcraft MSVC ile derlendiğinden
rand uygulaması genel durum tabanlı bir üreteçti
uint32_t state;
int rand() {
state = state * 214013 + 2531011;
return (state >> 16) & 0x7fff;
}
- Bu uygulama süreç genelinde tek bir rastgele sayı durumunu paylaşıyordu ve zayıf bir doğrusal eşlenik üreteçti
MSVC rand durumunu geri yükleme
rand çıktısı, durumun bir parçası olan 15 biti doğrudan açığa çıkarıyordu
- Durum uzayı küçük ve çıktının bir kısmı görünür olduğundan, olası durum adayları korunup ek çıktılarla yanlış adaylar elenebiliyordu
- Daha verimli yöntem, iki RNG çıktısı
r0, r1 gözlemlenerek gizli 16 bitlik durum parçasının adaylarını hesaplamaktı
- MSVC
rand için sabitler şöyleydi
- İlk ve ikinci çağrıdan sonraki gizli 16 bitlik parçalar sırasıyla
h0, h1 olarak alınırsa, durum geçiş denkleminden h0 adayları türetilebiliyordu
- Hesap sonucunda yalnızca
-1 <= k < 7 aralığına bakmak gerektiğinden, gizli durum adayları en fazla 8'e düşüyordu
- Ardından ek RNG çağrılarının sonuçlarıyla aday RNG çıktıları karşılaştırılarak yanlış adaylar eleniyordu
- Örnek Python uygulamasında
while döngüsü kullanılmıştı; ancak pratikte üçüncü çıktı bile tek bir adaya daraltmak için yeterli görünüyordu
- O dönemde bu ayrık matematik türetimini tek başına yapmak zor olduğundan crypto.SE'de soru soruldu; gerekçe olarak da “bir meslektaşıma bu RNG'nin ne kadar zayıf olduğunu göstermek istiyorum” denildi
Güvenli ortamda istenen eylemi seçme yöntemi
- RNG'nin iç durumu geri yüklenebildiğinde, güvenli ortama keyfi otomasyon kararı aktarılabiliyordu
- Süreç şu şekilde işliyordu
- Güvenli ortam kodu çalışmadan hemen önce tetiklenen bir güvenli olmayan hook kaydediliyordu
- Hook içinde tüm bilgilere erişilebildiği için hangi eylemin yapılacağı belirleniyordu
- Belirlenen eylem, sabit kodlanmış eylem listesindeki karşılığı bulunarak bir indekse çevriliyordu
- Mevcut RNG durumu yukarıdaki yöntemle geri yükleniyordu
- Sonraki RNG çıktısının eylem listesi uzunluğuna göre kalanı istenen indeks değilse, RNG ilerletilip tekrar kontrol ediliyordu
- İstenen çıktının geleceği sıraya gelindiğinde hook dönüyor ve güvenli ortam
random çağırarak o indeksteki eylemi gerçekleştiriyordu
- Güvenli ortamda bu, rastgele bir sayıyla eylem listesini indeksliyormuş gibi görünüyordu; ama gerçekte bir sonraki
random çağrısının zamanlaması ayarlanarak istenen eylem seçiliyordu
- Eylem listesinin boyutu
n ise istenen değeri aktarmak için ortalamada RNG'yi n adım ilerletmek gerekiyordu; ancak bu pratik kullanımda sorun yaratmıyordu
Sonraki durum
- Birkaç yıl sonra yeniden denendiğinde bu yöntem artık çalışmıyordu
- Blizzard'ın zayıf ve paylaşılan RNG durumu sorununu ne zaman düzelttiği ya da bunu bir sorun olarak görüp görmediği bilinmiyor
- Olası değişiklikler arasında başka bir algoritmaya geçmek veya güvenli ortam için düzgün biçimde ayrılmış bir RNG durumu kullanmak yer alıyor
- Kullanılması planlanan bir kod olmasa da, görünüşte rastgele olan bir şeyi istenen sonuca yönlendirmeyi başaran dar kapsamlı bir oyun güvenliği aşma örneğiydi
1 yorum
Hacker News görüşleri
Uzun zaman önce WoW GM olarak çalışırken, popüler Titan Bar eklentisinin belirli bir sürümünde bir hata vardı ve bu hata sürekli “GM’e ticket yaz” arayüzünü açan API’yi çağırıyordu
İptal etseniz de tekrar açılıyor ve sorunlu eklentiyi silmek dışında pencereyi kapatmanın tek yolu metin kutusuna bir şey yazıp göndermek oluyordu
GM açısından bir iki gün gerçekten çok zordu ve birçok oyuncu GM’in ne olduğunu, hatta ticket gönderebildiğini bile bilmiyordu
“Muhtemelen eklenti yüzünden ticket gönderdiniz, ben de müşteri destek görevlisi olarak bu yüzden size ulaştım” diye açıklamak da genelde kolay olmuyordu
Normal yanıt sürelerini fiilen mahvettiği için geliştiriciler bir hotfix çıkardı ve o API çağrısını yalnızca Blizzard’ın kendi LUA kodu tarafından yapılabilecek şekilde koruma altına aldı
Toplam altın, onarım oranı gibi çeşitli UI öğelerini tek satırlık bir çubukta birleştiren eklentiydi
Garip şekilde, neredeyse aynı “rastgele sayı üretecini tersten çözme” sorusuna, soru Crypto.SE’de açılmadan birkaç ay önce StackOverflow’da cevap vermiştim: https://stackoverflow.com/a/15237585/1204143
Ancak MSVC rastgele sayı üreteci yerine Java rastgele sayı üretecini hedef almıştım
İkisi de iç durumu kesilmiş biçimde çıktı veren basit doğrusal eşlenik üreteçler (LCG) olduğundan saldırı yöntemi de birbirine çok benziyor
import java.util.Random;
public class Hayley {
public static void main(String... args) {
byte[] b1 = new byte[4], b2 = new byte[2];
(new Random(0x2effe2140e00L)).nextBytes(b1);
(new Random(0xc2f0097)).nextBytes(b2);
System.out.println(new String(b1) + new String(b2));
}
}
Sunucuda da aynı rastgele sayı üretecinin kullanılmış olma ihtimali olup olmadığını merak ediyorum
Öyleyse, kullanımı çok düşük bir sunucu, düşük gecikme, rastgele sayı üretecinin mevcut durumunu oldukça doğru daraltabilme yeteneği ve rastgeleliğe bağlı ekonomik sapması yüksek bir olayı hızla yeniden tetikleyebilme imkânı olduğunda teorik olarak suistimal edilebilir gibi görünüyor
Blizzard, batıl inançlı oyuncuların “loot seed” gibi bir şey olduğuna dair güçlü inancını kırmaya yönelik, büyük ölçüde başarısız bir çaba sırasında sunucu tarafı rastgele sayı üretiminin ayrıntılarının epey fazlasını paylaşmıştı
Rastgele sayı üreteçlerinin ekonomisi ve teşvikleri ilginç
Ortada gerçek bir risk yoksa ve insanlar bunu kolay fark etmiyorsa, oyunlardaki gibi kusurlu hatta kötü rastgele sayı üreteçleri bile yeterli olabilir
Ama işin içinde kripto cüzdanları veya online casino gibi para ya da güvenlik varsa, bir anda aşırı önemli hale geliyor
Daha da kötüsü, verilen doğrusal eşlenik rastgele sayı üreteci yalnızca 12.445 farklı sayı ürettikten sonra tekrar ediyor
Bu algoritmada sadece daha iyi parametreler kullanmak bile çok daha makul olurdu
Duman izlerindeki parçacık hareketi gibi basit işler için basit ama hızlı bir rastgele sayı üreteci gerekir
Kriptografi ya da casino oyunlarında ise yalnızca en az 32 bayt durum taşıyan daha iyi bir rastgele sayı üreteci kullanmakla kalmaz, sonuçların tahmin edilmesini daha da zorlaştırmak için motoru rastgele aralıklarla fazladan ilerletirsiniz
World of Warcraft, programlamaya ilgi duymamın nedeni olmuştu
Çıktığında 6 yaşındaydım ve özel sunucular ortaya çıkmaya başlayınca kendi NPC’mi nasıl yapacağımı merak edip Lua öğrendim
O dönem aktif olan MMOwned forumundaki birçok gönderi hâlâ duruyor ve o zaman öğrenmeme yardım eden kişilerden biri bugün bile ara sıra yazıyor
Özel sunucu çekirdeğini bizzat derleyerek derleme, SVN ve patch uygulamayı öğrendim; sanırım büyücünün Fireball yeteneğiyle ilgili bir bug vardı ama tam hatırlamıyorum
Bugün internetin iyi yanlarının önemli bir kısmı, dopamin tetikleyen sosyal medya uygulamaları ve Reddit gibi kapalı forumlarla yer değiştirmiş gibi geliyor
Hâlâ HN’de bulunma nedenim de muhtemelen bana eski forumları hatırlatması
“Aritmetik yöntemlerle rastgele sayı üretmeye çalışan herkes elbette günahkâr bir durumdadır. Defalarca belirtildiği gibi rastgele sayı diye bir şey yoktur. Yalnızca rastgele sayı üretme yöntemleri vardır ve sıkı bir aritmetik prosedür elbette bunlardan biri değildir.” — John von Neumann
Neumann’a bir itirazım yok ama bunu bilgece bir özdeyiş gibi yayanlar genelde sadece yanlış bilgi aktarıyor
Bağlamında, gereksiz felsefi bir şakaya daha yakın
On yıllardır hızlı ve güvenilir kriptografik rastgele sayı üreteçlerine sahibiz
Bunlar çok küçük bir seed ve aritmetik işlemlerle gayet düzgün çalışır; ürettikleri sayılar da başka herhangi bir uygun rastgele kaynaktan ayırt edilemez ve her amaç için kullanılabilir
Bunu anlamayan çok fazla insan var ve hatta “gerçek rastgelelik” diye yılan yağı satan şirketler bile ortaya çıktı
Gerçekten berbat bir rastgele sayı üretecine iyi bir örnek Monster Hunter 3 Ultimate içinde var ve muhtemelen başka oyunlarda da olabilir
Sadece iyi loot almak için tamamen suistimal edilebilir olmakla kalmıyordu, bir de “charm table” oluşuyordu
Bazı eşyaların nitelikleri rastgele üretiliyor ama başlangıç seed’i kayıt dosyasında tutulduğu için elde edebileceğiniz eşya aralığı sınırlı kalıyor
Şanssızsanız, aslında periyodu çok kısa olan bir rastgele sayı üretecine denk gelen “lanetli tabloya” düşüp en yüksek değerleri asla elde edemeyebilirsiniz
Oyunu bozacak kadar değil ama yüksek seviye oynanış için kötü
Auction house script’i yazmıştım
Tüm açık artırmaları tarıyor, düşük fiyatlanmış eşyaları alıp yeniden listeliyordum
Biri daha ucuza koyarsa iptal edip ondan biraz daha düşük fiyata tekrar koyabiliyordum ve bu da fiilen sınırsız altın demekti
“Şey, aslında oldukça iyi bir benzetme. Fark şu ki… şey… gerçekten iyi bir benzetmeymiş!”
“Değişkenler değişmediğinde ve sabitler sabit olmadığında”
https://www.theregister.com/2006/07/26/constants_are_not/
“Bu yazının başlığındaki programlamanın kaprisliliğine dair yakınmayı, ‘Variables Won't Constants Aren't’, C ortaya çıkmadan birkaç yıl önce Creative Computing’de ilk kez okumuştum.”
Bu memin kanonik sürümü sayılabilecek belirli bir belge varsa okumak isterim