Lezione 5 UIC
(molta pazienza)


05/01/2000

by "syscalo"

 

 

UIC's Home Page

Published by Quequero

 

Bravissimo sys, ti ostini come sempre a spiegare ogni singola istruzione..perciò a 30 anni sarai morto di pazzia :), bravo il tutorial è davvero completo fin nei minimi dettagli ma manca il keygenerator.

 
UIC's form
Home page se presente: http://syscalo.cjb.net 
E-mail: x4sys@iname.com
UIC's form

Difficoltà

(X)NewBies (X)Intermedio ( )Avanzato ( )Master

 

Soluzione lezione 5 UIC. Questa lezione presenta diversi gradi di difficoltà, come descritto nella presentazione. Io ho risolto i tre punti fondamentali, ma non ho avuto il tempo di scrivere i generatori del seriale e del keyfile (causa interessi extra reversing & feste con relativi sballi ;) comunque se volete provarci voi non è molto complicato, soprattutto se decidete di scriverli in asm, perchè potete "riciclare" quasi tutto il codice delle routine.


Lezione 5 UIC
(molta pazienza)
Written by syscalo

Introduzione

Vediamo un po' cosa richiede questo crackme:
- un codice fisso (Que ha scelto Cr4nB&Rr13$) da inserire nella prima casella (quella più in alto).
- un seriale, di lunghezza fissa di 15 caratteri, basato sul nickname. Se il nickname è lungo n caratteri, ma meno di 15, il seriale è determinato dal nickname solo per n caratteri ed i restanti possono essere scelti a caso. Se però li cambiamo dobbiamo ricordarci di generare il nuovo key file. Per capirci ecco i miei dati:
nickname: syscalo (7 caratteri)
          seriale: 0201856 (parte basata sul nick -7 caratteri-)   90909090 (parte scelta a caso -fino ad arrivare a 15 caratteri-)
- un keyfile, chiamato crykey.key, di 700 bytes, basato sul seriale.
Tutto qua ?-) direte voi!
No, no, Quequero ha voluto divertirsi ancora un po' ;) ha inserito un simpatico trucchetto che è necessario scoprire per far comparire la msgbox di congratulazioni (dopo aver trovato tutti i dati indicati sopra). Se osservate la form del programma vedete un tasto About; lo vedete?-) bene dovete premerlo 4 volte (ovviamente ogni volta dovete chiudere la msgbox presentata) prima che il programma effettui il controllo finale; vi consiglio di farlo subito prima di inserire i vari seriali.
Dimenticavo; per rendere un po' antipatico il programma sono presenti alcuni check anti softice che vanno eliminati solo se intendiamo utilizzare questo (magnifico) debugger; niente di particolare, vedremo in seguito come fare.
Ora siamo veramente giunti alla fine. Possiamo vedere un po' di asm. Buon divertimento ;)

Tools usati

SoftIce, Ida, HexWorkshop, Turbo Debugger per win32 del Tasm 5.

URL o FTP del programma

Devo dirvelo?

Essay

Ok passiamo all'assembler -tanto per cambiare-
Eliminazione check anti softice:
Il programma se trova softice mostra una msgbox; questo è un ottimo aiuto per ricercare i punti in cui vengono effettuati i check, passiamo quindi a disassemblare il programma. Ora ricercate il testo "Chi usa softice alzi la mano", andate dove viene richiamato e troverete i check, due realizzati tramite l'int 68h e uno tramite l'int 3h; i primi due vengono effettuati all'avvio del programma e li trovate all'indirizzo 00401062 e 004010DB, nella seguente forma:
00401062   mov   ah,43h  
00401064   int   68h  
00401066   cmp   ax,0F386h   se viene ritornato questo valore, softice è attivo...
0040106A   jz   loc_401B3E   ...e salta a visualizzare la msgbox (nel secondo cambia l'indirizzo a cui salta)
Il terzo viene effettuato prima del controllo del keyfile e lo trovate all'indirizzo 00401536, nella seguente forma:
00401536   mov ebp,4243484Bh   fa parte del trucco anti softice (x Que: mi sono informato ;)
0040153B   mov   ax,4
0040153F   int   3   Trap to Debugger -Commento inserito da Ida ;)-
00401540   cmp   al,4   se in al non c'è ancora 4 softice è attivo...
00401542   jnz   loc_4011EE   ...salta a visualizzare la msgbox
Per disabilitare i check è sufficiente nopparli come meglio credete. Nei primi due potreste noppare il jz, mentre nel terzo si potrebbe noppare l'int 3.
Dopo aver visualizzato la msgbox il programma termina con la chiamata all'API ExitProcess.
Ok ora possiamo tranquillamente utilizzare softice ;)
Passiamo ad analizzare il programma:
 
Ricerca del primo codice:
Impostiamo in sice un bpx GetWindowTextA, avviamo il programma; ora inseriamo una parola nella prima casella e premiamo il tasto register. Sice poppa all'indirizzo 00401247 dove troviamo il seguente codice:
 
