Luigi Auriemma

aluigi.org (ARCHIVE-ONLY FORUM!)
It is currently 19 Jul 2012 14:36

All times are UTC [ DST ]





Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 13 posts ] 
Author Message
 Post subject: enctypeX
PostPosted: 17 Oct 2008 14:48 

Joined: 17 Oct 2008 14:11
Posts: 8
ciao luigi!
ho aperto questo topic per chiederti alcune delucidazioni su come utilizzare le funzioni per decriptare le risposte del masterserver di gamespy.

io ho guardato il codice di enctypex_decoder.c pero' non ho capito bene che parametri passare alle funzioni.

in realta' la cosa che piu mi interesserebbe sapere e' il metodo che utilizzi quando devi analizzare e capire l'algoritmo per decriptare un blocco di dati, mi basta qualche dritta perche e' un argomento che mi ha sempre stuzzicato.

grazie


Top
 Profile  
 
 
 Post subject: Re: enctypeX
PostPosted: 17 Oct 2008 16:50 

Joined: 13 Aug 2007 21:44
Posts: 4068
Location: http://aluigi.org
immagino che con la query fatta dal client (tu) non ci siano problemi quindi salto quella parte ed il "formato" di tale query.

Per prima cosa, nel caso di enctypeX non esiste un unico master server valido per tutti i giochi ma ci sono circa una ventina di master servers con nomi tipo gamename.msnumero.gamespy.com
Per calcolare l'hostname del master server a cui ti devi connettere per un gioco specifico basta che usi la funzione enctypex_msname come nell'esempio per America's Army:
Code:
  char *hostname;
  hostname = enctypex_msname("armygame", NULL);
oppure:
Code:
  char hostname[256];
  enctypex_msname("armygame", hostname);
cosi' il tuo "hostname" avra' il giusto master server

quindi connettiti e fai la tua richiesta, in caso di problemi o dubbi sulla richiesta dai un'occhiata alla funzione tcpxspr nel file gsmyfunc.h di gslist, come puoi vedere da quel semplice codice e' uno scherzo la costruzione della query.

ora il server ti inviera' i dati crittati con una unica particolarita' che sta' a te decidere come gestire, ossia la connessione con il master server viene tenuta attiva e quindi non hai nessun modo veloce (a livello di socket) di sapere quando i dati finiscono.

In tal caso esistono 2 soluzioni che possono essere piu' o meno semplici da implementare.
Nella prima (quella usata da gslist, la migliore) i dati vengono decrittati e gestiti in tempo reale man mano che vengono ricevuti:
Code:
    while(!timeout(sd, 10)) {
        err = recv(sd, buff + len, dynsz - len, 0);
        if(err <= 0) break;
        len += err;
        if(len >= dynsz) {
            dynsz += BUFFSZ;
            buff = realloc(buff, dynsz);
            if(!buff) std_err();
        }
        p = enctypex_decoder(msgamekey, validate, buff, &len, &enctypex_data);
        if(p && enctypex_decoder_convert_to_ipport(p, len - (p - buff), NULL, NULL, 0)) break;
    }

come puoi vedere buff e' il buffer dinamico che continuo a riallocare man mano che ricevo i dati e non c'e' piu' spazio (dynsz) ove metterli.
"p" non e' nient'altro che un puntatore (char *p;), indica dove iniziano i veri dati (perche' i primi 20 bytes all'inizio non sono usati o forse sono un hash, comunque non vanno considerati).

L'altro modo invece e' ricevere tutti i dati dal server, aspettare che il socket vada in timeout (magari 3 o 5 secondi) e poi decrittare tutto cosi':
Code:
len = enctypex_wrapper(msgamekey, validate, buff, len);

dopo aver fatto cio' puoi passare al parsing dei dati per ricavare l'IP e la porta di ogni server oppure usare la funzione che automaticamente ti mette in un buffer tutti i dati nel formato "IP:PORTA \parametro\valore\parametro\valore...\parametro\valore"

ma magari ne riparliamo quando arrivi a questo punto.


Top
 Profile  
 
 Post subject: Re: enctypeX
PostPosted: 17 Oct 2008 19:14 

Joined: 17 Oct 2008 14:11
Posts: 8
ciao
grazie mille per la dritta!!! ora provo a buttare giu 2 righe e ti so dire!


Top
 Profile  
 
 Post subject: Re: enctypeX
PostPosted: 18 Oct 2008 02:06 

