Cd-Edit |
|
|
26/03/00 |
by "AndreaGeddon" |
|
|
Published by Quequero |
|
Ecco che vi presento il primo tutorial della sezione dedicata ai corsi per i NewBies totali, tutorial leggero ed esauriente, ottimo per iniziare a capire come funziona una protezione basata sul nome/serial che troverete molto spesso :) |
||
| UIC's form |
|
UIC's form |
Difficoltà |
(X)NewBies (X)Intermedio ( )Avanzato ( )Master |
Eccovi la spiegazione di come viene generato il serial per Cd-Edit. Cercherò di spiegare tutti i vari punti in modo che anche il più newbie lo possa capire.
Introduzione |
Trovare il serial di questo programma è un lavoro di 5 secondi, la routine di generazione del serial pensavo fosse difficile, invece no.
Tools usati |
- SoftIce
URL o FTP del programma |
E' il Quarto Corso Newbies sul sito di Quequero
Notizie sul programma |
A dire la verità non so manco a che cacchio serve sto programma del cavolo. Comunque la protezione è la solita solfa Nome/Serial.
Essay |
Come trovare il serial lo sapete già, visto che Quequero ha postato la soluzione. Io vi dico un trucchetto più semplice e veloce: avviate il programma, non andate su "register" nella schermata iniziale, ma entrate nel programma, andate sul menù ?->Register CdEdit, inserite un nome e numero casuale. Adesso settate col SoftIce un bpx su getwindowtexta, e premete "Register". Il Sice popperà. Non fatevi ingannare, la Api getwindowtexta in questo caso non serve proprio a nulla. Comunque, adesso che siete ne Sice, premete F12 per tornare al processo di CD-Edit e fate una ricerca di stringa sul serial falso che avete inserito. Lo potete fare col comando:
s 0 l FFFFFFFF '111222333444'
okay, il SoftIce troverà la stringa in memoria, e se guardate bene qualche riga sotto il serial finto c'è un trafiletto di numerelli strani.... segnateli ed inseriteli come serial. Funziona? Certo. Il serial fishing è tutto qui. Ora passiamo alle cose serie, al reversing della routine di generazione del serial.
Iniziamo inserendo un nome e serial a caso. Nel mio caso inserisco:
AndreaGeddon
111222333444
vado a cercare il serial e trovo:
284681884195
che guarda caso è lo stesso numero di caratteri del mio nome. Allora facciamo un pò di prove: se inserisco Andrea come nome, il serial generato non è di 6 char ma di 12. Se inserisco AndreaG il serial è di 14, insomma, dopo un pò di tentavi si arriva facilmente alla conclusione che se il nome è da 9 lettere in su, allora il serial avrà lo stesso numero di char, mentre se i char del nome sono meno di 9, il programma raddoppia il nome e ci calcola il serial. Questo vuol dire che il serial per Andrea sarà lo stesso che per AndreaAndrea. Comunque, ora abbiamo una minima idea di quello che succede: il prog prende il nome lettera per lettera e ci calcola il serial. Ora ci resta solo da scoprire come viene calcolato. Bene, settiamo un BPX HMEMCPY e registriamoci. il softice popperà. Disabilitate il breakpoint appena inserito (con bd *), premiamo sette volte F12 per tornare al processo del CD-Edit ed iniziamo a steppare. Ci troveremo un pò di RET vari, eseguiamoli tutti fino a che arriviamo alla linea 004757FC. Da qui inizierà la nostra indagine. Dobbiamo individuare dove viene generato il serial. Allora, fate come vi ho scritto sopra, cioè il break su Getwindowtexta e trovate il serial. Ora, la locazione dove si trovano il serial finto e quello vero è 00CAD134. Lasciate la data window su questa locazione, uscite da softice, levate il break su getwindowtexta e mettetene uno su hmemcpy. Prima di registrarvi inserite Nome e Serial diversi da quelli che c'erano prima, altrimenti in memoria vi ritroverete gli stessi numeri e non vedrete cambiamenti. Inserite entrambi da 12 caratteri, come me, così ritroverete le stesse cose che vi scrivo. Ecco un pò di codice:
:004757FC cmp dword ptr [ebp-04], 00000000
dopo i RET arriviamo qui:00475800 je 00475816
:00475802 lea edx, dword ptr [ebp-08]
:00475805 mov eax, dword ptr [ebx+000001EC]
:0047580B call 0041EA00
prende il numero finto:00475810 cmp dword ptr [ebp-08], 00000000
:00475814 jne 0047584E
......
:0047584E lea edx, dword ptr [ebp-04]
:00475851 mov eax, dword ptr [ebx+000001E4]
:00475857 call 0041EA00
prende il nome:0047585C mov eax, dword ptr [ebp-04]
:0047585F mov edx, 004759B0
:00475864 call 00403C38
:00475869 jne 004758A5
......
:004758A5 lea edx, dword ptr [ebp-04]
:004758A8 mov eax, dword ptr [ebx+000001E4]
:004758AE call 0041EA00
prende dei puntatori:004758B3 mov eax, dword ptr [ebp-04]
:004758B6 lea edx, dword ptr [ebp-0C]
:004758B9 call 00473B40
al posto del nome compare il serial giusto!:004758BE mov eax, dword ptr [ebp-0C]
:004758C1 push eax
Stavate eseguendo questo codice con la data window su 00CAD134? Allora avrete visto che in corrispondenza delle call che ho commentato sono comparsi prima il numero inserito, poi il nome, poi dei valori e alla fine sparisce il nome e compare il serial giusto. Quindi il serial viene generato nella CALL alla linea 004758B9. usciamo da SoftIce, registriamoci di nuovo, ma stavolta quando arriviamo alla linea 004758B9 invece di premere F10 premiamo F8 per tracciare la call, e arriveremo alla linea 00473B40. Da qui iniziamo a steppare fino ad arrivare al seguente codice.
:00473BD7 mov eax, dword ptr [ebp-1C]
mette in eax il puntatore al nome:00473BDA xor ebx, ebx
azzera ebx:00473BDC mov bl, byte ptr [eax]
mette in BL il primo char del nome:00473BDE mov eax, dword ptr [ebp-04]
in eax un altro puntatore al nome:00473BE1 call 00403B28
con questa call ottiene il numero di volte da elaborare il char (all'inizio 0Ch):00473BE6 sub eax, dword ptr [ebp-0C]
decrementa il numero di volte da elaborare il char:00473BE9 lea eax, dword ptr [eax+8*eax]
[eax| = numero di volte * 8 + numero di volte:00473BEC mov ecx, 00000003
|:00473BF1 cdq
| estende la dword eax in una quadword eax+edx:00473BF2 idiv ecx
| divide il numero contenuto in eax+edx per ecx (cioè per 3):00473BF4 add ebx, eax
aggiunge il risultato della divisione al relativo char del serial:00473BF6 cmp ebx, 00000009
controlla se il risultato di tutto questo calcolo è <= 9:00473BF9 jle 00473C82
se lo è salta:00473BFF lea edx, dword ptr [ebp-14]
:00473C02 mov eax, ebx
muovi il risultato in eax:00473C04 call 004070C4
trasforma il risultato da esadecimale a decimale:00473C09 jmp 00473C82
eax adesso punta alla locazione dove ci sarà il numero decimale:00473C0B xor edi, edi
:00473C0D lea eax, dword ptr [ebp+FFFFFDE4]
:00473C13 mov edx, dword ptr [ebp-14]
:00473C16 call 004075A0
:00473C1B xor edx, edx
:00473C1D push ebp
:00473C1E push 00473C71
:00473C23 push dword ptr fs:[edx]
:00473C26 mov dword ptr fs:[edx], esp
:00473C29 mov eax, dword ptr [ebp-14]
:00473C2C call 00403B28
:00473C31 mov esi, eax
:00473C33 dec esi
:00473C34 test esi, esi
:00473C36 jl 00473C5D
:00473C38 inc esi
:00473C39 lea ebx, dword ptr [ebp+FFFFFDE4]
:00473C3F lea eax, dword ptr [ebp+FFFFFDE0]
:00473C45 mov dl, byte ptr [ebx]
:00473C47 call 00403A50
:00473C4C mov eax, dword ptr [ebp+FFFFFDE0]
:00473C52 call 004070F4
:00473C57 add edi, eax
:00473C59 inc ebx
:00473C5A dec esi
:00473C5B jne 00473C3F
:00473C5D lea edx, dword ptr [ebp-14]
:00473C60 mov eax, edi
:00473C62 call 004070C4
:00473C67 xor eax, eax
:00473C69 pop edx
:00473C6A pop ecx
:00473C6B pop ecx
:00473C6C mov dword ptr fs:[eax], edx
:00473C6F jmp 00473C82
:00473C71 jmp 00403154
:00473C76 call 004033F8
:00473C7B jmp 00473CB8
:00473C7D call 004033F8
:00473C82 mov eax, dword ptr [ebp-14]
:00473C85 call 004070F4
:00473C8A cmp eax, 00000009
:00473C8D jg 00473C0B
:00473C93 lea eax, dword ptr [ebp-10]
:00473C96 mov edx, dword ptr [ebp-14]
:00473C99 call 00403B30
:00473C9E inc [ebp-0C]
:00473CA1 inc [ebp-1C]
:00473CA4 dec [ebp-18]
:00473CA7 jne 00473BD7
questa è la routine in cui viene generato il seriale. La parte che mi è servita è stata solo quella che ho commentato. Dopo un pò di stepping mi sono segnato i primi quattro valori che ottengo da quei calcoli. Per capire meglio questi calcoli, eccovi un pò di formule comprensibili:
inizio:
valore_1 = lunghezza_del_nome * 8 + lunghezza_del_nome
dividi valore_1 per 3
valore_2 = valore_2 + char
converti valore_2 da esadecimale a decimale
decrementa lunghezza_del_nome
char = prossimo char del nome
vai a inizio
beh, mica tanto più comprensibili.... eccovi un pò di esempi per chiarire del tutto i vostri dubbi:
facciamo i calcoli per le prime 4 lettere del mio nome
-- A 0Ch * 8 + 0Ch = 6Ch
6Ch / 3 = 24h
24 + A = 65h (con A = 41)
65 hex = 101 dec
-- n 0B * 8 + 0B = 63
63 / 3 = 21
21 + n = 8F (con n = 6E)
8F hex = 143 dec
-- d 0A * 8 + 0A = 5A
5A / 3 = 1E
1E + d = 82 (con d = 64)
82 hex = 130 dec
-- r 9 * 8 + 9 = 51
51 / 3 = 1B
1B + r = 8D (con r = 72)
8D hex = 141 dec
okay, visto che ora è tutto molto più semplice? Però ancora non abbiamo finito. Io per le lettere A n d r ho ottenuto i rispettivi valori decimali 101, 143, 130, 141. Adesso invece di rimettermi a steppare come uno scemo mi sono soffermato a pensare un attimo: "che relazione può esserci tra questi numeri e quelli del serial giusto"? Mentre stavo per ricominciare a steppare mi è venuta in mente la soluzione:
101 = 1+0+1 = 2
143 = 1+4+3 = 8
130 = 1+3+0 = 4
141 = 1+4+1 = 6
ed ottengo 2846 che guarda un pò sono i primi 4 char del serial! Ho rifatto i conti per tutti i char del nome e mi è venuto fuori il serial completo. Certo che qui sapendo il serial in anticipo, abbiamo potuto "barare" in questo modo, se non avessi saputo il serial avrei dovuto steppare e steppare per trovare la routine che sommava le varie cifre decimali. Ma dopotutto sono pigro, e se il programma lo permette, io baro! Ecco così svelato il mistero del serial di Cd-Edit.
Ps. se qualcuno di voi si è registrato per sbaaglio e vuole tornare non registrato, andate nel registro alla chiave:
HKEY_LOCAL_MACHINE\Software\Stefano Falda\CD Edit\
e cancellate il valore "Code".
Eccovi il keygen che ho scritto in asm (cioè, in TASM). Siccome non avevo tempo, l'ho scritto senza mettere alcuni accorgimenti, tipo il controllo dei caratteri digitati, quindi scrivete solo le lettere del nome e battete invio (non premete tasti funzione, spazio e altre cagate, altrimennti il serial verrà fuori errato). Non fate caso al fatto che è scritto di merda, l'importante è che funziona.
BEGIN OF CODE_________________________________________________________________________________
;direttive del compilatore
.386
.MODEL SMALL
.STACK 400h
.DATA
;definisco le stringhe e variabili che userò
Titolo
DB 13,10,'KeyGenerator per CDedit ',13,10,'$'
Titolo2
DB 13,10,'Scritto da AndreaGeddon ',13,10,'$'
Prompt
DB 13,10,'Inserisci il nome: (tra 9 e 14 char) ',13,10,'$'
Serial
DB 13,10,'00000000000000000000',13,10
SerialTitle
DB 13,10,'Il tuo serial: ',13,10,'$'
Buffer
DB 13,10,'0000',13,10
Nome
DB 13,10,'Abcdefghijklmnopq',13,10
Num
DB 13,10,'00',13,10
Errore
DB 13,10,'Il nome deve essere tra 9 e 14 caratteri!',13,10,'$'
.CODE
start:
mov ax, @data
;metto nel registro DS (data segment)
mov ds, ax
;il puntatore alla sezione DATA
;ora scriviamo le due righe di titolo iniziale
mov dx, OFFSET Titolo
;metti in dx il puntatore alla 1° stringa
mov ah, 9
;indica la funzione 9...
int 21h
;per l'INT 21h, cioè "Print String"
mov dx, OFFSET Titolo2
;adesso printiamo la seconda stringa
mov ah, 9
int 21h
;ora scriviamo il prompt di richiesta nome
mov dx, OFFSET Prompt
mov ah, 9
int 21h
;adesso dobiamo prendere il nome
xor ecx, ecx
;azzero ecx che userò come contatore
PrendiNome:
mov ah, 1
;qui chiamo la funzione 1...
int 21h
;dell' INT 21, cioè "Prendi Char"
cmp al, 0Dh
;controllo se è stato battuto invio
je Calcoli
;se si, il nome l'abbiamo preso
mov [Nome+ecx], al
;mette il carattere preso nella variabile Nome
inc ecx
;incrementa il contatore
jmp PrendiNome
;prendi un altro char
;adesso inizia la sezione dei calcoli:
Calcoli:
;restrizioni sul nome
mov [Nome+ecx], 00
;aggiunge 00 alla fine del nome (termiatore)
cmp ecx, 09
;il nome è maggiore di 9 char?
jl BadExit
;se no, termina con errore
cmp ecx, 0Eh
;il nome è minore di 14 char?
jg BadExit
;se no, termina con errore
xor edi, edi
;azzero edi che userò come contatore
mov byte ptr [Num], cl
;salvo il contatore nella variabile Num
;inizia calocli veri e propri
Inizio:
xor eax, eax
;azzero eax che mi servirà presto
mov al, byte ptr [Num]
;metto il contatore in al
mov ecx, 08
;metto in ecx 8...
imul ecx
;e moltiplico eax per ecx
add al, byte ptr [Num]
;aggiungo al risultato il contatore
mov ecx, 03
;metto il divisore (3) in ecx...
cdq
;azzero edx
idiv ecx
;...divido eax per ecx (per 3)
add al, byte ptr [Nome+edi]
;aggiungo il char
corrente del nome al risultato
call Converti
;chiamo la procedura che converte il numero da hex a dec
xor esi, esi
;azzero esi e lo uso come contatore generale
xor eax, eax
;ormai lo sapete
Confr:
cmp byte ptr [Buffer+esi], 0FFh ;controlla se la cifra corrente del numero decimale appea convertito è FF
je Decimal
;se lo è, abbiamo finito di sommare
add al, byte ptr [Buffer+esi]
;se non lo era,
sommiamola ad eax
inc esi
;incrementa il contatore
jmp Confr
;ripeti
Decimal:
cmp eax, 09
;vediamo se la somma delle cifre è minore di 9
jle Finito
;se lo è, abbiamo finito il calcolo per la cifra e quindi salta
call Converti
;se non lo è, riconverti (sarà 0A, 0B, 0C etc.)
xor eax, eax
;riazzera l'accumulatore
xor esi, esi
;e il contatore
jmp Confr
;torna a sommare le cifre
Finito:
add eax, 30h
;se la cifra è quella finale (da 0 a 9) aggiungigli 30 ed otterremo
il corrispondente ascii
mov byte ptr [Serial+edi], al
;muovi il numero del
serial attuale nella variabile Serial
dec byte ptr [Num]
;decrementa il numero di cifre da calcolare ancora
inc edi
;incrementa il contatore generale
cmp byte ptr [Num], 00
;se il numero di cifre rimaste da calcolare non è zero...
jne Inizio
;torna all'inizio e calcola la prossima cifra
mov byte ptr [Serial+edi], '$'
;altrimenti aggiungi il
terminatore al serial ($)
mov dx, OFFSET SerialTitle
;così lo possiamo mostrare
mov ah, 9
int 21h
mov dx, OFFSET Serial
mov ah, 9
int 21h
mov ah,4ch
;Fuzione: termina programma
mov al,0
;return code = 0
int 21h
;termina il programma
;uscita in caso di
errore
BadExit:
mov dx, OFFSET Errore ;mostra l'errore
mov ah, 9
int 21h
mov ah, 4Ch
;e termina il programma
mov al, 0
int 21h
;---------------------------------------------------------------
;procedura che converte da hex a dec
;richiede in eax il numero da convertire, e restituisce
;nella variabile Buffer il valore dec.
;nota che questa routine non va bene per le normali coversioni perchè
;vi restituirà il numero decimale con le cifre invertite, ma siccome qui ci
;interessa la somma delle singole cifre del numero decimale, non ha importanza
;se sono dritte o
invertite
Converti proc
xor ebx, ebx ;ebx lo uso come contatore
mov ecx, 0Ah ;metto in ecx il divisore (10 decimale)
Riconv:
cdq
;estendi la dword eax in una quadword eax+edx (praticamente azzero
edx)
idiv ecx
;dividi eax per 10dec
mov byte ptr [Buffer+ebx], dl
; muovi il resto della
divisione in buffer
inc ebx
; incrementa il contatore
cmp eax, 00
; la cifra in eax è 0?
jne Riconv
; se non lo è continua la conversione
mov byte ptr [Buffer+ebx], 0FFh ; metti FF alla fine di Buffer (lo uso come terminatore)
ret
; ritorna
Converti endp
;----------------------------------------------------------------
End Start
END OF CODE____________________________________________________________________
AndreaGeddon rules again !!!!
Note Finali |
Spero che questo tute sia alla portata di tutti, newbies e non. Saluto tutti gli amici della mailing list.
Disclaimer |
Home
Anonimato Assembly
CrackMe ContactMe Forum Iscrizione
Lezioni Links Linux NewBies News Playstation
Tools Tutorial Search
UIC Faq