sub_401206   cmp   byte_403271,8   flag per impostare a una sola volta il check sul primo seriale
   jz   loc_401323   se =8 (->già eseguito) salta a loc_401323
   push   3E9h  
   push   dword_40201C  
   call   j_GetDlgItem   ottiene l'handle della prima casella
   mov   dword_402030,eax   salva l'handle
   push   68h  
   push   dword_40201C  
   call   j_GetDlgItem   ottiene l'handle della seconda casella
   mov   dword_402034,eax   salva l'handle
   push   0Ch   numero max chr da leggere (0Ch=12)
   push   offset dword_403273   ind a cui salvare il primo seriale
   push   dword_402030   passa handle casella
loc_401247: call   j_GetWindowTextA   legge la prima casella
   call   sub_40159C   procedura che crea dei valori (usati in seguito per le crittazioni) basati sulle dimensioni dei file autoexec.bat e system.ini
   xor   ecx,ecx   azzera ecx
loc_401253:   xor   dword_403273[ecx],0EDh   xor di 4 chr alla volta del seriale letto con 0EDh
   inc   ecx   incrementa conteggio chr (sposta di una posizione)
   cmp   ecx, 0Ch   continua per 12 volte
   jnz   short loc_401253   esegue le istr precedenti
   xor   ecx, ecx   azzera ecx
loc_401265:   xor   dword_403273[ecx], 134F7432h   xor di 4 chr del seriale alla volta
   xor   dword_403273[ecx], 4A710930h   questi tre valori equivale a fare lo xor con 01E960E4h
   xor   dword_403273[ecx], 58D71DE6h
   add   ecx, 4   incrementa di 4 il conteggio dei chr (sposta di 4 posizioni)
   cmp   ecx, 0Ch   esegue per 12 chr
   jnz   short loc_401265   esegue le istr prec (per 3 volte)
   call   j_GetTickCount   ottiene un valore "casuale" chiamando l'API che ritorna il tempo da cui è attivo windows (ritorna il valore in eax)
   xor   dword_403273, eax   xora i primi 4 byte del seriale con TickCount
   xor   dword_403277, eax   xora i successivi 4 byte
   xor   dword_40327B, eax   xora i successivi 4 byte (in tutto 12)
   xor   dword_40327F, eax   in queste locazioni sono memorizzati i valori di confronto
   xor   dword_403283, eax   esegue lo stesso xor anche su queste
   xor   dword_403287, eax  
   and   dword_40327F, 627893h   and tra i primi 4 byte del valore di confronto e la maschera
   and   dword_403273, 627893h   and tra i primi 4 byte del seriale e la maschera
   mov   esi, offset dword_403273   copia in esi l'ind del seriale
   mov   edi, offset dword_40327F   copia in edi l'ind del valore di confronto
   mov   ecx, 0Ch   ecx=12 - numero di volte che deve essere eseguito il confronto
   rep cmpsb confronta byte per byte il seriale e il valore di confronto
   jz   short loc_401300   salta se sono uguali
 
Spiegazione di come si ricava il seriale corretto:
A noi interessa il valore di confronto prima delle istruzioni di xor con il TickCount. Quindi l'algoritmo di cui ci occupiamo arriva fino a prima della chiamata call j_GetTickCount.
Dobbiamo andare a leggere i 12 byte dalla locazione 00403283 (compresa) e elaborarli nel seguente modo:
- Li dividiamo in 3 gruppi di 4 bytes e ogni gruppo lo xoriamo con 01E960E4 (che è il valore equivalente ai tre xor indicati nel listato).
- Ora xoriamo ogni singolo byte con 0EDh.
Valutiamo ogni byte ottenuto con il codice ASCII corrispondente e se non avete sbagliato i calcoli dovreste ottenere: Cr4nB&Rr13$
Nota: il dodicesimo byte vi risulta 0 ed è giusto; infatti le stringhe devono terminale con il carattere Null(=0).
 
Passiamo al seriale basato sul nickname:
Inseriamo il nick (syscalo) e il seriale (1234567890) e premiamo il tasto register; sice poppa all'indirizzo 00401330 dove troviamo il seguente codice:
loc_401323:   push   14h   # max chr da leggere
   push   offset unk_403249   ind a cui salva il nome
   push   dword_402030   passa handle prima casella
loc_401330: call   j_GetWindowTextA   legge nome
   mov   dword_403241, eax   salva il numero di chr letti effettivamente
   cmp   eax, 6   confronta se il nick è almeno di   6 chr
   jl   loc_40141E   se è minore salta (visualizza msg che avvisa che la lunghezza deve essere almeno di 6 chr)
   call   j_GetTickCount   acquisisce valore casuale TickCount
   mov   dword_40323D, eax   salva il valore
   xor   ecx, ecx   azzera ecx
   xor   ebx, ebx   azzera ebx
   mov   edx, dword_40324A   copia in edx 4 byte del nome partendo dal secondo
   mov   eax, dword ptr unk_403249   copia in eax 4 byte del nome partendo dal primo
   imul   eax, edx   moltiplica i due valori (salva in eax)
   mov   dword ptr unk_403249, eax   sovrascrive 4 byte del nome dal primo
   xor   ecx, ecx   azzera ecx
   add   ecx, 4   somma 4 a ecx
   dec   dword_403241   decrementa la lunghezza del nome
loc_40136F:   inc   ecx   incrementa ecx
   mov   al, byte ptr unk_403249[ecx]   copia in al i byte del nome (dal 6°)
   add   al, byte ptr dword_40324A[ecx]   somma i byte del nome (dal 6°+7°)
   mov   byte ptr unk_403249[ecx], al   sovrascrive i byte del nome (dal 6°)
   cmp   ecx, dword_403241   confronta ecx con la lunghezza del nome
   jl   short loc_40136F   se minore esegue le istruzioni precedenti
   mov   eax, dword ptr unk_403249   copia 4 byte del nome dal primo in eax
   mov   ebx, dword_40324A+3   copia in ebx i secondi 4 byte del nome
   imul   eax, ebx   moltiplica i due valori (salva in eax)
   mov   dword ptr unk_403249, eax   sovrascrive 4 byte dal primo
   inc   dword_403241   incrementa la lunghezza del nome (riporta al valore corretto)
   xor   ecx, ecx   azzera ecx
   mov   ecx, dword_403241   copia la lunghezza del nome in ecx
loc_4013AB:   mov   eax, dword ptr unk_403249[ecx]   copia in eax 4 byte (la prima volta quelli dopo la fine del nome-dovrebbero essere 0)
   xor   eax, 4CF580Fh   xora con questo valore
   mov   dword ptr unk_403249[ecx], eax   sovrascrive i 4 byte
   dec   ecx   decrementa ecx (conteggio byte)
   test   ecx, ecx   verifica se vale 0
   jnz   short loc_4013AB   se non è zero esegue le istruzioni precedenti
 
dopo la seguente call andando a leggere i byte dal secondo del nome, troviamo la parte del seriale relativa al nome.(leggere un # di byte pari alla lunghezza del nome)
   call   sub_401438   procedura di elaborazione del nome
 
le seguenti elaborazioni servono solo a mascherare i valori del nome e del seriale prima del confronto:
loc_4013C6:   xor   eax, eax   azzera eax
   call   sub_4013EF   procedura che elabora il TC
   call   sub_4014AE   critta il nome con il TC elaborato
   push   14h   # max chr da leggere
   push   offset unk_40325D   ind in cui memorizzare il seriale
   push   dword_402034   handle seconda casella
   call   j_GetWindowTextA   legge seriale
   call   sub_40157A   critta il seriale con TC elaborato
   call   sub_4015EF   verifica la coincidenza del seriale elaborato con il nome elaborato (inoltre prosegue con la verifica del keyfile prima di ritornare)
   retn   ritorna dalla chiamata
sub_401206   endp   fine procedura
 
Qui riporto le procedure richiamate nella parte precedente del programma:

richiamata da call sub_401438; questa chiamata serve a portare in un range da 0 a 9 i caratteri del nome (in pratica si ottiene la parte del seriale che corrisponde all'elaborazione del nome)
sub_401438   mov   ecx, dword_403241   copia in ecx la lunghezza del nome
loc_40143E:   mov   al, byte ptr unk_403249[ecx]   copia i byte del nome dall'ultimo al primo
loc_401444:   cmp   al, 30h   confronta con 30h
   jl   short loc_401468   se minore salta
   nop  
   nop  
   nop  
   nop  
   cmp   al, 39h   confronta con 39h
   jg   short loc_401470   se maggiore salta
   nop  
   nop  
   nop  
   nop  
   mov   byte ptr unk_403249[ecx], al   sovrascrive il byte elaborato del nome
   dec   ecx   decremnta ecx (conteggio byte nome)
   test   ecx, ecx   testa se è 0
   cmp   ecx, 2   confronta ecx con 2
   jz   short loc_401478   se è uguale salta (diversifica l'elaborazione per i primi due byte)
   nop  
   nop  
   nop  
   nop  
   jnz   short loc_40143E   salta all'inizio della procedura (passa al byte succezzivo)
loc_401468:   add   al, cl   somma cl ad al
   cmp   al, 30h   fino a quando al diventa maggiore di 30h
   jl   short loc_401468   esegue le istruzioni precedenti
   jmp   short loc_401444   salta a ricontrollare il valore
loc_401470:   sub   al, cl   sottrae cl ad al
   cmp   al, 39h   fino a quando diventa minore di 39h
   jg   short loc_401470   esegue le istruzioni precedenti
   jmp   short loc_401444   salta a ricontrollare il valore
loc_401478:   mov   al, byte ptr unk_403249[ecx]   sovrascrive il byte del nome con quello elaborato
loc_40147E:   cmp   al, 30h   cofronta con 30h
   jl   short loc_40149E   se minore salta
   nop  
   nop  
   nop  
   nop  
   cmp   al, 39h   confronta con 39h
   jg   short loc_4014A6   se maggiore salta
   nop  
   nop  
   nop  
nop  
   mov   byte ptr unk_403249[ecx], al   sovrascrive il byte del nome con quello elaborato
   dec   ecx   decrementa ecx (conteggio byte nome)
   test   ecx, ecx   controlla se è 0
   jnz   short loc_401478   se diverso salta (passa al prossimo byte)
   jmp   loc_4013C6   ritorna dalla procedura (ind istruzione successiva alla call)
loc_40149E:   add   al, 4   somma 4 ad al
   cmp   al, 30h   fino a quando diventa maggiore di 30h
   jl   short loc_40149E   esegue le istruzioni precedenti
   jmp   short loc_40147E   salta a ricontrollare il valore
loc_4014A6:   sub   al, 5   sottrae 5 ad al
   cmp   al, 39h   fino a quando diventa minore di 39h
   jg   short loc_4014A6   esegue le istruzioni precedenti
   jmp   short loc_40147E   salta a ricontrollare il valore
sub_401438   endp   fine procedura
 
richiamata da call sub_4013EF (elabora il TickCount):
sub_4013EF   call j_GetTickCount ritorna TickCount
   mov   dword_403235, eax   salva in 403235
   mul   dword_403239 dx:ax=ax*1538h (403239 contiene il valore 1538h)
   inc   eax   ;incrementa eax
   mov   dword_403235, eax   ;salva il valore ottenuto
   retn   ritorna dalla chiamata
sub_4013EF   endp
 
richiamata da call sub_4014AE (critta il nome):
 
sub_4014AE   xor   ecx, ecx   azzera ecx
   xor   eax, eax   azzera eax
loc_4014B2:   inc   ecx   incrementa ecx (conteggio byte)
   mov   al, byte ptr unk_403249[ecx]   copia i byte del nome dal 2° in al
   mov   bl, byte ptr dword_403235   copia in bl il valore del TC elaborato nella procedura precedente
   xor   al, bl   xora i due valori
   mov   byte ptr unk_403249[ecx], al   sovrascrive i byte del nome
   cmp   ecx, dword_403241   esegue le istr prec fino per tutti i byte del nome (meno il primo)
   jl   short loc_4014B2   esegue le istruzioni precedenti
   retn   ritorna dalla chiamata
sub_4014AE   endp
 
richiamata da call sub_40157A (critta il seriale):
 
sub_40157A   xor   ecx, ecx   azzera ecx
   xor   eax, eax   azzera eax
loc_40157E:   inc   ecx   incrementa ecx
   mov   al, byte ptr unk_40325C[ecx]   copia in al il primo byte del seriale
   mov   bl, byte ptr dword_403235   copia in bl il valore del TC elaborato nella procedura sub_4013EF
   xor   al, bl   xora i due valori
   mov   byte ptr unk_40325C[ecx], al   sovrascrive i byte del seriale
   cmp   ecx, dword_403241   esegue le istruzioni precedenti per tanti byte del seriale quanti sono quelli del nome
   jl   short loc_40157E   esegue le istruzioni precedenti
   retn   ;ritorna dalla chiamata
sub_40157A endp
 
richiamata da call sub_4015EF (verifica il seriale basato sul nick e poi passa alla verifica del keyfile):
 
sub_4015EF   push   dword_402034   passa l'handle della seconda casella
   call   j_GetWindowTextLengthA   ritorna la lunghezza del seriale
   cmp   eax, 0Fh   il seriale deve essere di 15 chr
   jnz   loc_401108   se non sono 15 salta (seriale sbagliato)
   mov   esi, offset dword_40324A   copia ind del secondo byte del nome (il primo viene ignorato -qui-)
   mov   edi, offset unk_40325D   copia l'indirizzo del seriale
   mov   ecx, dword_403241   copia in ecx la lunghezza del nome
   rep   cmpsb   confronta il nome elaborato con il seriale elaborato
   jz   loc_4014F4   se sono uguali salta (seriale giusto - slata al controllo del keyfile)
   mov   dword_40329F, 91C2h   flag per la correttezza del seriale
   jmp   loc_4014FE   salta a proseguire l'esecuzione (controllo keyfile)
sub_4015EF   endp
 
Generazione e verifica del keyfile:
Il keyfile è generato interamente dal seriale basato sul nick; il programma procede nel seguente modo:
- elabora il seriale fino ad ottenere il keyfile di 700 bytes.
- critta i valori ottenuti con valori (circa) casuali.
- legge il keyfile e lo critta con gli stessi valori (circa) casuali.
- verifica che i byte così crittati coincidano.
 
Vediamo il disassemblato:
La routine di generazione del keyfile è molto lunga (e noiosa ;) quindi prima di tutto vediamo come procurarci un keyfile valido. Per fare ciò dobbiamo addentrarci nella routine che elabora il seriale riportata in seguito.
loc_4014F4:   mov   dword_40329F, 91B2h   salva il flag per il seriale basato sul nick (salta qui se il seriale basato sul nick è corretto)
loc_4014FE:   push   14h   passa # max chr da leggere
   push   eax   passa l'indirizzo a cui salvare i dati
   push   dword_402030   passa l'handle della prima casella
   call   j_GetWindowTextA   legge il nick (prima casella)
   mov   dword_403241, eax   copia il # di chr letti effettivamente in dword_403241
   mov   eax, offset unk_402BFC   copia in eax l'indirizzo a cui salvare il seriale
   add   eax, 14h   somma un offset di 14h
   push   14h   passa # max chr da leggere
   push   eax   passa l'ind a cui salvare il seriale
   push   dword_402034   passa l'handle della seconda casella
   call   j_GetWindowTextA   legge il seriale (seconda casella)
   call   sub_40167F   chiama la routine di elaborazione del seriale per il confronto con il keyfile
   call   sub_401B79   chiama routine di lettura del keyfile
   call   sub_401BCE   chiama routine di crittazione del keyfile
   mov   ebp, 4243484Bh   fa parte del trucco anti sice
   mov   ax, 4   copia 4 in eax
   int   3   chiama l'interrupt 3 (test anti SI-segnalato da Ida come Trap to Debugger ;)
   cmp   al, 4   controlla se in al c'è 4
   jnz   loc_4011EE   se è diverso salta (visualizza "msgbox chi usa SI")
   mov   esi, offset unk_402BFC   copia ind seriale elaborato in esi
   mov   edi, offset dword_4025F0   copia ind dati keyfile in edi
   mov   ecx, dword_4031FC   copia il numero di byte da confrontare in ecx (700 bytes)
   rep    cmpsb controlla i byte puntati da esi e edi
   jz   loc_401DE9   se sono uguali salta al controllo finale di tutti i test
loc_401560:   mov   dword_4032A3, 57A3h   salva flag keyfile (keyfile sbagliato)
   jmp   loc_401DF3   salta al controllo finale di tutti i test
 
Routine richiamate dal codice precedente:

routine di elaborazione del seriale:
per avere il keyfile è sufficiente eseguire il codice fino alla locazione 0040190Bh, dove termina l'elaborazione "non casuale" del seriale, ed andare a leggere 700 bytes a partire dalla locazione 00402BFCh. Questi 700 bytes vanno copiati così come sono in un file chiamato crykey.key; per fare ciò ci sono diversi metodi, dipende dal sw che usate; io ho usato il turbo debugger del tasm, eseguendo il programma fino all'indirizzo indicato e poi ho fatto un dump.
Note: la scrittura *(423423h) sta ad indicare il valore della locazione all'indirizzo 423423h; la scritta (base)seriale indica l'indirizzo del primo byte dei 700 che verranno generati dal seriale.
 
sub_40167F   mov   ecx, 23h   copia 23h(=35) in ecx (fine seriale)
   mov   bl, 23h   copia 23h in bl
   mov   eax, offset unk_402BFC   copia l'ind del seriale in eax
loc_40168B:   xor   [eax+ecx-1], bl   xora tutti i byte del seriale con 23h dal penultimo (escluso lo 0) al primo
   dec   ecx   decrementa ecx
   test   ecx, ecx   controlla se è 0
   jnz   short loc_40168B   esegue le istr prec
   mov   ecx, offset unk_402BFC   copia in ecx l'ind del seriale elaborato
   mov   al, [ecx]   copia in al il primo byte del (base)seriale
   mov   ah, [ecx+14h]   copia in ah il 20° byte del (base)seriale
   add   al, ah   somma e sovrascrive al
   mov   edx, dword_403241   copia in edx la lunghezza del nome
   mov   bl, [ecx+edx]   copia in bl i byte del seriale *((base)seriale+lunghezzaNome)
   mov   bh, [ecx+23h]   copia in bh l'ultimo byte del seriale
   add   bl, bh   somma e sovrascrive bl
   xor   al, bl   xora e sovrascrive al
   xor   ecx, ecx   azzera ecx
   mov   ebx, offset unk_402BFC   copia ind (base)seriale
loc_4016B7:   xor   [ebx+ecx], al   xora i byte da (base)seriale con al
   inc   al   incrementa al
   inc   ecx   incremento conteggio byte
   cmp   ecx, 23h   confronta ecx con 23h
   jl   short loc_4016B7   se minore esegue le istr prec
   mov   al, [ebx+5]   copia in al il 5° da (base)seriale
   add   al, 0Fh   somma 0Fh ad al
   xor   ecx, ecx   azzera ecx
   mov   ecx, 23h   copia 23h in ecx
loc_4016CE:   xor   [ebx+ecx], al xora i byte dal 35° al 1° con al
   dec   ecx   decrementa ecx
   test   ecx, ecx   controlla se 0
   jnz   short loc_4016CE   esegue le istr prec
   mov   edi, offset unk_402BFC   copia in edi ind (base)seriale
   mov   al, [edi+4]   copia il 4° byte in al
   mov   ecx, 23h   copia 35 in ecx
   mov   edx, 46h   copia 70 in ecx
loc_4016E8:   mov   bl, [edi+ecx]   copia in bl il byte *(edi+ecx)
   xor   bl, al   xora con al
   mov   [edi+edx], bl   sovrascrive *(edi+edx)
   dec   edx   decrementa edx
   dec   ecx   decrementa ecx
   test   ecx, ecx   azzera ecx
   jnz   short loc_4016E8   esegue le istr prec
   mov   eax, offset unk_402BFC   copia l'ind (base)seriale
   mov   ecx, 2BCh   copia 2BCh(=700) in ecx
   mov   ebx, dword_403241   copia in ebx la lunghezza del nome
   add   ebx, 0Fh   somma 0Fh a ebx
loc_401709:   xor   [eax+ecx], bl   xora *(eax+ecx) con bl
   dec   ecx   decrementa ecx
   test   ecx, ecx   controlla se è 0
   jnz   short loc_401709   esegue le istr prec
   mov   ebx, 0F1h   copia 0F1h in ebx
loc_401716:   xor   byte ptr [eax+ecx], 0F1h   xora *(eax+ecx) con 0F1h
   dec   ebx   decrementa ebx
   test   ebx, ebx   controlla se è 0
   jnz   short loc_401716   esegue le istr prec
   mov   ecx, 2BCh   copia 2BCh in ecx
   mov   eax, offset unk_402BFC   copia ind (base)seriale
   mov   ebx, 100D10Fh   copia 100D10h in ebx
loc_40172E:   xor   [eax+ecx], ebx   xora 4 byte *(eax+ecx) con ebx
   sub   ecx, 4   sottrae 4 a ecx
   test   ecx, ecx   controlla se è 0
   jnz   short loc_40172E   esegue le istr prec
   mov   eax, offset unk_402BFC   copia ind (base)seriale
   mov   edx, eax   copia eax in edx
   add   edx, 100h   somma 100h a edx
   mov   ecx, 14h   copia 14h in ecx
loc_40174A:   mov   bl, [eax+ecx]   copia in bl *(eax+ecx)
   xor   bl, [eax+ecx+0Ch]   xora bl con *(eax+ecx+0Ch)
   mov   [edx+ecx], bl   copia bl in *(edx+ecx)
   dec   ecx   decrementa ecx
   test   ecx, ecx   controlla se è 0
   jnz   short loc_40174A   esegue le istr prec
   xor   ecx, ecx   azzera ecx
   mov   eax, offset unk_402BFC copia ind (base)seriale
loc_401760:   mov   bl, byte ptr aHeadacheByQueq[ecx]   copia in bl i byte da copiare
   mov   [eax+ecx+28Ah],bl   copia bl in *(eax+ecx+28Ah)
   inc   ecx   incrementa ecx
   cmp   ecx, 15h   confronta con 15h
   jnz   short loc_401760   se diverso esegue le istr prec
   xor   ecx, ecx   azzera ecx
   mov   eax, offset unk_402BFC   copia ind (base)seriale
loc_40177A:   and   dword ptr [eax+ecx], 27934438h   esegue l'and dei byte *(eax+ecx) con 27934438h
   add   ecx, 4   somma 4 a ecx
   cmp   ecx, 2BCh   confronta ecx con 2BCh(=700)
   jnz   short loc_40177A   esegue le istr prec
   mov   eax, offset unk_402BFC   copia ind (base)seriale
   xor   edx, edx   azzera edx
   mov   cl, [eax]   copia *(eax) in cl
loc_401795:   rol   dword ptr [eax+edx], cl   rol di [cl] volte la dword *(eax+edx)
   inc   edx   incrementa edx
   cmp   edx, 2BCh   confronta edx con 2BCh
   jnz   short loc_401795   esegue le istr prec
   mov   eax, offset unk_402BFC   copia ind (base)seriale
   xor   ecx, ecx   azzera ecx
   mov   edx, dword_402BF4   copia dword *(402BF4h) in edx
loc_4017AE:   xor   [eax+ecx], edx   xora *(eax+ecx) con edx
   add   ecx, 4   somma 4 a ecx
   cmp   ecx, 2BCh   confronta ecx con 2BCh
   jnz   short loc_4017AE   esegue le istr prec
   xor   ecx, ecx   azzera ecx
   mov   edx, offset unk_402BFC   copia ind (base)seriale
loc_4017C3:   mov   eax, [edx+ecx]   copia la dword *(edx+ecx) in eax
   shr   eax, 2   shift a dx eax di 2
   mov   [edx+ecx], eax   sovrascrive *(edx+ecx) con eax
   add   ecx, 4   somma 4 a ecx
   cmp   ecx, 2BCh   confronta con 700
   jnz   short loc_4017C3   esegue le istr prec
   mov   eax, offset unk_402BFC   copia ind (base)seriale
   mov   ebx, [eax+5]   copia in ebx *(eax+5)
   add   eax, 110h   somma 272 a eax
   xor   ecx, ecx   azzera ecx
loc_4017E6:   xor   [eax+ecx], ebx   xora la dword *(eax+ecx) con ebx
   add   ecx, 4   somma 4 a ecx
   cmp   ecx, 290h   confronta ecx con 656
   jnz   short loc_4017E6   esegue le istr prec
   xor   ecx, ecx   azzera ecx
   mov   eax, offset unk_402BFC   copia ind (base)seriale
   mov   edx, offset unk_402BFC   copia ind (base)seriale
   add   edx, 0C0h   somma 192 a edx
loc_401806:   mov   ebx, [eax+ecx]   copia in ebx la dword *(eax+ecx)
   xor   ebx, 0D468B23Ah   xora la dword con 0D468B23Ah
   mov   [edx+ecx], ebx   copia ebx in *(edx+ecx)
   add   ecx, 4   somma 4 a ecx
   cmp   ecx, 40h   confronta con 40h
   jnz   short loc_401806   esegue le istr prec
   xor   ecx, ecx   azzera ecx
   mov   eax, offset unk_402BFC   copia ind (base)seriale
   mov   ebx, offset unk_402BFC   copia ind (base)seriale
   mov   edx, offset unk_402BFC   copia ind (base)seriale
   add   ebx, 50h   somma 50h a ebx
   add   edx, 0A0h   somma 0A0h a edx
loc_401834:   mov   edi, [eax+ecx]   copia in edi *(eax+ecx)
   xor   edi, [edx+ecx]   xora edi con *(edx+ecx)
   mov   [ebx+ecx], edi   copia edi in *(ebx+ecx)
   add   ecx, 4   somma 4 a ecx
   cmp   ecx, 40h   confronta con 40h
   jnz   short loc_401834   esegue le istr prec
   xor   ecx, ecx   azzera ecx
   mov   eax, offset unk_402BFC   copia ind (base)seriale
   mov   ebx, offset unk_402BFC   copia ind (base)seriale
   mov   edx, offset unk_402BFC   copia ind (base)seriale
   add   edx, 80h   somma 80h a edx
   add   ebx, 110h   somma 110h a ebx
loc_401862:   mov   edi, [eax+ecx]   copia *(eax+ecx) in edi
   mov   esi, [edx+ecx]   copia *(edx+ecx) in esi
   xor   edi, esi   xora edi con esi
   mov   [ebx+ecx], edi   copia edi in *(ebx+ecx)
   add   ecx, 4   somma 4 a ecx
   cmp   ecx, 28h   confronta con 28h
   jnz   short loc_401862   esegue le istr prec
   xor   ecx, ecx   azzera ecx
   mov   eax, offset unk_402BFC   copia ind (base)seriale
   mov   ebx, offset unk_402BFC   copia ind (base)seriale
   add   ebx, 98h   somma 98h a ebx
loc_401887:   rol   dword ptr [eax+ecx], 13h   rotazione a sx 13h volte la dword *(eax+ecx)
   rol   dword ptr [ebx+ecx], 8   rotazione a dx 8 volte la dword *(ebx+ecx)
   add   ecx, 4   somma 4 a ecx
   cmp   ecx, 98h   confronta ecx con 98h
   jnz   short loc_401887   esegue le istr prec
   mov   eax, offset unk_402BFC   copia ind (base)seriale
   mov   ebx, offset unk_402BFC   copia ind (base)seriale
   add   ebx, 130h   somma 130h a ebx
   xor   edi, edi   azzera edi
   xor   ecx, ecx   azzera ecx
   add   edi, 130h   somma 130h a edi
loc_4018B4:   mov   edx, [ebx+edi]   copia *(ebx+edi) in edx
   xor   edx, [eax+ecx]   xora edx con *(eax+ecx)
   add   ecx, 4   somma 4 a ecx
   sub   edi, 4   sottrae 4 a edi
   cmp   ecx, 130h   confronta ecx con 130h
   jnz   short loc_4018B4   esegue le istr prec
   mov   eax, offset unk_402BFC   copia ind (base)seriale
   mov   ebx, offset unk_402BFC   copia ind (base)seriale
   add   ebx, 140h   somma 140h a ebx
   xor   ecx, ecx   azzera ecx
loc_4018DA:   mov   edx, [eax+ecx]   copia *(eax+ecx) in edx
   xor   edx, [ebx+ecx]   xora edx con *(ebx+ecx)
   mov   dword ptr unk_4032C5[ecx], edx   copia edx in *(4032C5h+ecx) -usata come locazione temporanea per l'elaborazione dei dati-
   add   ecx, 4   somma 4 a ecx
   cmp   ecx, 140h   confronta con 140h
   jnz   short loc_4018DA   esegue le istr prec
   mov   eax, offset unk_402BFC   copia ind (base)seriale
   add   eax, 140h   somma 140h a eax
loc_4018FB:   mov   edx, dword ptr unk_4032C5[ecx]   copia in edx *(4032C5h+ecx)
   mov   [eax+ecx], edx   copia edx in *(eax+ecx)
   sub   ecx, 4   sottrae 4 a ecx
   test   ecx, ecx   controlla se è 0
   jnz   short loc_4018FB   esegue le istr prec
   mov   eax, offset unk_402BFC   fine elaborazione non casuale del seriale
 
da qui inizia la crittazione dei 700 byte ottenuti, per poi effettuare il confronto con il keyfile crittato.
In sostanza tutte le istruzioni precedenti operano in modo da costruire 700 byte partendo dal seriale; questo viene realizzato elaborando fra loro i byte alle diverse locazioni in questa zona di memoria; se volete realizzare un generatore di key file dovete prendere queste istruzioni e tradurle in un linguaggio ad alto livello (come il C) oppure potete "costruirci intorno" un programma in assembler.
 
Routine di lettura del keyfile:
sub_401B79   push   2   passa la modalità di apertura del keyfile
   push   offset dword_402050   passa info sul tipo di file
   push   offset aCrykey_key   passa ind in cui è memorizzato il nome del keyfile
   call   j_OpenFile   apre il file
   mov   dword_402048, eax   salva l'handle del file
   cmp   eax, 0FFFFFFFFh   controlla se l'handle è nullo (=-1)
   jz   loc_401560   se si salta
   push   0  
   push   0  
   push   dword_4032A7   passa l'offset
   push   dword_402048   passa l'handle del file
   call   j_SetFilePointer   setta il puntatore al file (come seek in C)
   push   0   passa ind struttura dati (0=nessuna)
   push   offset dword_402320   passa ind a cui salvare # byte letti
   push   dword_4031FC   passa il # di byte da leggere
   push   offset dword_4025F0   passa ind a cui salvare i byte letti
   push   dword_402048   passa l'handle del file
   call   j_ReadFile   legge il file
   retn   ritorna dalla chiamata
sub_401B79   endp   fine routine

routine di crittazione dei dati del keyfile:
La crittazione del keyfile è identica a quella del seriale elaborato ed è effettuata con valori pseudo casuali. A mio parere non è molto importante vedere come viene effettuata visto che il keyfile si può già ottenere come visto sopra (potrebbe essere utile vederla per vedere un po' di assembler, ma io per adesso ne ho abbastanza ;-).
Siamo quasi giunti al termine; resta solo da vedere la parte finale di verifica di tutti i check:
durante i vari controlli vengono salvati dei valori diversi in base ai vari test. Qui vengono sommati tra loro e poi ad un altro valore dato dal numero di visualizzazioni della msgbox di about (deve essere visualizzata 4 volte prima del test del keyfile). Infine il valore così ottenuto viene xorato e rollato per giungere al valore finale di confronto.
loc_401DE9:   mov   dword_4032A3, 57B3h   salva questo valore se il keyfile è giusto
loc_401DF3:   xor   eax, eax   azzera eax (salta qui se il keyfile è sbagliato)
   mov   eax, dword_40329B   copia in eax il flag di controllo del primo seriale
   mov   ebx, dword_40329F   copia in ebx il flag di controllo del seriale basato sul nick
   add   eax, ebx   somma ebx a eax
   mov   ebx, dword_4032A3   copia in ebx il flag di controllo del keyfile
   add   eax, ebx   somma ebx a eax (in pratica eax contiene la somma dei flag dei tre test)
   mov   ebx, dword_403431   trucco by que ;) il valore a questa locazione viene incrementato ogni volta che viene visualizzata la msgbox di About -per individuare il significato di questo valore è sufficiente andare a vedere dove viene scritto, provate-
   add   eax, ebx   somma ebx a eax
   mov   ecx, 5723814Ah   copia il valore in ecx
   xor   eax, ecx   xora la somma dei flag (eax) con il valore (ecx)
   rol   eax, cl   rol a sx di 4Ah volte
   cmp   eax, 8982D55Ch   test finale
   jnz   loc_401108   se sono diversi salta (non viene visualizzato alcun msgbox)
   call   sub_401B26   altrimenti visualizza la msgbox di congratulazioni, finalmente ;-)
 
Ok, se avete resistito fino a qui sarete miei complici nella spedizione punitiva a Que per questa lezione ;)))
A parte gli scherzi, io ho scoperto il suo indirizzo di casa!!!-) Ma va, e come? :)
va bhe, è meglio che me ne vada....
×bye to all×
syscalo
 
Note finali

E' dura scrivere i tute dopo l'ultimo dell'anno.........

Disclaimer

No disclaimer nedeed

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

Home   Anonimato   Assembly    ContactMe  CrackMe   Links   
NewBies   News   Forum   Lezioni  
Tools   Tutorial   Search

UIC