Copy Link
Add to Bookmark
Report

Old Style Crackin & Dongle

DrWatson's profile picture
Published in 
guide hacker
 · 6 years ago

Questo tutorial è rivolto a persone che hanno una discreta conoscenza del linguaggio macchina, padronanza di un debugger sotto Win32 e ovviamente una minima esperienza di reverse engeneering. Per seguire questo piccolo tutorial sono necessari almeno 2 tools, ossia un buon debugger (io ho usato il debugger incorporato nel M$ Visual C++) e un Hex Editor (io uso Hex Workshop, per il fix-up finale). L' Hex Editor in realtà vi servirà per rendere definitiva la modifica e quindi non è strettamente necessario a livello didattico. Non indispensabile ma molto utile si puo' rivelare un buon disassemblatore, io consiglierei in questo caso il WDasm. Ok, passiamo al crack vero e proprio.
Il programma target è ORCAD Capture 7.01, un ottimo CAD elettrico per la realizzazione di circuiti elettronici, e come molti prg dello stesso genere decisamente costoso. Insieme al prg viene fornita la chiave HW, e senza di essa ORCAD Capture (ovviamente :) non parte.
Durante l'installazione del prodotto viene richiesto un S/N, se avete l'originale tanto meglio, altrimenti metteteci un numero qualsiasi di 6 cifre e installatelo da qke parte nell' HD.
La directory contenente il programma avrà al suo interno il file .EXE principale e un po' di .DLL; come primo approccio tendenzialmente bisognerebbe aprire il .EXE con il disassemblatore, soprattutto per farsi una idea di quali funzioni vengono importate dal file eseguibile. WDasm in questi casi è un ottimo mezzo, perchè sebbene meno potente è decisamente piu' immediato e veloce di altri disassm tipo IDA. Ho detto all' inizio che il disassemblatore non era necessario, ed infatti è cosi. Per il crack fine a se stesso non serve, la prima volta che ho sprotetto ORCAD avevo solo il VC++ a disposizione (non ero a casa) e al posto dell' Hex Editor ho fatto un prg in Turbo Pascal per il fix-up finale. Cio' non toglie che in altri casi (moltissimi) e soprattutto per chi non ha molta dimestichezza con il L.M. la soluzione di disassemblare l'eseguibile e le .DLL da esso importate contestualmete al suo debugging non solo è utile per risparmiare tempo, ma necessaria.
Aprite il debugger e caricate il programma eseguibile, nel Developer Studio premete F11 (STEP INTO) e vi troverete all'inizio del programma. Ecco un DUMP della situazione :

 
006027B0 64 A1 00 00 00 00 mov eax,fs:[00000000]
006027B6 55 push ebp
006027B7 8B EC mov ebp,esp
006027B9 6A FF push 0FFh
.
.


Se le istruzioni vi spaventano, scaricatevi il mio primo tutorial, leggetelo, esercitatevi e riaprite questo tra un po' di tempo ;-)
Ok, ci siamo. Munitevi di carta e penna, perchè dovrete scrivervi qcosina qua e la (poca roba tranky), e cominciamo. Il comando di STEP OVER è F10, mentre per il RUN TO CURSOR è piu' semplice posizionarsi sulla riga e premere il tasto destro del topo. La mia prima regola è : FATTI UNA IDEA DI COME FUNZIONA IL PROGRAMMA. Puo' sembrare stupido al giorno d'oggi quando ci sono toolz kome SoftICE mettersi a tracciare a mano un prg, ma vi assicuro che non è così. Spesso crackare col SoftICE equivale a usare il lanciafiamme per ammazzare una zanzara, quando basterebbe un giornale arrotolato. SoftICE usatelo quando serve, laddove fallite con altri toolz (per loro limiti, non per vostra incapacità, altrimenti siamo daccapo!). Iniziamo con uno STEP OVER. Premete F10, noterete che all' indirizzo 00602888 l'HD si mette in moto, senza che succeda nulla; prendete quaderno e penna e annotatevelo, dovesse mai servire.
Il primo 'intoppo' lo troviamo a 006028A1 :

 
006028A1 46 inc esi
006028A2 8A 06 mov al,byte ptr [esi]
006028A4 84 C0 test al,al
006028A6 74 04 je 006028AC
006028A8 3C 22 cmp al,22h
006028AA 75 F5 jne 006028A1
006028AC 80 3E 22 cmp byte ptr [esi],22h
.
.


