- UNIVERSITA' ITALIANA CRACKING -
2° Corso per Studenti

 CREARE UN KEYMAKER
(Key Maker e tecniche basilari di mascheramento del seriale)


Scarica qui il programma per questo corso (1.7 kb)


Benvenuti a tutti nella seconda lezione della UIC, stavolta il livello sarà leggermente più alto della prima lezione, oggi parleremo di programmi che generano una chiave e la salvano nel seriale nel registro in forma crittata.

Nella prima lezione avevamo fatto un accenno ai generatori di chiavi ma non eravamo andati oltre dal momento che dovevamo crackare il programma e non reversarlo, questa volta invece vi verrà chiesto di creare un keymaker per un programma e di spiegare la routine di generazione, quindi questo corso è indicato a chi ama di più il reversing rispetto al cracking.

Dal momento che dovevamo parlare di programmi che creano un seriale da un nome facciamo subito un piccolo esempio: al giorno d'oggi la maggior parte dei programmi shareware mette a disposizione dell'utente un box di registrazione nel quale deve essere inserito il proprio nome ed un numero che verrebbe venduto in genere a molto da una SoftwareHouse, il lavoro del reverser è allora quello di capire cosa cerca il programma in quel box e darglielo. Come al solito per brekkare nella routine principale si possono usare i tre breakpoint più famosi nel mondo del reversing cioè: GetWindowTextA, GetDlgItemTextA, hmemcpy

una volta premuto il pulsante di registrazione steppate finchè vi ritrovate nella routine, una volta dentro osservate il codice ed andate avanti, in linea di massima vedrete che ogni carattere del vostro nome verrà manipolato nei più vari modi per poi essere confrontato con il seriale che avevate inserito, o meglio vedrete che verrà generato un seriale dal vostro nome, verrà poi crittato e dopo ancora verrà confrontato con il vostro serial crittato allo stesso modo, per rendervi le idee più chiare vi faccio uno schemetto che riassume il modo "generale" di agire di quasi tutti i programmi di questo genere:

 
Fase 1)
 
Viene preso il nome...
Quequero             |
        |             ....Che viene manipolato.....------------
        |                                                     |
       ---- (Quequero*2)+(Que*quero)+(Que/2) = 568           | 
                                                 |           .....E crittato!
                                                 |
                                                 ------ (568 xor 25)rol6(xor 40)...874  
Fase 2)
 
Viene preso il numero.....
  666111666              |
           |             | 
           |             .....Che viene crittato allo stesso modo                              
           |
           --------- (568 xor 25)rol6(xor 40)...874 
 
 
Fase 3)
 
I due numeri crittati vengono confrontati..... 
874  & 874  = OK
874  & 975  = NO
...E se combaciano il numero viene salvato nel registro con il nome, altrimenti NO, talvolta il numero viene salvato anche se sbagliato ma il programma quando viene avviato se ne accorge e si setta automaticamente in modalità shareware.   
 
Adesso che sapete come agisce la generazione del numero, vediamo anche come ne avviene la lettura al riavvio del programma:
 
1) Il prg apre la propria chiave nel registro (RegOpenKeyA) e la legge (RegQueryValueA)
2) Il prg apre la chiave che contiene il nostro nome e lo legge, lo manipola, lo critta e lo salva
3) Il prg richiama il numero e nome (manipolato) letti e li confronta
4) Sono uguali? Setta modalità Registrata altrimenti setta modalità Shareware   
 
Da questo momento sapete che per brekkare nella routine avete ben due momenti cioè: la registrazione e la lettura, se volete crackare il target vi consiglio di usare il secondo attacco, se invece lo volete reversare vi consiglio il primo. 
Attenzione però che alcuni programmi (come Advanced Zip Password Recovery) fanno un terzo check al numero ogni volta che avviate una qualunque funzioni, quindi amici crackatori state attenti.
Dopo questo noioso ma indispensabile pezzo di teoria vi presento qualche esempietto pratico, partiamo con una semplice routine di manipolazione che manipola i primi 4 caratteri del nome:
 
Call GetWindowTextA, hwnd, offset nome, 15 ; Prende il nome e lo mette nel buffer "nome"
mov edi, offset  nome                       ; routine di calcolo della lunghezza del nome
or  ecx, -1                                ; routine di calcolo della lunghezza del nome
not ecx                                    ; lunghezza in ECX
xor eax, eax
mov eax, dword ptr [nome]          ; Muovi 4 caratteri del nome in eax   
cdq                                ; Convert DoubleWord to Quad per preparare una divisione
mov edi, 185h                      ; Prepara il divisore
div edi                            ; Dividi EDI per eax (nome/185h)
add eax, edx                       ; Aggiungi al risultato il resto della divisione
sub ecx, 4                         ; Sottrai 4 lettere alla lunghezza del nome (le abbiamo messe in eax)
cmp ecx, 0                         ; il nome è finito?
jle ......                         ;...........
 