Joined: 17 Oct 2008 14:11
Posts: 8
mi servirebbe sapere a cosa corrispondono i parametri msgamekey e validate nella funzione qui sotto:

Code:
len = enctypex_wrapper(msgamekey, validate, buff, len);


Top
 Profile  
 
 Post subject: Re: enctypeX
PostPosted: 18 Oct 2008 12:06 

Joined: 13 Aug 2007 21:44
Posts: 4068
Location: http://aluigi.org
msgamekey e' il gamekey (hai presente i valori tutti a destra che si vedono se usi "gslist -l"?) del gamename che fa' la richiesta.
Praticamente quando tu fai la query enctypeX hai 2 gamename che possono essere ad esempio "armygame" "armygame" nel qual caso il "richiedente" (il primo) e' uguale al nome del gioco di cui vuoi ricavare le informazioni, mentre in Gamespy Arcade hai "gslive" "armygame".
La gamekey che devi usare e' quindi quella del richiedente: "g3sR2b" nel primo esempio e "Xn221z" nel secondo.

"validate" invece non e' nient'altro che una stringa random, puoi usare una sequenza di 8 'a' o '0' o quello che vuoi oppure usare direttamente la funzione enctypex_decoder_rand_validate:
Code:
  char validate[9];
  enctypex_decoder_rand_validate(validate);
il termine "validate" infatti non e' corretto, sarebbe stato meglio definirlo "client-challenge" ma vabbe' 8-)


Top
 Profile  
 
 Post subject: Re: enctypeX
PostPosted: 19 Oct 2008 18:05 

Joined: 17 Oct 2008 14:11
Posts: 8
aluigi wrote:
dopo aver fatto cio' puoi passare al parsing dei dati per ricavare l'IP e la porta di ogni server oppure usare la funzione che automaticamente ti mette in un buffer tutti i dati nel formato "IP:PORTA \parametro\valore\parametro\valore...\parametro\valore"

ma magari ne riparliamo quando arrivi a questo punto.


ok ci sono arrivato.
per semplicit?? adesso ho usato il metodo che decripta tutti i dati alla fine:
Code:
len = enctypex_wrapper(msgamekey, validate, buff, len);


ora ho qualche domanda da fare:
1_ devo passare tutti i dati che arrivano alla funzione, o saltare i primi n?? byte?

2_ i dati che arrivano hanno separatori o sono tutti ip e porte concatenate?

3_ 4 byte ip e 2 byte porta?

4_ c'e qualche funzione gia fatta che mi parsa i dati?

5_ io sto utilizzando come gioco unreal tournament 3 per le prove: il videogioco fa la query con "ut3pc" "ut3pc", invece gslist la fa con "ut3" "gslive". quali sono le differenze tra i due? qual'e il metodo migliore?


Top
 Profile  
 
 Post subject: Re: enctypeX
PostPosted: 19 Oct 2008 18:49 

Joined: 13 Aug 2007 21:44
Posts: 4068
Location: http://aluigi.org
ottimo, ora non devi fare altro che usare il codice seguente che converte i dati ricevuti da gamespy nel classico "4bytes_IP 2bytes_port":
Code:
  unsigned char *lista;
  lista= malloc((len / 5) * 6);
  len = enctypex_decoder_convert_to_ipport(buff, len, lista, NULL, 0);
ora tu ti starai chiedendo che cos'e' quel lista, in pratica nulla vieterebbe di utilizzare lo stesso buff come destinazione per il formato 4:2 ma purtroppo (o per fortuna a seconda dei casi) Gamespy usa un metodo particolare per ridurre i bytes da inviare a chi fa' le richieste, ossia specifica una porta fissa all'inizio del pacchetto e se un server nella lista usa quella stessa porta non la rispecifica di nuovo... tradotto: se nella risposta e' stato usato questo trucchetto molte volte ti ritroveresti a buttare dentro buff 6 bytes alla volta con un input di 5 sovrascrivendo dopo un po' il tuo stesso input.
Non ti dico le bestemmie quando mi accorsi di questa cosa e quindi della necessita' di allocare ed usare un nuovo buffer.

quindi ora "lista" contiene gli IP e le porte nel classico formato (ricordati di usare htons() per le porte).

per la prima domanda, enctypex_wrapper effettua automaticamente l'eliminazione dei bytes iniziali che non servono a nulla.

