Universe 1.61
Serial Fishing e Keygen reversing


30/04/2000

by "AndreaGeddon"

 

 

UIC's Home Page

Published by Quequero


Qualche mio eventuale commento sul tutorial :)))

Allora io qui non ci devo scrivere, giusto??? :-P

Esatto! :)))))

Bravo Andrea che continua a cimentarsi in programmi con routine pallosissime :)...Bravo, fa bene al cervello, ma questo form NON � degno di nota, insisto nel dire che il Notepad (oppure QuePad? :) ed il courier new per il codice sarebbero un'ottima accoppiata :)))

 
UIC's form
Home page:  www.andreageddon.8m.com
E-mail: [email protected]
IRC chan:   #crack-it
UIC's form

Difficolt�

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

 

Vediamo come si trova il seriale di Universe 1.61, poi cerchiamo di capire come vegono generati i seriali.


Universe 1.61
Serial Fishing e Keygen reversing
Written by AndreaGeddon

Introduzione

Fiiiico! Un programmillo per disegnare sfondi stellati con tanto di galassie, nebulose, nane bianche e chi pi� ne ha pi� ne metta. Peccato che alcuni pulsanti di disegno siano disattivati nella demo.... attiviamoli! Una volta tanto so a che cosa serve il prog che voglio reversare  :-)

Tools usati

-  SoftIce

URL o FTP del programma

http://www.diardsoftware.com

Notizie sul programma 

Nome e serial number.

Essay

PARTE PRIMA:  L' OSSERVAZIONE

Questa secondo me � la parte pi� importante di tutte, infatti vi permette di partire con informazioni preziose e vi fa risparmiare parecchio tempo. Ricordatevi, quindi, di cercare di scoprire pi� cose possibili invece di buttarvi subito sul SoftIce. Okay, iniziamo.

Andiamo su Help->Register, voil�, il dialog con Nome e Key. Prima osservazione: notate che nel campo del serial � gi� presente uno 0. Bene, questo ci fa pensare che il serial debba essere un numero. Un qualsiasi numero? Vediamo... Proviamo ad inserire un numero compreso di lettere, tipo: 114455AABB. Che succede? Oltre che a dire che il serial � sbagliato, dice anche che il numero deve essere un intero! Grazie! Quindi probabilmente il meccanismo di calcolo non deve essere molto complesso, si baser� sui numeri gestibili da un registro, cio� da 0 a 2^32. Bene, per adesso abbiamo parecchie informazioni. Quindi procediamo con il softice.

 

PARTE SECONDA: L'ATTACCO

Okay, adesso partiamo col Sice. Inserisco il mio nome (AndreaGeddon) ed un intero, cio� 123456789, e tanto per comodit� segnamoci il corrispondente hexa, cio�: 75BCD15. Ricordatelo. Adesso settiamo un breakpoint su GetWindowTextA. Premete invio e ...pop... ecco il sice; premete ctrl-d cos� ripopperete sulla seconda chiamata a getwindowtexta. Ora possiamo iniziare lo stepping. La prima cosa che facciamo e steppare conn F10 per cercare la call che ci spara il messagebox di errore. Dove la troviamo? Alla riga:

0040AE15    CALL     00464957

Quindi dobbiamo trovare unn jump che ci permetta di evitare questa parte di codice. Se risteppate daccapo trovere che alla riga:

0040ADD2    JZ     0040AE0C

il jump ci spara alla call di errore. Se provate ad invertire il jump il prog non mostrer� il messagebox di errore, ma rimarrete non registrati. Va bene. Diamo uno sguardo pi� attento all'intorno del JZ:

0040ADC6    CALL     004167EB                         | che succede qui dentro?

                      MOV      [ebp-04|, eax                     |   praticamente controlla se il valore restituito dalla call

                      CMP      dword ptr [ebp-04|, 00      |  in eax � 0

0040ADD2    JZ           0040AE0C                        |  se lo �, salta al messaggio di errore

� chiaro che la call decide se il prog deve andare al messaggio di errore oppure no. Quindi � proprio nella call che andremo a cercare. Risteppiamo fino alla call, ed entriamoci con F8. Qui ci aspetteremo quindi di trovare la routine di controllo del seriale. Sappiamo che il valore di controllo sar� restituito in eax, quindi andremo a cercare qualche istruzione XOR o SETZ dopo unn call, probabilmente verso la fine della routine. Infatti andiamo alla linea:

00416938    CALL     00428D20             strana call... restituisce in eax un numero strano

                     XOR      ecx, ecx                 azzeriamo ecx

                    CMP       [ebp-38|, eax       in ebp-38 c'� il numero che abbiamo messo, ma in hexa (quindi eax sar� il giusto serial?)

                    SETZ      cl                           se sono uguali setta il flag cl

                    MOV      eax, ecx                 metti ecx in eax, che verr� usato come flag di controllo fuori dalla call

....

                    RET

okay. Dopo la call in EAX ci troveremo uno strano numero. Poi viene azzerato ecx. Viene effettuato il compare di una locazione di memoria con eax. Se andiamo a vedere la locazione di memoria (ebp-38) ci troveremo un valore in hexa, una dword, che connvertita in decimale ci dar� il numero che avevamo inserito. Bene. Allora anche eax sar� il corrispondente decimale del giusto seriale? Proviamo... Io in eax ci ho trovato il valore 2F9C56D4 che in decimale sarebbe 798774996, che infatti � il serial valido per il nome AndreaGeddon. Ecco come trovare il seriale. Adesso vogliamo vedere come viene generato.

 

PARTE TERZA: CAPIAMO L'ALGORITMO

Se entriamo nella call precedentemente citata, troveremo dei calcoli effettuati con dei valori di cui non sappiamo la provenienza, per cui dobbiamo rivedere l'intera routine dalla riga 004167EB. Iniziamo a vedere quali sono i punti importanti.

 

:004167EB   push ebp

... sniip   8<

qui inizia il primo ciclo...

:00416874   mov edx, dword ptr [ebp-18]

:00416877   add edx, 00000001

:0041687A   mov dword ptr [ebp-18], edx 

:0041687D   mov ecx, dword ptr [ebp+08]     mette in ecx il puntatore al nome

:00416880   call 00403530                              ottiene la lunghezza del nome (in eax)

:00416885   cmp dword ptr [ebp-18], eax       la confronta con il valore inn ebp-18, che � il contatore

:00416888   jge 004168D9                              salta se abbiamo finito il ciclo

:0041688A   mov eax, dword ptr [ebp-18]

:0041688D   push eax

:0041688E   mov ecx, dword ptr [ebp+08]     di nuovo inn ecx il puntatore al nome

:00416891   call 00416C70                             ottiene l' n-esimo char in al

:00416896   movsx ecx, al                               mette al in ecx

:00416899   mov dword ptr [ebp-20], ecx       salva il char attuale in ebp-20

:0041689C   mov edx, dword ptr [ebp-10]      mette in edx le somme delle eguenti moltiplicazioni

:0041689F   add edx, dword ptr [ebp-20]       gli aggiunge il char corrente

:004168A2   mov dword ptr [ebp-10], edx     aggiorna la variabile con la nuova somma

:004168A5   mov eax, dword ptr [ebp-18]      mette in eax il contatore

:004168A8   cdq                                             azzera edx

:004168A9   xor eax, edx                                alcuni calcoli...

:004168AB   sub eax, edx                                ... che portano...

:004168AD   and eax, 00000001                     ... a decidere...

:004168B0   xor eax, edx                                 ...se per la moltiplicazione....

:004168B2   sub eax, edx                                 ... useremo il fattore...

:004168B4   test eax, eax

:004168B6   je 004168C1

:004168B8   mov [ebp-1C], FFFFFFFF         ... FFFFFFFF...

:004168BF   jmp 004168C8                            ...oppure...

:004168C1   mov [ebp-1C], 00000001           ... 00000001.

:004168C8   mov eax, dword ptr [ebp-1C]     prende in eax il fattore (00000001 oppure FFFFFFFF)

:004168CB   imul eax, dword ptr [ebp-20]      lo moltiplica per il char corrente

:004168CF   mov ecx, dword ptr [ebp-10]      mette in ecx il valore dei precedenti risultati

:004168D2   add ecx, eax                                gli aggiunge il fattore precedentemente usato

:004168D4   mov dword ptr [ebp-10], ecx      salva il nuovo valore

:004168D7   jmp 00416874                             loop per tutti i char del nome

... e qui finisce. Alla fine in ebp-18 avremo il totale di tutto questo calcolo. Nel mio caso sar� il numero 448.

 

:004168D9   mov edx, dword ptr [ebp-10]      mette in edx il totale

:004168DC   mov dword ptr [ebp-14], edx     lo salva nella locazione ebp-14

:004168DF   mov eax, dword ptr [ebp-10]     mette anche in eax il totale

:004168E2   imul eax, dword ptr [ebp-10]       |  ebp-10 = (totale)^2

:004168E6   mov dword ptr [ebp-10], eax      |  adesso ebp-10 contiene il totale^2

:004168E9   mov ecx, dword ptr [ebp-10]      metti in ecx totale^2

:004168EC   add ecx, dword ptr [ebp-14]      ecx = totale^2+totale

:004168EF   mov dword ptr [ebp-10], ecx      salva il tutto in ebp-10

:004168F2   mov edx, dword ptr [ebp-10]      prepara il totale^2+totale

:004168F5   push edx                                      per la call che segue

:004168F6   call 00428D00                   copia il valore totale^2+totale in eax e nella locazione 004906F8

:004168FB   add esp, 00000004

:004168FE   mov [ebp-18], 00000000

:00416905   jmp 00416910

 

secondo piccolo ciclo...

:00416907   mov eax, dword ptr [ebp-18]     mette in eax il contatore

:0041690A   add eax, 00000001                    lo incrementa

:0041690D   mov dword ptr [ebp-18], eax    lo salva

:00416910   mov ecx, dword ptr [ebp-2C]    mette in ecx il puntatore al numero di iterazioni

:00416913   mov edx, dword ptr [ebp-18]     mette in edx il contatore

:00416916   cmp edx, dword ptr [ecx]          controlla quante volte abbiamo eseguito il ciclo

:00416918   jge 00416921                             se il contatore � uguale al valore puntato da ecx, abbiamo finito

:0041691A   call 00428D20                            vedi  SUB-CALL pi� sotto

:0041691F   jmp 00416907                           loop

... che dura fin qui

 

:00416921   cmp dword ptr [ebp+0C], 00000000    ebp+0c = nostro serial, lo confronta con 0

:00416925   jle 0041692F                                         salta se � 0 (ma noi mica abbiamo messo 0!)

:00416927   mov eax, dword ptr [ebp+0C]                metti il serial in eax

:0041692A   mov dword ptr [ebp-38], eax                 e poi mettilo in ebp-38

:0041692D   jmp 00416938                                       e salta alla call!

:0041692F   mov ecx, dword ptr [ebp-2C]

:00416932   mov edx, dword ptr [ecx+10]

:00416935   mov dword ptr [ebp-38], edx

:00416938   call 00428D20                                       di nuovo: vedi SUB-CALL pi� sotto

finalmente alla fine!

:0041693D   xor ecx, ecx                                azzera ecx

:0041693F   cmp dword ptr [ebp-38], eax     confronta il giusto serial (eax) con il nostro (ebp-38)

:00416942   sete cl                                         se sono uguali setta il flag cl

:00416945   mov eax, ecx                               metti il flag cl in eax

:00416947   mov ecx, dword ptr [ebp-0C]   

:0041694A   mov dword ptr fs:[00000000], ecx

:00416951   mov esp, ebp

:00416953   pop ebp

:00416954   ret 0008                                      torna indietro!

 

 

SUB-CALL  per comodit� ho esploso direttamente qui le due ulteriori sub-call, che trovate spostate pi� a destra :-)

:00428D20   mov eax, dword ptr [004906F8]  che � sto valore? � totale^2+totale, rivedete la riga 004168F6!

:00428D25   push 78B30C40                   salva il valore 78B30C40    (!)

:00428D2A   cdq                             azzera edx

:00428D2B   push 00000000                   pusha 0

:00428D2D   push 25A2A40D                   salva il valore 25A2A40D  (!)

:00428D32   push edx                        pusha edx (zero)

:00428D33   push eax                        pusha eax (totale^2+totale)

:00428D34   call 00440590

:00440590   mov eax, dword ptr [esp+08] metti in eax il valore 00000000
:00440594   mov ecx, dword ptr [esp+10] metti 00000000 in ecx
:00440598   or ecx, eax                 
:0044059A   mov ecx, dword ptr [esp+0C] mette in ecx il valore 25A2A40D
:0044059E   jne 004405A9                 salta se il risultato dell'or non era 0
:004405A0   mov eax, dword ptr [esp+04] mette in eax il valore totale^2+totale
:004405A4   mul ecx                      e lo moltiplica per 25A2A40D
004405A6   ret 0010

:00428D39   add eax, 00000001              aggiungi 1 al risultato "parte bassa"

:00428D3C   adc edx, 00000000              aggiungi con riporto 0 al risultato "parte alta"

:00428D3F   push edx                       pusha la parte alta

:00428D40   push eax                       pusha la parte bassa

:00428D41   call 00428DA0

    :00428DA0    push ebp                                     |

    :00428DA1    mov ebp, esp               | crea nuovo stack

    :00428DA3    push ebx                   ebx = contatore

    :00428DA4    mov eax, dword ptr [ebp+08]  metti in eax il valore che gi� ha

    :00428DA7    mov edx, dword ptr [ebp+0C]  metti in ecx il valore che gi� ha

    :00428DAA    mov ebx, dword ptr [ebp+10]  richiama in ebx 78B30C40, valore pushato alla riga 428D25

    :00428DAD    div ebx                       dividi eax (parte bassa) per 78B30C40

    :00428DAF    mov eax, edx                  copia il resto di questa divisione in eax

    :00428DB1    pop ebx

    :00428DB2    pop ebp

    :00428DB3    ret

:00428D46   add esp, 0000000C

:00428D49   mov dword ptr [004906F8], eax    metti il resto salvato poco fa nella locazione 004906F8

:00428D4E   ret                               attenzione perch� al prossimo ciclo la locazione 004906F8

                                                                                          non contiene pi� il valore totale^2+totale ma il nuovo valore!

 

Fiuu! Che faticaccia commentare questa luuuuunghissima routine. Ho ricontrollato pi� volte, ma potrebbe esserci scappato qualche errore, ma comunque in generale adesso la routine che crea il seriale giusto dovrebbe essere chiara. Di scriverci un keymaker non se ne parla, non ho n� il tempo n� la voglia, ma visto che ora sapete come fare, potete provarci. Calcolarsi un serial valido a mano sarebbe stato abbastanza complicato, fortuna che i programmatori ci hanno risparmiato il lavoro e ci hano lasciato il bel compare in chiaro! Alla proxima.

AndreaGeddon

 

                                                                                         Note finali

Saluto tutti gli amici della mailing list. Saluto pure GiOcRaCk che ho conosciuto da poco, ma sembra uno in gamba. Pare che per� abbia lo stesso accento di Zoa (voi leim... roba da leim....) hahahaha!

Disclaimer

Queste informazioni sono solo a scopo puramente didattico.

                                         
UIC's page of reverse engineering, scegli dove andare:
Home   Anonimato   Assembly    CrackMe   ContactMe   Forum   Iscrizione
Lezioni    Links   Linux   NewBies   News   Playstation
Tools   Tutorial   Search   UIC Faq
UIC