se continuiamo a premere F10 rimaniamo bloccati all'interno del ciclo. Una rapida occhiata fa subito vedere che la condizione di uscita è una sola perchè sia 'je 006028AC' che l'istruzione 'jne 006028A1' fanno si che COMUNQUE il programma continui dall' indirizzo 006028AC; sarà sufficiente quindi far proseguire il programma fino alla istruzione a tale indirizzo posizionandovisi sopra e selezionando dal menu' del tasto dx del mouse RUN TO CURSOR (con un debugger a riga di comando come il DEBUG sarebbe 'G 006028AC'). Attenzione perchè in altri casi all'interno del ciclo potrebbero trovarsi piu' istruzioni di salto condizionato a locazioni differenti. In tali casi occorre studiare un po' piu' attentamente il ciclo oppure se si è particolarmente pigri (io spesso) andate a occhio e ne provate un po' a caso. Ho scoperto che statisticamente faccio prima e sbaglio meno, credo sia frutto dell'esperienza e ne godo alquanto ;-)
Bene, se avete fatto tutto come doveva essere fatto ora il programma dovrebbe essere in attesa di eseguire l'istruzione 'cmp byte ptr [esi],22h', al che possiamo continuare allegramente il notro tracing con F10, fino ad incontrare l'indirizzo 006028ED. Vediamo cosa ha disassemblato per noi il debugger :

 
006028ED 8B 45 A8 mov eax,dword ptr [ebp-58h]
006028F0 25 FF FF 00 00 and eax,0FFFFh
006028F5 50 push eax
006028F6 56 push esi
006028F7 6A 00 push 0
006028F9 6A 00 push 0
006028FB FF 15 48 0B 6A 00 call dword ptr ds:[6A0B48h]
.
.


mmhhh sembra proprio una chiamata sospetta, con 4 parametri pushati nello stack. Arriviamo con F10 all'istruzione 'call dword ptr ds:[6A0B48h]' ed eseguiamola (Sempre F10) prima di decidere se valga o meno la pena di tracciarla internamente. Non succede nulla.... Pero il valore del registro EAX, che contiene certamente il valore di ritorno della call viene messo di nuovo nello stack prima di un' altra call, ovvero :

 
00602901 50 push eax
00602902 E8 DD BA 01 00 call 0061E3E4
00602907 50 push eax
00602908 FF 15 8C 1C 6A 00 call dword ptr ds:[6A1C8Ch]
0060290E EB 28 jmp 00602938
.
.


