Zoom Icon

Lezione 4 Nag Screens

From UIC Archive

Nag Screens

Contents


Lezione 4 Nag Screens
Author: Quequero
Email: Que addr.gif
Website: UIC
Date: 01/09/2008 (dd/mm/yyyy)
Level: Very Easy, if you can read this, you can do it
Language: Italian Flag Italian.gif
Comments: Self-mummification was practiced until the late 1800s in Japan, by people who thought being a mummy looked so awesome they couldn't wait until actual death to be one.



Introduzione

Benvenuti alla quarta lezione per newbies, se siete arrivati fin qui significa che le altre sei vi sono piaciute, e quindi siete in grado di muovervi con relativa agevolezza nel mondo del reverse engineering. Tutto quello che avete imparato fino ad ora, e tutto quello che imparerete in seguito, vi sara' utile per sviluppare una forma mentis differente da quella di tutte le altre persone. Un reverser (come tutti gli hacker) e' infatti abituato ad affrontare i problemi che gli si presentano davanti prima osservandoli, e poi attaccandoli da fronti differenti. Vi assicuro che non si tratta di un'ovvieta', la maggior parte delle persone davanti ad un problema tenta degli approcci standard, dopo di che si arrende e chiede aiuto... O al massimo ignora il problema. Il reverser invece interpreta il problema come una sfida, lo sviscera e col tempo impara che solo osservandolo da punti differenti e' possibile arrivare alla migliore soluzione possibile. E' un po' come leggere, lo sanno fare tutti ma se giriamo il libro al contrario... In quanti riusciranno a continuare senza sforzo? Con il reversing e' la stessa cosa, con la differenza che saper leggere al contrario rappresenta un vantaggio relativo, ma saper pensare in maniera diversa dagli altri puo' invece generare un abisso.


Tools


Essay

Veniamo ora alla lezione vera e propria, oggi parleremo di nag-screen, ovvero di quelle finestre che spessissimo compaiono nei programmi trial, e che non ci consentono di accedere alle funzionalita' del software per un determinato periodo di tempo. Un esempio lampante e' sicuramente WinZip v_11.2: al primo avvio viene creata una finestra come quella in figura.

Newbies 7 Nag.png

Che risulta interessante per due ragioni: la prima e' che il tasto per accedere all'interfaccia di WinZip, vale a dire Use Evaluation Version, non si trova sempre sul lato destro, ma viene posizionato casualmente all'avvio. Si tratta di un semplice trick per evitare clicker automatici etc... La seconda ragione e' che scaduti i 45 giorni di valutazione appare un counter che segna il numero di giorni passati dall'installazione, e diventa sempre piu' lento man mano che il tempo passa, ovviamente il tasto Use Evaluation Version verra' abilitato al termine del conteggio. Il nostro scopo sara' quello di rimuovere il nag screen, l'attacco non si discosta molto dall'analisi dell'algoritmo che genera un seriale, ma ci sono comunque delle differenze.

All'attacco!

Avviando WinZip vediamo che appare il solito nag screen, il pulsante di accesso viene dislocato sulla parte destra o sinistra della finestra e dopo il click si avvia il programma. Questo significa che probabilmente viene fatto un check sullo stato di registrazione, se il programma e' in evaluation si effettua un conto dei giorni, si genera il nag e dopo il click si avvia l'applicazione. Perfetto, non abbiamo bisogno d'altro. Apriamo OllyDbg, clickiamo su File | Open” ed apriamo WINZIP32.EXE. Attendiamo che il debugger termini l'analisi automatica del programma e.... Ed ora che facciamo? L'ideale sarebbe settare un breakpoint sulla chiamata che genera il nag e bypassarla, il problema e' che non abbiamo idea di quale sia, un dettaglio non da poco. Tuttavia vediamo che viene creata una finestra, e quindi verra' chiamata una delle tante API di Windows, ma quale? Fondamentalmente la creazione di quasi tutte le finestre viene portata a termine utilizzando piu' o meno indirettamente la CreateWindowEx(), possiamo tranquillamente brekkare su questa chiamata e seguire il codice, ma abbiamo anche una seconda via d'accesso: i nag screen spesso vengono generati utilizzando le seguenti API:

  1. DialogBoxIndirectParam()
  2. DialogBoxParam()
  3. CreateDialogIndirectParam()
  4. CreateDialogParam()

Non ci sarebbe alcun problema nel brekkare su CreateWindowEx(), perche' ognuna di queste API ne fa uso, ma tanto che ci siamo proviamo prima con il modo piu' rapido, se dovessimo fallire avremmo comunque gia' bella e pronta una strategia di backup. Quindi dentro Olly andiamo su View | Executable modules, o premiamo direttamente Alt+E.

Newbies 7 Modules.png

Immediatamente apparira' la lista di tutti i moduli che vengono caricati/utilizzati da WinZip, quello di cui abbiamo bisogno e' user32.dll, infatti tutte le API che abbiamo elencato poco fa vengono esportate proprio da questa DLL:

Newbies 7 User32.png

Premiamo Ctrl+N, oppure facciamo click col tasto destro del mouse sul nome della dll e clickiamo su View names, nella finestra che si aprira' dovremo cercare le API elencate poco sopra, invece che fare lo scroll manuale possiamo digitare direttamente nella finestra il nome della funzione da cercare, una volta trovate iniziamo a metterci sopra dei breakpoint premendo il tasto F2, se la procedura e' corretta la riga interessata verra' evidenziata in rosso:

Newbies 7 Bp.png

I piu' attenti avranno notato che alcune API hanno il nome che termina con una A, altre invece con una W, nel primo caso significa che la funzione gestisce le stringhe in formato ASCII, mentre la seconda gestisce il formato Wide-char. Mettiamo i breakpoint su tutte quante, ma se WinZip e' stato scritto con un minimo di coscienza allora utilizzera' la versione W.... Lo scopriremo a breve :). Avviamo quindi il programma e non appena una delle API su cui abbiamo messo un breakpoint verra' utilizzata, il debugger si fermera'. Clickiamo quindi sul pulsantino play o premiamo F9, WinZip verra' avviato all'interno di Olly e dopo qualche secondo in basso a destra apparira' una scritta rossa su sfondo giallo: Paused, significa che il programma ha attraversato un breakpoint ed e' stato fermato. Ma quale breakpoint e' stato la causa dello stop? Per saperlo guardiamo sempre nella parte bassa della finestra di Olly, questa volta sulla parte sinistra, e vedremo:

Newbies 7 Paused.png

Quindi la funzione interessata e' stata la DialogBoxParamW()... La versione W come dicevamo poco fa :). Prima di procedere disabilitiamo tutti i breakpoint visto che l'API appena chiamata utilizza internamente la DialogBoxParamAorW(), e quindi rischiamo di incappare in un altro breakpoint che non farebbe altro che confonderci le idee. Premiamo Alt+B per visualizzare i breakpoint e poi premiamo Canc su tutte le righe per eliminarli. Fatto cio' possiamo tornare alla finestra del codice: guardando gli indirizzi nel debugger, o il titolo della finestra principale di Olly, notiamo che non ci troviamo nel codice di WinZip ma dentro: module USER32, ovvero all'interno di USER32.dll come mai? Abbiamo messo un breakpoint su un'API che risiede dentro questa dll, e quindi il debugger ha piazzato il suo INT3 sull'entrypoint della funzione, solo in questo modo e' possibile intercettare tutte (piu' o meno ;p) le chiamate all'API da parte del programma. Quindi ora dobbiamo tornare al codice di WinZip, in verita' non e' un'operazione complessa. Possiamo fare lo step su tutte le istruzioni dell'API ma non ci servirebbe a molto, quindi clickiamo su Debug | Execute till return o premiamo Ctrl+F9, vedremo apparire il nag screen di WinZip, clickiamo su Use Evaluation Version ed arriveremo automaticamente all'istruzione di ritorno che ci fara' rientrare nel nostro programma... Premiamo F8 per eseguire la singola funzione (facendo il cosidetto step) ed eccoci di nuovo all'interno di WinZip, piu' precisamente su un'istruzione di salto:

Newbies 7 Ret.png

Nella parte destra del debugger vediamo il listato dei registri, il valore di ritorno di un'API e' sempre conservato dentro EAX, quindi prendiamone nota perche' potrebbe tornarci utile dopo. Giunti a questo punto dobbiamo risalire l'albero delle chiamate e vedere qual'e' quella che da il via alla routine di preparazione e creazione del nag screen. In pratica dobbiamo cercare qualcosa che, traslato in C, assomigli a questo:

if(evaluation == TRUE)

   GenerateNagScreen()

else

   StartWinZip()

Qualcuno potra' chiedersi: perche' non disabilitiamo direttamente l'API per la creazione del nag screen? La domanda e' piu' che lecita, ma diamo uno sguardo all'API utilizzando la documentazione dell'MSDN:

INT_PTR DialogBoxParam(

   HINSTANCE hInstance,
   LPCTSTR lpTemplateName,
   HWND hWndParent,
   DLGPROC lpDialogFunc,
   LPARAM dwInitParam

);

Questi sono i parametri che si devono passare alla funzione, se guardiamo il quarto vediamo che si tratta di una DLGPROC, cioe' quella funzione che gestisce tutti i messaggi in arrivo sulla finestra del nag screen. WinZip potrebbe benissimo impostare dei flag (cosa che in effetti fa davvero, provare per credere) dalla DLGPROC e poi controllarli una volta chiuso il nag screen. Non eseguendo la DLGPROC quei flag non verrebbero mai impostati e quindi WinZip si accorgerebbe della modifica al codice e potrebbe rifiutarsi di partire (anzi... Si rifiuta di partire!). Dobbiamo risalire in modo da evitare l'albero delle chiamate che effettua anche il controllo dei flag, e poi evitando il caricamento della finestra diminuiamo anche il tempo di startup, non male vero? :). All'interno di un programma possiamo seguire una ferrea logica: se siamo dentro una chiamata, vuol dire che c'e' stata un'altra funzione che l'ha invocata, e questo e' vero praticamente per tutte le funzioni. Potremmo usare questo ragionamento per andare all'indietro fino al momento del boot del computer ;p. Ad ogni modo, troviamo la chiamata che ha invocato la procedura dentro cui ci troviamo, possiamo farlo steppando con F8 fino al RET o usando lo stesso procedimento di prima, in entrambi i casi approderemo all'indirizzo 0x424FE1, di nuovo F8 ed eccoci arrivare su 0x425332, esaminiamo questo pezzettino di codice:

Newbies 7 Call.png

Vediamo che come prima cosa viene salvato dentro EDI il valore di ritorno della chiamata, che a sua volta era il valore di ritorno della DialogBoxParamW(). E' evidente che quel valore e' importante altrimenti il programma non l'avrebbe tenuto a portata di mano per ben tre chiamate. Subito dopo questo valore viene confrontato con -1 (all'indirizzo 0x425337), e se non e' uguale si salta verso la fine della chiamata. Quel -1 non e' un caso, infatti come dice l'MSDN:

If the function [DialogBoxParamW()] fails for any other reason, the return value is –1.

Percio' siamo sicuri che il salto non verra' preso, proseguiamo quindi con F8 fino a raggiungere l'altro RET... Ma prima di tornare nuovamente date un'occhio a 0x42535D, il valore di ritorno della DialogBox viene nuovamente ritornato anche da questa chiamata.... Seguiamolo! Arriveremo qui:

Newbies 7 Setne.png

Questa chiamata gia' ad occhio sembra interessante, e per varie ragioni: la prima e' che troviamo una chiamata a GetLastActivePopup() seguita da una bella IsWindowVisible(), la seconda e' che c'e' anche la chiamata che genera il nostro nag screen. Vi aggiungo comunque una nota di colore: all'indirizzo 0x405780 viene salvato il secondo argomento della chiamata che e' 0xB6D, seguendo quel valore scopriamo che viene utilizzato come secondo parametro della DialogBoxParamW(), e si tratta dell'ID del template che disegna il nostro nag screen. Non ne parlero' in questo tutorial ma i piu' smaliziati possono aprire WINZIP32.EXE con un resource editor, cercare l'ID 0xB6D e vedere che corrisponde proprio a quella finestra che compone il bel nag :). La faccenda si fa interessante, significa che la chiamata in cui ci troviamo e' ancora un preludio alla generazione della finestra iniziale, percio' vale la pena studiarla, ecco il codice commentato:

0040575A /$ 53 PUSH EBX ; Inizio della chiamata 0040575B |. 56 PUSH ESI 0040575C |. FF35 647A5C00 PUSH DWORD PTR DS:[5C7A64]  ; /hOwner = 0010010C ('WinZip (Evaluation Version)',class='WinZipWClass') 00405762 |. FF15 A0675700 CALL DWORD PTR DS:[<&USER32.GetLastActiv>; \GetLastActivePopup 00405768 |. 8BF0 MOV ESI,EAX 0040576A |. 56 PUSH ESI  ; /hWnd 0040576B |. FF15 A4675700 CALL DWORD PTR DS:[<&USER32.IsWindowVisi>; \IsWindowVisible 00405771 |. 33DB XOR EBX,EBX 00405773 |. 85C0 TEST EAX,EAX 00405775 |. 75 02 JNZ SHORT WINZIP32.00405779 00405777 |. 33F6 XOR ESI,ESI 00405779 |> 53 PUSH EBX  ; /Arg5 0040577A |. 68 C9374000 PUSH WINZIP32.004037C9  ; |Arg4 = 004037C9 0040577F |. 56 PUSH ESI  ; |Arg3 00405780 |. 68 6D0B0000 PUSH 0B6D  ; |Arg2 = 00000B6D 00405785 |. FF35 6C795C00 PUSH DWORD PTR DS:[5C796C]  ; |Arg1 = 00400000 0040578B |. E8 6EFB0100 CALL WINZIP32.004252FE  ; \ Crea il Nag screen 00405790 |. 83C4 14 ADD ESP,14 00405793 |. 381D A1645C00 CMP BYTE PTR DS:[5C64A1],BL ; Viene azzerato un flag 00405799 |. 891D C47E5C00 MOV DWORD PTR DS:[5C7EC4],EBX ; Anche qui 0040579F |. 891D 70855C00 MOV DWORD PTR DS:[5C8570],EBX ; E qui... 004057A5 |. 66:891D CC755E>MOV WORD PTR DS:[5E75CC],BX ; E qui... Quanti flagghini! 004057AC |. 75 04 JNZ SHORT WINZIP32.004057B2 ; Se il primo flag non e' zero.. Salta 004057AE |. 32C0 XOR AL,AL 004057B0 |. EB 05 JMP SHORT WINZIP32.004057B7 004057B2 |> 3BC3 CMP EAX,EBX ; Confronta il valore di ritorno del Nag Screen con EBX 004057B4 |. 0F95C0 SETNE AL ; Se sono DIVERSI, setta AL ad 1 e poi ritorna 004057B7 |> 5E POP ESI 004057B8 |. 5B POP EBX 004057B9 \. C3 RETN

Come vediamo vengono azzerati dei flag, gli stessi che vengono utilizzati da altre chiamate per controllare che il nag screen sia stato effettivamente creato, fin qui tutto bene allora, notiamo una cosa importante: il registro AL viene settato a 1 se il valore di ritorno della DialogBox e' diverso da 0, altrimenti viene impostato a 0. Traslando in C otteniamo qualcosa di simile a questo:

if(GenerateNagScreen() != 0)

   return 1;

else

   return 0;

Che sembra interessante ancora una volta, ma direi che il traguardo e' oramai vicino, saltiamo sul ret e torniamo ancora indietro.

Newbies 7 Final.png

La cosa e' interessante, guardate cosa succede prima e dopo la chiamata da cui siamo ritornati, vi ripropongo il codice commentato per semplicita':

004058BF |. E8 82E21200 CALL WINZIP32.00533B46 004058C4 |. 84C0 TEST AL,AL 004058C6 |. 59 POP ECX 004058C7 |. 59 POP ECX 004058C8 |. 75 12 JNZ SHORT WINZIP32.004058DC 004058CA |. E8 8BFEFFFF CALL WINZIP32.0040575A ; Noi torniamo da qui 004058CF |. 84C0 TEST AL,AL ; Controlla il nostro caro valore di ritorno 004058D1 |. 75 10 JNZ SHORT WINZIP32.004058E3 ; Se e' 1 salta 004058D3 |. EB 10 JMP SHORT WINZIP32.004058E5 ; Se e' 0 vai a 0x4058E5 004058D5 |> C605 C9755E00 >MOV BYTE PTR DS:[5E75C9],1 004058DC |> C605 C1755E00 >MOV BYTE PTR DS:[5E75C1],1 004058E3 |> B0 01 MOV AL,1 004058E5 |> 5B POP EBX 004058E6 |> 8B4D FC MOV ECX,DWORD PTR SS:[EBP-4] 004058E9 |. 5F POP EDI 004058EA |. 33CD XOR ECX,EBP 004058EC |. 5E POP ESI 004058ED |. E8 BE070E00 CALL WINZIP32.004E60B0 004058F2 |. C9 LEAVE

Bene, giunti qui sembra proprio che questo sia l'inizio di tutto, se steppiamo vediamo che il primo JNZ viene preso e subito dopo viene avviato WinZip... Quindi cosa ci conviene fare?

Memory Patch

Abbiamo molte informazioni utili, la prima e' che tutte quelle chiamate tornano 1 se abbiamo clickato sul pulsante “Use Evaluation Version” del nag screen, ed in questo caso il primo salto condizionale viene eseguito. Potremmo mettere un jump al posto di quella chiamata per far saltare l'esecuzione del programma direttamente a 0x4058E3, sarebbe una buona idea, tuttavia abbiamo visto che WinZip ci tiene parecchio a quel valore di ritorno, e quindi potrebbe controllarlo in seguito, cosa fare dunque? A mio avviso una buona idea e' quella di patchare la chiamata in modo da mettere dentro AL il valore 1 che il programma si attende, in questo modo se venissero fatti degli altri controlli ci troveremmo abbastanza al sicuro. Facciamo quindi un click all'indirizzo 0x4058CA e premiamo la barra spaziatrice per iniziare ad assemblare un'istruzione, invece di scrivere MOV AL, 1 scriviamo direttamente: MOV EAX, 1 perche' occupa lo stesso numero di byte dell'istruzione attuale (prendete nota dei byte modificati), fatto cio' dovremmo ottenere qualcosa del genere:

Newbies 7 MemoryPatch.png

Premiamo F9 e vediamo WinZip fare la sua felice comparsa. Ok, ora possiamo riapplicare la patch in memoria per vedere se funziona: andiamo di nuovo su File | Open, apriamo WinZip, premiamo Ctrl+G per andare all'indirizzo 0x4058CA, assembliamo l'istruzione da modificare, disabilitiamo tutti i breakpoint e premiamo F9... Il programma dovrebbe partire senza alcun nag screen. Prima vi ho spiegato perche' non abbiamo patchato direttamente la chiamata a DialogBoxParamW(), ma esiste anche un'altra ragione: quella stessa chiamata viene utilizzata per generare molte altre finestre all'interno del programma, quindi modificarla avrebbe portato a dei problemi di funzionalita', ecco perche' siamo risaliti fino al primo check, in modo da esser sicuri di patchare solamente il necessario. Detto cio', passiamo al patching vero e proprio!

File Patch

Con un editor esadecimale apriamo WINZIP32.EXE, l'istruzione modificata si trova all'indirizzo 0x4058CA, ma dobbiamo trasformarlo in offset, quindi sottraiamo a questo numero l'imagebase che e' 0x400000 (potete vederlo con un PE Editor) ed otterremo appunto l'offset: 0x58CA. Sostituiamo i byte attuali: E88BFEFFFF con i byte modificati da noi: B801000000,

Newbies 7 Before.png

Newbies 7 After.png

salviamo la modifica ed avviamo WinZip, state attenti che se cambiate nome al file, rifiuta di avviarsi, tenetelo a mente :). Doppio click sull'eseguibile... Uhm, sembra funzionare :). Perfetto, ora possiamo scrivere una piccola patchina che apra il file e scriva i byte per noi:

// This a proof-of-concept patch to remove WinZip v11.2 initial nag screen // Coded by -=Quequero=-, NewBies Reverse Engineering Lesson number 7 // http://quequero.org

  1. include <Windows.h>
  2. include <stdio.h>

int main(int argc, char *argv[]){ HANDLE hFile = INVALID_HANDLE_VALUE; DWORD dwOffset = 0, dwRead = 0, dwWrite = 0; BYTE dwReadBuf[10], dwWriteBuf[] = {0xB8, 0x01, 0x00, 0x00, 0x00}; BYTE dwCheckBuf[] = {0xE8, 0x8B, 0xFE, 0xFF, 0xFF}; // Actual bytes

wprintf(L"NewBies Lesson No 7. - Removing Nag Screen from WinZip v11.2\n");

// Let's make a backup :) CopyFile(L"WINZIP32.EXE", L"WINZIP32.EXE.bak", FALSE);

// Remove read-only attribute if(!SetFileAttributes(L"WINZIP32.EXE", FILE_ATTRIBUTE_NORMAL)){ wprintf(L"Run this file from WinZip's install directory\n(usually: c:\\Program Files\\WinZip\\)\n"); return 1; }

// Open main file hFile = CreateFile(L"WINZIP32.EXE", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

if(hFile == INVALID_HANDLE_VALUE){ wprintf(L"Run this file from WinZip's install directory\n(usually: c:\\Program Files\\WinZip\\)\n"); return 1; }

// Let's move to our offset dwOffset = SetFilePointer(hFile, 0x58CA, NULL, FILE_BEGIN);

if(dwOffset == INVALID_SET_FILE_POINTER){ wprintf(L"This could be a different version of WinZip... Patching aborted.\n"); CloseHandle(hFile); return 1; }

// Read some bytes if(!ReadFile(hFile, &dwReadBuf, 5, &dwRead, NULL)){ wprintf(L"This could be a different version of WinZip... Patching aborted.\n"); CloseHandle(hFile); return 1; }

// And compare them with what sould be there :) if(memcmp(dwReadBuf, dwCheckBuf, _countof(dwCheckBuf))){ wprintf(L"This could be a different version of WinZip,\nchecked bytes don't match... Patching aborted.\n"); CloseHandle(hFile); return 1; }

// Rollback the file pointer dwOffset = SetFilePointer(hFile, 0x58CA, NULL, FILE_BEGIN);

if(dwOffset == INVALID_SET_FILE_POINTER){ wprintf(L"This could be a different version of WinZip... Patching aborted.\n"); CloseHandle(hFile); return 1; }

// If we've opened the right file... Patch it! if(!WriteFile(hFile, dwWriteBuf, _countof(dwWriteBuf), &dwWrite, NULL)){ wprintf(L"Error patching file... Patching aborted.\n"); CloseHandle(hFile); return 1; }

wprintf(L"Patching done! Enjoy WinZip, then buy it!\n"); CloseHandle(hFile); return 0; }

Il progetto della patch potete scaricarlo all'inizio della pagina. E per questa lezione... E' tutto :).

Quequero


Conclusioni

Abbiamo visto come si approccia un programma quando lo si vuole patchare, ma soprattutto abbiamo utilizzato un metodo di analisi intelligente, per evitare di modificare qualcosa di troppo che avrebbe potuto compromettere le funzionalita' del programma. La prossima volta che attaccherete un programma ricordatevi di non fermarvi alla prima opportunita', ma di proseguire nello studio del disassemblato, in fondo si impara piu' studiando un listato che patchando il primo byte disponibile :). Vorrei ringraziare tutti i membri UIC che si sono resi disponibile per la stesura delle nuove lezioni, e soprattutto Pnluck che si e' fatto carico della revisione e pubblicazione di ogni singolo tutorial. Ci vediamo alla prossima lezione!!! :)


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.