####################################################################### Luigi Auriemma Applicazione: SDK di Gamespy usato per la verifica delle cd-keys online (codice nascosto implementato nei videogiochi di terze parti) Giochi/ver: Battlefield 1942 <= 1.6.19 and 1.6rc1 ___________________________http://www.battlefield1942.com Contract Jack <= 1.1 ___________________________________http://nolf.sierra.com Gore <= 1.48 (1.49) _________________________________http://gore.cryogame.com Halo <= 1.031 _____________________http://www.microsoft.com/games/halo/ Hidden & Dangerous 2 <= 1.04 ______________________http://www.hidden-and-dangerous.com IGI 2: Covert Strike <= 1.3 _________________________________http://www.igi2-game.com Need For Speed Hot Pursuit 2 <= 242 ______________http://www.eagames.com/pccd/nfshp2/home.jsp TRON 2.0 <= 1.042 ____________________________________http://www.tron20.com probabilmente anche altri giochi: http://aluigi.org/papers/gshlist.txt Piattaforme: Windows, Linux e MacOS Bugs: A] crash dei servers di gioco B] problema di privacy Exploitation: remoto Data: 24 Feb 2004 Autore: Luigi Auriemma e-mail: aluigi@autistici.org web: aluigi.org ####################################################################### 1) Introduzione 2) Bugs 3) Analisi del codice nascosto 4) The Code 5) Fix 6) Conclusione ####################################################################### =============== 1) Introduzione =============== Prima di tutto voglio premettere che questi bugs sono stati trovati durante una ricerca in un gioco specifico ed ho saputo della implicazione di Gamespy solo qualche minuto piu' tardi. Gamespy, le persone che dicono di "accogliere qualsiasi aiuto" e poi mi inviano un inutile Cease&Desist e DIFFAMANO me e soprattutto il mio hobby, le stesse persone che dicono di "proteggere i diritti dei giocatori e provvedere alla sicurezza" e poi lasciano (tuttora) RogerWilco e Gamespy3d vulnerabili a vecchi bugs altamente critici e pubblici, le stesse "persone fidate" che affermano "I giocatori hanno fiducia in noi" ed allo stesso tempo inseriscono funzioni nascoste nei giochi sviluppati da altre persone. http://aluigi.org/papers/castleoflies-ita.txt Il codice ora oggetto di questa ricerca e' proprio l'SDK che Gamespy da'/vende agli sviluppatori di videogiochi per implementare la gestione e la verifica online delle cd-keys dei giochi. La cosa peggiore di tale SDK e' che esso usa dei semplici metodi di "security through obscurity" per nascondere informazioni agli stessi utenti che usano questi giochi vulnerabili (qualsiasi tipo di demo, gioco completo e server dedicato) quindi questo advisory fara' soprattutto chiarezza su questi metodi vergognosi evitando che tali utenti come me continuino ad essere presi in giro. I bugs che voglio analizzare sono essenzialmente i seguenti: A] bug di sicurezza: crash dei severs di gioco B] security through obscurity bug: problemi di privacy Fortunatamente gli sviluppatori hanno il codice sorgente dell'SDK vulnerabile quindi tutte le persone che ho contattato svariate settimane fa' hanno avuto la possibilita' di correggere il primo bug senza problemi. Inoltre qualche settimana fa' Gamespy ha anche rilasciato un SDK corretto, infatti sono stati contattati da uno degli sviluppatori con cui ho parlato... come tutti sanno per me e' impossibile mettermi in contatto con Gamespy proprio perche' sono incapaci di capire e gestire le mie segnalazioni di bugs. Comunque ho anche rilasciato dei fix non ufficiali per i giochi che al momento in cui scrivo non sono stati corretti o che non sono piu' supportati. ####################################################################### ======= 2) Bugs ======= ----------------------------- A] crash dei servers di gioco ----------------------------- Il problema e' localizzato nelle istruzioni che copiano la richiesta nel pacchetto ricevuto delimitata da backslashes (come \query\) in un nuovo buffer. Le istruzioni vulnerabili sono simili alle seguenti: int size = strchr(buff + 1, '\\') - buff; if(size > 32) return; strncpy(querybuff, buff + 1, size); "buff" e' il pacchetto decodificato (leggere la prossima sezione) contenente uno dei comandi nascosti di Gamespy, "size" e' un numero con segno contenente l'ammontare di bytes da copiare e "querybuff" e' il buffer di destinazione che conterra' la richiesta per il confronto con i comandi nascosti. In tale codice possiamo trovare ben 2 errori di programmazione: - il valore di ritorno della funzione strchr() non e' controllato quindi se essa fallisce il codice di Gamespy non si accorge di nulla e pensa che l'indirizzo della stringa che e' ritornato sia valido anche se uguale a 0 (fallito). - "size" e' gestito come un numero intero con segno (+/-) quindi quando strchr() fallisce la funzione esegue l'operazione "0 - buff" (differenza tra la fine e l'inizio della stringa) che risulta in un numero negativo a 32bit. Il problema avviene quando la funzione controlla se "size" e' maggiore di 32 in quanto naturalmente questo e' un confronto con segno e "size" ha segno negativo. L'effetto del bug e' un'eccezione nella funzione strncpy() che interrompe immediatamente il server. ---------------------- B] problemi di privacy ---------------------- Come gia' detto, il codice di Gamespy implementa delle piccole tecniche di security through obscurity per evitare che gli amministratori dei servers di gioco vedano o capiscano le richieste inviate e ricevute ai loro sistemi (perche'??? non so, chiedetelo a Gamespy). Queste richieste comunque non sono nulla di cosi' "speciale" ma possono causare dei problemi di privacy ai servers di gioco ed ai clients che giocano in essi. L'unico comando che da' tali problemi e' il seguente: ison: usato per conoscere se in un server di gioco sta' giocando un utente con una cd-key specifica Tale comando per esempio puo' essere usato per tracciare un utente se noi conosciamo la sua cd-key od il suo hash MD5 (inviato ad ogni server di gioco dove entra l'utente). ####################################################################### ============================== 3) Analisi del codice nascosto ============================== L'SDK di Gamespy e' una funzione parzialmente nascosta che viene attivata quando il server di gioco riceve un pacchetto con un byte specifico in esso o deve verificare la cd-key di un client. Io sono proprio l'utente di alcuni dei giochi vulnerabili e non accetto che qualcuno inserisca codice nascosto nei giochi che compro (soprattutto se non sono gli sviluppatori e non mi fido di loro) quindi tale analisi fara' finalmente luce su una parte di questo codice, ossia quella che interessa direttamente gli utenti. La funzione nascosta usata per gestire le richieste "non documentate" e' attivata quando un pacchetto che inizia con il carattere ';' (byte 0x3b) raggiunge la porta del server di gioco adibita alle richieste. Tale porta e' quella UDP usata per ricevere le richieste di informazioni come "basic", "info", "status", "rules" e tutte le altre. Il carattere ';' in realta' e' il carattere backslash (lo stesso usato all'inizio di qualsiasi richiesta) "XORato" con il carattere 'g' della stringa "gamespy", infatti il pacchetto che raggiunge il server di gioco e' semplicemente codificato usando l'operatore XOR. Di seguito una funzione C ottimizzata che spiega come lavora tale operazione di codifica/decodifica: void gamespyxor(u_char *string, int len) { u_char gamespy[] = "gamespy", *gs; for(gs = gamespy; len; len--, gs++, string++) { if(!*gs) gs = gamespy; *string ^= *gs; } } Dopo avere decodificato i dati la funzione di Gamespy assembla in memoria i 4 comandi disponibili per un confronto con quello contenuto nel pacchetto appena ricevuto. Il metodo usato per questa operazione e' molto semplice e il suo unico scopo e' quello di nascondere i comandi disponibili a chiunque provi ad aprire l'eseguibile del gioco con un disassemblatore od un editor esadecimale. Quello che segue e' un esempio reale che mostra come vengono assemblati i 4 comandi usati nella funzione: :004422B7 B175 mov cl, 75 :004422B9 B06F mov al, 6F :004422BB 56 push esi :004422BC 8BF2 mov esi, edx :004422BE B26E mov dl, 6E :004422C0 884C240C mov byte[esp+0C], cl :004422C4 884C2410 mov byte[esp+10], cl :004422C8 884C2420 mov byte[esp+20], cl :004422CC 884C2423 mov byte[esp+23], cl :004422D0 33C9 xor ecx, ecx :004422D2 85F6 test esi, esi :004422D4 8844240D mov byte[esp+0D], al :004422D8 88442412 mov byte[esp+12], al :004422DC 8844241A mov byte[esp+1A], al :004422E0 88442422 mov byte[esp+22], al :004422E4 C644240E6B mov byte[esp+0E], 6B :004422E9 C644240F00 mov byte[esp+0F], 00 :004422EE 88542411 mov byte[esp+11], dl :004422F2 C64424136B mov byte[esp+13], 6B :004422F7 C644241400 mov byte[esp+14], 00 :004422FC C644241869 mov byte[esp+18], 69 :00442301 C644241973 mov byte[esp+19], 73 :00442306 8854241B mov byte[esp+1B], dl :0044230A C644241C00 mov byte[esp+1C], 00 :0044230F C644242163 mov byte[esp+21], 63 :00442314 88542424 mov byte[esp+24], dl :00442318 C644242574 mov byte[esp+25], 74 :0044231D C644242600 mov byte[esp+26], 00 La porzione di codice proviene direttamente dal file BF1942_w32ded.exe di Battlefield 1942 Win32 dedicated server 1.6.19 ma tale "tecnica di occultamento" e' la stessa usata da tutti gli altri giochi vulnerabili e soprattutto dai prodotti di Gamespy (..."Gamers trust us"... "I giocatori hanno fiducia in noi"...). I comandi generati sono esattamente: "uok", "unok", "ison" e "ucount". I primi 2 comandi in realta' sono delle risposte che il master server di Gamespy invia ai servers di gioco quando questi richiedono la verifica di una cd-key usando la richiesta "auth". Invece molto piu' interessanti sono i comandi "ison" ed un po' anche "ucount" che sono usati rispettivamente per conoscere se una cd-key specifica e' usata al momento in un server di gioco e quanti giocatori usano delle cd-key. Ecco degli esempi pratici: \uok\\cd\0123456789abcdef0123456789abcdef\skey\1\errmsg\Valid CD Key \unok\\cd\0123456789abcdef0123456789abcdef\skey\1\errmsg\Invalid CD Key \ison\skey\1\cd\0123456789abcdef0123456789abcdef \ucount\ Dove "skey" e' un numero ID (identificativo) usato per tracciare richieste multiple e "cd" e' l'hash della cd-key. L'hash delle cd-keys e' semplicemente l'hash MD5 calcolato dal client sulla sua cd-key, esso e' inviato da ogni client al server di gioco che lo usa per convalidare il client attraverso il master server. Quando il server ha assemblato i comandi disponibili in memoria esso confrontera' la richiesta ricevuta con ognuna di queste 4 stringhe di testo e dopodiche' inviera la risposta relativa se necessaria. Di seguito ecco delle possibili risposte per i comandi "ison" e "ucount": \uon\\skey\1 la cd-key richiesta e' usata nel server di gioco \uoff\\skey\1 la cd-key richiesta non e' usata nel server di gioco \ucount\9 nel server ci sono 9 giocatori che usano delle cd-key ####################################################################### =========== 4) The Code =========== ----------------------------- A] crash dei servers di gioco ----------------------------- Per testare il bug e' necessario soltanto l'invio del carattere ';' alla porta UDP per le richieste del server di gioco che sta' ospitando la partita il quale crashera' all'istante, comunque ho scritto anche un utile proof-of-concept: http://aluigi.org/poc/gshboom.zip ---------------------- B] problemi di privacy ---------------------- Ho scritto un tool per controllare i giochi che usano il codice di Gamespy, esso invia tutti e 4 i comandi disponibili (da ricordare che "uok" e "unok" non sono richieste ma risposte e quindi inutili): http://aluigi.org/papers/gshinfo.zip Poi ho scritto anche un semplice analizzatore di pacchetti per Windows che decodifica al volo tutti i pacchetti UDP inviati e ricevuti al proprio server dal master server di Gamespy o da qualsiasi altro host a scelta dell'utente: http://aluigi.org/papers/gshsniff.zip L'ultimo tool invece e' un semplice logger usato per tenere traccia dei comandi decodificati (e solo di quelli) che vengono inviati e ricevuti su una porta UDP specifica: http://aluigi.org/papers/gshlog.zip ####################################################################### ====== 5) Fix ====== UPDATE 19 March 2005: An universal patcher is available here: http://aluigi.org/patches/gshboomfix.lpatch ----------------- Patches ufficiali ----------------- Come gia' detto, alcune settimane fa' Gamespy ha rilasciato un SDK aggiornato che dovrebbe correggere la vulnerabilita' quindi tutti i giochi vulnerabili che non conoscevo hanno o avranno un fix presto. Comunque TUTTI gli sviluppatori dei giochi che io sapevo vulnerabili ed ho controllato personalmente sono stati avvertiti velocemente con mails multiple e per un mese Quella che segue e' la situazione delle patches al momento in cui scrivo: Battlefield 1942.....................FIX solo per Linux DS 1.6RC2. ero in contatto con Dice riguardo tale bug ma dopo la patch per il server dedicato di Linux ho perso qualsiasi contatto quindi non conosco lo stato attuale del fix per il gioco completo ed il server dedicato per Win32 Contract Jack........................NO, sembra non piu' supportato Gore.................................NO, MYFIX Haegemonia...........................NO, sembra usare una modifica dell'SDK che non lo rende vulnerabile al classico attacco ma ugualmente contiene le istruzioni vulnerabili Halo.................................FIX in 1.04 Hidden & Dangerous 2.................NO, MYFIX solo per DS IGI 2: Covert Strike.................NO, MYFIX solo per DS Judge Dredd: Dredd vs. Death.........NO Need For Speed Hot Pursuit 2.........NO Terminator 3: War of the Machines....FIX in arrivo, comunque il gioco non e' vulnerabile all'attacco classico spiegato nella sezione precedente TRON 2.0.............................NO, sembra non piu' supportato ---------- I miei fix ---------- Fortunatamente correggere il bug e' molto molto semplice quindi ho creato delle patches manuali (c'e' bisogno di un editor esadecimale) che correggono completamente il problema in quasi tutti i giochi non patchati: Game file offset old patch ---------------------------------------------------------------------- BF1942 win32 DS 1.6.19 BF1942_w32ded.exe 00042370 7f 77 Gore 1.48 and 1.49 gore.exe 000B86F2 7f 77 Hidden & Dangerous 2 1.04 DS HD2DS.exe 003498CA 7f 77 Igi2 1.3 dedicated server igi2.exe 001C937A 7f 77 Tutti gli altri giochi o versioni retail fanno uso di eseguibili crittati per le loro stupide protezioni CD ed io non li supporto con i miei fix. Questa e' una ulteriore conferma che le protezioni dei CD sono solo un limite per gli utenti ed in questo caso anche per le persone che vogliono correggere dei giochi "non piu' supportati": http://aluigi.org/patches/nocd.txt Spiegazione del mio fix ----------------------- Il mio fix converte soltanto un JG (confronto con segno) in un JA (senza segno). Praticamente quando strchr() fallisce esso ritorna uno 0 e la funzione di Gamespy esegue uno "0 - buff" che trova la grandezza della richiesta e controlla se e' maggiore di 32. MA tale confronte avviene con segno e dato che il risultato di "0 - buff" in realta' e' un numero negativo il confronto fallisce. Il mio fix fa' solo un confronto SENZA segno di modo che "0 - buff" e' maggiore di 32 e la richiesta dell'attacker non viene accettata. ####################################################################### ============= 6) Conclusion ============= La fiducia dovrebbe essere guadagnata con fatti reali e non con bugie e segreti. #######################################################################