CDRWin 3.9F Serial Fishing

Data

by Spider

 

12 Luglio 2004

UIC's Home Page

Published by Quequero


Bisogna essere dei grandi ignoranti per rispondere a tutto quello che ci viene chiesto. (Voltaire)

Non devo scrivere in questo spazio
Non devo scrivere in questo spazio
...

Quasi quasi metto quella foto che mi hai mandato, in cui sei nudo, qui dentro... ;p. Grazie per il tute, la protezione del cdrwin e' noiosissima e ingarbugliata, non so come hai avuto voglia di farci un tute, ti ammiro per la pazienza ;p

Disapprovo quello che dite, ma difenderò sino alla morte il vostro diritto di dirlo. (Voltaire)

....

Home page: http://bigspider.has.it o http://bigspider.cjb.net
E-mail: spider_xx87 (AT) hotmail (DOT) com
Nick, canale IRC frequentato: ^Spider^ su irc.azzurra.org
canali #crack-it e #asm

....

Difficoltà

( )NewBies (X)Intermedio ( )Avanzato ( )Master

 

Pensavate di esservi liberati di me, di non vedermi più. Ma vi sbagliavate :-). Spero per voi che ne siate contenti, perché in caso contrario rimarrete ancora più delusi venendo a sapere che non ho nemmeno l'intenzione di andarmene... :-D


CDRWin 3.9F Serial Fishing

Written by Spider

Introduzione

Un po' di giorni fa mi è tornata la nostalgia del reversing. Erano 3 mesi che non reversavo nulla, e negli ultimi 6 mesi ho reversato un solo crackme e più nulla (o quasi). Mentre pensavo alle belle ore passate a consumare i tasti F8 e F10, mi sono connesso su IRC e ho trovato (e non succede tanto spesso) Quequero online. Perciò ho pensato subito di chiedere a lui un consiglio su un buon target da crackare :-)

Tools usati

Tools usati:

- SoftICE 4.30;
- IDA Pro 4.30;
- Resource Hacker 3.4 o qualunque altro editor di risorse.

E mi raccomando... NIENTE HexEditor! :-)

URL o FTP del programma

http://www.goldenhawk.com

Notizie sul programma

Il programma della Golden Hawk Technology serve per masterizzare; sembra abbastanza carino. Di più non so, né mi interessa sapere. E' colpa di Quequero: come vi ho detto è lui che mi ha suggerito questo target! Ciao Que! :)

Essay

Quando si cerca di crackare/reversare un programma, ci si possono aspettare due possibilità: in alcuni casi la difficoltà del reversing è nel trovare quello di cui abbiamo bisogno. Innumerevoli possono essere le tecniche per rendere più difficile l'individuazione del codice critico. In tali occasioni, succede spesso che, una volta trovato il codice con qualche stratagemma più o meno furbo, il reversing sia pressoché risolto. In altri casi, invece, ci sono più punti da considerare, e bisogna analizzare per bene il codice, senza tralasciare nulla. Se l'attacco è corretto e completo, allora ci avvicineremo sempre di più alla soluzione, fino ad averla in pugno. Oggi sferreremo proprio questo secondo tipo di attacco. Detto ciò, si comincia :-).

Anzitutto, apriamo IDA e cominciamo a disassemblare. Anche quando dovessimo utilizzare solo il debugger, l'analisi di IDA aiuta spesso a non perdere tempo.
Mentre IDA lavora per noi, apriamo il symbol loader di softice, carichiamo cdrwin.exe e mettiamo un breakpoint sulle classiche API GetDlgItemTextA e GetWindowTextA. Andiamo nella finestra di registrazione e vediamo che il programma chiede quattro campi: "name", "Company/email", "Unlock Key" e "Check key". Io ho messo rispettivamente "Spider", "Spidersoft" [ :-) ], "123123123", "456456456". Clicchiamo OK e softice poppa immediatamente su GetWindowTextA. Premiamo F11 per tornare nel codice del programma e ci troviamo all'address 0047685A. Qui non c'è nulla di interessante: in realtà, è facile rendersi conto che ci troviamo in una funzione ponte per la GetWindowTextA, pertanto steppiamo ancora fino al
RET e arriviamo all'indirizzo 0041E36F. Vediamo una serie di call tutte allo stesso indirizzo (0047682F), che corrispondono alle varie chiamate a GetWindowTextA. Più avanti ci sono altre call, ma non ci va di steppare tutto, perciò diamo un'occhiata all'output di IDA:

