KeyGen Fishing in WinZip 8.1 | ||
Data |
by "Ox87k" |
|
14/12/2004 |
Published by Quequero | |
St. Jimmy's comin' down across the alleyway. Up on the boulevard like a zip code on parade. Light on the sillohette |
Ottimo inizio Ox87k :) |
|
.... |
|
.... |
Difficoltà |
(X)NewBies ( )Intermedio ( )Avanzato ( )Master |
Introduzione |
Tools usati |
URL o FTP del programma |
Notizie sul programma |
Notizie su WinZip??? Muhahuauhahuahuahu!!! Se non lo conosci forse è meglio che leggi qualche libro su come usare un computer dopo averlo acceso!!!
Essay |
:0040BD00 call ds:GetDlgItemTextA //tornati dalla API siamo qui. :0040BD06 push esi //esi contiene il seriale inserito :0040BD07 call sub_4607BD //fa dei controlli sul seriale. non ci interessa :0040BD0C push esi :0040BD0D call sub_4607E6 //altri controlli sul serial, nemmeno li guardiamo :0040BD12 cmp nome, 0 //controlla se il primo carattere del nome inserito è 0 :0040BD19 pop ecx :0040BD1A pop ecx :0040BD1B jz short loc_40BD7C //salto relativo al controllo sul nome (vedi sopra) :0040BD1D cmp serial, 0 //controlla se il primo carattere del serial inserito è 0 :0040BD24 jz short loc_40BD7C //salto relativo al confronto del serial :0040BD26 call Genera_Codice //CHIAMATA PER GENERARE IL SERIAL VERO, Entriamoci! :0040BD2B test al, al :0040BD2D jz short loc_40BD7C |
:0040B783 CALL WINZIP32.0040B875 //CALL KE GENERA IL SERIALE |
//Call
relativa all'opcode :0040B783 :0040B875 push ebp //siamo sbarcati qui :) :0040B876 mov ebp, esp :0040B878 mov ecx, dword ptr ss:[ebp+8] //ecx contiene il nome :0040B87B push ebi :0040B87C push esi :0040B87D push edi :0040B87E mov dl, byte ptr ds:[ecx] //dl contiene il primo carattere del nome ke è in ecx :0040B880 xor ebx, ebx //azzero ebx :0040B882 xor eax, eax //azzero l'accumulatore eax :0040B884 mov esi, ecx //copio il nome che è in ecx anche in esi :0040B886 xor edi, edi //azzero l'indice di destinazione //Primo ciclo per il seriale: :0040B888 +-> test dl, dl //sono arrivato all'ultimo carattere del nome? :0040B88A | je short Fine_primo_ciclo //se si esco dal primo ciclo e proseguo sotto :0040B88C | movzx dx, dl //metto il carattere che ho in dl nella parte bassa di dx :0040B890 | imul edx, edi //moltiplica il edx che contiene il carattere con il | //contatore dei caratteri del nome che ogni ciclo viene inc. :0040B893 | add ebx, edx //aggiunge al primo pezzo del serial il risultato :0040B895 | mov dl, byte ptr ds:[esi+1] //dl punta al carattere successivo :0040B898 | inc edi //incremento il contatore di caratteri :0040B899 | inc esi //esi punta quindi al carattere successivo :0040B89A +-> jmp short Inizio_primo_ciclo //torno su //Fine primo ciclo |
Ora, l'algoritmo ha generato metà del seriale valido. Specificamente ha generato la parte bassa. Prende ogni carattere del nome inserito e lo moltiplica per l'indice che funge da contatore di caratteri. Vediamo come sarebbe questa parte in c;
//primo pezzo del serial, parte bassa for (int i=0;name[i]!=0;i++) { serial1+=(name[i] * i); } |
Ok, continuiamo l'analisi della seconda parte del serial... il codice ke segue sotto è la parte seguente all'algoritmo sopra esaminato:
:0040B89C mov byte ptr ds:[4CC78B],1 :0040B8A3 mov esi, ecx //copio il nome contenuto in ecx in esi :0040B8A5 mov cl, byte ptr ds:[ecx] //cl contiene il primo carattere del nome //secondo ciclo: :0040B8A7 +-> test cl, cl //sono arrivato all'ultimo carattere del nome? :0040B8A9 | je short Fine_secondo_ciclo //se si esco dal secondo ciclo e proseguo sotto :0040B8AB | movzx cx, cl :0040B8AF | push 1021 //prendo questo valore 00001021, poi vedremo a cosa serve :0040B8B4 | push ecx :0040B8B5 | push eax :0040B8B6 | call Calcoli_del_serial //VEDIAMO SOTTO COSA ACCADE IN QUESTA CALL :0040B8BB | mov cl, byte ptr ds:[esi+1] //finita la call, carico in cl il carattere successivo :0040B8BE | add esp, 0c :0040B8C1 | inc esi :0040B8C2 +-> jmp short Inizio_secondo_ciclo //torno su all'inizio x ripetere tutto //fine secondo ciclo |
Ora notiamo quella chiamata, andiamo a vedere cosa succede quando arriviamo li. Una volta arrivati sopra la call, premiamo F7 ed entriamo anke qui.
//Call
relativa all'opcode :0040B8B6 :0040B8E4 push ebp :0040B8E5 mov ebp, esp :0040B8E7 mov eax, dword ptr ss:[ebp+8] :0040B8EA push esi //nello stack il nome :0040B8EB xor ecx, ecx //azzero il contatore ecx :0040B8ED push 8 //nello stack il valore 8 :0040B8EF mov ch, byte ptr ss:[ebp+C] //in ch il primo carattere del nome :0040B8F2 pop edx //edx=8 cioe' le volte ke ripete il seguente ciclo //Ciclo che viene ripetuto 8 volte per ogni singolo carattere del nome :0040B8F3 +-> mov esi, eax //esi = eax :0040B8F5 | xor esi, ecx //esi ^= ecx (ecx, nella parte alta, contiene il carattere) :0040B8F7 | test si, 8000 //if (esi & 0xFFFF) >= 8000 :0040B8FC | je short 2° //se esi & 0xFFFF è minore di 8000 salta alla parte 2° :0040B8FE |1°: add eax, eax //altrimenti [se è maggiore o uguale a 8000] eax = eax+eax :0040B900 | xor eax, dword ptr ss:[ebp+10] //e poi SS:[EBP+10] = 1021 ---> eax ^= 1021 :0040B903 | jmp short 3° //salta alla parte 3° [siamo fuori dal if/else] :0040B905 |2°: shl eax, 1 //eax = eax<<1; shifto eax di 1 :0040B907 |3°: shl ecx, 1 //[FUORI IF ELSE] ecx = ecx<<1; shifto ecx di 1 :0040B909 | dec edx //decremento le 8 volte iniziali :0040B90A +-> jnz short Inizio_ciclo //torno all'inizio del ciclo //Fine ciclo :0040B90C pop esi :0040B90D pop ebp :0040B90E retn //Finita la CALL torno al ciclo di prima ovvero all'opcode :0040B8BB |
Ok.. siamo più o meno sani e salvi!! Tutto il codice in c che riporto di seguito è il secondo pezzo del serial, ovvero la parte alta questa volta. Vediamo tutto sto macello in c per cercare di capire meglio: [non ho messo commenti perchè mi pare di averne messi fin troppi sopra... poi magari il Que s'incaz!!!]
//Genera serial2 [seconda parte del serial]: for (int x=0;name[x]!=0;x++) { ecx=(name[x]<<8); for (z=0;z<8;z++) { esi=eax; esi=esi^ecx; if ((esi & 0xFFFF)>=0x8000) { eax=eax+eax; eax=eax^0x1021; } else { eax=eax<<1; }; ecx=ecx<<1; }; }; |
Ora andiamo a completare l'opera. Analizziamo le righe finali situate sotto la primissima call ke abbiamo visto prima, all'inizio del tute:
:0040B8C4 add eax, 63 //Aggiunge ad eax 63 ---> eax += 0x63; :0040B8C7 movzx ecx, bx :0040B8CA movzx eax, ax //metto nella parte bassa di eax il valore di ax, ovvero la //1° metà del mio serial :0040B8CD push ecx //ecx contiene la seconda meta del mio serial :0040B8CE push eax //eax contiene la prima parte del serial :0040B8CF push %04X%04X //prelevo questi caratteri dallo stack --> %04X%04X :0040B8D4 push dword ptr ss:[ebp+C] :0040B8D7 call winzip32.00493104 :0040B8DC add esp, 10 :0040B8DF pop edi :0040B8E0 pop esi :0040B8E1 pop ebx :0040B8E2 pop ebp :0040B8E3 retn //ritorno della prima call |
name: Ox87k
serial: 9F4F0339
KEYGEN:
The End! Finito di esaminare il proggy, prendiamo un qualsiasi compilatore c [io ho usato Borland 5] ed eccovi il KeyGen: [una cosa.. se volete potete creare anke il keygen del winzip 9.0 sr1. La routine ke genera il seriale è identica alla versione 8.1 solo che non accetta numeri sul nome.]
//KEYGEN WINZIP 8.1 #include <stdio.h> #include <conio.h> char name[100]; char serial[9]; unsigned int serial1 = 0; unsigned int serial2 = 0; unsigned int esi = 0; unsigned int eax = 0; unsigned int ecx = 0; void main() { printf(" [ winzip 8.1 keygen ]\n\n"); printf("name: "); gets(name); for (int i=0;name[i]!=0;i++) { serial1+=(name[i] * i); } for (int x=0;name[x]!=0;x++) { ecx=(name[x]<<8); for (int z=0;z<8;z++) { esi=eax; esi=esi^ecx; if ((esi & 0xFFFF)>=0x8000) { eax=eax+eax; eax=eax^0x1021; } else { eax=eax<<1; } ecx=ecx<<1; } } serial2=eax+0x63; serial2=serial2&0xFFFF; sprintf(serial, "%0.4X%0.4X", serial2, serial1); printf("serial: "); printf("%s",serial); printf("\n\npress any key to exit...."); getch(); } |
Bene.. Questo era il mio primo tute e ho preso una scannata pazzesca per scriverlo tutto, spero almeno ne sia valsa la pena.
Note finali |
Oddio la sezione più difficile di tutto il
tutorial! Essendo il mio primo tute, devo ASSOLUTAMENTE ringraziare
[active85k], (il mio nick è un onore a lui) che mi ha dato le prime dritte
tramite email sul mondo del reverse, e sopratutto che mi ha sopportato!!!
Oltre a lui devo ringraziare, Quequero ke mi ha dato la possibiltà di
studiare grazie al suo sito, ad AndreaGeddon perchè mi ha aiutato anke
lui, e al mitico Zero_G che nel forum è sempre un amore :)
Poi ringrazio tutti quanti voi perchè solo grazie ai vostri tute ho potuto
studiare e imparare sempre di più. Lonely Wolf, faina_mdc,
pnluck, bender0, zarathustra e via via tutti gli altri, grazie
ankora per i vostri tute ke in un certo qual senso mi hanno cresciuto :)
X ultimo ma non meno importante, i Dream Theater che mi hanno tenuto compagnia
nel reverse e mentre scrivevo e alla brioche ke nel frattempo mi sono pappato!
Disclaimer |
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 che ogni sviluppatore ha dovuto portare avanti per fornire ai rispettivi consumatori i migliori prodotti possibili.
Reversiamo al solo scopo informativo e per migliorare la nostra conoscenza del linguaggio Assembly.