Crackare
CloneCD 4.3.1.7 |
||
Data |
by "Graftal" |
|
03/Oct/2004 |
Published by Quequero.. |
|
|
Graft anche a te davvero complimenti, grazie del tute. |
..in collaborazione con Graftal ;p |
If freedom is outlawed.. |
|
..only outlaws will have freedom
|
Difficoltà |
( )NewBies (X)Intermedio ( )Avanzato ( )Master |
In questo tute andremo ad affrontare un Manual Unpacking di Asprotect e ci crackeremo il CloneCD 4.3.1.7
Introduzione |
Tools usati |
URL o FTP del programma |
Notizie sul programma |
Essay |
__________________
|MANUAL UNPACKiNG|
Prendiamo in mano l'exe originale CloneCD.exe e apriamolo con OllyDbg. Bene, il
solito schema iniziale alla Aspr :) Per proseguire, dovete avere il plug-in per
olly IsDbgPresent, che ci nasconderà dalla suddetta api. Nascondiamo quindi
OllyDbg e andiamo direttamente con F9, tanto verranno generate un bel po' di
eccezioni. Premiamo molte volte Shit+F9 fino a quando vedete che siamo arrivati
a:
|
NB. Ciò a cui dovete fare attenzione è l'indirizzo :P
Bene, mettete un bp sull'istruzione successiva e premete nuovamente Shift+F9 per atterrarci. Togliete il bp (altrimenti Olly si incazza, provare per credere :) e steppate fino al ret. Ora andate avanti SEMPRE con F7 in modo da entrare nelle numerose call presenti e prestate attenzione quando arrivate a:
|
Mettete un bp sulla call e premete F9, una volta arrivati premete F7 (step into) e steppate fino a:
|
Eccoci al push che ci farà arrivare all'OEP (ovvero 0040154C). Una volta arrivati vedrete che OllyDbg fa qualche casino (almeno a me) ovvero fa vedere un sacco di db 'byte' e rende praticamente illeggibile il programma. Basta semplicemente fare un Ctrl+A per fargli analizzare il tutto. Ora non continuiamo più a steppare, ma passiamo subito al dumping.
_________
|DUMPiNG|
Se avete il plug-in OllyDump usatelo pure con le impostazioni predefinite ma
ricordandovi ASSOLUTAMENTE di togliere il segno di spunta vicino alla voce
Rebuild Import, altrimenti usate pure qualsiasi altro prog (vedi Wark, ProcDump
ecc). Una volta che abbiamo l'exe sull'HD apriamolo subito senza indugi con
Olly per vedere una cosa particolare:
|
Huh? E noi abbiamo dumpato sto schifo? Non esattamente.. Aprite
il Wark (io uso la versione 1.3), andate nel rebuilder (per chi proprio non lo
sapesse, sta nel menu Utilities\PE Stuff\Rebuilder) e settate tutte le opzioni.
Una volta ricostruito potete riaprire il file con Olly e constatare
piacevolmente che la vostra creatura ha preso forma. Let's rock :)
Prestate ora attenzione a:
|
Questa è una chiamata ad un'api, ma come vedete non è risolta correttamente. Tutto questo è merito dell'asprotect, che fa un giochino strano e che ora vi spiego (se avete letto e capito il tute di andreageddon, saltate pure questo pezzo e passate al sodo). Il crypter usa una sorta di ponte tra il programma e le api che esso chiama. Se per esempio avviene una call a GetWindowTextA, il programma non salterà direttamente all'EP dell'api, bensì al ponte creato dall'aspr che si occupa di 'rubare' i primi byte dell'api (ovvero copia le prime istruzioni come push e istruzioni simili nel ponte) e poi effettua un salto a qualche istruzione dopo l'EP dell'api, saltando quindi ciò che ha già eseguito lui al posto dell'api. Usando la chiara tabella di andre, diremmo così:
executable |
redirection bridge |
dll |
... ... call [api] ---> ... ... ... ... ... |
... ... api instruction1 api instruction2 api instruction3 ... jmp api + n ---> ... |
... ... api instruction1 (stolen!) api instruction2 api instruction3 ... api instruction n ... |
"the aspr scans first n instruction at api entry point (n is variable), copies it in the redirection bridge (a buffer in the process space, 0x00C30000 in my pc), then adds a jump to the real api to continue execution. So the import address in the iat will not be the one of the api but the one of the redirection bridge. This is a nice trick, it also prevents api breakpoints: infact you usually set a bpx on the entry point of the api, but such entry point is not executed so the debugger will not break." (grande andre ;)
___________
|REBUiLDiNG|
Ok ma..Come facciamo a ricostruire il tutto? La IAT è completamente distrutta a
questo punto. La soluzione è semplice, dumpiamo il bridge quando è in memoria,
e creiamoci un rebuilder automatico. Da me il bridge che ci interessa comincia
da 00B6xxxx, quindi riapriamo l'exe originale e rifacciamo tutto quanto per
ritornare all'OEP. Apriamo quindi il Wark, selezioniamo un "Dump Partial" sul
nostro processo e mettiamo come indirizzo di partenza B60000 e come size 4000.
Salviamolo come ITasprotectB6xx.dump (questo per semplicità, dato che non
dovrete cambiare nulla del sorgente del rebuilder che vi presenterò tra poco) e
chiudiamo pure Olly. Anche nel tute di andreageddon c'è un rebuilder
automatico, ma dato che c'è qualche differenza tra questa versione di aspr e
quella sua, ho deciso di fare un rebuilder in win32asm che, passandogli l'RVA
del primo indirizzo delle api importate dal bridge, e l'ultimo (senza
preoccuparsi se in mezzo c'è qualche api già risolta, dato che verrà ignorata
automaticamente dal rebuilder) lui risolve tutto quanto correttamente. Il
sorgente è molto piccolo, circa 300 righe di codice, ma che da incollare qua
sono comunque molte: ho pensato quindi di mettere il source completo in
allegato e di analizzare solo alcune cose principale qua nel tute. Per prima
cosa, le variabili importanti:
FileDumpName db "CloneCD_dump.exe", 0
DumpedBridgeB6 db "ITasprotectB6xx.dump", 0
Cambiate pure la prima variabile con il nome del file dumpato e la seconda con il bridge che avete copiato sull'HD. Il programma comprende una procedura chiamata 'RebuildIT' che, come dice il nome, si preoccupa di ricostruire la Import Table. Fate attenzione al valore ritornato da questa funzione: se infatti è uguale a 0, allora significa che si è incontrato un indirizzo gia risolto o uno degli 8 indirizzi da risolvere manualmente (spiegato in seguito), se ritorna 1 allora significa che il processo di ricostruzione è stato completato con successo e non c'è più bisogno di richiamare la funzione un'altra volta. Per sicurezza e per evitare bug, ho anche messo una routine che azzera tutte le variabili usate in modo da poter utilizzare nuovamente il programma senza doverlo chiudere e poi riaprire. La funzione che effettua il check sugli indirizzi da risolvere o meno si chiama 'checkaddress'. Per usare il programma con il nostro target, dovremmo quindi usare come parametri nella dialog box:
Scrivi l'RVA da dove cominciare:
1389852
Scrivi l'ultimo RVA da ricostruire:
1390664
NB. Gli indirizzi vanno scritti, come vedete, in decimale.
NB2. Il tempo impiegato per ricostruire il tutto varia da PC a PC, ma
generalmente non dovrebbe essere molto: io impiego sul mio P4 1600 circa 5-10
secondi al massimo: contate che ci sono più di 200 import da ricostruire.
E otterremo gli indirizzi ricostruiti. Potete notare che non ho incluso i primi
indirizzi importati (ovvero da 5531A8 a 5532CC) perché sono corretti, vengono
infatti presi non da dll di sistema, ma dalle dll dello stesso CloneCD, vedasi
CCDDriver.dll, ElbyECC.dll ecc.
Ora dobbiamo ricostruire quelle 8 api importate di cui parlavo prima. Questa
api sono caricate nel bridge in modo particolare, infatti sono delle vere e
proprie "Emulazioni di API". Vediamoli nel dettaglio:
Indirizzo B51CF0:
|
Questo pezzo di codice ritorna il path del file. Andiamo a vedere dove viene chiamata questa funzione:
|
Mhm..però, la chiamata non serve proprio a nulla, perché come vedete non viene più usato il valore di ritorno in eax. Dobbiamo quindi sostituirlo con una funzione che non fa nulla, io ho messo FreeResource (troppo bello reversarlo :). Api Reference, a me:
|
Hehe, non a caso reversando la funzione abbiamo:
|
:)
Indirizzo B51CD8:
|
Può sembrare una call a GetModuleHandleA, ma in realtà è l'API GetCommandLineA.
Indirizzo B51CB8:
|
Questa è una chiamata a GetCurrentProcessA, se infatti lo andate a reversare troverete:
|
Dove eax vale 0.
Indirizzo B51CC0:
|
Questa è invece una call a GetCurrentProcessId. Se infatti andate a reversarvi un po' il loader dell'asprotect, vedrete che salva questo valore in precedenza per poi usarlo qua.
Indirizzo B51C64:
|
Questa è invece la call a GetModuleHandleA: se il parametro passato è NULL, allora non si chiama l'API ma si ritorna direttamente l'hInstance standard per ogni exe (00400000).
Indirizzo B517A4:
|
Questa è una chiamata a GetProcAddress.
Indirizzo B51C8C:
|
Chiamata a GetVersion, essa infatti ritorna un valore salvato precedentemente dal loader.
Indirizzo B51CC8:
|
Questa è una cosa molto interessante: AndreaGeddon dice "this just returns the only parameter this function takes ([ebp+8]) Can't be fixed with an api, it must be replicated!". Mi dispiace doverlo contraddire ma sono riuscito a trovare un'api che fa la stessa cosa (!!):
|
L'API è SetHandleCount e non fa proprio nulla, se non ritornare se stessa. Il reference dice:
The SetHandleCount function sets the number of file handles available to a process. This function has no effect under Windows NT and Windows 95, because there is no explicit file handle limit for applications on these platforms. Under Win32s, there are only 20 file handles available to a process by default; however you could use SetHandleCount to allow a process to use up to 255 file handles. UINT SetHandleCount(
UINT uNumber // number of file handles needed
Parameters uNumber Specifies the number of file handles needed by the application.
Return Values Under Windows NT and Windows 95, this function simply returns the
value specified in the uNumber parameter.
Remarks Under Windows NT and Windows 95, the maximum number of files that an application can open is determined by the amount of available non-paged memory pool, because each open file handle requires non-paged memory. |
Ecco quindi che capiamo subito perché non fa nulla :)
Bene, queste sono le funzioni che ci andremo a fixare a mano, ecco gli EP delle varie API (in ordine di comparsa):
|
Bene, a questo punto gli indirizzi sono a posto, non ci rimane che ricostruire l'Import Table vera e propria. Per fare ciò dobbiamo per prima cosa rimettere a posto gli Import Descriptor. Vanno bene tutti i valori gia presenti tranne per gli Original First Thunk e i First Thunk. Gli OFT e i FT devono essere uguali, e entrambi devono puntare alla prima API importata dalla dll: fate attenzione però che non abbiamo ancora messo tra l'ultima API importata da una dll e la prima di quella dopo, una DWORD nulla. Ecco quindi che ci prendiamo il nostro eseguibile parzialmente ricostruito e andiamo all'indirizzo 500D8C dove comincia il tutto. Da OllyDbg guardate i vari jmp e vedrete che i primi riguardano la dll Elbicdio.dll. Il primo indirizzo importato sta a 5531A8 e l'ultimo a 5531F4. Subito dopo la dword presente a questo indirizzo (10003DB0) cancellate una bella dword, in modo da avere 8 zeri. Fate la stessa cosa per ogni altra dll, ovvero andate dove è presente l'ultimo indirizzo importato e subito dopo piazzateci una dword nulla. Dato che dopo la dll Elbicdio.dll non si vede più a quale dll appartiene l'indirizzo importato, basta solo guardare l'Image Base: da 553250 fino a 55329C (dove metterete una dword nulla subito dopo l'ultimo indirizzo importato) gli indirizzo sono in forma 33xxxx, e da 5532BC fino a 5532CC (dove metterete una dword nulla subito dopo l'ultimo indirizzo importato) hanno prefisso 34xxxx. Una volta che il vostro lavoro è stato completato, siete pronti per aprire il WPE (presente insieme al Wark se non lo sapeste) e potete quindi andrare a editare l'IT. Cliccate su ogni dll importata e cambiate gli OFT e i FT in modo che siano uguali e che abbiano il valore del primo indirizzo importato in RVA. Per esempio, il kernel32 avrà come OFT e FT il valore 15351C. Una volta salvato il valore vedete che gli import dal kernel32 sono 129, e credetemi, sono giusti (se non vi fidate contateveli a mano :). Vi metto qui tutti i valori di tutte le dll importate. Ah, prima che mi dimentichi, la dll oleaut32 è presente due volte: cancellate semplicemente il secondo import descriptor.
|
Bene, una volta terminato questo semplice compito, non ci resta
che ricostruire l'exe con il rebuilder di prima del Wark e gli diciamo di
ricostruire l'import table senza effettuare il binding. Salviamo il file finale
e abbiamo ottenuto il nostro file bello che unpackato :)
Bello eh? :P
Ora dobbiamo solamente più crackare il programma, cosa che sarà una passeggiata
:)
___________
|#CRACK-iT|
Ora abbiamo l'eseguibile completamente funzionante: per la cronaca comunque, vi
dico anche che esiste un bell'unpacker per Asprotect :) Il programma si chiama
Stripper e la versione 2.03 non riesce ad unpackare il clonecd, mentre la 2.07
è perfetta per questo compito. "Eh sì, e dopo tutto sto casino, me lo dici ora
che c'è anche l'unpacker? Limortacc.." :) Ma tanto siamo qua per imparare, mica
per fare le cose alle svelta senza capirci nulla (cfr lamer :).
Ora che l'exe è pronto e pulito proviamo ad aprirlo una volta, solo per vedere
se funge. La prima volta che ho provato, mi dava un errore strano, riguardante
il calling thread, poi ho riprovato a manual unpackarlo ancora, e l'errore non
si è più presentato: probabilmente ho sbagliato qualcosa io la prima volta.
Bene, ora che sappiamo che il nostro exe è unpackato e funziona a meraviglia,
reversiamoci RegCloneCD.exe con il nostro fido Olly. Qui viene chiamata la
funzione che chiede all'utente di scegliere il file di registrazione:
|
Steppiamo allora dentro e andiamo avanti fino a
|
Anche qui un bel step into e guardiamoci un po i filtri che ci sono nell'OPENFILENAME. La struttura OPENFILENAME è dichiarata come segue:
typedef struct tagOFN { //
ofn
WORD nFileOffset;
|
In lpstrFilter troviamo il filtro che fa vedere solo i file con
l'estensione voluta dai programmatori, e noi dobbiamo assolutamente sapere
qual'è per crearci il file di registrazione truccato. In realtà non serve a
nulla fare ciò che stiamo per fare, perché tanto andremo a crackare il prog,
però è sempre utile fare un po' di sano reversing :)
Vediamo quindi un paio di righe di codice interessanti:
|
E subito dopo lo wsprintf troviamo in edi ciò che ci serve:
ASCII "*.key;*.CloneCD"
Dato che tutti voi sapete che i file .key servono per aggiungere
voci al registro di sistema, al posto di fare un file .key fatene uno .clonecd,
almeno abbiamo un'estensione nuova sul pc :)
Ok, cretinate a parte, fatevi questo file .CloneCD e preparatevi ad aprirlo
quando arriva la dialog. Ed eccola qua, poche righe di codice più sotto:
|
GetOpenFileName, perfetto. Arrivati qua sceglietevi il vostro bel file e proseguiamo fino al ret. Steppiamo con tranquillità, e una volta finito il loop equivalente ad uno lstrlenA, arrivate a:
|
Step-into (F7) e vediamo che il programma 'costruisce' tramite
wsprintfA la chiave di registro nella quale dovrà andare a finire il nostro
serial, ovvero
HKEY_LOCAL_MACHINE\Software\SlySoft\CloneCD\Key
Bene, arriviamo all'istruzione fatidica:
|
I parametri passati a GetPrivateProfileStringA:
DWORD GetPrivateProfileString(
LPCTSTR lpAppName, // points to section name
|
In questo abbiamo:
|
E' quindi semplicissimo farsi il file, basta mettere nel nome
della sezione
[HKEY_LOCAL_MACHINE\Software\SlySoft\CloneCD\Key]
e sotto la stringa "Key" = serialnumber
Io per esempio ho chiamato, come avete notato, il file di registrazione
asd.clonecd e il suo contenuto è:
|
Due righe :)
Ora il programma vi ringrazia e vi chiede di avviare il CloneCD: seguiamo il
consiglio.
Analyzing CloneCD.exe - 53% - press SPACE to interrupt
Ok, appena finisce la prima cosa da fare è mettere un bel bp sulle api che leggono valori dal registro di sistema: RegCreateKeyA e RegOpenKeyExA dovrebbero bastare. Andate avanti con F9 e vedete che si arriva ad un punto in cui il programma cerca dei 'vecchi' serial number, ovvero quelli delle versioni 4.2.x.x, ma a noi non interessa. Comunque io non ho trovato nulla di interessante in tutte queste chiamate alle API e mi sono quindi andato ad aprire il file con DeDe. Già, è scritto in Delphi, si capisce subito dall'EP:
|
Questi db sono presenti in molti programmi scritti in Delphi. Se non avete il
DeDe, beh, scaricatevelo, apritelo e ditegli di analizzare il nostro caro
CloneCD.exe. Andiamo ora in Procedures e vediamo le varie Form presenti..Non
avete trovato qualcosa di sospetto? Eh sì, TReminderForm è davvero MOLTO
sospetto :) Clicchiamoci sopra, e negli eventi presenti a sinistra facciamo
doppio click su FormShow, segnamoci l'indirizzo e riapriamo OllyDbg: Ctrl+G e
scrivete l'indirizzo (0041630C) e vediamo un po' cosa fare. Vediamo se olly ci
dice da dove avviene la chiamata: right-click, GoTo e vediamo in fondo se c'è
qualche call o qualche jmp..nisba. Va bene, niente di più facile, settate un bp
su
0041630C 55 PUSH EBP
e runnate il prog. Eseguite fino al ret e fate un ultimo step per trovarvi qua:
|
La call quindi è quella qua sopra, ovvero a 004873D1. Guardate poco sopra e troverete un je che fa in modo di saltare questa call: non pensate nemmeno lontanamente di trasformarla in JMP, perché la call in questione viene chiamata per far vedere anche molti altri form. Piuttosto dobbiamo andare ancora più indietro, seguendo l'abitudine dei gamberi (:P), e per farlo dobbiamo continuare a steppare (sembra una contraddizione in termini, ma vedrete che non è così). Siamo usciti dalla call, e ora sappiamo che il tutto viene chiamato da:
|
Anche qua, guardando un po' sopra, ci sono dei jump condizionati, ma anche qui come prima, non cambiate nulla, perché queste call sono condivise anche dalle altre form. Piuttosto mettete un bp su:
|
e riavviate il programma. dopo pochi bp atterrerete qui, e avrete modo di steppare con calma. La prima volta che ci arrivate lasciate stare, mentre la seconda volta è importante che steppiate oltre la call presente a 48A43D e che andiate avanti sempre con F8 per superare una numerosa serie di ret. Capirete di essere arrivati al punto giusto quando vedrete:
|
Ora steppate un poco fino ad arrivare a:
|
Prestate attenzione a questo je, perché ci siamo: lasciate invariato il programma e steppate, vedrete che passando per una serie di call presenti dopo questo salto condizionato verranno caricate stringhe come NON REGISTRATO, %d di %d giorni di prova rimasti, Registrato a nome di: NON REGISTRATO ecc. Non pensate anche voi di essere finalmente arrivati al punto giusto? Direi di sì, ma non pensate subito di trasformare il je in jmp, hehe :) Perché facendo così non avrete risolto proprio nulla. Steppate ancora invece, e vedete che nel seguente pezzo di codice non c'è più nulla che centri con la registrazione:
|
Eh sì, infatti guardandoci un po' dentro vedete che avete trovato il pezzo di codice che si occupa dell'update del prodotto, che non avviene se non avete registrato il programma grazie al je presente a 00403B4B. Perfetto, io ho già in mente cosa fare: trasformiamo quel je che abbiamo trovato prima a 00403A64 in un jmp 403B4D (doppio click sull'istruzione, scrivete la nuova istruzione e premete assemble). Le nuove istruzioni saranno quindi:
|
Fatto ciò, cliccate col destro sulla nuova istruzione (o dovunque vi pare) e scegliete Copy to executable -> All Modifications, quindi Copy All, altro right-click e quindi Save File. Chiamatelo come volete, chiudete Olly ed eseguitelo :) Yes, funge :) Se vi dà fastidio il fatto che ogni volta che aprite CloneCD vi chiede di aggiornarlo, allora cambiate il nostro jmp in jmp 00403B76 e sarete a posto ;). Pensate di aver finito? Forse direte di sì, ma fate attenzione ad un particolare poco professionale: l'about box :) Ma come sarebbe a dire, Registrato a nome di: NON REGISTRATO ?? Hehe, niente di particolarmente complesso. Se avete fatto caso, il clonecd carica le stringhe da dei file .lng. Un metodo sarebbe quello di trovare la stringa NON REGISTRATO nel file e modificarlo con il vostro nome o nick: non ho però provato a vedere se si può scrivere una stringa più lunga di NON REGISTRATO, provate voi magari. Comunque sia, io modificherei pure il file .lng, ma se volete passare il crack a qualcuno, gli dovete dare due file al posto di uno. Scegliete quello che vi piace di più, a vostra discrezione. Se intendete modificare il file CloneCDit.lng vi basta usare anche solo il notepad, ma io vi consiglio un hex editor, è più comodo: trovate NON REGISTRATO, metteteci il vostro nick e azzerate ciò che avete in più. Per esempio, io ho usato Graftal, e mi rimaneva ISTRATO, che mi è bastato 'fill'-are di zeri. L'altro metodo invece, richiede un pochino di reversing, ma è anche più divertente. Prima di tutto, dobbiamo trovare un qualche cave (punti dell'exe che sono vuoti e inutilizzati) per mettere il nostro nick: andiamo alla fine del file e vedremo il nostro bel zeropadding: andate in un punto qualsiasi e in olly cliccate col destro e fate Binary\Edit, togliete il segno di spunta a Keep Size, cliccate sull'edit ASCII e scrivete il vostro nick. Io ho messo il tutto all'indirizzo 5019B0. Ora dobbiamo trovare la funzione che carica la stringa NON REGISTRATO e la mostra nell'about box. Apriamo di nuovo il DeDe allora (nel caso l'aveste chiuso) e andiamo a guardare nelle Procedures la classe TAboutBox, quindi click con il destro su FormShow e poi Copy current RVA to clipboard. Andiamo in olly, Ctrl+G e poi incolliamo l'indirizzo. Mettiamo un bp e facciamo partire il prog, clicchiamo su Informazioni: quando Olly poppa steppiamo fino a:
|
Hehe, qua viene caricata la stringa NON REGISTRATO:
|
Facciamo quindi una bella cosa: trasformiamo il push e la call che ho copiato qua sopra in un:
|
e basta :)
Ora avviate il programma e...TADA! L'exe è bello che unpackato e crackato, cosa
volete di più dalla vita? E non rispondetemi "Un Lucano", grr.. :)
Note finali |
Allora, vorrei ringraziare prima di tutto i frequentatori di #graftal (hehe, evviva la pubblicità occulta :), quelli di #crack-it (AndreaGeddon compreso per il suo tute sull'aspr ;), #informazionelibera, #focushack, #asm (grande deim :) e gente come Eimiar, Nt e Quake per il Wark e il WPE, SiberianSTAR, [Brux] (mea lux :P), DaFixer per il DeDe, il GRANDE evilcry ;), Quequero (MITTTICCO!.. MABBAFFANCULO VA! :P Ewwiwa Giampiero Galeazzi :), and, last but not least, il Misanthripic-o (WOLF :D) e tutti quelli che conosco :)
Byezzzzzzz..
If freedom is outlawed, only outlaws will have freedom..
Se un prodotto vi piace, fate come me, COMPRATEVELO :P
Disclaimer |
Every reference to facts, things or persons (virtual, real or esoteric) are purely casual and involuntary. Any trademark nominated here is registered or copyright of their respective owners. The author of this manual does not assume any responsability on the content or the use of informations retriven from here; he makes no guarantee of correctness, accuracy, reliability, safety or performance. This manual is provided "AS IS" without warranty of any kind. You alone are fully responsible for determining if this page is safe for use in your environment and for everything you are doing with it! We reverse just to improve assembly coding.
Secondo disclaimer (in ita, non si sa mai ;p):
Vorrei ricordare che il software va comprato e non rubato, dovete registrare il vostro prodotto dopo il periodo di valutazione. Non mi ritengo responsabile per eventuali danni causati al vostro computer determinati dall'uso improprio di questo tutorial. Questo documento è stato scritto per invogliare il consumatore a registrare legalmente i propri programmi, e non a fargli fare uso dei tantissimi file crack presenti in rete, infatti tale documento aiuta a comprendere lo sforzo immane che ogni singolo programmatore ha dovuto portare avanti per fornire ai rispettivi consumatori i migliori prodotti possibili.
Noi reversiamo al solo scopo informativo e di miglioramento del linguaggio Assembly.