Capture Express 2000 v1.1
registriamoci

Data

by "ZaiRoN"

 

03-02-2k+1

UIC's Home Page

Published by Quequero


scritta sur muro:

'nella mì vita ho visto più comete 'he fie'

 ...anonimo

Complimenti Zai, il tute è molto molto completo, la routine non era neanche poi tanto semplice ma sei cmq riuscito a spiegarla davvero bene, bravo!

scritta su di un muro:

'nella mia vita ho visto più comete che donne'

...anonimo

....

Home page se presente: non presente...
E-mail: [email protected]

....

Difficoltà

(Z)NewBies ( )Intermedio ( )Avanzato ( )Master

 

cosa si fa oggi? vediamo come è possibile registrare questo programma...


capture express 2000 v1.1

registriamoci
Written by ZaiRoN

Introduzione

il nostro scopo è quello di registrare il programma con una giusta combinazione nome-codice.
l'algoritmo di protezione non è complicatissimo; basterà un pò d'attenzione vista la presenza di una discreta quantità di codice inutile

Tools usati

DeDe
GetType
SoftIce

URL o FTP del programma

http://www.captureexpress.com

Notizie sul programma

direttamente dall'help del programma: "Capture Express is a screen capture utility.  It brings unprecedented ease and functionality to the capturing of areas by allowing you to both stretch and move the area grabber.  It also sports virtually unlimited shape captures (diamonds, stars, polygons, etc) with optional borders and shape masking.  It is also one of the few capture utilities that allows you to capture and send the image via e-mail at the same time." mi sembra chiaro!

Essay

ehilà a tutti...
bando alle ciance. lanciamo il programma e notiamo subito un leggero cambiamento nella nostra system tray. tasto destro del mouse sulla nuova icona e cominciamo a girellare tra le varie voci del menù. cosa stiamo cercando? ovvio, un form di registrazione. di solito lo mettono nel form dell'about ma stavolta pare proprio che non ci sia. magari ce lo propongono quando chiudiamo il programma? bah. chiudiamo il programma e tac. ci restano soltanto 30 giorni per registrare il proggie:)))))
 
1° parte: alla ricerca del form di registrazione
visto che del form di registrazione non se ne vede la minima ombra cerchiamo di carpire più informazioni possibili sul programma. un ottimo strumento che ci aiuta a tale scopo è gettype. usiamolo (sapete usarlo vero???). l'utilizzo è una puttanata quindi non starò qui a spiegarvelo. vi riporto qua sotto le poche righe interessanti prodotte da gettype:
 
    Portable executable (starting at 256 for 820992 bytes)
      Compiler: Borland Delphi 3/4 (heuristic)
 
delphi... bene, DeDe farà al caso nostro. lanciamolo, carichiamo il file capexp.exe e premiamo il tasto process. fatto tutto? bene. cominciamo a girellare nelle varie sezioni (Classes Info, Forms, Procedures, etccte).
avete notato qualcosa di interessante??? beh, io si. nella sezione Forms, tra le varie voci troviamo: 'TDoLicense', clicchiamoci e andiamo a leggere le info relative a questa bestia. hmmm, è un form con caption 'License Software', con due label: 'Your Name', 'Code' e due bottoni: 'OK', 'Cancel'; non c'è dubbio, E' IL FOTTUTO FORM DI REGISTRAZIONE. vediamo di scoprire dove si nasconde. andiamo nella sezione 'Procedures' e clicchiamo sulla Unit Name 'About'; tra i vari eventi uno in particolare mi salta subito all'occhio: CompanyLogoClick. clicchiamo due volte su questa voce. ecco qua il codice relativo alla gestione dell'evento click sull'oggeto Company Logo. guardando il codice notiamo la seguente cosa: '* Possible reference to class TDoLicense', hehehe qualcosa mi dice che siamo sulla buona strada. torniamo alla sezione Forms e stavolta clicchiamo su TfrmAboutBox. guardiamo le informazioni contenute nel frame di sinistra e andiamo alla ricerca di qualcosa tipo 'company logo'. trovato. company logo è l'immagine presente nell'about box. inoltre qualche riga più sotto troviamo la seguente cosa: OnClick = CompanyLogoClick. ecco qua dove si nascondeva il form. lanciamo captureexpress e andiamno nell'about box. clicchiamo sull'immagine (è il pianeta giallo ocra con una sorta di anello che lo circonda) e...ecco qua il form cercato. ok. finalmente possiamo iniziare.
 
