.:HoMe:.     .:CrackMe:.     .:My ProGGie:.     .:BuGs & ExpLoiTs:.     .:TOoLs:.     .:VaRiE:.

> ReVerSiNg di: All Seeing Eye <
Realizzato da NoRpiUs

ToOLz uTiLiZzATi:
- Debugger ( Olly Dbg )
- Hex Editor
- W32DASM

SpiEgaZiOnE:
Oh eccoci qua al nostro primo reversing.. e cominciamo con un bel programma, ovvero                  All Seeing Eye. I Netgamers lo conosceranno molto bene, tool usato per scannare i server di gioco, pingarli, amministrarli da remoto e altre comode funzioni. Bene, cominciamo con il reversing. Apriamo OllyDbg e carichiamo eye.exe... e subito ci compare una box da parte del nostro olly che ci dice che il codice e' compresso o criptato, quindi da qui capiamo che gli stronzi della UDPSOFT hanno packato il programma :). Ecco, la prima volta che ho provato a cracckare ase a questo punto ero gia bloccato perche' io riguardo a unpacking e balle varie so poco o niente, ma ecco che un giorno vedo in chat una figura angelica... un certo Xtremer che non si sa da dove sia comparso fatto stà che anche lui aveva bisogno di cracckare ase ed era riuscito a trovare l'unpacker giusto! Subito me lo sono fatto dare e mi sono spacchettato l'exe di ase, e finalmente ho potuto continuare quello che avevo iniziato tanto tempo prima :)). All Seeing Eye è packato con UPX, l'unpacker lo allego qua. Per spacchettare ase basta scrivere da dos: upx.exe -d eye.exe. Ok una volta fatto questo, ricarichiamo il nostro eye.exe e cazzeggiamo un po'. Cominciamo con la piu' comune dei procedimenti, ovvero mettere un breakpoint su ogni call a GetWindowTextA o GetDlgItemTextA, ma questo programma ha solo GetWindowTextA quindi mettiamo un bp lì. Lanciamo eye.exe (all'inizio fa diverse call a GetWindowTextA, quindi invece di fare play ogni volta che si ferma, io ho disabilitato i bp all'inizio per riattivarli piu' tardi) e andiamo su Help e poi su Register e scriviamo qualcosa facendo un copia e incolla, e vediamo che il nostro Olly ci poppa. Andiamo avanti di una 20 di istruzioni e arriviamo in un punto in cui controlla quello che e' stato scritto: 

