Il nostro primo Crack -
Update al 10/2003 |
||
Data |
by "Quequero" |
|
02/Oct/2003 |
Published by Quequero |
|
Accadono
cose che sono come domade. |
Questo tutorial e' stato scritto con lo scopo di essere lo starting point per tutti quelli che volessero avvicinarsi al reversing, buona fortuna ragazzi! |
Non c’è al mondo nulla di così difficile per l’uomo come percorrere la strada che lo conduce a se stesso. (Herman Hesse) |
.... |
|
.... |
Difficoltà |
(X)NewBies ( )Intermedio ( )Avanzato ( )Master |
Introduzione |
Tools usati |
URL o FTP del programma |
Notizie sul programma |
Essay |
Esaminiamo cosa c'e' all'indirizzo 004074A6:
004074A6 MOV EAX,DWORD PTR SS:[ESP+318]
004074AD PUSH 30
004074AF PUSH roger.004130D8 // Title
= "Roger Wilco"
004074B4 PUSH roger.004156E8 // Text
= "The registration key you entered is invalid"
004074B9 PUSH EAX
004074BA CALL DWORD PTR DS:[<&USER32.MessageBoxA>>
Nulla di buono a quanto pare... E' proprio
il pezzo di programma che fa comparire la messagebox di registrazione fallita
(che in gergo viene chiamato: Beggar Off), ma proviamo a fare una cosa... Facciamo
in modo che il programma NON effettui quel salto e vediamo cosa succede.
Per prima cosa portatevi col mouse all'indirizzo 00407431, premete F2, se la
riga si fa rossa allora abbiamo piazzato un nuovo breakpoint, ma quello vecchio
non ci serve piu' percio' premete Alt+B e cancellate con DEL (o CANC) tutte
le righe dove sta scritto "MessageBoxA", deve restare solo il breakpoint
che abbiamo appena piazzato... Tornate in RogerWilco (se la finestra non appare
allora vi siete scordati che il debugger ha congelato il programma, premete
un paio di volte sull'icona Play poi tornate in Roger :)) e clickate su register...
Zack, il debugger si ferma dove volevamo noi, guardate ora nella finestra a
destra dove stanno i nomi dei registri (EAX, ECX, EBX, EDX...), se guardate
poco piu' in basso c'e': CPAZSTD... Ecco questo e' il flag register e Z e'
proprio lo zero flag e come potete vedere e' a 0 (unsettato), infatti Ollydbg
appena sotto la finestra del codice ci dice "Jump is taken", facciamo
in modo che questo jump non avvenga, clickate sullo 0 di fianco alla Z e premete
invio (oppure clickate col destro sullo 0 e scegliete "Set"), lo
0 e' diventato 1? Se si perfetto! Guardate sotto la finestra del codice: "Jump
is NOT taken", ottimo! Premete play e guardate, il programma risulta registrato
:))).
Ma se provate a chiudere il programma e a riaprilo... Allora noterete che torna
ad essere non registrato... Il motivo e' chiaro, all'avvio il programma prende
il seriale fittizio e vede che e' falso, cosa possiamo fare? Cerchiamo il seriale
a questo punto!
Vedrete che sara' semplice, ora sapete anche come invertire i salti! Quindi
facciamo ancora un po' di backtrace e vediamo dove viene generato questo bel
numerello, usiamo un po di zen... Trasformare il nome in un numero puo' essere
un'operazione che richiede molte istruzioni quindi magari avranno messo questa
conversione in una subroutine richiamata da una call, avviamo di nuovo RogerWilco
dentro Olly... Premiamo play e inseriamo il seriale, i breakpoint sono stati
salvati, ottimo, guardiamo in alto e all'indirizzo 004073F0 troviamo una call...
Mettiamo un breakpoint con F2 su quella CALL, magari siamo fortunati, premiamo
play, reinseriamo il seriale e zack... Siamo sulla call, premete F8 una solta
volta, in questo modo eseguite la subroutine SENZA entrarci dentro, F8 viene
anche detto single-step perche' fa eseguire una riga di codice alla volta.
Guardate la finestra dei registri a destra... EAX, ECX ed EDX sono in rosso,
vuol dire che la sub-routine sulla quale siamo passati li ha modificati. Vediamo
se dentro questi registri c'e' qualcosa, scrivete nella commandline: d eax,
vuol dire: dump eax, cioe': fammi vedere cosa c'e' dentro eax. Ed ora guardate
nella finestra in basso a sinistra:
00416A10 52 64 47 44 2D
35 45 52 72 2D 32 72 32 51 2D 36 RdGD-5ERr-2r2Q-6
00416A20 62 67 45 00 00 00 00 00 00 00 00 00 00 00 00 00 bgE.............
Quel numero: RdGD-5ERr-2r2Q-6bgE (ovviamente diverso se avete inserito
un nome diverso dal mio) non potrebbe essere il nostro seriale appena generato
dalla call??? Boh, proviamo! Premete play, mettetelo e clickate register, se
il debugger si ferma premete play di nuovo.
Wow! ce l'abbiamo fatta il seriale e' proprio questo!!! Come avevamo ipotizzato
la CALL ha generato il numero per il confronto col nostro seriale e noi l'abbiamo
pescato con le mani nel sacco :), terminiamo qui? Naaaa cerchiamo adesso di
capire COSA e' successo dalla call in poi.
Appena dopo la call, come potete vedere con Olly, EAX non contiene il seriale
bensi un numero: 00416A10, questo numero indica l'indirizzo in memoria nel
quale si trova il seriale, per verificarlo digitate appena dopo la call: "d
00416A10" nella commandline, nella finestra in basso troverete esattamente
il nostro seriale. Il seriale e' numero lungo 19 caratteri che ovviamente non
entrerebbe dentro EAX che e' grande soltanto 32bit (cioe' 4 byte), e' piu'
convienente allora dire al programma dove si trova in memoria, in questo modo
ne possiamo prendere un pezzetto alla volta per esaminarlo, ed e' quello che
succede esattamente nel nostro caso. Quando un registro contiente un indirizzo
di memoria, si dice che quel registro punta ad una locazione, nel nostro caso
eax PUNTA al seriale.
Prima di continuare spieghiamo l'ultima istruzione della serata: MOV, come
potete immaginare significa MOVE, cioe' muovi e si usa in questa maniera:
mov eax, ebx //
Copia il valore che sta in ebx dentro eax
mov ebx, 12 // Copia il numero 12 dentro ebx
mov eax, [ebx]
// Copia in eax il valore puntato da
ebx
Spieghiamo l'ultimo caso: immaginate
che ebx punti al seriale, quindi ebx = 00416A10, se io facessi:
mov eax, ebx
allora copierei in eax il valore che sta in ebx, percio' eax = ebx = 00416A10,
ma se invece che copiarne il valore volessi mettere dentro eax il seriale?
Beh dovrei dire al programma di copiare in eax quello che si trova all'indirizzo
di memoria contenuto da ebx, e si fa cosi:
mov eax, [ebx]
che sarebbe equivalente a scrivere:
mov eax, [00416A10]
non dovrebbe essere troppo complicato... Ma c'e' una cosa, con le due istruzioni
qui sopra muoviamo in eax 4byte dalla locazione 00416A10, e se volessimo avere
nel registro un byte alla volta? Non sarebbe difficile, tutti e 4 i general
purpose registers possono essere suddivisi in registrini piu' piccoli, ecco
come:
eax - 32bit cioe' 4 byte
ax - 16 byte cioe' 2 byte
ah, al - 8 bit ciascuno, cioe' un byte
Ecco quindi che copiare 2 byte puntati da ebx a eax diventa:
mov ax, [ebx]
// Copia in ax i primi due byte puntati da ebx (ax e' grande 16bit percio'
piu' di due byte non ci entrano)
spostarne uno:
mov al, [ebx]
// Copia in al il primo byte puntato da ebx (al e' grande 8bit percio' piu'
di un byte non ci entra)
Lo stesso vale per gli altri, avremo quindi "ebx, bx, bh, bl", "ecx,
cx, ch, cl", "edx, dx, dh dl", la H sta per "High",
la L per "Low", vi faccio un disegnino per chiarirvi le idee:
|---AH---|---AL---|
|-------AX--------|
bit
31 |---------------EAX----------------|
bit 0
NB: Questa suddivisione vale sono per i 4 general purpose registers, gli altri:
ESI, EDI, EBP, ESP, possono essere suddivisi soltanto in parti da 16bit l'una:
ESI, SI; EDI, DI; EBP, BP; ESP, SP e cosi via.
Un esempio pratico: dentro OllyDbg prendete un registro qualunque nella finestra
di destra, ad esempio in questo istante EAX contiene 00416A10 percio': eax
= 00416A10, ax = 6A10, ah = 6A, al = 10.
Come vedete e' semplicissimo. Ora che conoscete piu' nel dettaglio i registri
e sapete cosa vuol dire che un registro "punta a", possedete tutti
gli strumenti necessari per studiare la call qui sotto e crackare il vostro
primo programma:
004073F0 CALL roger.00407120
; Questa e' la call che crea il seriale, dopo di essa
EAX punta al vero seriale
004073F5 ADD ESP,4
004073F8 MOV ESI,EAX ; Copia in ESI l'indirizzo
di memoria contenuto in EAX (quindi ora anche ESI punta al seriale)
004073FA LEA ECX,DWORD PTR SS:[ESP+110] ;
ECX punta al nostro seriale (fate "d ecx" nella commandline dopo
questa riga)
00407401 MOV
DL,BYTE PTR DS:[ECX] ; Copia un byte del valore puntato
da ECX (il nostro seriale) in DL
00407403 MOV BL,BYTE PTR DS:[ESI] ; Copia
un byte del valore puntato da ESI (il vero seriale) in BL
00407405 MOV AL,DL ; Copia in AL un byte
del vero seriale
00407407 CMP DL,BL ; Confronta quindi un
byte del seriale vero con una cifra del nostro
00407409 JNZ SHORT roger.00407429 ; Se sono
diversi vai verso la Beggar Off
0040740B TEST AL,AL ; AL = 0? (Il seriale
e' finito)
0040740D JE SHORT roger.00407425 ; Se si
allora il seriale e' finito
0040740F MOV DL,BYTE PTR DS:[ECX+1] ; Copia
in DL il byte successivo del nostro seriale
00407412 MOV BL,BYTE PTR DS:[ESI+1] ; Copia
in BL il byte successivo del nostro seriale
00407415 MOV AL,DL ;
Copia in AL un byte del vero seriale
00407417 CMP DL,BL ; Anche questa cifra e'
uguale?
00407419 JNZ SHORT roger.00407429 ; No? Vai
verso la beggar off
0040741B ADD ECX,2 ; Altrimenti aumenta ECX
di 2
0040741E ADD ESI,2 ; E ESI di 2
00407421 TEST AL,AL ; Il seriale e' terminato?
00407423 JNZ SHORT roger.00407401 ; No? Allora
continua ad esaminarlo
Note finali |
Saluto e ringrazio AndreaGay, tutti gli amici di #crack-it, #ahccc, #fogna, #asm, i fratellini Spp e quelle 7 tipe che ieri al pub si sono tanto divertite con me ihihihih :)))
Disclaimer |
Vorrei ricordare che il software va comprato e non rubato, dovete registrare il vostro prodotto dopo il periodo di valutazione. Non mi ritengo responsabile per eventuali danni causati al vostro computer determinati dall'uso improprio di questo tutorial. Questo documento è stato scritto per invogliare il consumatore a registrare legalmente i propri programmi, e non a fargli fare uso dei tantissimi file crack presenti in rete, infatti tale documento aiuta a comprendere lo sforzo che ogni sviluppatore ha dovuto portare avanti per fornire ai rispettivi consumatori i migliori prodotti possibili.
Reversiamo al solo scopo informativo e per migliorare la nostra conoscenza del linguaggio Assembly.