2° parte: studio del codice
inseriamo un nome (ZRN), un codice (1234-56789-0abcd) e premiamo ok. il programma ci aiuta:)), la lunghezza del nome deve contenere almeno 6 caratteri; lo accontentiamo cambiando il nome (ZaiRoN). premiamo di nuovo ok. codice sbagliato. ma và:))) eppure una volta sono riuscito ad azzeccare il codice alla prima:P .
CTRL-D per attivare softice e settiamo un breakpoint sulla funzione Hmemcpy (bpx hmemcpy). torniamo al nostro programma (F5) e premiamo l'ok button. sice poppa, disabilitiamo il breakpoint (bd n° breakpoint). come tutte le sante volte che usiamo un breakpoint su hmemcpy dobbiamo immancabilmente premere F12 un tot numero di volte per raggiungere la sezione .code (stavolta dovrebbero essere 7); più precisamente ci troviamo all'indirizzo 425D42. visto che le poche istruzioni che seguono sono per noi inutili premiamo un'altra volta F12. stesso discorso anche qui, per farla breve premiamo F12 finchè non si raggiunge l'indirizzo 47A6F8. e ora? ora iniziamo a steppare (F10) cercando di capire che cosa succede.
prima di proseguire un pò di precisazioni. d'ora in poi indicherò con:
- 'len_name' la sequenza di bytes (in hex): 06 5A 61 69 52 6F 4E. non è altro che la lunghezza del nome che ho inserito seguito dai valori in esadecimale dei singoli caratteri componenti il nome stesso.
- 'len_code' la sequenza di bytes (in hex): 0E 31 32 33 34 35 36 37 38 39 30 41 42 43 44. non è altro che la lunghezza del codice che ho inserito seguito dai valori in esadecimale dei singoli caratteri componenti il codice stesso.
- 'code_1', 'code_2' e 'code_3' rispettivamente la prima, la seconda e la terza parte del codice che abbiamo inserito.
steppiamo:
 
:0047A6F8   mov eax, dword ptr [ebp-0208]   <--- EAX punta al nome inserito
:0047A6FE   lea edx, dword ptr [ebp-0204]   <--- prepara EDX. servirà alla call seguente
:0047A704   call 00408274   <------------------- copia l'indirizzo in cui è memorizzato il nome nella locazione puntata da edx
:0047A709   mov edx, dword ptr [ebp-0204]   <--- punta al nome
:0047A70F   lea eax, dword ptr [ebp-0100]   <--- prepara EAX. servirà alla call seguente
:0047A715   mov ecx, 000000FF   <--------------- ECX = FF
:0047A71A   call 00403F90   <------------------- copia len_name nella locazione puntata da EAX
:0047A71F   cmp byte ptr [ebp-0100], 06   <----- lunghezza(nome) >= 6 ???
:0047A726   jnb 0047A754   <-------------------- si: salta...no: errore, la lunghezza del nome deve essere almeno 6 chrs (si sapeva già:))))
 
per ora niente di particolare. continuiamo.
 
:0047A754   lea edx, dword ptr [ebp-0208]   <--- EDX punta all'indirizzo contenente il nostro nome
:0047A75A   mov eax, dword ptr [ebx+000002D4]
:0047A760   call 0042E560   <------------------- estrae code_1 dal codice inserito
:0047A765   mov eax, dword ptr [ebp-0208]   <--- EAX punta a code_1
:0047A76B   lea edx, dword ptr [ebp-0204]   <--- prepara EDX. servirà alla call seguente
:0047A771   call 00408274   <------------------- copia l'indirizzo in cui è memorizzato code_1 nella locazione puntata da EDX
:0047A776   mov edx, dword ptr [ebp-0204]   <--- EDX punta a code_1
:0047A77C   lea eax, dword ptr [ebp-0200]   <--- prepara EAX. servirà alla call seguente
:0047A782   mov ecx, 000000FF   <--------------- ECX = FF
:0047A787   call 00403F90   <------------------- fa in modo che EAX punti alla sequenza di bytes formata dalla lunghezza di code_1 seguita dai caratteri di code_1
:0047A78C   cmp byte ptr [ebp-0200], 00   <----- lunghezza(code_1) == 0 ???
:0047A793   jne 0047A7C1   <-------------------- si: ERRORE; no: salta
:0047A795   push 00000000   <------------------- strada verso il msgbox errore
 
vi è chiaro cosa fà? controlla semplicemente che code_1 non sia vuoto. questo controllo viene ripetuto pari pari anche per code_2 e code_3. non sto qui a piazzarvi il codice, vi basti sapere che sono tra gli indirizzi : 47A7C1/47A800 e 47A82E/47A86D. fatti questi controlli premiamo F10 finchè non arriviamo qui:
 
:0047A923   mov edx, dword ptr [ebp-0204]   <---- EDX punta al codice inserito (tutto)
:0047A929   lea eax, dword ptr [ebp-0200]   <---- prepara EAX. servirà alla call seguente
:0047A92F   mov ecx, 000000FF
:0047A934   call 00403F90   
<-------------------- fa puntare EAX a len_code
:0047A939   lea eax, dword ptr [ebp-020C]    
:0047A93F   lea edx, dword ptr [ebp-0200]
:0047A945   call 00403F58
:0047A94A   mov eax, dword ptr [ebp-020C]   
<---- EAX punta al codice
:0047A950   lea edx, dword ptr [ebp-0204]   <---- EDX punta all'indirizzo contenente il codice
:0047A956   call 004080FC   <-------------------- fa l'uppercase (se serve) del codice
:0047A95B   mov edx, dword ptr [ebp-0204]   <---- EDX punta al codice (uppercase-ato)
:0047A961   lea eax, dword ptr [ebp-0200]   <---- EAX punta a len_code (non uppercase-ato)
:0047A967   mov ecx, 000000FF
:0047A96C   call 00403F90   
<-------------------- fa in modo che EAX punti a len_code (uppercase-ato)
:0047A971   movzx esi, byte ptr [ebp-0200]   <--- ESI = lunghezza del codice
:0047A978   test esi, esi   <-------------------- testa ESI
:0047A97A   jle 0047A9B6   <--------------------- salta se esi è =< 0
 
chiaro? anche questo è semplice. se nel codice c'è qualche carattere in minuscolo viene trasfromato in maiuscolo.
nel nostro caso all'indirizzo 47A974 il salto non viene effettuato e si passa ad un pezzo di codice abbastanza interessante che si propone di controllare la validità dei singoli caratteri presenti nel codice. infatti tali caratteri devono appartenere ad un determinato range di valori. vediamolo in dettaglio. d'ora in avanti lavoreremo soltanto con il codice e il len_code uppercase-ati.
 
:0047A97C   lea eax, dword ptr [ebp-01FF]   <--- EAX punta al codice
*Jump at Address:
|:0047A9B4
:0047A982   mov dl, byte ptr [eax]   
<---------- DL = i-esimo carattere del codice
:0047A984   add dl, D0   <---------------------- DL = DL + 0xD0
:0047A987   sub dl, 0A   <---------------------- DL = DL - 0x0A
:0047A98A   jb 0047A9B2   <--------------------- segue spiegazione
 