MOV ECX,DWORD PTR DS:[EDI+64]                 ;mette in ecx l'indirizzo dove c'è quello da noi scritto
MOV AL,BYTE PTR DS:[ECX]                          ;mette in al il primo carattere 
XOR ESI,ESI                                               ;azzera esi (fara' da contatore)
XOR EBP,EBP                                               ;azzera ebp
XOR EBX,EBX                                              ;azzera ebx
TEST AL,AL                                                ;controlla al se e' = 0
MOV DWORD PTR SS:[ESP+10],ESI                
JE SHORT eye.00485295                               ;se sì salta
CMP AL,61                                                 ;confronta al con la 'a'
JL SHORT eye.00485277                               ;salta se e' minore
CMP AL,70                                                 ;confronta al con la 'p'
JG SHORT eye.00485277                               ;salta se e' maggiore
CMP ESI,8                                                  ;confronta il contatore con 8
JGE SHORT eye.0048524C                             ;salta se e' maggiore o uguale
MOVSX EAX,AL                                           ;calcoli ....
SHL EBP,4                                           
LEA EBP,DWORD PTR SS:[EBP+EAX-61]
JMP SHORT eye.0048526F
CMP ESI,10
JGE SHORT eye.0048525D
MOVSX EDX,AL
SHL EBX,4
LEA EBX,DWORD PTR DS:[EBX+EDX-61]
JMP SHORT eye.0048526F
MOV EDX,DWORD PTR SS:[ESP+10]
MOVSX EAX,AL
SHL EDX,4
LEA EDX,DWORD PTR DS:[EDX+EAX-61]
MOV DWORD PTR SS:[ESP+10],EDX
INC ESI                                                     ;incrementa esi di 1
CMP ESI,14                                                ;confronta esi con 14
JE SHORT eye.00485295                               ;se e' uguale salta
JMP SHORT eye.0048527B
CMP AL,2D
JNZ SHORT eye.00485285

MOV AL,BYTE PTR DS:[ECX+1]                      ;mette in al il char successivo della stringa
INC ECX                                                    ;incrementa ecx
TEST AL,AL                                               ;confronta se la stringa e' finita
JNZ SHORT eye.00485233                            ;se no torna a inizio ciclo...


Bene, da qua scopriamo che il nostro serial deve per forza essere compreso tra la 'a' e la 'p', il che vuol dire che non contiene ne' numeri, ne lettere maiuscole, ne' caratteri extra. Notiamo anche che all'8 lettera fa dei calcoli diversi, e che il ciclo finisce quando il contatore arriva a 14, quindi il seriale giusto deve essere lungo 14 caratteri. Quando e' finito questo ciclo il programma va avanti ma provando a seguirlo anche parecchio non si nota nulla di particolare, quindi direi di tentare qualcos'altro. Il secondo tentativo che ho provato e' stato quello di cercare la stringa di ringraziamento se il seriale immesso fosse stato quello giusto, quindi sono andato su "Search for" poi su "All referenced text strings" e ho cercato la stringa "Thanks" e subito mi si ferma su una stringa "Thanks for registering!", doppio click e andiamo nella zona di codice dove viene usata quella stringa:

PUSH ESI
MOV ESI,ECX
MOV EAX,DWORD PTR DS:[ESI+5C]          ;mette in eax il valore di DS:0012FC40
TEST EAX,EAX                                     ;controlla se e' a 0
JNZ SHORT eye_unpa.004851F0              ;se si non jumpa
MOV EAX,DWORD PTR DS:[ESI+60]          ;mette in eax il valore di DS:0012FC44
TEST EAX,EAX                                     ;controlla se e' a 0
JNZ SHORT eye_unpa.004851F0              ;se si non jumpa
PUSH 31                                             ;qua pusha i parametri per la messagebox
PUSH eye_unpa.004F9B74 ; ASCII "Warning"
PUSH eye_unpa.0050140C ; ASCII "Pressing OK will unregister this copy of All-Seeing Eye."
CALL eye_unpa.004C957E                      ;call MessageBoxA
CMP EAX,2                                          
JE SHORT eye_unpa.00485207
MOV ECX,ESI
CALL eye_unpa.004BDD77
POP ESI
RETN
PUSH 0                                               ;se invece le 2 zone di memoria hanno un valore diverso
PUSH 0                                               ;dallo 0 il proggy arriva qua e passa questi parametri
PUSH eye_unpa.005013F4 ; ASCII "Thanks for registering!"         ;alla MessageBoxA
MOV ECX,ESI
CALL eye_unpa.004C957E
MOV ECX,ESI
CALL eye_unpa.004BDD77
POP ESI
RETN


Ecco, guardando questo pezzo di codice si direbbe che il fatto che il programma sia registrato o no dipenda dalla zona di memoria 0012FC44 e 0012FC40, ma provando a mettere un bp on access su quelle 2 zone di memoria non si nota nulla di particolare, quindi ho fatto un altro tentativo ancora. Stavolta sono partito cercando delle stringhe che non davano accesso a certe parti del programma perche' non si era registrati. Quindi ho cercato la stringa "Sorry" questa volta, anche perche' mi ricordavo alcune messagebox che mi uscivano per dirmi che non potevo fare certe azioni perchè non ero un utente registrato. Bene, stesso procedimento di prima, cerchiamo su "Search for" e troviamo diverse stringhe che contengono la parola "Sorry"... doppio click sulla prima:

MOV EAX,DWORD PTR DS:[50CF50]            ;mette in eax il valore contenuto in DS:[50CF50]
TEST EAX,EAX                                        ;controlla se e' a 0
JNZ SHORT eye_unpa.004077D9                ;se si non salta
MOV EAX,DWORD PTR DS:[50CF54]            ;mette in eax il valore contenuto in DS;[50CF54]
TEST EAX,EAX                                        ;controlla se e' a 0
JNZ SHORT eye_unpa.004077D9                 ;se si non salta
PUSH 0                                                  ;e passa questi parametri per la messagebox
PUSH 0
PUSH eye_unpa.004F97A0 ; ASCII "Sorry, this option is for registered users only."

Ancora una volta controlla 2 zone di memoria, e se sono a 0 il programma segue un percorso. se hanno un valore diverso dallo 0 il programma ne segue un altro. Ok, passiamo alla prossima stringa contenente "Sorry" (per farlo velocemente si usa la combinazione di tasti CTRL+L):

NOP
NOP
NOP
PUSH 30
PUSH eye_unpa.004FAFB8 ; ASCII "Buddy list full"
PUSH eye_unpa.004FAF84 ; ASCII "Sorry, unregistered users are limited to 4 buddies."
CALL eye_unpa.004C957E

Ok questa parte di codice e' un po isolata dal resto quindi probabilmente sara una parte di una call. Saltiamola e passiamo alla prossima stringa:


MOV EAX,DWORD PTR DS:[50CF50]                ;mette in eax il valore contenuto in DS[00CF50]
TEST EAX,EAX                                            ;controlla se e' a 0
JNZ SHORT eye_unpa.0046FD80                    ;se si non jumpa
MOV EAX,DWORD PTR DS:[50CF54]               ;mette in eax il valore contenuto in DS[00CF54]
TEST EAX,EAX                                           ;controlla se e' a 0
JNZ SHORT eye_unpa.0046FD80                   ;se si non jumpa e passa i successivi parametri
alla mb
PUSH 40030 
PUSH eye_unpa.004FFE0C     ;ASCII "Unregistered"
PUSH eye_unpa.004FFDD8     ;ASCII= "Sorry, unregistered users are limited to 1 channel."
PUSH 0 ; |hOwner = NULL
CALL DWORD PTR DS:[<&USER32.MessageBoxA>]       ;call MessageBoxA

Mmmm... di nuovo per dire questa stringa controlla la zona di memoria 50CF50 e 50CF54... interessante.. controlliamo un altra stringa per essere sicuri :D :

MOV EAX,DWORD PTR DS:[50CF50]              ;mette in eax il valore contenuto in DS:[50CF50]
TEST EAX,EAX                                         ;controlla se e' a 0
PUSH ESI                
MOV ESI,ECX
JNZ SHORT eye_unpa.004835EF                  ;se si non jumpa
MOV EAX,DWORD PTR DS:[50CF54]              ;mette in eax il valore contenuto in DS:[50CF54]
TEST EAX,EAX                                         ;controlla se e' a 0
JNZ SHORT eye_unpa.004835EF                  ;se si non jumpa
PUSH 0                                                   ;e passa questi parametri alla call
PUSH 0
PUSH eye_unpa.00500F10 ; ASCII "Sorry, searching by clan tag or part of name is for registered users only."
CaLL eye_unpa.004C94F7


Mmm.. quelle 2 zone di memoria hanno qualcosa di sospetto :)). Come si puo' notare dalle istruzioni, se quelle 2 zone di memoria contengono lo 0 il programma dice "Sorry, non puoi fare questo perche' non sei registrato bla bla bla", se contengono un valore invece... chissa' proviamo :D
Mettiamo un bp on access su quelle 2 zone di memoria, in modo da controllare quando vengono azzerrate e cercare di non lasciarle con il valore 0. Dopo aver messo i bp runniamo il programma, che ci poppa qua:

MOV DWORD PTR DS:[50CF54],EAX        ;mette in 50CF54 il valore di eax, che e' 0 in quel punto :)
CALL eye_unpa.004D85B5                    
CMP DWORD PTR DS:[50CF54],ESI         ;confronta 50CF54 con esi, che e' a 0 
MOV DWORD PTR DS:[50CF50],EAX        ;mette in 50CF50 il valore di eax, che ricordo e' 0 
JE SHORT eye_unpa.00489E0A              ;salta se 50CF54 = 0
CMP EAX,ESI 
JNZ SHORT eye_unpa.00489E16
MOV DWORD PTR DS:[50CF50],ESI        ;se salta arriva qua e mette in 50CF50 esi, ovvero 0
MOV DWORD PTR DS:[50CF54],ESI        ;mette in 50CF54 il valore di esi, ovvero 0 

Ok abbiamo trovato il primo punto dove si azzerra le 2 zone di memoria, e per fare in modo che questo non avvenga basta sostituire le ultime 2 istruzioni con:
MOV DWORD PTR DS:[50CF50],EDI
MOV DWORD PTR DS:[50CF54],EDI

Cioe' al posto di esi (che ha valore 0) gli mettiamo edi (che ha valore 79263024). Facciamo play e continuiamo ad andare avanti:

MOV ECX,DWORD PTR DS:[50CF54] 

Qua mette semplicemente in ecx il valore di 50CF54, che ha ancora il valore di esi (logicamente). Avanti ancora e ci compare una box: "Invalid or expired registration code. Would you like to renew now?". Qui il programma ha visto che le 2 zone di memoria non erano a 0, quindi presumendo che sia stato registrato ha controllato il serial (mooooolto probabilmente online, perche' non avrebbe senso controllarlo ogni volta che il programma viene avviato) ma siccome non c'è ci dice che e' invalido :D. Noi facciamo no e olly ci poppa qua:

MOV DWORD PTR DS:[50CF54],EDI            ;mette in 50CF50 edi, che e' a 0
MOV DWORD PTR DS:[50CF50],EDI            ;mette in 50CF54 edi, che e' a 0

Logicamente dopo aver scoperto che il serial e' invalido, si azzerra le 2 zone di memoria, se no avremmo i privilegi da user registrato lo stesso =D. Ok, anche qui per risolvere il problema basta fargli mettere esi al posto di edi, in quanto esi contiene un valore, quindi non e' a 0. Facciamo play e notiamo che il olly non ci poppa più, quindi ase non fa piu controlli sulle 2 zone di memoria. Proviamo a fare qualche comando da user registrato del tipo invitare qualcuno su un server... e funziona!!!! Tutto l'inghippo era attorno a quelle 2 zone di memoria, come sospettavo all'inizio :). Ora io avevo come zone di memoria di riferimento 50CF50 e 50CF54 ma non e' detto che possano cambiare per le successive versioni, anzi di sicuro cambieranno perche' ase e' un tool in continuo aggiornamento. Non finirò mai di ringraziare Xtremer per avermi passato quel unpacker kazzoso, veramente thx!!! Byez a tutti e divertitevi con ase :)

Crack di All Seeing Eye :)
Screenshoot del programma cracckato (chi vuole notare la differenza, la noti :D )




Sito ottimizzato per:
Browser: I.E.
Risoluzione: 1024 x 768
.:ReVeRsiNg:.     .:CoNTaCt Me:.     .:LiNks:.     .:ThaNksTo:.     .:FuCkTo:.