che a sua volta passa EAX di ritorno a quella successiva. Dato che non sappiamo ancora nulla del programma, non ci resta altro da fare che eseguire tenendo a mente (o scrivendo) tutte queste considerazioni. Procediamo ancora con F10 fino ad eseguire la chiamata e *SORPRESA* ;) il progamma parte. E' importante cercare di capire a che 'livello' del programma ci si trova osservando come si comporta la routine appena eseguita. Nel nostro caso 'call 0061E3E4' è l'entrata principale del programma. Noterete infatti che dopo qke secondo di 'freeze' il programma visualizzerà una MessageBox dicendoci che (ma tu guarda...) la chiave HW non c'è o è rotta (aspetta aspetta che ora la aggiustiamo noi :P) dopodichè il programma si chiude, anche se formalmente il debugger ci riporta all'istruzione successiva. Continuando a tracciare l'unico risultato sarebbe di chiudere il programma del tutto. E' evidente che 'call 0061E3E4' alla locazione 00602902 va esaminata attentamente per cui restartiamo il programma (RESTART o CTRL+SHIFT+F5)e stavolta possiamo dire al debugger di eseguire il programma fino alla locazione incriminata 00602902, posizionandoci sopra con il cursore e premendo CTRL+F10 (RUN TO CURSOR) oppure per command line debuggers con 'G 00602902'. Ora il programma sta per eseguire la chiamata, ma noi non vogliamo piu' eseguirla, tanto sappiamo che cosa fa. Ci interessa tracciarla (STEP INTO) con F11. Ci ritroveremo con il sotto mano la prima istruzione eseguita dalla call ovvero :

 
0061E3E4 55 push ebp
0061E3E5 8B EC mov ebp,esp
0061E3E7 FF 74 24 14 push dword ptr [esp+14h]
0061E3EB FF 75 10 push dword ptr [ebp+10h]
0061E3EE FF 75 0C push dword ptr [ebp+0Ch]
0061E3F1 FF 75 08 push dword ptr [ebp+8]
0061E3F4 E8 89 00 00 00 call 0061E482
0061E3F9 5D pop ebp
0061E3FA C2 10 00 ret 10h
.
.


Per ora possiamo intuire poco di cosa fa la chiamata in 0061E3F4, ma ci vuole poco per osservare che a) la chiamata è una standard call che usa variabili locali b) non ci sono istruzioni di salto PRIMA dell'istruzione 'ret 10h' e nemmeno un uso improprio dello stack per falsare l'istruzione di ret. La cosa piu' ovvia da pensare è che la 'call 0061E482' si comporti esattamente come nel caso della chiamata vista in precedenza all'indirizzo 00602902 e faccia cioè partire il programma. Non resta che accertarsene!
Tracciamo il programma (F10) fino ad eseguirla e stiamo a vedere che succede.
Avevamo visto bene, questa call si comporta come la precedente, segnamoci l'address 0061E482. Ora abbiamo questa successione:

 
00602902
|______\ 0061E3F4
/ |_______\ 0061E482
/


Possiamo piazzare un bel breakpoint a 0x0061E482 e vedere che succede al prossimo restart (ricordatevi di riattivare il breakpoint dopo aver restartato il programma !); è il momento di restartare il prg (RESTART o CTRL+SHIFT+F5) e settare il breakpoint o riattivarlo, tutto cio' nel menu Edit --> Breakpoints (ALT+F9) inserendo 'Break at : 0x0061E482' e clikkando OK. Ora si puo' comodamente eseguire il programma con GO (F5) e ci troveremo proprio
:

 
0061E482 FF 25 E0 1A 6A 00 jmp dword ptr ds:[6A1AE0h]
0061E488 CC int 3
.
.


non abbiamo scelta, dobbiamo eseguire il salto con F10 trovando stavolta :

 
7C42D26D 55 push ebp
7C42D26E 8B EC mov ebp,esp
7C42D270 53 push ebx
7C42D271 56 push esi
7C42D272 57 push edi
7C42D273 BE FF FF FF FF mov esi,0FFFFFFFFh
7C42D278 E8 D8 3D FF FF call 7C421055
7C42D27D FF 75 14 push dword ptr [ebp+14h]
7C42D280 FF 75 10 push dword ptr [ebp+10h]
7C42D283 FF 75 0C push dword ptr [ebp+0Ch]
7C42D286 FF 75 08 push dword ptr [ebp+8]
7C42D289 8B 78 04 mov edi,dword ptr [eax+4]
7C42D28C E8 10 FC FF FF call 7C42CEA1
.
.


direi che conviene a questo punto segnarsi l' EIP ovvero 7C42D26D in modo da levare l'indirizzo del breakpoint precedente e sostituirlo appunto con 0x7C42D26D per evitare altre perdite di tempo. A questo punto cominciamo ad essere abbastanza 'dentro' il programma, in ogni caso dobbiamo esplorare anche questa nuova routine sempre con il nostro fido F10.
L' istruzione alla locazione 7C42DA5 :

 
7C42D2A3 8B CF mov ecx,edi
7C42D2A5 FF 53 54 call dword ptr [ebx+54h]
7C42D2A8 85 C0 test eax,eax
7C42D2AA 74 07 je 7C42D2B3
7C42D2AC 8B CF mov ecx,edi
.
.


è un'altra chiamata che si comporta in tutto e per tutto come la precedente. Ora il livello di nesting delle routines è:

 
00602902
|______\ 0061E3F4
/ |_______\ 0061E482
/ |_______\ 7C42D26D
/ |_______\ [ebx+54h]
/


difatti per ora ignoriamo l'indirizzo a cui punta [ebx+54h] (d'accordo, potremmo ricostruirlo, ma perchè sprecarci ? :-) ma è nostro compito scoprirlo : stiamo infatti addentrandoci sempre piu' all'interno del programma e la routine di check dovrebbe essere nei paraggi oramai.
Restartiamo (CTRL+SHIFT+F5) il prg e sostituiamo il breakpoint precedente con quello appena trovato cioè 0x7C42D2A5 dopodichè eseguiamo il prg con F5 fino a tale locazione. Tracciamo la call con F11 e ci troviamo in :

 
004F5910 64 A1 00 00 00 00 mov eax,fs:[00000000]
004F5916 55 push ebp
004F5917 8B EC mov ebp,esp
004F5919 6A FF push 0FFh
004F591B 68 1B 5D 4F 00 push 4F5D1Bh
004F5920 50 push eax
.
.


anche se lo sconforto sta per impadronirsi del nostro cervello, mai abbattersi, altrimenti tantovale lasciar perdere il crackin'. Ogni volta (ogni) che metto le mani su un prg trovo un ostacolo nuovo, se dovessi abbattermi ogni volta non avrei nemmeno cominciato. Tornando a ORCAD, indovinate? F10 per tracciare il programma! Eheheh comincerete ad odiare anche lo scooter F10 Malaguti tra un po'...
Pero' stavolta ci siamo.
Tutto fila liscio fino a :

 
004F59A9 8B CA mov ecx,edx
004F59AB E8 80 84 07 00 call 0056DE30
.
.


dove viene creata la MDI principale e la splashform di presentazione di ORCAD! Ma la cosa piu' interessante che dovreste notare subito è il TEMPO che ci vuole per riavere il controllo del debugger, ovvero pochissimo mentre la routine di check della chiave HW dura qche secondo. Cio' significa che non è ancora stata eseguita! Bene bene.... Continuiamo il nostro STEP OVER con F10 (sempre lui) aspettandoci da un momento all' altro questo maledetto check; l' attesa dura poco poichè già a :

 
004F59EC E8 AF FB FA FF call 004A55A0
004F59F1 85 C0 test eax,eax
004F59F3 75 0F jne 004F5A04
004F59F5 8B 55 F0 mov edx,dword ptr [ebp-10h]
004F59F8 8B 8A E8 00 00 00 mov ecx,dword ptr [edx+0E8h]
004F59FE 85 C9 test ecx,ecx
004F5A00 74 D7 je 004F59D9
004F5A02 EB C2 jmp 004F59C6
004F5A04 E8 F7 B1 FA FF call 004A0C00
.
.


accade il fattaccio. Dopo aver eseguito 'call 004A55A0' il debugger si blocca in attesa della fine della chiamata, e nel progamma ORCAD dopo qualche secondo spunta la MessageBox che come sempre ci ricorda che siamo dei malandrini e non abbiamo le carte in regola per usare il programma. Credo che a questo punto non valga nemmeno la pena di dire quanto sia sospetto quel 'test eax,eax' seguito da 'jne 004F5A04' ....
La prima cosa da fare per levarsi il dubbio è vedere cosa farebbe il programma e invertire la condizione, in questo caso il registro EAX vale 0 , basta mettere EAX=00000001 (fate visualizzare la finestrella dei registri e modificatelo) e vedere cosa accade dando un GO (F5).
Yeppaaaaaa! **IL PROGRAMMA PARTE!** Ok, Ok, non è stato nulla di eccezionale, ma ogni crack per semplice che sia da una piccola soddisfazione! A questo punto verrebbe la tentazione (mi è venuta e puntualmente ho fatto cosi' :-) di modificare l'eseguibile e rendere definitiva la modifica sostituendo a 'jne 004F5A04' un piu' utile 'jmp 004F5A04' ovvero modificando i bytes all'interno dell' .EXE da ....750F.... a ....EB0F.... solo che il crack NON E' ANCORA FINITO.
Se con mente fredda si testasse il programma ci si accorgerebbe che in realtà la chiave HW viene cercata ad esempio anche immediatamente PRIMA DI SALVARE, e non è bello lavorare su un progetto senza poterlo salvare.....
La prima cosa che verrebbe in mente è quella di cercare l'altra chiamata e fare anche li' un bel jnz -> jmp ma cio' implicherebbe tracciare ancora il programma o cercare di brekkare subito prima del save, per non parlare del fatto che non sappiamo a priori quante altre call alla routine di check ci possano essere. Una strada molto piu' elegante e che mette al riparo anche da altri eventuali check sparsi nel programma è quella di modificare la call che verifica la presenza della chiave in modo che restituisca sempre EAX diverso da 0 evitandoci la noia di cercare i punti nel programma in cui essa viene chiamata. L'ultimo 'sforzo' è quindi quello di tracciare anche la call di check e vedere come modificarla per asservirla ai nostri biechi scopi.
Cancelliamo il vecchio breakpoint e settiamo quello nuovo all'istruzione di call vista in precedenza (vedi dump sopra) ovvero a 0x004F59EC e diamo nuovamente GO (F5). Entriamo nella chiamata con F11 e diamo una occhiata in giro :

 
004A55A0 64 A1 00 00 00 00 mov eax,fs:[00000000]
004A55A6 55 push ebp
004A55A7 8B EC mov ebp,esp
004A55A9 6A FF push 0FFh
004A55AB 68 0B 59 4A 00 push 4A590Bh
004A55B0 50 push eax
004A55B1 64 89 25 00 00 00 00 mov dword ptr fs:[0],esp
004A55B8 83 EC 7C sub esp,7Ch
004A55BB 8D 4D F0 lea ecx,dword ptr [ebp-10h]
004A55BE 53 push ebx
004A55BF 56 push esi
004A55C0 57 push edi
004A55C1 BE D8 A6 62 00 mov esi,62A6D8h
004A55C6 E8 33 BA 15 00 call 00600FFE
.
.


a prima vista nulla di particolare, senonchè dato il fatto che la call restituisce in EAX il risultato e si preoccupa pure di visualizzare una MessageBox, potremmo essere cosi' fortunati da essere talmente addentro il programma da aver beccato la routine di check che oltre a fare la verifica non fa null'altro. Se cosi' fosse la soluzione sarebbe di sostituire le prime istruzioni della call con un 'mov eax,00000001' dopodichè 'ret' ed il gioco sarebbe fatto. Altrimenti la sostituzione o l'alterazione andrebbe fatta subito PRIMA del 'ret' vero e proprio dopo che la routine ha eseguito i suoi compiti. Vi dico già che oggi siamo stati fortunati ;-) per cui ci andrà bene al primo tentativo. Aprite il vostro Hex Editor e caricate il file CAPTURE.EXE. Dovrete sostituire i bytes che rappresentano l' istruzione

 
004A55A0 64 A1 00 00 00 00 mov eax,fs:[00000000]
^^^^^^bytes^^^^^^