piccola spiegazione: il carattere è ok se in 47A98A si esegue il salto a 47A9B2. ma quand'è che si salta? si salta se e solo se l'istruzione sub pone il carrie flag a 1. e quando accade???
accade se: DL + 0xD0 - 0x0A =< 0xFF
cioè: DL + 0xC6 =< 0xFF
cioè: DL =< 0x39 (che è il '9').
questo ci da soltanto il limite superiore al range dei valori accettati. ovviamente c'è anche un limite inferiore. per calcolarlo basta semplicemente prendere i 10 caratteri (0x0A) limitati superiormente dal 9 (0x39); il limite inferiore è 0x30 (lo '0'). per cui si salta per valori compresi tra 0 e 9 (inclusi).
vediamo invece che cosa succede se non saltiamo:
 
:0047A98C   add dl, F9   <---- DL = DL + 0xF9
:0047A98F   sub dl, 06   <---- DL = DL - 0x06
:0047A992   jb 0047A9B2   
<--- segue spiegazione
 
piccola spiegazione: arrivo qui se il carattere non è un numero (e se DL >=0). come prima, il carattere va bene se la sub mi pone il carrie flag a 1. e questo accade se:
DL - 0x06 + 0xF9 =< 0xFF
cioè: DL + 0xF3 =< 0xFF
cioè: DL =< 0x0C
per arrivare al carattere che stiamo cercando invertiamo le operazioni fatte in precedenza e otteniamo:
0x0C + 0x0A - 0xD0 = 0x46
per cui: DL =< 0x46 (la 'F').
e questo è il limite superiore; come prima calcoliamo il limite inferiore prendendo i 6 caratteri limitati superiormente dalla 'F'; otteniamo 0x41 (la 'A'). abbiamo trovato il range dei caratteri accettati: 0...9, A...F, a...f (le minuscole per il discorso fatto sopra sull'uppercase, vi ricordate?:))
vediamo l'ultima parte relativa al controllo dei caratteri inseriti:

:0047A994   push 00000000   <--- parte la gestione dell'errore (semplice msgbox)
* Possible StringData Ref from Code Obj ->"Error"
                                  |
:0047A996   push 0047AB80
* Possible StringData Ref from Code Obj ->"Invalid code entered."
                                  |
:0047A99B   push 0047AC7C
:0047A9A0   mov eax, ebx
:0047A9A2   call 00434274
:0047A9A7   push eax
* Reference To: user32.MessageBoxA, Ord:0000h
                                  |
:0047A9A8   Call 00406E94
:0047A9AD   jmp 0047AB3F
*Jump at Addresses:
|:0047A98A, :0047A992
|
:0047A9B2   inc eax   <--------
se il carattere va bene si sposta sul prossimo
:0047A9B3   dec esi   <-------- se ESI = 0 ho scandito l'intero codice
:0047A9B4   jne 0047A982   <--- torna su se restano altri caratteri
 
mi sembra di aver già detto abbastanza su questo spezzone...passiamo di corsa a ciò che segue.steppiamo per un pò; in questo modo evitiamo un pò di codice-spazzatura (inutile:)). se proprio siete curiosi dateci pure un'occhiata:)))). ok, arriviamo qui:
 
:0047A9D7   mov eax, dword ptr [ebx+000002E0]
:0047A9DD   mov byte ptr [eax+00000324], 01
:0047A9E4   call 0047A3D4   
<----------------------- entriamo qui
 
entriamo nella call (F8).
d'ora in poi indicherò con CAP la sequenza di bytes (in hex): 05 43 41 50 31 30. è il valore 5 seguito dalla stringa 'CAP10'. steppiamo fino a
 
:0047A402   lea ecx, dword ptr [esi+00000224]   <--- ECX punta a CAP
:0047A408   lea edx, dword ptr [esi+24]   <--------- EDX punta a len_code
:0047A40B   mov eax, esi
:0047A40D   call 0047A0D0   
<----------------------- entriamo anche qui
 
appena entrati steppiamo a randa finchè non arriviamo all'indirizzo 47A317. ciò che segue è il kernel di tutto l'algoritmo di protezione; si tratta di un ciclo che itera per 6 volte e...vediamo che cosa fa:
 