per la quinta domanda invece non cambia nulla perche' io uso gslive come richiedente per motivi di praticita' (cosi' gslist non deve dipendere per forza da gslist.cfg o dovrei conoscere la gamekey esatta di TUTTI i giochi da querare).
Io ti consiglio di usare ut3pc ut3pc con gamekey nT2Mtz


Top
 Profile  
 
 Post subject: Re: enctypeX
PostPosted: 19 Oct 2008 23:57 

Joined: 17 Oct 2008 14:11
Posts: 8
ho riscontrato qualche problema e ho paura di aver sbagliato nel costruire la prima query:
Code:
char msg[] = {
         0x00, 0x24, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, //dati fissi
         0x75, 0x74, 0x33, 0x70, 0x63, 0x00, //ut3pc\0
         0x67, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x00, //gslive\0
         0x56, 0x41, 0x43, 0x7a, 0x55, 0x44, 0x77, 0x5e, //problema???
         0x00, 0x00, 0x00, 0x00, 0x00, 0x01 //dati fissi
      };

la prima riga sono dati fissi la seconda e la terza sono "gamestr" e "msgamestr" poi inizia il problema:
guardando il codice della funzione tcpxspr, ...
Code:
int tcpxspr(int sd, u8 *gamestr, u8 *msgamestr, u8 *validate, u8 *filter, u8 *info, int type) {  // enctypex
   [...]

    len = 2 + 7 + strlen(gamestr) + 1 + strlen(msgamestr) + 1 + strlen(validate) + strlen(filter) + 1 + strlen(info) + 1 + 4;
    buff = malloc(len);

    p = buff;
    p += 2;
    *p++ = 0;
    *p++ = 1;
    *p++ = 3;
    *p++ = 0;   // 32 bit
    *p++ = 0;
    *p++ = 0;
    *p++ = 0;
    p += sprintf(p, "%s", gamestr) + 1;     // the one you are requesting
    p += sprintf(p, "%s", msgamestr) + 1;   // used for the decryption algorithm
    p += sprintf(p, "%s%s", validate, filter) + 1;
    p += sprintf(p, "%s", info) + 1;
    *p++ = 0;
    *p++ = 0;
    *p++ = 0;
    *p++ = type;

    [...]
}

dopo il "msgamestr", viene aggiunto il "validate" e il "filter" senza separatori \0 tra di essi, poi altri dati fissi ("type" ho notato che e' sempre 0x00 0x01)

bene, sniffando "gslist -n ut3pc" il valore dopo "msgamestr" dovrebbe essere "g3sR2b" + "filter" (filter immagino sia vuoto) ma invece ci sono valori diversi ogni volta che eseguo il comando e che non centrano nulla con il validate + filter.
Questa cosa mi ha un po confuso e credo di sbagliare proprio li...

la query me la esegue pero' uso sempre i dati fissi che vedi nel primo codice, questo puo influire sulla decriptazione? secondo te sono fuori strada??


Top
 Profile  
 
 Post subject: Re: enctypeX
PostPosted: 20 Oct 2008 03:32 

Joined: 13 Aug 2007 21:44
Posts: 4068
Location: http://aluigi.org
la tua query fissa va' bene, l'ho appena provata ed il master server ut3pc.ms3.gamespy.com invia dati tranquillamente e li ho pure decrittati con successo usando il programma di testing "enctypedec" (http://aluigi.org/papers/enctypedec.zip enctypedec -g Xn221z -v "VACzUDw^" x dati_ricevuti.txt)

gslist utilizza il "validate" casuale ogni volta quindi e' normale che cambi.


Top
 Profile  
 
 Post subject: Re: enctypeX
PostPosted: 20 Oct 2008 11:34 

Joined: 17 Oct 2008 14:11
Posts: 8
ok perfetto!

adesso ti spiego il mio problema:

quando faccio la query e il master server mi risponde, passo tutti i dati in un blocco unico alla funzione "enctypex_wrapper" che li decripta poi li ripasso a "enctypex_decoder_convert_to_ipport" che pero' mi ritorna 0.
Come compilatore uso mingw32 su win (devo ancora provare su linux), e fa il pignolo dandomi errori di conversione nelle tue funzioni (i vari malloc e conversioni tra char * e unsigned char *) che ho dovuto correggere con dei cast .
Probabilmente ho fatto qualche cast pericoloso e quindi le funzioni non compiono il loro dovere.
Ora mi servirebbe sapere se per caso usi qualche opzione particolare per compilare il tuo codice con il gcc in maniera che non mi rompa le balle con i cast.

ps. Uso il mingw perche sto facendo un applicazione opensource in Qt 4.4.3 cross platform per il browsing dei server di gioco.

grazie ancora per lo sbattimento


Top
 Profile  
 
 Post subject: Re: enctypeX
PostPosted: 20 Oct 2008 11:54 

Joined: 13 Aug 2007 21:44
Posts: 4068
Location: http://aluigi.org
penso che il problema sia nel casting perche' qui ho provato e funzia, quindi aggiungi -Wno-pointer-sign al compilatore per saltare quei fastidiosi warning.

Quello che ho usato io qui come test iperveloce e':
Code:
len = enctypex_wrapper(gamekey, validate, buff, len);
unsigned char *lista, *limit;
lista = malloc((len / 5) * 6);
len = enctypex_decoder_convert_to_ipport(buff, len, lista, NULL, 0);
limit = lista + len;
for(p = lista; p < limit; p += 6) {
    printf("%hhu.%hhu.%hhu.%hhu %hu\n", p[0], p[1], p[2], p[3], (p[4] << 8) | p[5]);
}
e no, non uso opzioni particolari nel compilatore (tanto qualsiasi opzione usi il codice deve andare sempre e comunque)


Top
 Profile  
 
 Post subject: Re: enctypeX
PostPosted: 23 Oct 2008 21:06 

Joined: 17 Oct 2008 14:11
Posts: 8
bene ora che abbiamo scoperto che il tuo enctypeX va compilato col gcc e non il g++, sono riuscito a risolvere il problema del make(notare output sotto) pero' non riesco a far vedere le funzioni alla mia classe anche se inserisco i prototipi!!!

ecco l'output:

Code:
mingw32-make debug
mingw32-make -f Makefile.Debug
mingw32-make[1]: Entering directory `X:/snake/workspace/gamespy'
gcc -c -g -Wall -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DQT_NEEDS_QMAIN -I"c:\Programmi\Qt\4.4.3\include\QtCore" -I"c:\Programmi\Qt\4.4.3\include\QtCore" -I"c:\Programmi\Qt\4.4.3\include\QtNetwork" -I"c:\Programmi\Qt\4.4.3\include\QtNetwork" -I"c:\Programmi\Qt\4.4.3\include\QtGui" -I"c:\Programmi\Qt\4.4.3\include\QtGui" -I"c:\Programmi\Qt\4.4.3\include" -I"c:\Programmi\Qt\4.4.3\include\ActiveQt" -I"debug" -I"." -I"c:\Programmi\Qt\4.4.3\mkspecs\win32-g++" -o debug\enctypex_decoder.o enctypex_decoder.c
g++ -c -g -frtti -fexceptions -mthreads -Wall -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DQT_NEEDS_QMAIN -I"c:\Programmi\Qt\4.4.3\include\QtCore" -I"c:\Programmi\Qt\4.4.3\include\QtCore" -I"c:\Programmi\Qt\4.4.3\include\QtNetwork" -I"c:\Programmi\Qt\4.4.3\include\QtNetwork" -I"c:\Programmi\Qt\4.4.3\include\QtGui" -I"c:\Programmi\Qt\4.4.3\include\QtGui" -I"c:\Programmi\Qt\4.4.3\include" -I"c:\Programmi\Qt\4.4.3\include\ActiveQt" -I"debug" -I"." -I"c:\Programmi\Qt\4.4.3\mkspecs\win32-g++" -o debug\MasterQuery.o MasterQuery.cpp
g++ -c -g -frtti -fexceptions -mthreads -Wall -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DQT_NEEDS_QMAIN -I"c:\Programmi\Qt\4.4.3\include\QtCore" -I"c:\Programmi\Qt\4.4.3\include\QtCore" -I"c:\Programmi\Qt\4.4.3\include\QtNetwork" -I"c:\Programmi\Qt\4.4.3\include\QtNetwork" -I"c:\Programmi\Qt\4.4.3\include\QtGui" -I"c:\Programmi\Qt\4.4.3\include\QtGui" -I"c:\Programmi\Qt\4.4.3\include" -I"c:\Programmi\Qt\4.4.3\include\ActiveQt" -I"debug" -I"." -I"c:\Programmi\Qt\4.4.3\mkspecs\win32-g++" -o debug\main.o main.cpp
C:\Programmi\Qt\4.4.3\bin\moc.exe -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DQT_NEEDS_QMAIN -I"c:\Programmi\Qt\4.4.3\include\QtCore" -I"c:\Programmi\Qt\4.4.3\include\QtCore" -I"c:\Programmi\Qt\4.4.3\include\QtNetwork" -I"c:\Programmi\Qt\4.4.3\include\QtNetwork" -I"c:\Programmi\Qt\4.4.3\include\QtGui" -I"c:\Programmi\Qt\4.4.3\include\QtGui" -I"c:\Programmi\Qt\4.4.3\include" -I"c:\Programmi\Qt\4.4.3\include\ActiveQt" -I"debug" -I"." -I"c:\Programmi\Qt\4.4.3\mkspecs\win32-g++" -D__GNUC__ -DWIN32 MasterQuery.h -o debug\moc_MasterQuery.cpp
g++ -c -g -frtti -fexceptions -mthreads -Wall -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DQT_NEEDS_QMAIN -I"c:\Programmi\Qt\4.4.3\include\QtCore" -I"c:\Programmi\Qt\4.4.3\include\QtCore" -I"c:\Programmi\Qt\4.4.3\include\QtNetwork" -I"c:\Programmi\Qt\4.4.3\include\QtNetwork" -I"c:\Programmi\Qt\4.4.3\include\QtGui" -I"c:\Programmi\Qt\4.4.3\include\QtGui" -I"c:\Programmi\Qt\4.4.3\include" -I"c:\Programmi\Qt\4.4.3\include\ActiveQt" -I"debug" -I"." -I"c:\Programmi\Qt\4.4.3\mkspecs\win32-g++" -o debug\moc_MasterQuery.o debug\moc_MasterQuery.cpp
g++ -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc -mthreads -Wl -Wl,-subsystem,windows -o debug\gamespy.exe debug/enctypex_decoder.o debug/MasterQuery.o debug/main.o debug/moc_MasterQuery.o  -L"c:\Programmi\Qt\4.4.3\lib" -lmingw32 -lqtmaind -lQtGuid4 -lQtNetworkd4 -lQtCored4
debug/MasterQuery.o(.text+0x22fc): In function `ZN11MasterQuery11displayDataEv':
X:/snake/workspace/gamespy/MasterQuery.cpp:143: undefined reference to `enctypex_decoder_rand_validate(unsigned char*)'
debug/MasterQuery.o(.text+0x2327):X:/snake/workspace/gamespy/MasterQuery.cpp:145: undefined reference to `enctypex_wrapper(unsigned char*, unsigned char*, unsigned char*, int)'
debug/MasterQuery.o(.text+0x23b1):X:/snake/workspace/gamespy/MasterQuery.cpp:151: undefined reference to `enctypex_decoder_convert_to_ipport(unsigned char*, int, unsigned char*, unsigned char*, int)'
mingw32-make[1]: Leaving directory `X:/snake/workspace/gamespy'
collect2: ld returned 1 exit status
mingw32-make[1]: *** [debug\gamespy.exe] Error 1
mingw32-make: *** [debug] Error 2


con i prototipi mi da "undefined reference to ..."

a voi il testimone...


Top
 Profile  
 
 Post subject: Re: enctypeX
PostPosted: 23 Oct 2008 21:42 

Joined: 13 Aug 2007 21:44
Posts: 4068
Location: http://aluigi.org
nessun problema, ora nel file CPP principale del tuo progetto metti queste righe di codice in alto a tutto:
Quote:
extern "C" {
unsigned char *enctypex_decoder(unsigned char *key, unsigned char *validate, unsigned char *data, int *datalen, void *enctypex_data);
unsigned char *enctypex_msname(unsigned char *gamename, unsigned char *retname);
int enctypex_wrapper(unsigned char *key, unsigned char *validate, unsigned char *data, int size);
int enctypex_decoder_convert_to_ipport(unsigned char *data, int datalen, unsigned char *out, unsigned char *infobuff, int infobuff_offset);
}
dopodiche' ricompila enctypex_decoder come segue:
Quote:
gcc -s -O2 -c enctypex_decoder.c
ar rcs enctypex_decoder.a enctypex_decoder.o
ed infine anziche' aggiungere il .o nel tuo makefile mettici il .a (libreria statica)
ad occhio dovrebbe andare senza problemi ora


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 13 posts ] 

All times are UTC [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for: