Fractal eXtreme 1.60b
(trovare facilmente il seriale, capire come viene generato e creare un rudimentale key-maker con HLA)

Data

by "ZedTec"

 

29/02/2001

UIC's Home Page

Published by Quequero


Il programma non era difficile da crackare ma devo riconoscere che l'idea di usare HLA per il keygen è stata davvero una bella pensata, bravo zed :)

 

....

E-mail: [email protected]

....

Difficoltà

(*)NewBies ( )Intermedio ( )Avanzato ( )Master

 

Troveremo tramite un minimo uso di SIce il seriale giusto e creeremo con HLA un piccolo key-maker.


Fractal eXtreme 1.60b
(trovare facilmente il seriale,capire come viene generato e creare un rudimentale key-maker con HLA)
Written by ZedTec

Introduzione

La nascita di questo tutorial è data dal mio interesse verso il reverse engineering. Tra i tanti tutorial letti, decisi di tradurre (per me) uno di un certo Dr.ME! che altro non si trattava di una raccolta di spiegazioni di protezioni ecc... Dopo aver trovato casualmente un programma che utilizzava un tipo di protezione (non si tratta di una protezione vera e propria ma di una routine per calcolare la lunghezza del seriale immesso) spiegata dal sopracitato, ho deciso di utilizzare quello che ho acquisito come tut. Mi scuso con chi sta leggendo questo in caso di errori, imprecisoni e stronzate varie riportate. In futuro se possibile, vorrei pubblicare la traduzione dell'intero tutorial di Dr.ME! (sono 55 pagine in file di testo) oppure andate su zencrack2.cjb.net e scaricatevi l'originale. (che è meglio)
 
N.B. il testo della routine per il calcolo della lunghezza della stringa è stato liberamente tradotto da me (ZedTec), gli eventuali diritti e/o copyright sono da attribuirsi a Dr.ME!.

Tools usati

SoftIce
 
W32dasm

URL

www.cygnus-software.com

Notizie sul programma

Il programma serve per creare, salvare ecc. frattali. Sinceramente non ho perso molto tempo per capire come funziona e, a vista d'occhio, un vecchio prog DOS (di cui non ricordo il nome...tipo...XAOS95 o qualcosa di simile) mi è sembrato mooolto meglio.
(...oltre il danno, la beffa!!)

Essay

Calcolare la lunghezza di una stringa immessa

(preso da: Basic Tutorials on Key Generation and Key File Routines by Dr.ME!
 liberamente tradotto da me)   

xxxx:00406587 mov ecx, FFFFFFFF

N.B. Ogni volta che vedrai il valore FFFFFFFF spostato in ecx,
quasi sicuramente ti troverai all'inizio di una routine che determinerà
la lunghezza di stringhe o numeri.


 xxxx:0040658C sub eax, eax
 xxxx:0040658E repnz ; ripeti affinchè 0 
 xxxx:0040658F scasb ; confronta AL con il byte a ES:DI 
                     ; e setta il flag.
                     ; Questa è una istruzione comune
                     ; per quanto riguarda il calcolo
                     ; della lunghezza della stringa 
 xxxx:00406590 not ecx ; ecx = lunghezza stringa + 1
 xxxx:00406592 dec ecx ; lunghezza stringa 
 xxxx:00406593 je 004066A4 ; se ecx=0 salta a 4066A4
                           ; altrimenti continua 

Questo codice calcola il numero dei caratteri da noi immessi; il risultato sarà 'salvato' in ECX.

FRACTAL eXtreme 1.60b
(by ZedTec)

...aprendo il programma noteremo con finto stupore un nag che ci ricorda che non siamo registrati...
Andiamo ora a vedere come funziona la registrazione.
Innanzitutto, bisogna compilare una form (da Help ---> Purchase Fractal eXtreme ---> I Accept) con i nostri dati; Dopo come tipo di pagamento scegliete Check(By Mail Only) ossia di volere comprare il prodotto tramite posta.(oppure, se avete pazienza scegliete una carta di credito e riempite gli appositi spazi)
A questo punto dopo aver cliccato su DONE, il prog creerà il file rsagent.ini nella directory c:\windows.
Se aprite il file con un editor di testo (tipo notepad) vedrete che contiene tutte le informazioni da noi inserite più il nostro codice personale.
Qui il codice può essere cambiato a nostro piacimento(!), infatti il prog al momento della registrazione non verificherà se questo corrisponde ai dati inseriti prima.
Ora torniamo al prog e andiamo a registrarlo (HELP ---> PURCHASE FRACTAL EXTREME) apparirà una form con i dati del nome, cognome immessi prima, il codice personale e la spazio appunto, per inserire il codice.

* fondamentale *
Inserite un seriale di 10 (dieci) caratteri e date O.K.

Dopo il messaggio di errore, convalidate e entrate in SoftICE (ctrl + D) e mettete il solito break point:

bpx getdlgitemtexta

... ora uscite da SIce (X e invio oppure F5) e premete su OK (sempre con il falso codice seriale da 10 cifre inserito) entreremo in SIce, premiamo F11 per tornare all'istruzione chiamante e vediamo che siamo dentro la DLL RSAGNT32.
(per meglio dire, il debugger è entrato in funzione nella parte di codice per la generazione del seriale, contenuto appunto nella DLL)
Noteremo la routine per la lunghezza della stringa.

      call EBP          ---> 
     mov ECX, FFFFFFFF --->
     sub EAX, EAX      ---> ROUTINE CALCOLO 
     repnz scasb       ---> LUNGHEZZA STRINGA
     not ECX           --->
     dec ECX           --->
     cmp ECX, 0A ---> qui controlla che il seriale immesso da noi sia
                 ---> di 10 cifre (Ah = 10 decimale)
     jz 10029460 ---> se = 10 cifre salta altrimenti continua
     ...
     mov EDI, 10029460 ---> copia il codice personale in EDI
     mov ECX, FFFFFFFF
     sub EAX, EAX
     REPNZ SCASB 
     not ECX 
     sub EDI, ECX
     mov EAX, ECX
     shr ECX, 02
     mov ESI, EDI ---> copia il codice personale in ESI
     lea EDI, [ESP+000000D8]
     REPZ MOVSD
     mov ECX, EAX
     and ECX, 03
     REPZ MOVSB
     lea ECX, [ESP+0000010C] ---> * sposta il seriale giusto in ECX!! *
     mov EAX, 1002EA34
     push ECX  

basterà steppare (F10) fino all'istruzione successiva e digitare

d ecx (invio)

per vedere il contenuto di ecx, ossia il seriale.

Questo è possibile solamente se prima avete eseguito il punto * fondamentale *
altrimenti il seriale giusto non verrà generato.
La generazione del seriale avviene nelle istruzioni successive.

      add EAX, B6
     lea ECX, [ESP+000000DC]
     push EAX ---> immette la stringa per generare il seriale
              ---> Gy549nmwF2 (contenuta nell'eseguibile)
     push ECX
     call 1004CB0 ---> chiamata alla routine che genera il seriale
     lea ecx, [esp+00000118]
     add ESP, 0C
     push 1002F630 ---> seriale inserito da noi
     push ECX ---> seriale giusto

Andiamo a vedere in che modo viene generato il seriale.
Arrivati con F10 sopra alla call, premiamo F8 ovvero step into (salta dentro).
(nel caso vi appaiano tutte scritte INVALID, premete di nuovo F8)
Il codice per la generazione del seriale è il seguente (preso con W32dasm):

CALL at Addresses:
|:10001FAB , :100046D4
|
:10004CB0 sub esp, 00000018

* StringData Ref ->"PQYZMERUOA"
     |
     :10004CB3 mov ecx, 10021D78 ---> copia in ECX la stringa PQYZMERUOA
     :10004CB8 lea edx, dword ptr [esp]
     :10004CBC push ebx
     :10004CBD push esi
     :10004CBE mov eax, dword ptr [ecx] ---> copia in EAX 4 byte (caratteri) di ECX
     :10004CC0 push edi
     :10004CC1 mov ebx, dword ptr [ecx+04] ---> copia in EBX 4 byte dal quarto
                                           ---> byte di ECX
     :10004CC4 push ebp
     :10004CC5 mov dword ptr [edx], eax ---> copia in EDX 4 byte di EAX 
     :10004CC7 mov bp, word ptr [ecx+08] ---> copia in BP il valore dall'ottavo      
                                         ---> byte di ECX
     :10004CCB mov al, byte ptr [ecx+0A]
* StringData Ref ->"JIKLICBXZC"
     |
     :10004CCE mov ecx, 10021D6C ---> copia in ECX la stringa JIKLICBXZC 
     :10004CD3 mov dword ptr [edx+04], ebx ---> copia al quarto byte di EDX
                                           ---> il valore in EBX
     :10004CD6 mov word ptr [edx+08], bp   ---> EDX ritorna al valore PQYZMERUOA
     :10004CDA mov ebx, dword ptr [ecx+04] ---> copia dal 4 byte di ECX      
                                           ---> 4 byte in EBX
     :10004CDD mov bp, word ptr [ecx+08] ---> ...e via dicendo...
     :10004CE1 mov byte ptr [edx+0A], al
     :10004CE4 lea edx, dword ptr [esp+1C]
     :10004CE8 mov eax, dword ptr [ecx]
     :10004CEA xor di, di
     :10004CED mov dword ptr [edx], eax  
         :10004CEF mov al, byte ptr [ecx+0A] 
     :10004CF2 mov esi, dword ptr [esp+34]
     :10004CF6 mov ecx, dword ptr [esp+30] ---> copia in ECX la stringa per la
                                           ---> generazione del seriale
                                           ---> (quella immessa poco prima 
                                           ---> della chiamata) Gy549nmwF2

N.B. La stringa è presente non in questa DLL ma nell'eseguibile e la sua lunghezza è maggiore di 10 caratteri ma per la generazione del seriale vengono usati solamente i primi 10 ossia Gy549nmwF2. Molto probabilmente la stringa viene usata in tutta la sua lunghezza per generare il codice personale.

     :10004CFA mov dword ptr [edx+04], ebx
    :10004CFD mov word ptr [edx+08], bp 
                                        ---> in questo punto si ha in EDX il 
                                        ---> valore copiato all'inizio
                                        ---> in ECX: JIKLICBXZC
        :10004D01 mov byte ptr [edx+0A], al

 

In questa parte di codice vengono preparati i registri per le operazioni successive
ossia per la generazione del seriale:
* Jump at Address:
     |:10004D4B(C)
     |
     :10004D04 mov eax, dword ptr [esp+2C] ---> copia il codice personale in EAX
     :10004D08 mov dl, 19
     :10004D0A movsx ebp, di ---> contatore 
     :10004D0D mov bl, 19
     :10004D0F mov al, byte ptr [ebp+eax] ---> copia una cifra (carattere) del
                                          ---> codice personale in AL
     :10004D13 xor al, byte ptr [esp+ebp+10] ---> XOR tra cifra e PQYZMERUOA
     :10004D17 xor al, byte ptr [ebp+ecx] ---> XOR con la stringa per la
                                          ---> generazione del seriale G..
     :10004D1B sub ah, ah
     :10004D1D div dl
     :10004D1F mov al, ah
     :10004D21 mov dl, byte ptr [esp+ebp+1C] ---> copia un carattere di J.. in DL
     :10004D25 add al, 41 ---> aggiunge 41h in AL
     :10004D27 mov byte ptr [ebp+esi], al ---> copia il risultato in [ebp+esi]
     :10004D2B xor dl, byte ptr [ebp+ecx] ---> XOR tra un carattere di J.. e      
                                          ---> un carattere della stringa G..
     :10004D2F xor dl, al ---> XOR tra risultato precedente e AL
     :10004D31 mov al, dl ---> copia il risultato in AL
     :10004D33 sub ah, ah ---> sottrae 
     :10004D35 div bl ---> divide
     :10004D37 mov al, ah ---> copia 
     :10004D39 add al, 41 ---> aggiunge 41h e si ha il N
                          ---> carattere del seriale giusto
     :10004D3B cmp al, 4F ---> lo confronta con il carattere "O"
     :10004D3D jne 10004D41 ---> se diverso, salta 
     :10004D3F mov al, 58 ---> altrimenti diventa il carattere "X"
* Jump at Address:
     |:10004D3D(C)
     |
     :10004D41 inc di 
     :10004D43 mov byte ptr [ebp+esi], al
     :10004D47 cmp di, 000A ---> verifica se DI = A (10 in decimale) 
     :10004D4B jl 10004D04 ---> salta se minore (DI < 10)
     :10004D4D mov [esi+0A], 00
     :10004D51 pop ebp
     :10004D52 pop edi
     :10004D53 pop esi
     :10004D54 pop ebx
     :10004D55 add esp, 00000018
     :10004D58 ret ---> ritorna 

Riassumendo, i punti fondamentali per la generazione del seriale sono:

(oltre alla sottrazione di AH e divisione di BL):

1. XOR tra N carattere del codice personale e il relativo N carattere della stringa "PQUIZMERUOA"      
2. XOR tra risultato precedente e relativo N carattere della stringa "Gy5..."
3. XOR tra N carattere stringa "JIKLICBXZC" e relativo N carattere della stringa  
   "Gy5..." 
4. XOR tra risultato precedente e risultato punto 2
6. Aggiungere 41h al risultato della sottrazione e divisione
7. Eventuale modifica del carattere del seriale in caso fosse una "O", diventa
   una "X" 
Ora, creiamoci un rudimentale keymaker con HLA.
 
*piccola parentesi su HLA*
HLA è l' acrostico di High Level Assembly, troverete tutte le informazioni al riguardo sul sito webster.cs.ucr.edu
Per l'istallazione (più che installazione si dovrebbe parlare di copiatura files) è necessario avere oltre all'eseguibile del compilatore (HLA.EXE) i seguenti files aggiornati:
(se avete il masm installato non ne avete bisogno)
 
- ML.exe ossia il compilatore del masm
- ML.err file con le descrizione degli errori riguardanti il compilatore
- LINK.exe il linker del masm
- i file libreria KERNEL32.lib e USER32.lib
- MSPDB50.dll
 
Questi sono reperibili su internet ma se non possedete il masm e volete fare una cosa moooolto più veloce, andate sul sito (di) iczelion.cjb.net (che fornisce anche tutorial sul HLA) e scaricatevi il pacchetto MASM32.EXE installatelo, createvi una directory dove mettere il HLA e copiate i file soprascritti(per i file lib copiateli tutti).
Per far funzionare l'hla dovete inizializzare il vari collagementi alle librerie ecc. qui potete fare in due modi, o modificate il file autoexec.bat nel seguente modo:
 
 
path=c:\percorso dove avete installato HLA;%path
set lib=c:\percorso dove avete installato HLA\hlalib;%lib%
set include=c:\percorso dove avete installato HLA\include;%include%
set hlainc=c:\percorso dove avete installato HLA\include
set hlalib=c:\percorso dove avete installato HLA\hlalib\hlalib.lib 
oppure createvi un file .BAT con i comandi qui sopra che però dovrete lanciare ogni volta che volete usare HLA.
Questo file bat è scaricabile dal sito del HLA (si chiama IHLA.bat) ed è contenuto nel file zip contentente la documentazione.N.B. il file IHLA.bat è configurato in modo che avete installato HLA come directory principale in c: ossia C:\HLA.
Già che ci siete createvi un secondo file bat che cancellerà alla sua esecuzione i file di compilazione dell'eseguibile ovvero *.asm *.link *. obj, nel seguente modo:
 
@echo off
del *.asm
del *.link
del *.obj
cls
 
è importante che questo file risieda dove è HLA altrimenti cancellerà i file con quella estensione nella directory in cui si trova!!

Non aspettatevi un granchè di key-maker, e comunque è una applicazione per la console non una strafigata con la gui :-(

Ecco il sorgente:

/* PURAMENTE A SCOPO DIDATTICO
Non mi assumo nessuna responsabilità
dell'uso di questa merda di sorgente.
Siete pregati di non distribuire né questo
né possibilmente l'eventuale eseguibile.*/

program keyz1; //diamo un nome al programma
#include("stdlib.hhf");

// qui dichiariamo le variabili
static

  codice:string; 
   
readonly 
   testo:string:="Fractal eXtreme 1.xx KeyMaker by ZedTec";
        testo2:string:="Inserisci il codice personale: ";
        stringa1:string:="PQYZMERUOA";
        stringa2:string:="JIKLICBXZC";
        stringa3:string:="Gy549nmwF2";
// fine dichiarazione variabili

begin keyz1; //inizio programma
forever //iniziamo il ciclo dei controlli
console.cls(); //puliamo lo schermo
stdout.put(testo); //visualizziamo l'intestazione
stdout.newln(); //andiamo a capo (saltiamo la riga corrente)
stdout.put(testo2); //visualizziamo il messaggio per l'input
stdin.a_gets(); //attendiamo per il codice personale (che viene spostato in EAX)
mov(eax,codice); //e qui invece lo spostiamo nella stringa 'codice'

if((type str.strRec[eax]).length != 10) then //controlla se il codice
                                             //e' diverso ( != )
                                             //di 10 cifre 
    //di consequenza scrive (sulla barra del nome) il relativo messaggio di errore
        console.setTitle("Il codice personale deve essere di 10 cifre");
        else //altrimenti
                
                try //inizio controllo eccezioni
                conv.strToi64(eax,0); //prova a fare una conversione numerica del codice immesso
        
                break; //se a buon fine esce dal ciclo
        
                exception(ex.ConversionError) //altrimenti segnala un errore
                console.setTitle("Il codice personale deve essere NUMERICO");


                endtry; //fine controllo eccezioni
endif; //fine ciclo
endfor; //fine ciclo controlli
   

stdout.put(nl,"Il seriale e': "); //salta una riga e scrive il testo

//questa e' l'intera routine per la generazione
//del seriale 'convertita' per HLA, infatti come potete notare
//non si ha una sintassi DESTINATARIO,SORGENTE
//ma una SORGENTE,DESTINATARIO tipica del PASCAL.
//Inoltre bisogna specificare che si tratta di valori esadecimali tramite il prefisso $.
//Commenterò solamente i cambiamenti apportati da me

mov(stringa1,ecx);
lea((type dword [esp]),edx);
push(ebx);
push(esi);
mov((type dword[ecx]),eax);
push(edi);
mov((type dword [ecx+$04]),ebx);
push(ebp);
mov(eax,(type dword [edx]));
mov((type word [ecx+$08]),bp);
mov((type byte [ecx+$0A]),al);

mov(stringa2,ecx);
mov(ebx,(type dword [edx+$04]));
mov(bp,(type word [edx+$08]));
mov((type dword [ecx+$04]), ebx);
mov((type word [ecx+$08]),bp);
mov(al,(type byte [edx+$0A]));
lea((type dword [esp+$1C]),edx);
mov((type dword [ecx]), eax);
xor(di,di);
mov(eax,(type dword [edx]));
mov((type byte [ecx+$0A]), al);
mov((type dword [esp+$34]),esi);
mov(stringa3,ecx);
mov(ebx,(type dword [edx+$04]));
mov(bp,(type word [edx+$08]));
mov(al,(type byte [edx+$0A]));

routine: //inizio routine calcolo seriale
mov(codice, eax);
mov($19,dl);
movsx(di,ebp);
mov($19,bl);
mov((type byte [ebp+eax]),al);
xor((type byte [esp+ebp+$10]),al);
xor((type byte [ebp+ecx]),al);
sub(ah,ah);
div(dl);
mov(ah,al);
mov((type byte [esp+ebp+$1C]),dl);
add($41,al);
xor((type byte [ebp+ecx]),dl);
xor(al,dl);
mov(dl,al);
sub(ah,ah);
div(bl);
mov(ah,al);
add($41,al);

if(al='O') then //confronta se il N carattere del seriale contenuto il al
mov($58,al);    //sia una O, in tal caso lo fa diventare una X
endif; 
inc(di); //incrementa di
stdout.putc(al); //nella routine originale gli N caratteri del seriale
                                 //veniva copiati in [esi+ebp], io per comodità glieli faccio visualizzare
                                 //uno alla volta
if(di<10) then //controlla se di è minore di 10
jmp routine;    //salta all'inizio della routine
endif;
stdout.newln(); //salta una riga
stdout.put("- PREMI INVIO PER FINIRE -");
stdin.a_gets();
end keyz1; //fine programma

Per compilare ora questo sorgente basterà scrivere:


hla (nome che avete dato al sorgente)
 
ZedTec

Note finali

Indubbiamente poteva venir fatto qualcosa di meglio...e forse con meno codice, scusate...
Questo tut è stato "testato" sia sulla versione 1.21 che sull'ultima (al 15/02/2001), 
ovvero la 1.60b. Credo che funzioni in tutte le versioni.


Dedico questo tutorial a:
- Michela per avermi sopportato da quando ci conosciamo. 
- P. Luca per aver creato qualcosa di più potente (quasi) dei Twilight!!! (il mitico P.UTILITY).
- ...e gli altri amici cazzoni...(Domenico e Gianluca questo è per voi)
- quel bastardo di Bejelit_Scarlatto che se non dice all'amica sui che è molto carina, 
  utilizzerà presto il suo hard-disk come posacenere.


Volevo inoltre ringraziare chi ha permesso la pubblicazione di questo tutorial e chiunque abbia 
apportato correzioni o miglior delucidazioni...(ma come cazzo parlo?) 

Disclaimer

NON MI ASSUMO NESSUNA RESPOSABILITA' RIGUARDANTE IL CONTENUTO DI QUESTA PAGINA.