Crackare CloneCD 4.3.1.7
(Manual Unpacking Asprotect)

Data

by "Graftal"

 

03/Oct/2004

UIC's Home Page

Published by Quequero..


La scrivo io la data? :P

Graft anche a te davvero complimenti, grazie del tute.

..in collaborazione con Graftal ;p

If freedom is outlawed..

Home page: N/A
irc.azzurra.org:6667 #crack-it #asm #graftal #informazionelibera #focushack #slipknot.it #--_XmX_-- #programmatori #cryptorev #spippolatori 

 

..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


Crackare CloneCD 4.3.1.7
(Manual Unpacking Asprotect)
Written by Graftal

Allegato

Introduzione

Bene, in questo tute vorrei parlare un po' di manual unpacking; ma non di manual unpacking solito, bensì del manual unpacking dell'asprotect. Questo packer/crypter con i controcazzi (:P) è arrivato alla versione 1.3.08.24 (io non ho incontrato programma packato con una versione più nuova) e noi ci analizzeremo un po' come fare a fregarlo. Ci verrà ovviamente in aiuto l'ottimo tutorial di AndreaGeddon. Il target sarà il CloneCD 4.3.1.7. La Elaborate Bytes dopo aver chiuso i battenti si è data il nuovo nome di SlySoft e ha continuato le sue release, e attualmente la versione più nuova che ho incontrato è stata la 5, ma tanto è la stessa identica cosa ho potuto notare. La protezione non è particolarmente complessa, anzi, è proprio semplice, ma è cambiata rispetto alle versioni 4.2.x.x perché non richiede più il serial tramite una nag del programma principale, ma si appoggia ad un piccolo exe chiamato RegCloneCD.exe che si preoccupa di caricare un file (vedremo il tutto nel dettaglio più avanti) e di leggerne il serial e metterlo nel registro di sistema; CloneCD.exe si occuperà poi di verificarne la correttezza. Bando alle ciance, diamoci dentro :)

Tools usati

OllyDbg
DeDe 
IsDbgPresent plug-in per OllyDbg  
OllyDump plug-in per OllyDbg  
HexWorkshop (o qualsiasi altro hex editor)
Wark 1.3 

URL o FTP del programma

Sinceramente non lo so, io l'ho preso da bittorrent: comunque guardando nell'about abbiamo l'indirizzo:
http://www.slysoft.com/ 

Notizie sul programma

Non conoscete CloneCD? E come fate a vivere? (Come disse nobo, se non sbaglio, nel suo numero due dei newbies riferito ad un altro programma ovviamente). CloneCD è un programma UTILISSIMO per fare una copia 1:1 di un qualsiasi cd: riuscerete a copiarvi Doom3 e a giocarci senza bisogno di crack :)  

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:

00B539EC XOR DWORD PTR DS:[EAX],EAX

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:

00B6C2FE POP ECX ; 00B6C2BE
00B6C2FF SUB EAX,1
00B6C305 JNZ 00B6C1ED
00B6C30B CALL 00B6C31A

Mettete un bp sulla call e premete F9, una volta arrivati premete F7 (step into) e steppate fino a:

00B6C37C ADD EAX,EBX ; CloneCD_.00400000
00B6C37E MOV EBX,0
00B6C383 OR EBX,EBX
00B6C385 JNZ SHORT 00B6C38E
00B6C387 MOV DWORD PTR SS:[ESP+1C],EAX
00B6C38B POPAD
00B6C38C PUSH EAX
00B6C38D RETN

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:

77F41993 MOVZX ECX,WORD PTR DS:[ECX]
77F41996 CMP ECX,DWORD PTR DS:[ESI+18]
77F41999 MOV DWORD PTR SS:[EBP+C],EBX
77F4199C MOV DWORD PTR SS:[EBP-4],ECX
77F4199F JNB SHORT 77F419E5

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:

0040156C PUSH 0
0040156E CALL CloneCD_.00500FBE

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:

00B51CF0 PUSH EBP
00B51CF1 MOV EBP,ESP
00B51CF3 MOV EAX,DWORD PTR DS:[B57E24]
00B51CF9 POP EBP
00B51CFA RETN 4

Questo pezzo di codice ritorna il path del file. Andiamo a vedere dove viene chiamata questa funzione:

004CFF1B MOV EAX,DWORD PTR DS:[ESI+14]
004CFF1E PUSH EAX
004CFF1F CALL CloneCD_.00500F40
004CFF24 MOV EDX,EBX
004CFF26 AND DL,0FC
004CFF29 MOV EAX,ESI

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:

The FreeResource function is obsolete. It is provided to simplify porting of 16-bit Windows-based applications. It is not necessary for Win32-based applications to free resources loaded by using the LoadResource function.

Hehe, non a caso reversando la funzione abbiamo:

77E4CB14 XOR EAX,EAX
77E4CB16 RETN 4

:)

Indirizzo B51CD8:

00B51CD8 PUSH 0
00B51CDA CALL 00B451B8 ; JMP to kernel32.GetModuleHandleA
00B51CDF PUSH DWORD PTR DS:[B57E14]
00B51CE5 POP EAX
00B51CE6 MOV EAX,DWORD PTR DS:[B57E24]
00B51CEC RETN

Può sembrare una call a GetModuleHandleA, ma in realtà è l'API GetCommandLineA.

Indirizzo B51CB8:

00B51CB8 MOV EAX,DWORD PTR DS:[B57E18] ; -1
00B51CBD RETN

Questa è una chiamata a GetCurrentProcessA, se infatti lo andate a reversare troverete:

77E59C90 OR EAX,FFFFFFFF
77E59C93 RETN

Dove eax vale 0.

Indirizzo B51CC0:

00B51CC0 MOV EAX,DWORD PTR DS:[B57E20] ; A08h
00B51CC5 RETN

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:

00B51C64 PUSH EBP
00B51C65 MOV EBP,ESP
00B51C67 MOV EAX,DWORD PTR SS:[EBP+8]
00B51C6A TEST EAX,EAX
00B51C6C JNZ SHORT 00B51C81
00B51C6E CMP DWORD PTR DS:[B57AA4],400000 ; ASCII "MZP"
00B51C78 JNZ SHORT 00B51C81
00B51C7A MOV EAX,DWORD PTR DS:[B57AA4]
00B51C7F JMP SHORT 00B51C87
00B51C81 PUSH EAX
00B51C82 CALL 00B451B8 ; JMP to kernel32.GetModuleHandleA
00B51C87 POP EBP
00B51C88 RETN 4

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:

00B517A4 PUSH EBP
00B517A5 MOV EBP,ESP
00B517A7 MOV EDX,DWORD PTR SS:[EBP+C]
00B517AA MOV EAX,DWORD PTR SS:[EBP+8]
00B517AD MOV ECX,DWORD PTR DS:[B56484]
00B517B3 MOV ECX,DWORD PTR DS:[ECX]
00B517B5 CMP ECX,EAX
00B517B7 JNZ SHORT 00B517C2
00B517B9 MOV EAX,DWORD PTR DS:[EDX*4+B563D8]
00B517C0 JMP SHORT 00B517C9
00B517C2 PUSH EDX
00B517C3 PUSH EAX
00B517C4 CALL 00B451C0 ; JMP to kernel32.GetProcAddress
00B517C9 POP EBP
00B517CA RETN 8

Questa è una chiamata a GetProcAddress.

Indirizzo B51C8C:

00B51C8C PUSH DWORD PTR DS:[B57E14] ; A280105h
00B51C92 POP EAX
00B51C93 RETN

Chiamata a GetVersion, essa infatti ritorna un valore salvato precedentemente dal loader.

Indirizzo B51CC8:

00B51CC8 PUSH EBP
00B51CC9 MOV EBP,ESP
00B51CCB MOV EAX,DWORD PTR DS:[B57E24] ; File Path
00B51CD1 MOV EAX,DWORD PTR SS:[EBP+8]
00B51CD4 POP EBP
00B51CD5 RETN 4

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 (!!):

77E5C931 MOV EAX,DWORD PTR SS:[ESP+4]
77E5C935 RETN 4

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.
Under Win32s, the return value specifies the number of file handles actually available to the application. It may be fewer than the number specified by 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):

FreeResource:        77E4CB14
GetCommandLine:      77E5C938
GetCurrentProcess:   77E59C90
GetCurrentProcessId: 77E60656
GetModuleHandle:     77E59F93
GetProcAddress:      77E5A5FD
GetVersion:          77E5C486
SetHandleCount:      77E5C931

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.

kernel32:  0015351C
elbicdio:  001531A8
elbiecc:   00153250
ccddriver: 001532BC
advapi32:  001532F4
rpcrt4:    00153734
version:   00153754
winspool:  00153778
comctl32:  001537F0
comdlg32:  00153860
gdi32:     001539C8
shell32:   00153B44
user32:    00153E50
winmm:     00154144
ole32:     00154158
oleaut32:  001541A8
oleaut32:  da cancellare

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:

0040171E PUSH EAX
0040171F CALL RegClone.00401270

Steppiamo allora dentro e andiamo avanti fino a

0040131C PUSH 104
00401321 LEA EAX,DWORD PTR SS:[ESP+11C]
00401328 PUSH EAX
00401329 PUSH ESI
0040132A CALL RegClone.00401050

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
DWORD lStructSize;
HWND hwndOwner;
HINSTANCE hInstance;
LPCTSTR lpstrFilter; // a noi interessa questo
LPTSTR lpstrCustomFilter;
DWORD nMaxCustFilter;
DWORD nFilterIndex;
LPTSTR lpstrFile;
DWORD nMaxFile;
LPTSTR lpstrFileTitle;
DWORD nMaxFileTitle;
LPCTSTR lpstrInitialDir;
LPCTSTR lpstrTitle;
DWORD Flags;

WORD nFileOffset;
WORD nFileExtension;
LPCTSTR lpstrDefExt;
DWORD lCustData;
LPOFNHOOKPROC lpfnHook;
LPCTSTR lpTemplateName;
} OPENFILENAME

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:

0040108D PUSH EAX ;                      /<%s> => "CloneCD"
0040108E LEA ECX,DWORD PTR SS:[ESP+15C]; |
00401095 PUSH RegClone.0040513C ;        |Format= "*.key;*.%s"
0040109A PUSH ECX ;                      |s
0040109B CALL ESI ;                      \wsprintfA

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:

004010E6 PUSH ECX
004010E7 MOV DWORD PTR SS:[ESP+C],4C
004010EF MOV DWORD PTR SS:[ESP+28],EDX
004010F3 MOV DWORD PTR SS:[ESP+40],80180C
004010FB MOV DWORD PTR SS:[ESP+18],EAX
004010FF MOV DWORD PTR SS:[ESP+3C],0
00401107 CALL DWORD PTR DS:[<&comdlg32.GetOpenFil>

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:

0040136A PUSH ESI
0040136B PUSH EDI
0040136C CALL RegClone.00401130

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:

00401184 PUSH EDX
00401185 PUSH 4000
0040118A LEA EAX,DWORD PTR SS:[ESP+210]
00401191 PUSH EAX
00401192 PUSH RegClone.00405152
00401197 PUSH RegClone.0040514C
0040119C LEA ECX,DWORD PTR SS:[ESP+11C]
004011A3 PUSH ECX
004011A4 CALL DWORD PTR DS:[<&KERNEL32.GetPrivate>

I parametri passati a GetPrivateProfileStringA:

DWORD GetPrivateProfileString(

LPCTSTR lpAppName, // points to section name
LPCTSTR lpKeyName, // points to key name
LPCTSTR lpDefault, // points to default string
LPTSTR lpReturnedString, // points to destination buffer
DWORD nSize, // size of destination buffer
LPCTSTR lpFileName // points to initialization filename
);

In questo abbiamo:

lpAppName = HKEY_LOCAL_MACHINE\Software\SlySoft\CloneCD\Key
lpKeyName = "Key"
lpDefault = ""
lpReturnedString = eax (esp+210)
nSize = 4000
lpFileName = "C:\Documents and Settings\hoseein\Desktop\asd.clonecd"

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 è:

[HKEY_LOCAL_MACHINE\Software\SlySoft\CloneCD\Key]
"Key"=asdasdasd

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:

0040154C JMP SHORT CloneCD.0040155E
0040154E 66 DB 66 ; CHAR 'f'
0040154F 62 DB 62 ; CHAR 'b'
00401550 3A DB 3A ; CHAR ':'
00401551 43 DB 43 ; CHAR 'C'
00401552 2B DB 2B ; CHAR '+'
00401553 2B DB 2B ; CHAR '+'
00401554 48 DB 48 ; CHAR 'H'
00401555 4F DB 4F ; CHAR 'O'
00401556 4F DB 4F ; CHAR 'O'
00401557 4B DB 4B ; CHAR 'K'
00401558 90 NOP
00401559 E9 DB E9
0040155A CWDE
0040155B AND BYTE PTR DS:[EAX],DL
0040155E MOV EAX,DWORD PTR DS:[50208B]

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:

004873D1 CALL DWORD PTR DS:[EBX+2C8]
004873D7 POP EBX ; Siamo atterrati qua
004873D8 RETN

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:

0048A28D MOV SI,0FFAE
0048A291 CALL CloneCD.004ED3E8
0048A296 XOR EAX,EAX ; noi siamo qua

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:

0048A41B CMP BYTE PTR DS:[EAX+1A6],0
0048A422 JE CloneCD_.0048A7C4

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:

004039C6 CALL CloneCD_.0048ABCC ; siamo usciti da qui
004039CB MOV EDX,DWORD PTR DS:[51A5E4] ; noi siamo qui
004039D1 PUSH EDX
004039D2 CALL <JMP.&user32.SetActiveWindow>

Ora steppate un poco fino ad arrivare a:

00403A62 TEST EBX,EBX
00403A64 JE SHORT CloneCD.00403A84

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:

00403B49 TEST EDX,EDX
00403B4B JE SHORT CloneCD.00403B76
00403B4D PUSH 1
00403B4F CALL CloneCD.00428684

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:

00403A64 JMP CloneCD.00403B4D
00403A69 NOP
00403A6A NOP

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:

0040AFAE PUSH 813
0040AFB3 CALL CloneCD_.0041D100

Hehe, qua viene caricata la stringa NON REGISTRATO:

0041D118 MOV EAX,DWORD PTR DS:[EDX*4+53395C]

Facciamo quindi una bella cosa: trasformiamo il push e la call che ho copiato qua sopra in un:

mov eax, 5019B0
nop
nop
nop
nop
nop

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.