:0047A317   xor eax, eax   <-------------------------- EAX = 0 :))
:0047A319   mov al, byte ptr [ebp+esi-00000214]   <--- AL = primo carattere di CAP (0x43)
:0047A320   xor eax, ebx   <-------------------------- lo xora con il 3° e 4° carattere del codice che abbiamo inserito: 0x43 xor 0x34 = 0x77
:0047A322   mov dword ptr [ebp-0C], eax   <----------- il risultato lo mette in EBP-0C
:0047A325   cmp edi, dword ptr [ebp-0C]   <----------- EDI < EAX ???  EDI contiene i primi 2 caratteri del codice che abbiamo inserito (0x12)
:0047A328   jl 0047A339   <--------------------------- si: salta, no: continua
:0047A32A   mov eax, dword ptr [ebp-0C]   <----------- EAX = risultato dello xor in 47A320
:0047A32D   add eax, 000000FF   <--------------------- EAX = EAX + 0xFF
:0047A332   sub eax, edi   <-------------------------- EAX = EAX - EDI
:0047A334   mov dword ptr [ebp-0C], eax   <----------- mette il risultato in EBP-0C
:0047A337   jmp 0047A33C   <-------------------------- salta giù
*Jump at Address:
|:0047A328
|
:0047A339   sub dword ptr [ebp-0C], edi   
<----------- EBP-0C = EBP-0C - EDI
*Jump at Address:
|:0047A337
|
:0047A33C   lea eax, dword ptr [ebp+FFFFFAD8]   
<----- EAX punta alla locazione che andrà a contenere i valori calcolati di volta in volta
:0047A342   mov edx, dword ptr [ebp-0C]   <----------- EDX = 0x65 (valore risultante dai calcoli fatti nelle poche righe precedenti
:0047A345   mov byte ptr [eax+01], dl   <------------- DL viene messo nel byte puntato da EAX+1
:0047A348   mov byte ptr [eax], 01   <---------------- 1 viene messo nel byte puntato da EAX
:0047A34B   lea edx, dword ptr [ebp+FFFFFAD8]   <----- EDX è l'input della seguente call
:0047A351   lea eax, dword ptr [ebp-0314]   <--------- prepara EAX. servirà alla call seguente
:0047A357   call 00402BFC   <------------------------- call interessante
 
vi spiego il significato della call 402BFC con un esempio (relativo al mio particolare caso) analizzando ciò che viene prodotto nelle 6 iterazioni:
1° iterazione: EDX=01 65, la call fa puntare EAX alla sequenza di bytes: 01 65
2° iterazione: EDX=01 E2. la call fa puntare EAX alla sequenza di bytes: 02 65 E2
3° iterazione: EDX=01 D1. la call fa puntare EAX alla sequenza di bytes: 03 65 E2 D1
4° iterazione: EDX=01 29. la call fa puntare EAX alla sequenza di bytes: 04 65 E2 D1 29
5° iterazione: EDX=01 0B. la call fa puntare EAX alla sequenza di bytes: 05 65 E2 D1 29 0B
6° iterazione: EDX=01 E2. la call fa puntare EAX alla sequenza di bytes: 06 65 E2 D1 29 0B E2
semplice no! se non vi è chiaro vi consiglio di entrare nella call e studiare le poche righe di codice presenti, vedrete che non è difficile.
 
:0047A35C   mov edi, ebx   <----------------------- EDI = 0x34, 3° e 4° carattere del codice
:0047A35E   add dword ptr [ebp-08], 00000002   <--- [EBP-8] = 3 + 2 = 5
:0047A362   xor eax, eax   <----------------------- EAX = 0
:0047A364   mov al, byte ptr [ebp-0114]   <-------- AL = E, lunghezza del codice inserito
:0047A36A   cmp eax, dword ptr [ebp-08]   <-------- AL > [EBP-8] ?
:0047A36D   jg 0047A2B1   <------------------------ si: salta su e inizia un nuovo ciclo con i prossimi caratteri...no: ho scandito tutto il codice e proseguo sotto
*Jump at Addresses:
|:0047A1A0, :0047A24A
|
:0047A373   mov eax, dword ptr [ebp+08]
:0047A376   lea edx, dword ptr [ebp-0314]   
<------ EDX punta a ciò che è stato prodotto in questo spezzone di codice. nel mio caso: 06 65 E2 D1 29 0B E2
 
confusi??? anch'io:))))) ecco qua come viene generata la sequenza 06 65 E2 D1 29 0B E2 a partire dal codice 1234-56789-0ABCD (i conti sono tutti in esadecimale):
 
- 1° iterazione:
EBX = 34
EDI = 12
47A319 --> AL = 43
47A320/47A322 --> [EBP-C] = 43 xor 34 = 77
47A325 ---> 12 < 77 ??? SI
47A339 ---> [EBP-C] = 77 - 12 = 65   
- 2° iterazione:
EBX = 56
EDI = 34
47A319 --> AL = 41
47A320/47A322 --> [EBP-C] = 41 xor 56 = 17
47A325 ---> 34 < 17 ??? NO
47A32A/47A334 ---> [EBP-C] = 17 + FF - 34 = E2
- 3° iterazione:
EBX = 78
EDI = 56
47A319 --> AL = 50
47A320/47A322 --> [EBP-C] = 50 xor 78 = 28
47A325 ---> 56 < 28 ??? NO
47A32A/47A334 ---> [EBP-C] = 28 + FF - 56 = D1
- 4° iterazione:
EBX = 90
EDI = 78
47A319 --> AL = 31
47A320/47A322 --> [EBP-0C] = 31 xor 90 = A1
47A325 ---> 78 < A1 ??? SI
47A339 ---> [EBP-C] = A1 - 78 = 29   
- 5° iterazione:
EBX = AB
EDI = 90
47A319 --> AL = 30
47A320/47A322 --> [EBP-0C] = 30 xor AB = 9B
47A325 ---> 90 < 9B ??? SI
47A339 ---> [EBP-C] = 9B - 90 = 0B   
- 6° iterazione:
EBX = CD
EDI = AB
47A319 --> AL = 43   (scandita l'intera stringa 'CAP10' si riparte dalla 'C' iniziale)
47A320/47A322 --> [EBP-0C] = 43 xor CD = 8E
47A325 ---> AB < 8E ??? NO
47A32A/47A334 ---> [EBP-C] = 8E + FF - AB = E2
lo 06 iniziale è il numero dei valori prodotti nelle varie iterazioni.
 
capito??? speriamo:))) continuiamo? premiamo 3 volte F12 e ci troviamo vicinissimi alla tanto desiderata meta finale:

:0047A9E9   lea eax, dword ptr [ebp-0314]
:0047A9EF   push eax
:0047A9F0   xor edx, edx
:0047A9F2   mov dl, byte ptr [ebp-0100]   
<----- DL = lunghezza del nome inserito
:0047A9F8   sub edx, 00000005   <--------------- DL = DL - 5 = 1
:0047A9FB   mov ecx, 00000006   <--------------- ECX = 6
:0047AA00   lea eax, dword ptr [ebp-0100]   <--- EAX punta a len_name
:0047AA06   call 00402808   <------------------- prende il len_name e produce una nuova stringa composta sempre dalla lunghezza del nome ma seguita dagli ultimi 6 chrs del nome. (es. se nome = 'sempronio' produce 06 seguito da 'pronio'). sia questa len_name1
:0047AA0B   lea edx, dword ptr [ebp-0314]   <--- EDX punta al len_name1
:0047AA11   mov eax, dword ptr [ebx+000002E0]
:0047AA17   add eax, 00000124   
<--------------- EAX punta alla sequenza 06 65 E2 D1 29 0B E2. vi ricordate cos'è, vero??
:0047AA1C   xor ecx, ecx   <-------------------- ECX = 0
:0047AA1E   mov cl, byte ptr [eax]   <---------- CL = 6
:0047AA20   inc ecx   <------------------------- ECX = 7
:0047AA21   call 00402D24   <------------------- confronta la sequenza contenuta in EAX con il len_name1
:0047AA26   jne 0047AB26   <-------------------- se sono uguali siamo registrati, altrimenti...
 
