Troviamo il seriale in GIF Movie Gear 2.51
Un pò di reversing


 

by "AndreaGeddon "

 

 

UIC's Home Page

 



Altro tutorial indicato ai newbies, il serial è molto semplice da trovare e può essere un buon allenamento

 
UIC's form
Home page: andreageddon.8m.com
E-mail: [email protected]
UIC's form

Difficoltà

(x)NewBies (x)Intermedio ( )Avanzato ( )Master

 

Vediamo cosa fa l'algoritmo e generiamoci un serial valido, e vediamo anche come crakkarlo.


Trovaimo il seriale di GIF Movie Gear 2.51
Un pò di conversione dec2hex
Written by AndreaGeddon

Tools usati

SoftIce 4.00

RegMon

APIspy

Un hex editor qualunque

URL o FTP del programma

Dunno... me lo ha passato un amico.

Notizie sul programma 

Un animatore di GIF semplice e rapido. Il programma consiste in un solo file eseguibile di 362k. Ha una scadenza a tempo, della durata di 30 giorni.

Essay

PUNTO PRIMO: IL CRACKING

Per prima cosa vogliamo crakkarlo per fargli credere di essere registrato anche con un seriale fake. Poi vedremo come rubare un seriale.

La prima cosa da fare è breakare su GetWindowTextA.

 

:00428FFB    call ebx      call a getwindowtexta

:00428FFD    lea eax, dword ptr [esp+78]

:00429001    push 00000064

:00429003    push eax

:00429004    push 00000450

:00429009    push esi

:0042900A    call edi

:0042900C    push eax

:0042900D    call ebx      di nuovo getwindowtexta

:0042900F    lea ecx, dword ptr [esp+78]   carica il Nome in ecx

:00429013    lea edx, dword ptr [esp+14]   carica il serial in edx

:00429017    push ecx                       li salva

:00429018    push edx                       e li passa alla call

:00429019   call 00428D90                  call a una serie di calcoli

:0042901E    add esp, 00000008              aggiungi 8 allo stack pointer

:00429021    test eax, eax                  controlla eax

:00429023    je 004290CF                    se eax=0 il codice era errato, quindi salta

 

Se avete inserito un serial finto, il jump vi manderà ad eseguire la message box di errore. Se non eseguite il jump, alcune ricge sotto si vede che vengono fatte delle chamate al registro, viene creata una chiave e vi vengono impostati 2 valori (nome e serial). Noppando il salto alla linea 00429023 il programma accetterà per buono il serial finto, e lo scriverà nel registro. Però non è ancora finita. Infatti ci sono altri controlli. Se riavviamo il prog ci dice di registrare, se andiamo su help->about ci dice di registrare. Evidentemente ci sono altri controlli. Carichiamo il regmon ed avviamo il programma. Vediamo che tra le ultime chiavi lette ci sono anche quelle corrispondenti a nome e serial, cioè:

HKEY_CURRENT_USER\Software\gamani\GIFMovieGear\2.0\RegName

HKEY_CURRENT_USER\Software\gamani\GIFMovieGear\2.0\RegCode

Vengono chiamate una volta sola. Adesso dopbbiamo trovare il punto nel codice in cui vengono chiamate, cosa che il regmon non ci dice, ma APIspy si. Quindi

carichiamo apispy, carichiamo come processo il movgear e mettiamo da spiare l'API RegQueryValueExA. Eseguiamolo e avremo la lista di alcune linee di codice in cui viene chiamata quest'api. Se andiamo a fare il confronto con la lista nel regmon, vediamo che le regqueryvalue ai valori che ci interessano sono la pnultima e la terzultima. Così nell'apispy le corrispondenti saranno anche la penultima e la terzultima. Ricordate che in apispy una blocco di due api tipo:

RegQueryValueExA( )

RegQueryValueExA = 0

Va considerato come un'unica chiamata. Arriviamo quindi a trovare le linee di codice in cui vengono chiamate le due chiavi per ricontrollare il Nome e Serial. Il codice è il seguente:

 

:00428EA5    call esi       prima chiamata a RegName

:00428EA7    test eax, eax

:00428EA9    jne 00428F42

:00428EAF    lea ecx, dword ptr [esp+10]

:00428EB3    lea edx, dword ptr [esp+78]

:00428EB7    push ecx

:00428EB8    push edx

:00428EB9    push eax

:00428EBA    push eax

:00428EBB    mov eax, dword ptr [esp+1C]

:00428EBF    push 004401D0

:00428EC4    push eax

:00428EC5    mov dword ptr [esp+28], edi

:00428EC9    call esi      chiamata a RegCode

:00428ECB    test eax, eax     controlla eax

:00428ECD    jne 00428F42     se eax=0 la chiave è stata letta

