Keygen del CoverXP

Data

by Mattia (active85k)

 

16/04/2004

UIC's Home Page

Published by Quequero


D'estate ragazzine schive...

LoL (la frase accanto ;p), grazie active!

...hanno le zinne accennate ma fanno le dive!

....

Home page se presente: www.active85k.da.ru
E-mail: active85k@hotmail.com
active85k, #fuckinworld | #crack-it | #informazionelibera @ Azzurra.org

....

Difficoltà

(x)NewBies ( )Intermedio ( )Avanzato ( )Master

 

Oddio... come algoritmo è proprio facile... la difficoltà sta nel fatto che il target è scritto in delphi, linguaggio un po' oneroso e difficoltoso da reversare... cmq si può fare! ;D


Keygen del CoverXP
Written by Mattia Buccarella (active85k)
 
Allegato

Introduzione

I politici: no, no, non sono più quelli di una volta;
Le donne: no, no, no, non sono più quelle di una volta;
Io: no, no, no, no, non sono più quello di una volta;
Solo la retorica è rimasta la stessa!!!

Tools usati

DeDe (Delphi decompiler)
SoftIce
Borland Delphi 6 per il keygen (non so perché stavolta ho scritto in delphi... però è bene cambiare :)

URL o FTP del programma

www.coverxp.com  

Notizie sul programma

E' un bel programmino fatto bene che serve per stampare le copertine dei cd...
A parte questo dovete sapere che io, ormai, sono il "cracker ufficiale" della darkwet: mi temono come la morte! :D Se un giorno smetteranno di produrre software sarà per causa mia. :D

Essay

Ola! :D
Niente panico... il programma è scritto in delphi (ve lo dico direttamente io :) e il caso ha voluto che io in delphi, modestamente... ;-). Iniziamo con la nostra analisi. Questi qua... nessun packer, nessun accorgimento... neanche un anti-softice... dupalle. :\ Prendiamo il dede, che è un ottimo decompilatore per il delphi. Attenzione: con la parola "decompilatore" non intendo un programma che, partendo dal compilato, ritorna ai sorgenti delphi! Intendo un programma che, partendo dal compilato, visualizza il listato assembly del programma con i sui riferimenti ai componenti che si trovano sulla form, col codice distribuito in tutte le sue procedure e funzioni.
Prendiamo il dele, carichiamo il coverXP e dumpiamolo una volta che finisce di caricare. Nel dede, andiamo nella scheda delle Form per vedere un po' come è fatto 'sto programmillo. L'occhio deve cadervi sulla form di classe TSerialForm, che è la form di registrazione. Andando avanti nella composizione della form, notiamo un pulsante che ha come caption "Registra". Ovviamente è lui! Vediamo la proprietà OnClick e andiamo nella sua corrispondente procedura, attraverso la scheda "Procedures"; doppio click e siamo dentro!

005026E8 55 push ebp
005026E9 8BEC mov ebp, esp
005026EB 83C4F8 add esp, -$08
005026EE 8955F8 mov [ebp-$08], edx
005026F1 8945FC mov [ebp-$04], eax

* Reference to pointer to GlobalVar_00558C30
|

005026F4 A1744E5500 mov eax, dword ptr [$00554E74]
005026F9 803800 cmp byte ptr [eax], $00
005026FC 750A jnz 00502708
005026FE 33D2 xor edx, edx

* Reference to serialform
|
00502700 8B45FC mov eax, [ebp-$04]

|
00502703 E89CECFFFF call 005013A4 ; questa è la chiamata che ci interessa.
00502708 59 pop ecx
00502709 59 pop ecx
0050270A 5D pop ebp
0050270B C3 ret

Beh... una volta qua dentro praticamente sappiamo dove dobbiamo mettere le mani... precisamente incominciando da 005013A4. Ok... ora: chi ca**o se ne frega del DeDe... chiudiamolo e prendiamo il softice! Steppa qua.. steppa là... arriviamo a 005014C6:

CODE:005014C6 mov eax, [ebp+var_2C]   ; eax = $40
CODE:005014C9 add eax, eax            ; eax = $80
CODE:005014CB add eax, 3              ; eax = $83
CODE:005014CE mov [ebp+var_20], eax
CODE:005014D1 mov eax, [ebp+var_C]
CODE:005014D4 mov edx, dword ptr [ebp+var_1C+4]
CODE:005014D7 movzx eax, byte ptr [eax+edx-4]   ; prende il quart'ultimo ch. del nome
CODE:005014DC mov [ebp+var_34], eax
CODE:005014DF mov eax, [ebp+var_34]
CODE:005014E2 imul [ebp+var_20]                 ; lo moltiplica per $83
CODE:005014E5 mov [ebp+var_28], eax
CODE:005014E8 mov eax, dword ptr [ebp+var_1C+4] ; salva la lunghezza del nome...
CODE:005014EB test eax, eax
CODE:005014ED jle loc_0_5015A9
CODE:005014F3 mov [ebp+var_44], eax             ; in [ebp-44]
CODE:005014F6 mov dword ptr [ebp+var_1C], 1     ; inizializza un contatore a 1
CODE:005014FD
CODE:005014FD loc_0_5014FD: ; CODE XREF: sub_0_5013A4+1FF j
CODE:005014FD mov eax, dword ptr [ebp+var_1C]
CODE:00501500 mov ecx, 3
CODE:00501505 cdq
CODE:00501506 idiv ecx                          ; divide il contatore per 3...
CODE:00501508 mov [ebp+var_24], edx             ; e salva il resto della div. (1)
CODE:0050150B mov eax, [ebp+var_24]
CODE:0050150E shl eax, 2
CODE:00501511 add [ebp+var_28], eax
CODE:00501514 mov eax, dword ptr [ebp+var_1C]   ; prende il contatore
CODE:00501517 add eax, 10h                      ; gli aggiunge $10
CODE:0050151A push eax
CODE:0050151B mov eax, [ebp+var_34]             ; prende il quart'ultimo ch. di prima
CODE:0050151E pop edx
CODE:0050151F mov ecx, edx
CODE:00501521 cdq
CODE:00501522 idiv ecx                          ; e lo divide per contatore+$10 (2)
CODE:00501524 mov [ebp+var_38], edx             ; per salvarne di nuovo il resto
CODE:00501527 mov eax, [ebp+var_24]             ; riprende il resto (c mod 3)
CODE:0050152A sub eax, 1
CODE:0050152D jb short loc_0_501536             ; if q-1 < 0 then
CODE:0050152F jz short loc_0_501558             ; else if q-1 = 0 then
CODE:00501531 dec eax
CODE:00501532 jz short loc_0_50157A             ; else if q-2 = 0 then
CODE:00501534 jmp short loc_0_50159D
CODE:00501536 ; ---------------------------------------------------------------------
CODE:00501536
CODE:00501536 loc_0_501536: ; CODE XREF: sub_0_5013A4+189 j (if q-1 < 0 then)
CODE:00501536 mov eax, [ebp+var_C]              ; eax = @username
CODE:00501539 mov edx, dword ptr [ebp+var_1C]   ; edx = contatore
CODE:0050153C movzx eax, byte ptr [eax+edx-1]   ; mette in eax il Cesimo ch. del nome
CODE:00501541 mov [ebp+var_30], eax
CODE:00501544 mov eax, [ebp+var_30]            
CODE:00501547 imul [ebp+var_38]                 ; lo moltiplica per il resto della
                                                ; seconda divisione [q2 o (2)]