Prima di affrontare una routine di crittazione vorrei fare un piccolo preambolo teorico: allora, crittare un seriale significa mascherarlo in modo da non farlo sembrare ciò che in realtà è, i programmatori per confonderci ricorrono a svariate tecnice di crittazione per non farci capire niente ma con un po' di pratica tutti saranno in grado in più o meno tempo di capire l'algoritmo. Adesso vi starete chiedendo: ora che sappiamo che significa crittare un seriale come facciamo a sapere se il nostro programma usa questa tecnica? Dunque il procedimento non è troppo complesso, vi dico subito che per cifrare qualcosa si usano degli operatori matematici e logici quali ad esempio: Rol, Ror, Shl, Shr e Xor che tratteremo dopo, se durante lo step vedete una delle prime 2 istruzioni state pur certi che quella è mano del programmatore dal momento che nessun, e ribadico NESSUN compilatore produce istruzioni come Rol e Ror, in genere se in una comune routine di calcolo trovate anche qualche shl o shr sarete quasi certi che anch'essa sia una routine di crittazione, se invece state reversando una demo grafica allora non fate caso ai vari shl o shr dal momento che in quel campo sono ampiamente usati.
Dopo questo breve preambolo è ora di fare le presentazioni per spiegare il funzionamento di queste istruzioni:
Ror = Rotate Right: ruota un bit a destra
Rol = Rotate Left: ruota un bit a sinistra
Shr = Shift Right: Shifta un bit a destra
Shl = Shift Left: Shifta un bit indovinate un po' dove? :)
Xor = Exclusive Or: Or esclusivo

 

------------------------------------------------------------------------------------------------------------
Mentre per gli operatori Shift e Rotate non mi sembra il caso di perdere tempo a spiegare, credo che sia invece necessario per lo Xor.
L'istruzione xor non fa altro che confrontare due valori e riportare un 1 se i due valori erano differenti ed uno 0 se erano uguali, ecco un esempio, prendiamo un numero binario e lo xoriamo con un altro numero sempre binario:

 

101100 Xor

110101  =

----------

011001

 
ecco cosa fa lo xor, la sua peculiarità e che se il risultato si rixora per lo stesso valore riotteniamo il numero di prima:

 

011001  Xor             011001  Xor

110101  =        &      101100  =

-----------             -----------

101100                  110101

 
elementare no? Si xora un valore per un altro valore e quindi lo si critta, lo si rixora per lo stesso valore e lo si decritta.
------------------------------------------------------------------------------------------------------------
 
bene bene, per capirne di più sullo Xor andate a leggere il mio tutorial alla UIC. Dunque vediamo ora come vengono usati questi operatori con un'altra semplice routine:
 
valore                dd 1234h
serial_esatto         dd ?
----- snip snip -----
mov  eax, dword ptr [serial_esatto] ; Muove il serial esatto dal buffer in eax
rol  eax, 5                         ; Ruota a sinistra di 5 bit eax
shr  eax, 4                         ; Shifta a destra eax
xor  eax, 45h                     ; Xora il risultato con un valore (45h)
xor  eax, serial_esatto           ; Xora eax con il serial esatto
xor  eax, dword ptr [valore]      ; Xora il risultato con un valore predefinito preso da valore
 
con questa routine abbiamo dimostrato alcuni dei più comuni modi di usare uno xor, ma partiamo dall'inizio, il seriale esatto viene spostato dal proprio buffer in eax, viene rotato di 5 bit, viene shiftato di 4 bit ed il risultato viene xorato con un valore predefinito, il numero viene poi rixorato con il serial esatto (e quindi con un numero variabile e non con un valore predefinito) e poi viene xorato con i primi 4 byte presi da una doubleword definita ad inizio programma, questa tecnica viene usata per non rendere troppo esplicito il valore con cui viene xorato il numero. Ma ora che il numero è crittato fino alle gengive come facciamo a decrittarlo?  Innanzitutto nella routine di un programma vero non sarebbe necessario ma se volessimo farlo per sniffare il seriale che ci interessa potremmo utilizzare un metodo abbastanza banale cioè: per decrittare un valore che è stato shiftato basta rishiftarlo dall'altro lato per lo stesso valore e questo vale anche per un valore rotato, se invece c'è anche stato uno xor, basta rixorarlo per lo stesso valore, ecco ad ogni modo la routine di decrittazione che dovremmo utilizzare per leggere il numero che esce fuori dalla routine di sopra, sarebbe totalmente inutile decrittare il numero dal momento che potremmo leggerlo dal buffer [serial_esatto]:

 

mov eax, dword ptr [serial_crittato] ; Muove il serial crittato in eax
ror   eax, 5                         ; Ruota a destra di 5 bit eax
shl   eax, 4                         ; Shifta a sinistra eax
xor   eax, 45h                       ; RiXora il risultato con un valore (45h)
xor   eax, serial_esatto             ; RiXora eax con il serial esatto
xor   eax, dword ptr [valore]        ; RiXora il risultato con un valore predefinito preso da valore
 
come vedete decrittare qualcosa conoscendo la routine "madre" è semplice ed è sempre la stessa pappa, quando studieremo il codice auto-modificante (SMC da Self-Modifyng Code) impareremo altre tecniche di crittazione più sofisticate.
Ci si ribecca alla prossima lezione :)

OBIETTIVI:  
  1. Trovare il serial relativo al proprio nome/nick e creare un piccolo keygenerator, se non conoscete alcun linguaggio (bhè almeno un pochetto di asm lo dovreste conoscere...È comunque ora di impararlo visto che in altre occasioni saranno richiesti veri e propri programmi) DOVETE spiegare molto dettagliatamente la routine utilizzata, potete usare Sice, IDA, W32Dasm, quello che volete insomma

  2. OBBLIGATORIO: trovare un bel nome per l'iguana di Quequero

Quequero


[Back]