:00428ECF    lea ecx, dword ptr [esp+78]  questo è uguale al precedente

:00428ED3    lea edx, dword ptr [esp+14]  frammento di codice:

:00428ED7    push ecx                      salva i valori del nome e serial

:00428ED8    push edx                      e li passa alla call

:00428ED9    call 00428D90                 call a calcoli

:00428EDE    add esp, 00000008       

:00428EE1    test eax, eax

:00428EE3    je 00428F42                salta se il codice era errato

 

Adesso basta noppare anche questo jump, ed il programma sarà registrato al 100%. Fortunatamente gli altri controlli sul serial finivano tutti qui, quindi non dobbiamo cercare altri punti di controllo. E questo è tutto per il craking. Vediamo ora come risolvere l'algoritmo di generazione del serial.

 

PUNTO SECONDO: TROVIAMO IL SERIAL

Crakkare non ci basta, vogliamo trovare il serial giusto (e magari scrivere anche un keygen), quindi ricominciamo. Rimettiamo un break su getwindowtexta. Ci ritroviamo nella prima parte di codice che ho scritto sopra. Arriviamo fino a:

00429019      call     00428D90

ed entriamo nella call.Arriviamo a:

 

:00428D90    push ebx

:00428D91    push ebp

:00428D92    mov ebp, dword ptr [esp+10]

:00428D96    push esi

:00428D97    push edi

:00428D98    cmp byte ptr [ebp+00], 6D   compare primo char del serial con 6D, cioè con "m"

:00428D9C    jne 00428E44                 se è diverso salta a Errore

:00428DA2    cmp byte ptr [ebp+01], 76   compare secondo char con 76, cioè "v"

:00428DA6    jne 00428E44                 se è diverso salta a Errore

:00428DAC    cmp byte ptr [ebp+02], 67   compare tezo char con 67, cioè "g"

:00428DB0    jne 00428E44                 se è diverso salta a Errore

:00428DB6    cmp byte ptr [ebp+03], 32   compare quarto char con 32, cioè "2"

:00428DBA    jne 00428E44                 se è diverso salta a Errore

da qui vediamo subito che i primi quattro char del serial devono essere  "mvg2", indipendentemente dall'algo.

 

:00428DC0    mov ebx, 004401F0

...          un pò di controlli con la blacklist. Non inserite i numeri che vedete

...          in memoria perchè non verranno accettati

:00428DF3    call 0042FFA0   --> questa ci interessa.

Entriamo nella call, entrate nelle eventuali sub-call che trovate fino ad arrivare

al codice:

 

:0042FF55    cmp dword ptr [00440E5C], 00000001

:0042FF5C    jle 0042FF6B

.... le righe qui in mezzo non vengono eseguite mai

:0042FF6B    mov edx, dword ptr [00440C50] muove in edx una tabella di valori

:0042FF71    mov al, byte ptr [edx+2*esi] mette in eax un valore della tabella corrispondente

                                                                 al valore edx+2*esi. Per i numeri ci mette sempre 84

Nota: il serial viene usato non tutto, ma solo la parte oltre la 7° cifra. Questo significa che il serial deve

essere del tipo:  "mvg2xxx" seguito dal numero, dove xxx è un valore qulasiasi.

:0042FF74    and eax, 00000004 fa l'and di 84 con 04.

:0042FF77    test eax, eax   se eax è 0

:0042FF79    je 0042FF8B    salta alla fine

:0042FF7B    lea eax, dword ptr [ebx+4*ebx]    |  questa è la parte importante

:0042FF7E    xor ecx, ecx                       |  abbiamo il cuore dell'algo

:0042FF80    mov cl, byte ptr [edi]             | di generazione del serial

:0042FF82    inc edi                            | che se guardate bene

:0042FF83    lea ebx, dword ptr [esi+2*eax-30] | consiste nel convertire il numero decimale

:0042FF87    mov esi, ecx                       | messo dopo "mvg2xxx" in esadecimale

:0042FF89    jmp 0042FF55                     ricomincia il ciclo

:0042FF8B    cmp ebp, 0000002D

:0042FF8E    mov eax, ebx              in eax ho il valore finale che verrà usato dopo

:0042FF90    jne 0042FF94

:0042FF92    neg eax

:0042FF94    pop edi

:0042FF95    pop esi

:0042FF96    pop ebp

:0042FF97    pop ebx

:0042FF98    ret

 

Okkey, da qui uscirà un valore contenuto in eax. Teniamolo a mente, perchè ci servirà. Per comodità lo chiameremo Valore_Serial.

