> 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 )
|