.text:0041E35E lea eax, [ebp+var_20]
.text:0041E361 mov ebx, 3
.text:0041E366 push eax
.text:0041E367 mov byte ptr [ebp+var_4], bl
.text:0041E36A call ?GetWindowTextA@CWnd@@QBEXAAVCString@@@Z ; CWnd::GetWindowTextA(CString &)
.text:0041E36F lea ecx, [ebp+var_1C]
.text:0041E372 push ecx
.text:0041E373 mov ecx, [esi+6Ch]
.text:0041E376 call ?GetWindowTextA@CWnd@@QBEXAAVCString@@@Z ; CWnd::GetWindowTextA(CString &)
.text:0041E37B mov ecx, [esi+70h]
.text:0041E37E lea edx, [ebp+var_18]
.text:0041E381 push edx
.text:0041E382 call ?GetWindowTextA@CWnd@@QBEXAAVCString@@@Z ; CWnd::GetWindowTextA(CString &)
.text:0041E387 mov ecx, [esi+74h]
.text:0041E38A lea eax, [ebp+var_14]
.text:0041E38D push eax
.text:0041E38E call ?GetWindowTextA@CWnd@@QBEXAAVCString@@@Z ; CWnd::GetWindowTextA(CString &)
.text:0041E393 lea ecx, [ebp+var_44]
.text:0041E396 lea edx, [ebp+var_40]
.text:0041E399 push ecx
.text:0041E39A lea eax, [ebp+var_3C]
.text:0041E39D push edx
.text:0041E39E mov edx, [ebp+var_18]
.text:0041E3A1 lea ecx, [ebp+var_38]
.text:0041E3A4 push eax
.text:0041E3A5 push ecx
.text:0041E3A6 push offset aLxLxLxLx ; "%lx-%lx-%lx-%lx"
.text:0041E3AB push edx
.text:0041E3AC call _sscanf
.text:0041E3B1 add esp, 18h
.text:0041E3B4 cmp eax, 4
.text:0041E3B7 jnz loc_41E454
.text:0041E3BD lea eax, [ebp+var_34]
.text:0041E3C0 lea ecx, [ebp+var_30]
.text:0041E3C3 push eax
.text:0041E3C4 lea edx, [ebp+var_2C]
.text:0041E3C7 push ecx
.text:0041E3C8 mov ecx, [ebp+var_14]
.text:0041E3CB lea eax, [ebp+var_28]
.text:0041E3CE push edx
.text:0041E3CF push eax
.text:0041E3D0 push offset aLxLxLxLx ; "%lx-%lx-%lx-%lx"
.text:0041E3D5 push ecx
.text:0041E3D6 call _sscanf
.text:0041E3DB add esp, 18h
.text:0041E3DE cmp eax, 4
.text:0041E3E1 jnz short loc_41E454
.text:0041E3E3 mov ecx, [ebp+var_1C]
.text:0041E3E6 mov byte ptr [ebp+var_4], al
.text:0041E3E9 lea edx, [ebp+var_34]
.text:0041E3EC lea eax, [ebp+var_44]
.text:0041E3EF push edx
.text:0041E3F0 mov edx, [ebp+var_20]
.text:0041E3F3 push eax
.text:0041E3F4 push ecx
.text:0041E3F5 push edx
.text:0041E3F6 call sub_425ED0
.text:0041E3FB add esp, 10h
.text:0041E3FE mov [ebp+var_4], ebx
.text:0041E401 push 0FFFFFFFFh
.text:0041E403 push 40h
.text:0041E405 push 0BAh
.text:0041E40A call sub_47B704
.text:0041E40F mov ecx, esi
.text:0041E411 call ?OnOK@CDialog@@MAEXXZ ; CDialog::OnOK(void)
.text:0041E416 call ?AfxGetThread@@YGPAVCWinThread@@XZ ; AfxGetThread(void)
.text:0041E41B test eax, eax
.text:0041E41D jz short loc_41E428

Già più interessante: molte delle chiamate che da softice ci sembravano tutte anonime sono state identificate da IDA. Faremo molto uso del debugger, pertanto sfruttiamo una piccola funzionalità di softice per rendere il codice più chiaro. Quello che faremo è esportare le informazioni dal disassemblato di IDA e importarle come simboli di softice, cosicché non dovremo continuamente passare a IDA per vedere se conosce una determinata chiamata...

Se IDA non ha ancora terminato l'analisi è meglio aspettare che lo faccia. A questo punto clicchiamo su "File-->Produce-->Create MAP file..." e salviamo il file nella stessa directory del programma, meglio se con lo stesso nome del file exe. IDA ci chiederà cosa vogliamo includere nel file .map. Noi selezioniamo tutto (meglio abbondare, non si sa mai :)). Adesso abbiamo un file MAP molto simpatico che contiene tutte le info che IDA ha scoperto (possiamo anche aprire e/o modificare il file con un editor, volendo), ma softice puoi importare solo files in formato ".sym" o ".dbg". Fortunatamente la Numega ci fornisce il rimedio anche per questo :-). Andiamo nella directory di softice ed entriamo nella cartella Util16. Qui troviamo alcuni programmini e un file di testo, util16.txt, con qualche info a riguardo. In particolare:

MSYM.EXE - Converts .MAP files to .SYM files
--------
Usage: MSYM file_name

Eccolo qua :-). Più semplicemente, anziché usarlo da prompt dei comandi, possiamo copiare MSYM.exe nella cartella di cdrwin e trascinarvici sopra il file .map creato prima, ed ecco comparire il nostro bel file .sym. Adesso entriamo nel symbol loader di softice, clicchiamo "File --> Open", come "tipo file" selezioniamo "Symbol Files", e apriamo il file cdrwin.sym. Non abbiamo ancora finito, neanche il formato sym, così com'è, va bene per softice, che usa invece un formato proprio. Ma basta cliccare su Translate (menu Module, oppure terzo pulsante della toolbar) per generare il file cdrwin.nms. A questo punto abbiamo quasi finito, carichiamo cdrwin.nms e clicchiamo su Load Symbols. Adesso possiamo caricare il file principale del programma (cdrwin.exe) e avviare e... ecco che stiamo debuggando nel sorgente fornito da ida :-). Non preoccupatevi, quello che abbiamo appena fatto è molto semplice e deve essere fatto solo la prima volta. Il file di simboli rimarrà caricato finché softice è attivo. Se riavviamo il pc, ci basta caricare direttamente il file .nms, cliccare "Load Symbols", e abbiamo di nuovo tutto.
Adesso possiamo tornare al codice del programma. Debuggando lo spezzone di codice visto prima, notiamo due chiamate alla funzione C
sscanf. Per chi non la conoscesse consiglio di consultare qualche manuale C per capirne il funzionamento. La stringa di formato è "%lx-%lx-%lx-%lx" e debuggando possiamo vedere facilmente che viene applicata sia alla Check Key, sia alla Unlock Key. "%lx" significa intero esadecimale lungo, cioè un qualunque numero esadecimale che stia in una dword, quindi di 8 cifre. Pertanto cambiamo le due key, rispettivamente, in "11111111-22222222-33333333-44444444" e "55555555-66666666-77777777-88888888" per rispettare il formato richiesto. Ovviamente la scelta di questi seriali è casuale ma oculata: in questo modo, quando debugghiamo, ci sarà facile renderci conto di quale parte del seriale il programma stia controllando. Clicchiamo di nuovo OK (ricordandoci eventualmente di mettere il breakpoint su GetWindowTextA), e steppiamo con F10. Non accade nulla sino alla call sub_425ED0. Steppando questa infatti compare la beggar off, pertanto è lì che deve essere tutto il controllo. Entriamo e debugghiamo. Dal listato infatti non si capisce molto, ma debuggando e controllando le locazioni di memoria utilizzate il codice diventa abbastanza semplice. Per comodità, chiamiamo a1, a2, a3 ed a4 le 4 parti della unlock key, e a5, a6, a7 ed a8 le 4 parti della check key (ricordatevi questa nomenclatura perché la useremo fino alla fine).

.text:00425ED0 mov ecx, [esp+arg_C]
.text:00425ED4 push ebx
.text:00425ED5 push ebp
.text:00425ED6 push esi
.text:00425ED7 mov esi, [esp+0Ch+arg_8]
.text:00425EDB mov ebx, [ecx]       ;ebx = a8
.text:00425EDD push edi
.text:00425EDE mov edi, [esi]       ;edi = a4
.text:00425EE0 mov eax, [esi+4]     ;eax = a3 <---------------------------------------------------+
.text:00425EE3 mov edx, edi         ;edx = a4                                                     |
.text:00425EE5 xor edx, eax         ;edx = a4 XOR a3                                              |
.text:00425EE7 cmp ebx, edx         ;a8 == (a4 XOR a3)?                                           |
.text:00425EE9 jnz short loc_425F10 ;no?? beggar off!                                             |
.text:00425EEB mov edx, [esi+8]     ;edx = a2                                                     |
.text:00425EEE mov ebx, edx         ;ebx = a2                                                     |
.text:00425EF0 xor ebx, eax         ;ebx = a2 XOR a3 (eax non è stato più toccato dopo 00425EE0)--+
.text:00425EF2 mov eax, [ecx+4]     ;eax = a7
.text:00425EF5 cmp eax, ebx         ;a7 == (a2 XOR a3)?
.text:00425EF7 jnz short loc_425F10 ;no?? beggar off!
.text:00425EF9 mov eax, [esi+0Ch]   ;eax = a1
.text:00425EFC mov ebx, eax         ;ebx = a1
.text:00425EFE xor ebx, edx         ;ebx = a1 XOR a2
.text:00425F00 mov edx, [ecx+8]     ;edx = a6
.text:00425F03 cmp edx, ebx         ;a6 == (a1 XOR a2)?
.text:00425F05 jnz short loc_425F10 ;no?? beggar off!
.text:00425F07 mov edx, [ecx+0Ch]   ;edx = a5
.text:00425F0A xor eax, edi         ;eax = a1 XOR a4 (trovate edi alla riga 425EDE :))
.text:00425F0C cmp edx, eax         ;a5 == (a1 XOR a4)?
.text:00425F0E jz short loc_425F23  ;si?? niente beggar off! :-)
.text:00425F10 
.text:00425F10 loc_425F10: ; CODE XREF: sub_425ED0+19j
.text:00425F10 ; sub_425ED0+27j ...
.text:00425F10 push 0
.text:00425F12 push 1
.text:00425F14 push 0
.text:00425F16 push 0FFFFFF38h
.text:00425F1B call sub_4297A0      ;visualizza la beggar off
.text:00425F20 add esp, 10h
.text:00425F23 
.text:00425F23 loc_425F23: ; CODE XREF: sub_425ED0+3Ej

In definitiva, questo codice si accerta di ciò che segue:

a5 = a1 XOR a4
a6 = a1 XOR a2
a7 = a2 XOR a3
a8 = a3 XOR a4

Pertanto, una volta stabilita la unlock key, la check key è univocamente determinata, ed è anche banale da calcolare. Ma poiché non ci va di generarla a mano, scriviamo due righe di codice C :-)

#include <stdio.h>
int main()
{
    unsigned long l1, l2, l3, l4;
    scanf("%lx-%lx-%lx-%lx", &l1, &l2, &l3, &l4);
    printf("%lX-%lX-%lX-%lX\n", l1^l4, l1^l2, l2^l3, l3^l4);
    system("PAUSE");
    return 0;
}

Una volta compilato, ci basta scrivere la unlock key e il programmino risponde con la check key :) La check key corrispondente al serial che abbiamo messo prima è 55555555-33333333-11111111-77777777. Correggiamola e andiamo avanti nel codice. A questo punto è chiaro che l'unica incognita rimane la unlock key.

.text:00425F23 mov ebp, [esp+10h+arg_4]
.text:00425F27 mov edi, [esp+10h+arg_0]
.text:00425F2B push esi
.text:00425F2C push ebp
.text:00425F2D push edi
.text:00425F2E call sub_426430
.text:00425F33 add esp, 0Ch
.text:00425F36 test eax, eax
.text:00425F38 jnz short loc_425F4B
.text:00425F3A push eax
.text:00425F3B push 1
.text:00425F3D push eax
.text:00425F3E push 0FFFFFF37h
.text:00425F43 call sub_4297A0 ;solita beggar off
.text:00425F48 add esp, 10h
.text:00425F4B 
.text:00425F4B loc_425F4B: ; CODE XREF: sub_425ED0+68j

Il jnz qui sopra salta se eax è diverso da 0, ma steppando a noi ritorna 0, quindi dobbiamo analizzare la sub_426430:

.text:00426430 mov eax, [esp+arg_8] ;eax punta ad un array contenente la unlock key in esadecimale
                                    ;con le 4 parti invertite (cioè, nell'ordine a4,a3,a2,a1)
.text:00426434 mov edx, [esp+arg_0] ;edx punta al nome inserito
.text:00426438 push ebx
.text:00426439 push ebp
.text:0042643A mov ebx, [eax]       ;ebx = a4 (cioè 44444444)
.text:0042643C push edi
.text:0042643D mov edi, edx
.text:0042643F or ecx, 0FFFFFFFFh
.text:00426442 xor eax, eax
.text:00426444 repne scasb
.text:00426446 not ecx
.text:00426448 dec ecx
.text:00426449 cmp ecx, 6
.text:0042644C jb short loc_4264B9
.text:0042644E mov ebp, [esp+0Ch+arg_4]
.text:00426452 or ecx, 0FFFFFFFFh
.text:00426455 mov edi, ebp
.text:00426457 repne scasb
.text:00426459 not ecx
.text:0042645B dec ecx
.text:0042645C cmp ecx, 6
.text:0042645F jb short loc_4264B9

Fin qui niente di strano (non commento il codice ma è semplice, basta steppare un attimo dal debugger), controlla solo che nome e company inseriti siano almeno 6 caratteri, altrimenti si incavola.


.text:00426461 test ebx, 0FFFFh
.text:00426467 jz short loc_4264B9
.text:00426469 test ebx, 0FFFF0000h
.text:0042646F jz short loc_4264B9

Abbiamo visto prima che ebx contiene a4. Qui controlla che la parte alta di a4 (prime 4 cifre esadecimali) o quella bassa (ultime 4 cifre) non siano azzerati. Altrimenti... beggar off! :-) 


.text:00426471 push esi
.text:00426472 push 2
.text:00426474 push edx
.text:00426475 call sub_4264C0
.text:0042647A push 2
.text:0042647C push ebp
.text:0042647D mov esi, eax
.text:0042647F call sub_4264C0
.text:00426484 mov ecx, eax
.text:00426486 mov edx, eax
.text:00426488 and ecx, 0FF0000h
.text:0042648E add esp, 10h
.text:00426491 shr edx, 10h
.text:00426494 or ecx, edx
.text:00426496 mov edx, eax
.text:00426498 and edx, 0FF00h
.text:0042649E shl eax, 10h
.text:004264A1 or edx, eax
.text:004264A3 xor eax, eax
.text:004264A5 shr ecx, 8
.text:004264A8 shl edx, 8
.text:004264AB or ecx, edx
.text:004264AD xor ecx, esi
.text:004264AF pop esi
.text:004264B0 cmp ecx, ebx
.text:004264B2 pop edi
.text:004264B3 pop ebp
.text:004264B4 pop ebx
.text:004264B5 setz al
.text:004264B8 retn

Possiamo vedere qui una buona dose di calcoli, e ci sono due chiamate alla sub_4264C0 che, a sua volta, esegue una gran quantità di calcoli prima sul nome e poi sulla company che abbiamo inserito. Se volessimo capire in dettaglio cosa faccia quel codice dovremmo studiarlo per bene, ma a noi interessa trovare il serial (e in realtà basterebbe un'analisi poco più approfondita per creare il keygen). Qui ci basta un'osservazione: abbiamo visto poco fa che dobbiamo uscire da questa call con una valore diverso da 0 in eax. Se osservate le ultime righe vedrete che viene confrontato il valore di ebx con ecx, e se sono uguali al viene messo ad 1 (setz al). ebx è stato impostato alla riga 0042643A e poi non è stato più modificato, dunque contiene ancora il valore a4. ecx, invece è il risultato dei calcoli nelle due call e nelle righe successive. Questo schema di protezione è molto debole, perché per quanto complicati possano essere i calcoli intermedi, a noi serve solo il risultato! :-) Nel mio caso ecx vale 118D4E1B. Dunque mettiamo come unlock key 11111111-22222222-33333333-118D4E1B, generiamo la check key (9C5F0A-33333333-11111111-22BE7D28) e stavolta questo controllo viene passato :-). Proseguiamo:

.text:00425F4B loc_425F4B: ; CODE XREF: sub_425ED0+68j
.text:00425F4B mov ebx, [esi]  ;ebx = a4 (cioè 118D4E1B nel mio caso)
.text:00425F4D shr ebx, 10h    ;prende la parte alta (118D)
.text:00425F50 xor bx, [esi+4] ;xor con la parte bassa di a3
.text:00425F54 and ebx, 0FFFFh ;istruzione totalmente inutile :)
                               ;chiamiamo x il contenuto attuale di ebx
                               ;dunque x = (a4 >> 16) XOR (a3 AND 0x0000FFFF)
.text:00425F5A lea eax, [ebx-0Fh]   ;eax = x - 0xF
.text:00425F5D cmp eax, 4DAh        ;confronta eax con 0x4DA
.text:00425F62 jle short loc_425F77 ;salta se è minore o uguale, beggar off altrimenti
.text:00425F64 push 0
.text:00425F66 push 1
.text:00425F68 push 0
.text:00425F6A push 0FFFFFF34h
.text:00425F6F call sub_4297A0
.text:00425F74 add esp, 10h
.text:00425F77 

Fin qui il programma ci fornisce la condizione x - 0xF <= 0x4DA, cioè x <= 0x4DA + 0xF, ovvero:

x <= 0x4E9

.text:00425F77 loc_425F77: ; CODE XREF: sub_425ED0+92j
.text:00425F77 add ebx, 0Fh         ;ebx = x + 0xF
.text:00425F7A cmp ebx, 4DAh        ;confronta con 0x4DA
.text:00425F80 jge short loc_425F95 ;salta se è maggiore o uguale, beggar off altrimenti
.text:00425F82 push 0
.text:00425F84 push 1
.text:00425F86 push 0
.text:00425F88 push 0FFFFFF35h
.text:00425F8D call sub_4297A0
.text:00425F92 add esp, 10h
.text:00425F95 

Seconda condizione: x + 0xF >= 0x4DA, che significa:

x >= 0x4CB

Unendo le due relazioni trovate abbiamo:

0x4CB <= x <= 0x4E9

Scegliamo un qualunque valore per x che sia contenuto in quell'intervallo, es.: x = 0x4D0. Ricordando che x = (a4 >> 16) XOR (a3 AND 0x0000FFFF), concludiamo:

(a4 >> 16) XOR (a3 AND 0x0000FFFF) = 0x4D0

Che è uguale a:

118D XOR (a3 AND 0x0000FFFF) = 0x4D0

Quindi:

a3 AND 0x0000FFFF = 0x4D0 XOR 0x118D = 0x155B

Detto a parole, la parte bassa di a3 è uguale a 155B. Dunque modifichiamo ancora unlock e check keys:

11111111-22222222-3333155B-118D4E1B
9C5F0A-33333333-11113779-22BE5B40

Clicchiamo ok e...

Welcome to CDRWIN...
This software is now unlocked and fully functional.

Evviva! Il programma si complimenta con noi! Adesso è perfettamente funzionante... o quasi. Riavviamo il programma e ci compare una bella finestrella:

THIS SOFTWARE HAS BEEN UNLOCKED WITH PIRATED KEYS

Golden Hawk Technology has spent three years and a large sum of money developing this software package. Without registered users, we would be unable to hire talented programmers or purchase the equipment needed to continue its future development.

You probably spent hundreds of dollars on your CDROM recorder and thousands more on your PC system. I would bet that you never considered stealing any of your hardware, so why steal the $49 software that actually makes it all do something useful?

We can't stop you from pirating this software, but we believe that in the long run you will only be hurting yourselves and others. Companies like us will no longer find it profitable to invest the time and money needed to develop quality software.

We offer a functional demo version on our web page, as well as a 30 day "no questions asked" money back guarantee if you purchase the software. Our return rate is less then 2%, so we are quite proud of our 98% approval rating.

Nobody expects you to do your job for free, so don't expect us to either. Thank you very much for your attention in this important matter...

Altro che complimenti! Il programma si è accorto di tutto. Un'intelligenza artificiale? Una microspia? Cavolo, siamo controllati, vi suggerisco subito di staccare il telefono... :P

Niente di tutto ciò ovviamente, non preoccupatevi :-). E' solo che il programma esegue altri controlli sul serial all'avvio successivo. La finestra appena visualizzata non è una MessageBox ma una comune Dialog. Per risalire in fretta al luogo dove viene chiamata utilizziamo un semplice trucchetto, che è un po' rozzo ma quasi sempre funziona :-). Apriamo il Resource Hacker, apriamo l'eseguibile di cdrwin e cerchiamo un po' tra le dialog. Troviamo quella appena vista e scopriamo che ha ID (identificativo di risorsa) 1031. Bene, che ce ne facciamo? Molto semplice: qualunque API per visualizzare la dialog avrà bisogno di questo numero, e dunque dovrà comparire da qualche parte nel disassemblato. IDA in genere lascia le costanti in esadecimale, quindi 1031, se presente, comparirà come 407h. Potremmo fare una ricerca testuale nel disassemblato, oppure, più semplicemente, clicchiamo su Search--->immediate value... Scriviamo nel campo di ricerca 0x407 e selezioniamo "Find all occurrences". IDA ci comunica 3 risultati, rispettivamente agli indirizzi 00412B48, 00473FE0, 00474349. Se andiamo a vedere il codice per gli ultimi due, notiamo che corrispondono a chiamate a SendMessage, che a noi non interessano: cerchiamo infatti dove la Dialog viene creata. Il primo risultato invece è interessante:

.text:00412B40 sub_412B40 proc near ; CODE XREF: sub_4034A0+E7p
.text:00412B40 
.text:00412B40 arg_0 = dword ptr 4
.text:00412B40 
.text:00412B40 mov eax, [esp+arg_0]
.text:00412B44 push esi
.text:00412B45 push eax
.text:00412B46 mov esi, ecx
.text:00412B48 push 407h       ;IDA aveva trovato questo
.text:00412B4D call ??0CDialog@@QAE@IPAVCWnd@@@Z ; CDialog::CDialog(uint,CWnd *)
.text:00412B52 mov dword ptr [esi], offset off_48A258
.text:00412B58 mov eax, esi
.text:00412B5A pop esi
.text:00412B5B retn 4
.text:00412B5B sub_412B40 endp

Qui evidentemente viene creata la finestra incriminata, ma non c'è niente di utile. Però è una buona base di partenza per il backtracing. Ha una sola XReference, e noi la controlliamo subito:

.text:00403564 push ebx
.text:00403565 push ebx
.text:00403566 push offset aCdrwin_dat ; "CDRWIN.DAT"
.text:0040356B mov byte ptr [ebp+var_4], 1
.text:0040356F call sub_425CA0
.text:00403574 add esp, 0Ch
.text:00403577 mov [ebp+var_4], ebx
.text:0040357A call sub_426C00      ;Tre righe
.text:0040357F test eax, eax        ;molto
.text:00403581 jnz short loc_4035C5 ;interessanti :)
.text:00403583 push ebx
.text:00403584 lea ecx, [ebp+var_78]
.text:00403587 call sub_412B40  ;<---- Questa è call che crea la dialog
.text:0040358C lea ecx, [ebp+var_78]
.text:0040358F mov byte ptr [ebp+var_4], 3
.text:00403593 call sub_475562
.text:00403598 lea ecx, [ebp+var_78]
.text:0040359B mov byte ptr [ebp+var_4], bl
.text:0040359E call sub_4751A3

Siamo arrivati :-). Come vedete il jnz alla riga 00403581 salta ben oltre la call cattiva :P. In effetti se da softice mettiamo un breakpoint a quel jump e lo invertiamo in modo da farlo saltare, il programma si avvia allegramente... FERMI!!! Avevo detto niente HexEditor, invertire il jmp era solo una prova, noi dobbiamo terminare il serial fishing :P
Poche righe più su vediamo che il programma va ad aprire CDRWIN.DAT, ed è infatti lì che il programma memorizza le informazioni sulla registrazione. Ad ogni modo la call che ci interessa è evidentemente quella alla
sub_426C00:

.text:00426C00 push ecx
.text:00426C01 mov eax, dword_4C6EF8 ;Debuggando vediamo che mette in eax 118D4E1B, cioè a4
.text:00426C06 push 0
.text:00426C08 push 0
.text:00426C0A push 1
.text:00426C0C push 0
.text:00426C0E push 0
.text:00426C10 lea ecx, [esp+15h+var_1]
.text:00426C14 push 4
.text:00426C16 add eax, 64h
.text:00426C19 push ecx
.text:00426C1A push offset unk_4B8A68
.text:00426C1F mov [esp+21h+var_1], eax
.text:00426C23 call sub_44E040
.text:00426C28 shr eax, 10h
.text:00426C2B xor edx, edx
.text:00426C2D cmp word ptr dword_4C6EFC+2, ax
.text:00426C34 setz dl
.text:00426C37 mov eax, edx
.text:00426C39 add esp, 24h
.text:00426C3C retn

La sub_44E040 esegue ancora una sfilza di calcoli sul seriale, ma, di nuovo, ci lascia il risultato in chiaro, e questo ci basta. Il confronto decisivo è alla riga 00426C2D. Qui ax vale (con nome e company che abbiamo inserito, s'intende), ADC5 mentre la word con cui il seriale viene confrontato vale 3333... Indovinate un po' cos'è? Ovviamente la parte alta della terza dword del seriale :-) Dunque il serial completo dovrà essere:

11111111-22222222-ADC5155B-118D4E1B

E la check key:

009C5F0A-33333333-8FE73779-BC485B40

Il programma così com'è non parte perché è ancora registrato con il seriale sbagliato di prima, quindi andate a prendere i files (basta anche solo cdrwin.dat) della copia di backup... avete fatto un backup, vero? Se no potete semplicemente reinstallare il programma, e avrà dimenticato tutto :-)

Con questo direi che è tutto... Non scappate! Ora ci sono i compiti per casa: scrivete un keygen analizzando anche quelle parti che io ho tralasciato :))

                                                                                                                Spider

Note finali

Ringrazio Quequero che in fondo in fondo è un bravo ragazzo :-)

Disclaimer

Vorrei ricordare che il software va comprato e  non rubato, dovete registrare il vostro prodotto dopo il periodo di valutazione.

Noi reversiamo perché è TROPPO BBELLOOOOOOOO