Questo Valore_Serial, se ci fate caso, non è altro che il corrispondente esadecimale del valore numerico immesso nel serial dopo la stringa "mvg2xxx". Se per serial avevate inserito il valore "mvg21234567", i primi sette char vengono scartati, e rimane 4567. Il suo corrispondente hex è 11D7, ed è quello che troveremo in eax.

Dopo il ret finiamo subito subito nella rotuine che fa dei calcoli sul nome. Eccola:

 

:00428DF8    mov edx, dword ptr [esp+18]

:00428DFC    add esp, 00000004

:00428DFF    mov edi, edx   edi anche contiene il puntatore al nome

:00428E01    xor ecx, ecx   azzera ecx

:00428E03    mov dl, byte ptr [edx] mette in dl il char del nome

:00428E05    mov esi, 000006FE   inizializza esi.

:00428E0A    test dl, dl  se il char è zero

:00428E0C    je 00428E36  salta vai alla fine

:00428E0E    inc ecx      incrementa ecx

:00428E0F    movsx edx, dl  mette dl in tutto edx

:00428E12    mov ebx, ecx   copia ecx in ebx (ecx = contatore dei char)

:00428E14    imul ebx, edx          | moltiplica edx per ebx (edx = char attuale)

:00428E17    add esi, ebx       | aggiungi ad esi il risultato della moltiplicazione

:00428E19    cmp esi, 00000DFD  | se esi è più piccolo di DFD

:00428E1F    jle 00428E27       | salta

:00428E21    sub esi, 00000DFD  | se esi è più grande, allora sottrai DFD a esi

:00428E27    cmp ecx, 0000000A  | se il contatore è minore di 0A

:00428E2A    jle 00428E2E   salta

:00428E2C    xor ecx, ecx   se è maggiore azzeralo

:00428E2E    mov dl, byte ptr [edi+01]  muovi in dl il prossimo char

:00428E31    inc edi       incrementa edi

:00428E32    test dl, dl   controlla dl

:00428E34    jne 00428E0E   se è zero abbiamo finito

:00428E36    cmp esi, eax    compare Valore_Serial  con  Valore_Nome

:00428E38    jne 00428E44    se non sono uguali salta a errore.

:00428E3A    mov eax, 00000001  mette in eax 1, il che vuol dire che ci abbiamo azzeccato se arriviamo qui

:00428E3F    pop edi

:00428E40    pop esi

:00428E41    pop ebp

:00428E42    pop ebx

:00428E43    ret

 

Bene. Dalla riga 00428E14 a 00428E27 abbiamo il cuore della routine. Qui alla fine in esi viene sommato di volta in volta un valore ottenuto dalla moltiplicazione, e gli viene tolto il valore DFD se lo supera. Quindi vediamo alla riga 00428E26 il compare tra il valore ottenuto da esi, che chiamerò Valore_Nome con il Valore_Serial. Il Valore_Serial lo conosciamo già. E' ovvio che dobbiamo fare in modo che il Valore_Serial sia uguale a quello generato dal nome. Come si può fare? Semplice. Il Valore_Serial vi avevo detto che era il corrispondente hex del valore numerico inserito dopo "mvg2xxx". Quindi se deve essere uguale al Valore_Nome, non dobbiamo fare altro che prendere il Valore_Nome, trasformarlo in decimale e attaccarlo a mvg2xxx. Nel mio caso ho inserito il nome AndreaGeddon, ed il serial mvg2xxx4567. Il Valore_Nome che trovo è 50C, mentre il Valore_Serial è 11D7. Basta convertire 50C in decimale, e ottengo 1292. Adesso inserisco come serial mvg2xxx1292 et voilà, il programma è registrato.

Concludendo, se si vuole fare un keygen riassumiamo il lavoro nei seguenti passi:

- badate che n varia da 0 a B inclusi, poi ricomincia da 0.

- Abbiamo in partenza ESI = 6FE

- Prendiamo il valore hex della lettera di posto n nel nome (a partire dalla prima) e la moltiplichiamo per n.

  Otterremo  n_mod

- ESI = ESI + n_mod

- Se ESI > DFD, allora ESI = ESI - DFD

- Ripeti il ciclo per ogni lettera del Nome

- Alla fine otterremo in ESI il Valore_Nome, da convertire in decimale e attaccare al serial.

Con questo è tutto.

AndreaGeddon

 

Note Finali

Saluto tutti gli amici della mailing list. Ciauuuz.

Disclaimer

Queste informazioni sono solo a scopo puramente didattico. Non mi ritengo responsabile dell'uso che ne verrà fatto.

 
UIC's page of reverse engineering, scegli dove andare:

Home   Anonimato   Assembly    CrackMe   ContactMe   Forum       
    Iscrizione   Lezioni    Links   NewBies   News   Playstation        
  Tools   Tutorial   Search   UIC Faq

UIC