CODE:0050154A xor eax, 0AAh                     ; poi xora il tutto con $aa
CODE:0050154F add [ebp+var_2C], eax             ; aggiunge il risultato ad r
CODE:00501552 sub [ebp+var_28], 6
CODE:00501556 jmp short loc_0_50159D
CODE:00501558 ; ---------------------------------------------------------------------
CODE:00501558
CODE:00501558 loc_0_501558: ; CODE XREF: sub_0_5013A4+18B j (if q-1 = 0 then)
CODE:00501558 mov eax, [ebp+var_C]              ; eax = @username
CODE:0050155B mov edx, dword ptr [ebp+var_1C]   ; edx = contatore
CODE:0050155E movzx eax, byte ptr [eax+edx-1]   ; mette in eax il Cesimo ch. del nome
CODE:00501563 mov [ebp+var_30], eax
CODE:00501566 mov eax, [ebp+var_30]             ; prende il char.
CODE:00501569 imul [ebp+var_38]                 ; lo moltiplica per q2
CODE:0050156C xor eax, 0CCh                     ; e lo xora con $cc
CODE:00501571 add [ebp+var_2C], eax             ; aggiunge il risultato ad r
CODE:00501574 sub [ebp+var_28], 6
CODE:00501578 jmp short loc_0_50159D
CODE:0050157A ; ---------------------------------------------------------------------
CODE:0050157A
CODE:0050157A loc_0_50157A: ; CODE XREF: sub_0_5013A4+18E j (if q-2 = 0 then)
CODE:0050157A mov eax, [ebp+var_C]              ; eax = @username
CODE:0050157D mov edx, dword ptr [ebp+var_1C]   ; edx = contatore
CODE:00501580 movzx eax, byte ptr [eax+edx-1]   ; mette in eax il Cesimo ch. del nome
CODE:00501585 mov [ebp+var_30], eax
CODE:00501588 mov eax, [ebp+var_30]             ; prende il char
CODE:0050158B imul [ebp+var_38]                 ; lo moltiplica per q2
CODE:0050158E xor eax, 1Ch                      ; e lo xora con $1c
CODE:00501591 add [ebp+var_2C], eax             ; aggiunge il risultato ad r
CODE:00501594 mov eax, [ebp+var_28]
CODE:00501597 add eax, 4
CODE:0050159A mov [ebp+var_20], eax
CODE:0050159D
CODE:0050159D loc_0_50159D: ; CODE XREF: sub_0_5013A4+190 j
CODE:0050159D ; sub_0_5013A4+1B2 j ...
CODE:0050159D inc dword ptr [ebp+var_1C]        ; incrementa il contatore
CODE:005015A0 dec [ebp+var_44]                  ; decrementa la lunghezza del ciclo
CODE:005015A3 jnz loc_0_5014FD                  ; abbiamo finito? no: ritorna sopra
CODE:005015A9
CODE:005015A9 loc_0_5015A9: ; CODE XREF: sub_0_5013A4+149 j
CODE:005015A9 cmp [ebp+var_2C], 2710h
CODE:005015B0 jle short loc_0_5015C8            ; while r > $2710 do
CODE:005015B2
CODE:005015B2 loc_0_5015B2: ; CODE XREF: sub_0_5013A4+222 j
CODE:005015B2 sub [ebp+var_2C], 2710h           ;   r := r - $2710;
CODE:005015B9 mov eax, [ebp+var_28]
CODE:005015BC add [ebp+var_20], eax
CODE:005015BF cmp [ebp+var_2C], 2710h
CODE:005015C6 jg short loc_0_5015B2
CODE:005015C8
CODE:005015C8 loc_0_5015C8: ; CODE XREF: sub_0_5013A4+20C j
CODE:005015C8 mov eax, [ebp+var_2C]             ; prende r
CODE:005015CB mov ecx, 9
CODE:005015D0 cdq
CODE:005015D1 idiv ecx                          ; lo divide per 9 e prende il resto..
CODE:005015D3 inc edx                           ; a cui ci aggiunge 1 (per evitare
                                                ; che sia zero)

CODE:005015D4 imul edx, dword ptr [ebp+var_1C+4]; e lo moltiplica per la lunghezza
                                                ; del nome (questo è q)

CODE:005015D8 mov [ebp+var_3C], edx 
CODE:005015DB cmp [ebp+var_3C], 64h
CODE:005015DF jle short loc_0_5015F4            ; while q > $64 do
CODE:005015E1
CODE:005015E1 loc_0_5015E1: ; CODE XREF: sub_0_5013A4+24E j
CODE:005015E1 sub [ebp+var_3C], 64h             ;   q := q - $64
CODE:005015E5 mov eax, [ebp+var_20]
CODE:005015E8 imul [ebp+var_28]
CODE:005015EB mov [ebp+var_28], eax
CODE:005015EE cmp [ebp+var_3C], 64h
CODE:005015F2 jg short loc_0_5015E1

Fatto questo il gioco è fatto. q è la prima parte del serial mentre r è la seconda parte. Basta unirle per ottenere il seriale valido. Vediamo la funzione come va:

function TForm1.Keygen(Username: String): String;
var
 
l, r, c, q, q2: Integer;
  ch, cg2: Char;
begin
  l := length(Username);
  if l < 5 then begin
    Result := 'Your user name must have at least 5 chars!';
    Exit;
  end;

  ch := Username[l-3];
  c := 1;
  r := $40;

  while l > 0 do begin
    q := (c mod 3);
    q2 := Integer(ch) mod (c + $10);
    ch2 := Username[c];

    if(q-1 < 0) then
      r := r + ((Integer(ch2) * q2) xor $aa)
    else if(q-1 = 0) then
      r := r + ((Integer(ch2) * q2) xor $cc)
    else if(q-2 = 0) then
      r := r + ((Integer(ch2) * q2) xor $1c);

    inc(c);
    dec(l);
  end;

  while r > $2710 do
    r := r - $2710;

  q := ((r mod 9) +1) * length(Username);

  while q > $64 do
    q := q - $64;

  Result := IntToStr(q) + IntToStr(r);
end;

Ecco qua il generatore di chiavi! Amici... anche questa volta, active85k ha perforato la darkwet! :D

Mattia Buccarella (active85k)

Note finali

Un ringraziamento va alla darkwet ovviamente.
Un altro ringraziamento va a L3V[iathan] che mi ha betatestato qualche seriale e mi ha trovato un particolare che avevo scordato ^^'
Un altro ringraziamento va a Capa Rezza -.- (grande il concertazzo! :)

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