tutto sommato mi sembra abbastanza semplice. l'unica cosa interessante di questo ultimo spezzone di codice è la call all'indirizzo 47AA06 che entra in gioco per nomi con lunghezza maggiore di 6.
qui finisce lo studio del codice. ora che sappiamo come vengono usati il nome e il codice inseriti troviamo una combinazione nome/codice che funzioni.
 
3° parte: costruzione nome/codice
costruire una giusta combinazione di nome/codice è molto semplice, anche se molto noioso. consideriamo il problema di trovare un codice giusto per il nome ZaiRoN.
il generico carattere può essere trovato in questo modo (prendo il primo per motivi di chiarezza):
nome[1] = (cap10[1] xor codice[3,4]) - codice[1]... (+ FF eventualmente)
per cui se:
- nome[1] + codice[1,2] >   FF  ho: codice[3,4] = (nome[1] + codice[1,2] - FF) xor cap10[1]
- nome[1] + codice[1,2] =< FF ho: codice[3,4] = (nome[1] + codice[1,2]) xor cap10[1]
dove ovviamente codice[1,2] e codice[3,4] sono le incognite.
questo va ripetuto anche per gli altri 5 caratteri, il che mi porta ad avere 6 equazioni in 7 incognite (codice[1,2]...codice[13,14]). è un bel casino...ci sono una marea di soluzioni relative ad un singolo nome. la
prima cosa che mi viene in mente è: fisso la prima coppia di caratteri del codice (codice[1,2]) e calcolo i restanti (oviamente posso fissare una qualsiasi tra le 7 coppie di caratteri componenti il codice).
ecco qua i passi relativi a ZaiRoN (i calcoli sono in esadecimale):
 
fisso i primi due caratteri del codice uguali a 0 (codice[1,2]=00).
- nome[1] + codice[1,2] = 5A + 00  = 5A =< FF ?   SI
codice[3,4] = (nome[1] + codice[1,2]) xor cap[1] = ( 5A + 00 ) xor 43 = 19
- nome[2] + codice[3,4] = 61 + 19 = 7A =< FF ?   SI
codice[5,6] = (nome[2] + codice[3,4]) xor cap[2] = ( 61 + 19 ) xor 41 = 3B
- nome[3] + codice[5,6] = 69 + 3B = A4 =< FF ?   SI
codice[7,8] = (nome[3] + codice[5,6]) xor cap[3] = ( 69 + 3B ) xor 50 = F4
- nome[4] + codice[7,8] = 52 + F4 = 146 =< FF ?   NO
codice[9,10] = (nome[4] + codice[7,8] - FF) xor cap[4] = ( 52 + F4 - FF ) xor 31 = 76
- nome[5] + codice[9,10] = 6F + 76 = E5 =< FF ?   SI
codice[11,12] = (nome[5] + codice[9,10]) xor cap[5] = (6F + 76 ) xor 30 = D5
- nome[6] + codice[11,12] = 4E + D5 = 123 =< FF ?   NO
codice[13,14] = (nome[6] + codice[11,12] - FF) xor cap[1] = ( 4E + D5 - FF ) xor 43 = 67
 
ottengo:
nome: ZaiRoN
codice: 0019-3BF47-6D567
inserisco e il programma è registrato...
                                                                                                            ZaiRoN
 

Note finali

ok...saluto tutti quelli che sono riusciti a leggere l'intero documento e tutti quelli che si sono arresi prima (ovviamente per la mia immensa incapacità di scrivere e spiegare le cose:(...
come sempre, se ho scritto qualche stronzata fatemelo sapè...
 

Disclaimer

ovviamente il tutto è a scopo puramente didattico. vi ricordo che il software va comprato e  non rubato. finito il periodo di valutazione se volete continuare ad usare il prodotto vi dovete frugàààààààààà...