con altri bytes in modo da farla diventare :

 
004A55A0 B8 01 00 00 00 mov eax,00000001
004A55A5 C3 ret


Voglio solo ricordare (vedi tutorial precedente) che i bytes possono solo essere SOSTITUITI e non AGGIUNTI o CANCELLATI, per cui bisogna stare attenti a NON SPEZZARE LE ISTRUZIONI, al limite aggiungendo dei NOP (90h) o se manca spazio a reinventare per così dire il codice in modo da farcelo stare. Tornando all' Hex Editor, mettete come stringa di ricerca esadecimale i bytes che rappresentano il codice originale, almeno 10 bytes in modo da non trovare troppe volte la stringa. Ad esempio in questo caso potete segnare '558BEC6AFF680B59' e una volta trovati accertarvi che anche i bytes prima e dopo coincidano. Nel nostro caso la sequenza compare una volta sola e quindi non c'è dubbio che sia proprio il pezzo di programma da modificare; altre volte puo' rendersi necessario controllare piu' bytes, in ogni caso una volta trovata la sequenza dobbiamo risalire ai bytes da modificare, che qui sono i 6 bytes precedenti. Dobbiamo modificare i bytes all' offset 000A49A0 da '64A100000000' in 'B801000000C3' e salvare il file magari come CAPTURE2.EXE. Fatto ?
Chiudete l' Hex Editor (non serve piu' ;-) e lanciate CAPTURE2.EXE.
Oh gioia oh gaudio, Va! E non dirmi che...... SALVA! Ehheheh e come dubitare? :P
E questo è quanto per ORCAD Capture 7.0 with Dongle (Sentinel per l'esattezza).
Alcune note :

1) Non sempre con i debuggers 'tradizionali' si riesce a tracciare con efficacia un programma, ma vale *SEMPRE* la pena di farlo come prima cosa, anche per farsi un'idea del programma.

2) Una volta scoperto che la routine di check era all'indirizzo 004A55A0 avremmo potuto caricare il programma in un disassemblatore, andare a tale indirizzo e vedere da quali indirizzi la chiamata veniva referenziata (chiamata) per modificare li' i jnz --> jmp, e nel caso specifico di ORCAD erano 7 tra cui il nostro 004F59EC. Molto piu' elegante e sicuro modificare quindi la call stessa che non le procedure chiamanti, anche se in altri casi se tutto funziona eliminando un jnz (verificate sempre pero'!) puo' bastare. Beh, noi ora abbiamo anche eliminato il tempo di attesa per il dongle check, in un certo senso those guys at ORCAD dovrebbero ringraziarci bwhahahah ;-)

3) Un altro motivo per cui si dovrebbe cercare di non usare i disassemblatori è perchè se il file è compresso il disassemblatore serve a una sega :-) a meno di non riuscire a spakkettare l' .EXE. Tuttavia dove possibile aprite il disassemblatore parallelamente al debugger, è sempre un utile aiuto.

4) Se il file è compresso (o crittato) e non si riesce ad applicare il patch finale, sono kazzetti amari. Sotto DOS utilizzavo un piccolo launcher che hokkava l' INT 08h, lanciava il prg target e verificava che si fosse scompattato/decrittato dopodichè cercava i bytes e applicava il patch. Era scritto in TP pero' andava benone. Purtroppo sotto Win32 non so ancora come realizzare un programma analogo, per ora accontentatevi di quello che ha fatto StonE in ASM che lancia il prg incriminato e invece di hokkare un INT o una API si segna l' Handle di processo, aspetta un tot e poi cerca nella memoria di tale processo la sequenza da patchare sostituendola.

5) Se il file non è compresso ma non trovate comunque la sequenza, potrebbe essere contenuta in una .DLL dinamica, percio' prima di spaccare il PC cercate in tutte le .DLL (anche in quelle che i cazzo di programmini di Setup infilano nella directory \windows\system).

6) non esistono crack impossibili, è solo questione di tempo e di palle.

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT