Zoom Icon

Corso UIC Avanzato 03 Int19

From UIC Archive

UIC Lezione 03 (Codice Automodificante)

Contents


Corso UIC Avanzato 03 Int19
Author: Int19
Email: [email protected], UIN: 4044843
Website: None
Date: 08/10/1999 (dd/mm/yyyy)
Level: Some skills are required
Language: Italian Flag Italian.gif
Comments: Complimenti anche stavolta Int19, hai fatto un tutorial davvero impeccabile e spiegato nei più minimi dettagli, bravo


Questa volta avremo a che fare con codice automodificante, lo crackeremo e creeremo un KeyMaker


Introduzione

Ciao a tutti, qui è Il.Socio che scrive, premetto che trattandosi di codice auto-modificante (SMC) un approccio "live" è quantomeno essenziale, per non lasciarsi ingannare da come il prog. si presenta "in apparenza", quindi scordatevi Win32Dasm e tenete SoftICE sottomano.

Leggete la lezione di Quequero riguardante proprio questo corso per degli approfondimenti relativi al SMC.

Inoltre tutto il codice presentato in questo tute, sarà riferito al codice che viene visualizzato da SoftICE.


Tools

Il classico e indispensabile SoftICE 4.0, Hiew 6.16 per patchare l'exe in modo da accettare come valida qualsiasi coppia nome/seriale e il Borland TurboC per il KeyMaker.

Inoltre ho utilizzato Base Calculator http://biosys12.ee.unsw.edu.au/personal/software/basecalc/ per il calcolo del serial.


Link e Riferimenti

Questo è la soluzione del Corso UIC Avanzato n°03 disponibile alla pagina Corso UIC Avanzato 03


Notizie sul Programma

Il programma presenta due box nei quali inserire nome e numero di serie, ed un bottone per la registrazione, inserendo un Serial errato non compare nulla, inoltre c'è un bottone about che a quanto pare non fa nulla (Quequero, che c'era per caso qualche routine imboscata che mi è sfuggita?) Ecco cosa mi ero dimenticato, il pulsante About, grazie int19 per avermelo ricordato NdQue Inserendo un serial corretto il prog. mostra un messaggio di congraturazioni.


Essay

Obiettivi:

1) Trovare il codice corrispondente al nostro nick 2) Crackare il programma in modo da ottenere codici sempre validi 3) Analizzare l'algoritmo di generazione del seriale 4) Scrivete un key-maker per il programma

Spero che Que non mi flagelli (splat..splat..splat :)) NdQue) ma personalmente non mi sono attenuto rigorosamente a questo ordine,

quindi vi presenterò l'ordine che a me è venuto più naturale quando ho crackato il prog. di esempio.

1) Individuare la protezione 2) Crackare il programma in modo da ottenere codici sempre validi 3) Trovare il codice corrispondente al nostro nick 4) Analizzare l'algoritmo di generazione del seriale 5) Scrivere un key-maker per il programma

Individuare la protezione

Per conseguire il primo obbiettivo dobbiamo ovviamente come prima cosa individuare la protezione, ovvero il luogo in cui il serial che andremo ad immettere viene confrontato con quello calcolato.

Iniziamo con il piazzare i classici breakpoint "BPX GetDlgItemTextA" e "BPX GetWindowTextA", inseriamo un nome (Int19) e un serial (12244331) ed appena pigiamo il bottone di registrazione arriva SoftICE in nostro aiuto, come potrete notare premendo F5, la funzione viene richiamata per ben quattro volte, ma solo alla quarta viene letto il seriale, le prime tre si riferiscono sempre al nome, e più precisamente il nostro codice seriale appena immesso, verrà salvato nella locazione 4020AF (come si deduce dai parametri passati alla funzione).

Ora la logica suggerisce di piazzare un bel BPM 4020AF 4020AF+8 rw, ma se date ancora un'ulteriore sguardo al codice che segue, vedrete che il serial inserito viene immediatamente manipolato...

0040132D push 00000018

Locazione nella quale sarà salvato il serial inserito 0040132F push 004020AF 00401334 push dword ptr [00402050]

Reference To: USER32.GetWindowTextA, Ord:0000h

0040133A Call 0040165B

Azzera la posizione per analizzare il primo char del serial

0040133F xor ecx, ecx 00401341 xor eax, eax

Preleva un char dal serial inserito usando ecx come contatore 00401343 mov al, byte ptr [ecx+004020AF] 00401349 xor al, 81 0040134B xor al, 40

Preleva un char dalla locazione 4020C7 usando ecx come contatore 0040134D mov bl, byte ptr [ecx+004020C7]

Esegue il confronto tra il char del serial e il char della locazione 4020C7 00401353 cmp al, bl

e salta se sono diversi 00401355 jne 00401170

incrementa il contatore (fino a qui sono stati analizzati ecx chars del serial) 0040135B inc ecx

Se non sono stati ancora analizzati i primi 4 chars 0040135C cmp ecx, 00000004

allora salta 0040135F jne 00401341 00401361 nop 00401362 nop Il ciclo qui sopra (da 401343 a 40135F) esegue un confronto ad uno ad uno dei primi 4 chars del serial opportunamente manipolati, con i primi 4 chars della locazione 4020C7 (nel mio caso questa locazione contiene i seguenti valori F9 F3 F5 F1 3A 34 essi sono certamente ricavati da una codifica del nome inserito poiché variano al variare del nome, vedremo in seguito) e se tutti i quattro confronti della linea 401353 hanno avuto successo allora si continua alla linea 401361 (Se ne deduce che il serial dovrà avere almeno 4 chars).

Per forzare il successo di questo check è sufficiente sostituire il cmp al, bl con un cmp al, al

00401363 mov esi, 004015C3 00401368 mov edi, 00401374 0040136D mov ecx, 00000049 00401372 repz movsb Le linee qui sopra servono per poter sovrascrivere 49hex bytes della zona di codice a partire dalla locazione 401374 con il codice presente alla locazione 4015C3, infatti se lo aprite con Win32Dasm osserverete il codice seguente... 00401374 mov eax, 00000008 00401379 xor edx, eax 0040137B mov bl, byte ptr [ecx+0040209B] 00401381 cmp edx, dword ptr [0040209B] (NOTA: Essendo questo un esempio e trattandosi di zone di codice relativamente piccole in un codice complessivo di dimensioni esigue, il reversing non risulta particolarmente ostico e fortunatamente Que non ha voluto renderci le cose troppo difficili, purtroppo però non credo vi capiterà mai ad aver a che fare con codice di 8kb. Lascio a voi immaginare le potenzialità del SMC quando implementato in un bel eseguibile da 2Mega e magari con qualche parte crittografata qua e la. Vi assicuro che fa girare altamente le palle il fatto di aspettarsi un certo comportamento dal programma e rimanerne delusi)

Ma dopo l'esecuzione runtime della linea 401372 il codice si è "magicamente" trasformato in questo modo...

I primi 4 chars sono già stati analizzati 00401374 mov ecx, 00000004

Credo non sia indispensabile 00401379 xor eax, eax

Carica il prossimo char dal serial immesso (dal 5° char in poi) 0040137B mov al, byte ptr [ecx+004020AF]

Se ha analizzato lunghezza_nome+1 chars 00401381 cmp ecx, dword ptr [0040210F]

Allora salta a MessageBoxA "Successo" 00401387 je 004013A5 00401389 xor al, 82 <---| Esegue alcune 0040138B shl al, 02 | manipolazioni sul char 0040138E ror al, 02 <---| corrente

Lo confronta con un char del nome codificato della locazione 4020C7 usando ecx come contatore 00401391 mov bl, byte ptr [ecx+004020C7] 00401397 cmp al, bl

e salta se sono diversi 00401399 jne 00401170

passa al prossimo char 0040139F inc ecx

se non ha ancora analizzato 8 chars 004013A0 cmp ecx, 00000008

allora continua il ciclo alla linea 401379 004013A3 jne 00401379

Referenced by a Jump at Address 004015D6</comment>

004013A5 push 00000020

Possible StringData Ref ->"SMC - - by Quequero for UIC"

004013A7 push 00402061

Possible StringData Ref ->"Serial esatto....Bravo!!!!"

004013AC push 00402113 004013B1 push 00000000 004013B3 call USER32!MessageBoxA 004013B8 jmp 00401170 Osservate che la locazione [40210F] contiene la lunghezza del nome inserito + 1 quindi... se è stato inserito un nome di 3 chars il check della linea 401381 sarà verificato al primo ciclo (poiche' inizialmente ecx=4) ed il prog. salterà all'indirizzo 4015D6 che come potete vedere mostra il messagebox di successo. Da questo deduciamo che il serial da inserire dovrà essere più lungo di un char rispetto alla lunghezza del nome.

Se forziamo il confronto della linea 401397 con cmp al, al potremo finalmente vedere il MessageBoxA...

Nel mio caso la locazione 4020C7 contiene i seguenti valori F9 F3 F5 F1 3A 34 quindi la linea 40137B con [ecx+4020C7] fa riferimento al valore 3A inizialmente, poi 34 al secondo ciclo ed esce al terzo ciclo poiché ecx=6 ed è uguale a lung_nome+1.

Bene, ora abbiamo individuato la protezione e patchato il prog. in modo da ottenere seriali sempre validi...PERO' se ora premiamo nuovamente il pulsante di registrazione non comparirà più alcun messaggio di congraturazioni, questo a causa del SMC di Que, in pratica il prog si è "Aggiustato" e il cmp al,al che noi avevamo inserito è nuovamente tornato cmp al,bl (Ecco un esempio di quando ho detto che il prog. non si comporta come ci si aspetterebbe)

Adesso possiamo passare al punto successivo...

Crackare il programma in modo da ottenere codici sempre validi

Come abbiamo visto il prog. si "corregge" o meglio si auto-modifica appunto...

Come possiamo procedere ? Dunque, l'idea è quella di individuare le locazioni di memoria "sorgente" dalle quali vengono copiati i bytes che vanno a sovrascrivere le nostre locazioni incriminate, modificarle, e incrociando le dita sperare che le cose non siano più complicate (ad esempio le locazioni "sorgente" potrebbero a loro volta essere modificate prima di essere copiate, vi dico subito che non è il nostro caso quindi rilassatevi)

Il codice che vi presento qui sotto è il codice che precede la chiamata alla GetWindowTextA che legge il seriale, ed ecco li la locazione "sorgente" 4014E5.

Esso copia 22hex bytes da 4014E5 a 40133F (sovrascrivendo il nostro primo check) 0040131C mov esi, 004014E5 00401321 mov edi, 0040133F 00401326 mov ecx, 00000022 0040132B repz movsb Quindi andando alla locazione 4014E5 troviamo la routine di check dei primi 4 chars e ora possiamo cambiare la locazione "sorgente" 004014F9 cmp al, bl con 004014F9 cmp al, al La prossima volta che verrà eseguito il codice SMC verrà copiato il codice da noi già patchato. Procedendo in modo analogo per il secondo check (che controlla dal 5° char in poi) 00401363 mov esi, 004015C3 00401368 mov edi, 00401374 0040136D mov ecx, 00000049 00401372 repz movsb Andiamo alla locazione 4015C3 e cambiamo la locazione "sorgente" 004015E6 cmp al, bl con 004015E6 cmp al, al Ora premendo il pulsante di registrazione più volte il progr. da sempre esito positivo.

Modificando il programma con un editor esadecimale le modifiche saranno permanenti ed il programma accetterà qualunque coppia nome/seriale come esatta. Sicuramente si sarebbe potuto crackare in altri modi, ma questo è quello che personalmente mi è sembrato il più "elegante" e meno invasivo.

Trovare il codice corrispondente al nostro nick

Bene, per questa parte vi consiglio di munirvi di calcolatrice e del codice che ho presentato poco sopra (mi riferisco a quello che parte da 40133F ovviamente)

Io ho inserito "Int19" come nome ed ho ottenuto i seguenti valori alla locazione 4020C7: F9 F3 F5 F1 3A 34

Ed ora diamo un'occhiata al primo check (quello relativo ai primi 4 chars del serial)

Indicherò con n_serial l'n-esimo char del seriale immesso quindi 1_serial si riferirà al 1°char del seriale 2_serial al secondo char ecc..

Prendendo in considerazione le manipolazioni che vengono effettuate sui char del seriale immesso concludiamo che per soddisfare il primo check si devono verificare le seguenti condizioni:

(1_Serial xor 81) xor 40 deve essere uguale a F9

Per le proprietà dell'xor (vedi il tute di Quequero sullo xor per ulteriori approfondimenti) possiamo convertirlo nel seguente modo...

(1_Serial xor 81) xor 40 = 1_Serial xor (81 xor 40) = 1_Serial xor (C1) qiundi...

1_Serial xor C1 deve essere uguale a F9

2_Serial xor C1 deve essere uguale a F3

3_Serial xor C1 deve essere uguale a F5

4_Serial xor C1 deve essere uguale a F1

Sempre grazie alle proprietà dell'xor deduciamo che...

1_Serial dovrà essere uguale a F9 xor C1 -> 1_Serial=38 "8"

2_Serial dovrà essere uguale a F3 xor C1 -> 2_Serial=32 "2"

3_Serial dovrà essere uguale a F5 xor C1 -> 3_Serial=34 "4"

4_Serial dovrà essere uguale a F1 xor C1 -> 4_Serial=30 "0"

Infatti se inseriamo questo come seriale "8240" riusciamo a passare il primo check con successo.

Adesso vediamo il secondo...

Vengono effettuate queste operazioni sul char in al...

((al xor 82) shl 02) shr 02

Che come ora vedremo possono essere ricondotte ad

(al xor 02) and 3F

Quando viene eseguito lo shift a sinistra di 2 bit, i 2 bit più significativi di al vengono persi quindi qualunque sia il loro valore è ininfluente, da questo deriva che xor al,82 (82 = 10000010) può essere ridotto

ad xor al,2 ( 2 = 00000010) e l'operazione di shift e rotate in un And 3F (per azzerare i 2 bit più significativi

ricapitolando *** ((al xor 82) shl 02) shr 02 ***

lo trasformiamo in *** (al xor 2) and 3F ***

Quindi per passare il 2° check dovranno essere verificate queste condizioni:

5_Serial dovrà essere uguale a (3A xor 2) and 3F -> 5_Serial=38="8"

6_Serial dovrà essere uguale a (34 xor 2) and 3F -> 6_Serial=36="6"

Infatti se inseriamo questo come seriale "824086" riusciamo a passare entrambi i check.

Ecco trovato il seriale per il mio nick.

NOTA:

Una conseguenza del fatto che i 2 bit significativi non vengono presi in considerazione diviene evidente perché ad uno stesso nome vi possono essere abbinati più numeri di serie ad esempio prendendo il seriale "824086" e settando ad 1 il secondo bit più significativo dei numeri coinvolti nel 2° check si ottiene un nuovo seriale (8240xv) che è anch'esso considerato come valido...

Poiche' i 2 bit significativi saranno scartati (riconducendo "8240xv" a "824086")

Mi rendo conto che queste manipolazioni sui bit possano sembrare un po' ostiche per i principianti, ma è fondamentale sapersi "destreggiare" tra i vari xor shift ecc... per poter affrontare schemi di "crittografia" sempre più complessi.

Ora che abbiamo qualche elemento possiamo iniziare ad abbozzare quello che sarà il nostro keymaker...

char name[9]={"Int19"}; char cryptname[9]={0xF9, 0xF3, 0xF5, 0xF1, 0x3A, 0x34}; int c; int namelength;

void main(void) {

 randomize();
 namelength=strlen(name);
 printf("Third Lesson Pre-KeyMaker by Int19\n");
 c=0;
 for (c=0; c<4; c++)
   printf("%c", cryptname[c]^0xc1);
 for (c=4; c<namelength+1; c++)
 {
   // Rende la generazione degli ultimi chars del seriale semi-casuale
   if (random(2)==1) 
     printf("%c", (cryptname[c]^2)& 0x3f);
   else
     printf("%c", (cryptname[c]^2)& 0x3f | 0x40 );
 }

} Questo programma si limita a stampare il numero di serie per il mio nick.

L'ultimo if.then.else è "facoltativo", esso si limita a settare ad 1 il secondo bit più significativo, in modo da generare seriali diversi per lo stesso nome.

Analizzare l'algoritmo di generazione del seriale

Quello che faremo in questa parte sarà scoprire il modo in cui vengono generati i bytes della locazione 4020C7 (quella che ho chiamato cryptname) in modo da cambiare i valori di cryptname a seconda del nome inserito, così da realizzare un keymaker.

Iniziamo pure piazzando un "BPR 4020C7 4020C7+6 rw" pigiamo il bottone di registrazione e SoftICE poppa all'interno di questo ciclo

00401277 mov dword ptr [0040210F], eax 0040127C xor ecx, ecx

Referenced by a Jump at Address 004012A9

Carica il prossimo char del Nome 0040127E mov al, byte ptr [ecx+0040209B]

si prepara per la divisione 00401284 mov edi, 0000000B

azzera edx (che conterrà il resto della divisione) 00401289 cdq

esegue la divisione del char per 0B (edx contiene il resto) 0040128A idiv edi

somma il resto della divisione al risultato 0040128C add eax, edx 0040128E shl eax, 1 00401290 mov dl, al

"Normalizza" il char contenuto in dl (routine analizzata sotto) 00401292 call 0040160C 00401297 xor eax, eax 00401299 mov al, dl <---| Manipola il char 0040129B xor al, 81 | 0040129D xor al, 40 <---|

Il char manipolato viene salvato (ed è qui che poppa SoftICE) 0040129F mov byte ptr [ecx+004020C7], al

Incrementa la posizione corrente per convertire il prossimo char 004012A5 inc ecx 004012A6 cmp ecx, 00000004

salta se non sono ancora stati convertiti i primi 4 chars 004012A9 jne 0040127E 004012AB nop 004012AC nop … … … … … … … … … … … …

Ecco qui la routine di "normalizzazione" che prende un char tramite dl e fa in modo che all'uscita dalla routine il char in dl sia compreso tra "0" e "z"

0040160C cmp dl, 7A

salta se il char è > "z" 0040160F jg 00401617 00401611 cmp dl, 30

salta se il char è < "0" 00401614 jl 00401621

Referenced by Jump at Addresses 0040161F, 00401629

all'uscita il char è per forza compreso tra "0" e "z" 00401616 ret

Referenced by a Jump at Addresses 0040160F, 0040161D

00401617 sub dl, 0A <---| 0040161A cmp dl, 7A | 0040161D jg 00401617 <---| Sottrae 0A al char fino a che non è <= di "z" 0040161F jmp 00401616

Referenced by a Jump at Addresses 00401614, 00401627

00401621 add dl, 0A <---| 00401624 cmp dl, 30 | 00401627 jl 00401621 <---| Somma 0A al char fino a che non è >= di "0" 00401629 jmp 00401616

Adesso che abbiamo analizzato il modo in cui vengono generati i primi 4 chars di cryptname andiamo a vedere come si comporta con i restanti dando uno sguardo al codice che si presenta poche linee dopo

004012C0 mov ecx, 00000004

Referenced by a Jump at Address 00401315

004012C5 xor eax, eax

carica un char dal nome (a partire dal 5°) 004012C7 mov al, byte ptr [ecx+0040209B]

40210F contiene lung_nome+1 004012CD cmp ecx, dword ptr [0040210F]

Salta se sono già stati convertiti lung_nome+1 chars 004012D3 je 0040131C

si prepara per la divisione per 8 004012D5 mov edi,00000008

azzera edx che conterrà il resto 004012DA cdq

divide il char per 8 004012DB idiv edi

somma il risultato della divisione ed il resto 004012DD add al, dl 004012DF shl al, 03 <---| varie 004012E2 ror al, 1 | manipolazioni 004012E4 add al, 06 | aritmetiche 004012E6 shl al, 1 <---| sul char

xor con lung_nome+1 (variando la lunghezza del nome varierà anche il nome cifrato) 004012E8 xor al, byte ptr [0040210F] 004012EE mov edi,00000003 <---| una ulteriore 004012F3 cdq | divisione per 3 004012F4 idiv edi | 004012F6 add al, dl <---| 004012F8 mov dl, al

"normalizza" il char contenuto in dl 004012FA call 0040160C 004012FF mov al, dl 00401301 xor al, 82 <---| 00401303 shl al, 02 | manipolazioni finali del char 00401306 ror al, 02 <---|

salva il risultato 00401309 mov byte ptr [ecx+004020C7], al 0040130F xor eax, eax

incrementa la posizione corrente per analizzare il prossimo char 00401311 inc ecx 00401312 cmp ecx, 00000008

se non sono stati esaminati ancora 8 chars continua il ciclo 00401315 jne 004012C5 00401317 nop 00401318 nop 00401319 nop 0040131A nop 0040131B nop 0040131C arriveremo qui se sono stati convertiti 8 chars del nome oppure se ne sono stati convertiti lung_nome+1 (se ne deduce che se il nome è più corto di 8 chars allora anche il char di fine stringa 0 verrà convertito)

Scrivere un key-maker per il programma

Vorrei farvi notare la forte analogia che esiste tra le operazioni aritmetiche che vengono effettuate dopo la chiamata alla funzione di normalizzazione e le operazioni che troviamo nella routine di check del seriale.... Come potete vedere per quel che riguarda i primi 4 chars vi sono queste operazioni in comune

  xor al, 81      <---| Ed abbiamo visto che possono essere
  xor al, 40      <---| unificate con "al xor C1"

Mentre per i restanti chars sono queste le operazioni in comune

  xor al, 82      <---| Che abbiamo 
  shl al, 02          | trasformato 
  ror al, 02      <---| in "(al xor 2) and 0x3f" 

In effetti il codice corretto lo otteniamo già al termine delle call alla routine di normalizzazione, "scartando" i 2 bit più significativi, l'xor serve solo per "mascherare" ulteriormente il codice corretto, quindi eliminando le operazioni inutili il nostro keygen possiamo scriverlo cosi'.... Iniziamo con il tradurre la routine di normalizzazione.... void normalize(char *ch) // Call dell'indirizzo 40160C {

 while (*ch>'z') *ch = *ch - 0x0a;
 while (*ch<'0') *ch = *ch + 0x0a;

}

char name[10]={"Int19"}; char serial[10]={0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int c; int namelength; char currchar; div_t res; void main(void) {

 printf("Third Lesson KeyMaker by Int19\n");
 printf("Name: ");
 scanf("%s", name);
 namelength=strlen(name);

// Ora traduciamo la routine che cifra i primi 4 chars del nome...

 for (c=0; c<4; c++)                  // Ciclo 40127E...4012A9
 {
   currchar=name[c];
   res=div(currchar, 0x0b);           // 401284...
   currchar= res.quot + res.rem;      // ...40128C
   currchar= currchar << 1;           // 40128E
   normalize(&currchar);              // 401290...401297
   serial[c]=currchar;                // 40129F
 }

// E adesso occupiamoci dei restanti

 c=4;
 while ((c<8) && (c < namelength+1))    // Ciclo 4012C5...401315
 {
   currchar=name[c];
   res=div(currchar, 0x08);           // 4012D5...
   currchar= res.quot + res.rem;      // ...4012DD
   currchar= (currchar<<2) & 0x7c;    // 4012DF...4012E2  shl 3 ror 1 --> 0xxxxx00
   currchar= currchar+6;              // 4012E4
   currchar= currchar<<1;             // 4012E6
   currchar= currchar^(namelength+1); // 4012E8
   res=div(currchar, 0x03);           // 4012EE...
   currchar= res.quot + res.rem;      // ...4012F6
   normalize(&currchar);              // 4012F8...4012FF

// Rende la generazione degli ultimi chars del seriale semi-casuale

   if (random(2)==1)  
     currchar=(currchar & 0x3f);      // 401301...401306
   else
     currchar=(currchar & 0x3f) | 0x40;
   serial[c]=currchar;                // 401309
   c++;
 }
 // Ora stampiamo il serial
 printf("S/N:  %s\n", serial);

}


Note Finali

Leggiti tutti i saluti del mio ultimo tute (mqmc4) ed aggiungi questi… George Lucas: Per le grandi sage che è riuscito a sfornare, da Indy a Monkey a StarWars. byez Il.Socio


Disclaimer

I documenti qui pubblicati sono da considerarsi pubblici e liberamente distribuibili, a patto che se ne citi la fonte di provenienza. Tutti i documenti presenti su queste pagine sono stati scritti esclusivamente a scopo di ricerca, nessuna di queste analisi è stata fatta per fini commerciali, o dietro alcun tipo di compenso. I documenti pubblicati presentano delle analisi puramente teoriche della struttura di un programma, in nessun caso il software è stato realmente disassemblato o modificato; ogni corrispondenza presente tra i documenti pubblicati e le istruzioni del software oggetto dell'analisi, è da ritenersi puramente casuale. Tutti i documenti vengono inviati in forma anonima ed automaticamente pubblicati, i diritti di tali opere appartengono esclusivamente al firmatario del documento (se presente), in nessun caso il gestore di questo sito, o del server su cui risiede, può essere ritenuto responsabile dei contenuti qui presenti, oltretutto il gestore del sito non è in grado di risalire all'identità del mittente dei documenti. Tutti i documenti ed i file di questo sito non presentano alcun tipo di garanzia, pertanto ne è sconsigliata a tutti la lettura o l'esecuzione, lo staff non si assume alcuna responsabilità per quanto riguarda l'uso improprio di tali documenti e/o file, è doveroso aggiungere che ogni riferimento a fatti cose o persone è da considerarsi PURAMENTE casuale. Tutti coloro che potrebbero ritenersi moralmente offesi dai contenuti di queste pagine, sono tenuti ad uscire immediatamente da questo sito.

Vogliamo inoltre ricordare che il Reverse Engineering è uno strumento tecnologico di grande potenza ed importanza, senza di esso non sarebbe possibile creare antivirus, scoprire funzioni malevole e non dichiarate all'interno di un programma di pubblico utilizzo. Non sarebbe possibile scoprire, in assenza di un sistema sicuro per il controllo dell'integrità, se il "tal" programma è realmente quello che l'utente ha scelto di installare ed eseguire, né sarebbe possibile continuare lo sviluppo di quei programmi (o l'utilizzo di quelle periferiche) ritenuti obsoleti e non più supportati dalle fonti ufficiali.