------------> Furb3T <-----------

presenta:

Capire un generatore di seriale: II parte.

   Salve giovani amanti dell'assembler, oggi andremo avanti con la lezione sui generatori di chiave e analizzeremo il codice di un programma che usiamo tutti o quasi: il MIRC 5.31. Utilizzeremo come al solito SOFTICE. Lanciamo Mirc, andiamo sotto HELP|REGISTER ed inseriamo il nome e il codice numerico. Ctrl-D e fissiamo un bel BPX MESSAGEBOXA, F5 per ritornare su Mirc, diamo l'OK e...BOOM eccoci su Softice, premiamo F12 e ci ritroviamo su Mirc che ci fa comparire la finestra di messaggio che ci dice che abbiamo sbagliato codice (...ancora per poco), premiamo OK e rieccoci dentro Softice, ed esattamente qui:

:00437E9C      push 00000010
:00437E9E   
  push 004B4EC2   
:00437EA3      push 004B4E2C
   
:00437EA8      mov eax, dword ptr [ebp+08]
:00437EAB     push eax
:00437EAC     Call USER32.MessageBoxA

:00437EB1       push 00000083          --------------> punto di atterraggio
:00437EB6      mov eax, dword ptr [ebp+08]

    Bene ora non vi resta che fare un pò di scroll up ovvero far scorrere verso l'alto per vedere quale è la parte di codice che chiama la MessageBox; scorrete scorrete ed arriverete qui:

:00437DE7        push 004C07CC     -----------> fate d 4C07CC leggerete il codice che avete scritto
:00437DEC       push 004C0510
       -----------> qui troverete il nome che avete scritto
:00437DF1        call 004822D0
        -----------> call che effettua il controllo della validità e ritorna il valore
:00437DF6        add esp, 00000008
                        in EAX
:00437DF9        test eax, eax
:00437DFB        je 00437E67            
-----------> se EAX = 0 allora salta alla MessageBox di prima
:00437DFD       push 004B77A4
:00437E02         push 004B4DC0

    Avrete capito che bisognerà andare a spulciare nella CALL che sta all'indirizzo 00437DF1; facciamo un bel Trace della call:

:004822D0    push ebp
:004822D1     mov ebp, esp
:004822D3      push ebx
:004822D4      push esi
:004822D5      push edi
:004822D6      mov esi, dword ptr [ebp+0C]
:004822D9      mov ebx, dword ptr [ebp+08]
:004822DC     push ebx
           -------------> Scrivete d ebx comparirà il nome che avete inserito
:004822DD     call 004A4060
  ------------> calcola la lunghezza del nome inserito e la mette in EAX
:004822E2      pop ecx
:004822E3      cmp eax, 00000005
  ----> se la lunghezza del nome inserito è più piccola di 5, non salta    
:004822E6      jnb 004822EC
            ------> quindi il nome da inserire deve essere più lungo di 5
:004822E8      xor eax, eax
:004822EA     jmp 00482363
:004822EC     push esi
:004822ED     push ebx
:004822EE     call 004821F0
        -------> un'altra Call che fa un controllo su nome e codice
:004822F3      add esp, 00000008
:004822F6      test eax, eax
        -------> la Call ritorna EAX= 0 se non è giusto il codice altrimenti EAX=1
:004822F8      je 00482301
:004822FA     mov eax, 00000001
:004822FF     jmp 00482363

    Non siamo ancora arrivati al pezzo di codice che ci serve per capire come viene generato il vero codice; dobbiamo fare il Trace della CALL che sta a 004822EE, quindi:

.....................
:004821FC  push 0000002D
--------> 2D non è altro che il "-" (trattino), ciò vuol dire che il codice vero
:004821FE  push esi
                              da inserire deve contenere il trattino e che quindi sarà composto
:004821FF  call 004A400C
                   da 2 parti. Questa Call verifica l'esistenza del trattino e ritorna 0 in
:00482204  add esp, 00000008
         EAX se non c'è.
:00482207  mov ebx, eax
:00482209  test ebx, ebx
:0048220B  jne 00482214
....................
....................

00482254       add ecx, 00000003 --------> questa parte calcola la prima parte di codice. In ECX abbiamo
:00482257     cmp edx, dword ptr [ebp-0C]
            il nome che abbiamo inserito. Osservate come
:0048225A     jge 00482278
                                 aggiunga a ECX il valore 00000003
:0048225C     movzx esi, byte ptr [ecx]
    ------> muove in ESI i caratteri in Ascii esadecimale dal 3 in poi
:0048225F     imul esi, dword ptr [4*eax+004BBB44]
  -----> moltiplica ESI per il risultato della parentesi e
:00482267     add ebx, esi
                                                         mette il risultato in ESI, per poi sommarlo a EBX
:00482269     inc eax
       ---------> incrementa il valore di EAX che partiva da 0
:0048226A    cmp eax, 00000026
:0048226D    jle 00482271
:0048226F    xor eax, eax
:00482271    inc edx     
-----------> incrementa EDX 
:00482272    inc ecx
      -----------> incrementa ECX
:00482273    cmp edx, dword ptr [ebp-0C]
    -----------> ripete il loop finchè EDX non è uguale alla 
:00482276    jl 0048225C
                                                        lunghezza del nome che avete inserito.

    Ok, mi sembra abbastanza facile da capire come viene generata la prima parte del codice, l'unica cosa che vi risulterà difficile da capire è cosa avviene nel prodotto tra ESI e [.....]. Allora che vuol dire 4*eax+004BBB44? Ve lo spiego subito. Se scrivete d 004BBB44, vedrete nella finestra una cosa tipo questa:

0B 00 00 00 06 00 00 00 11 00 00 00 0C
0C 00 00 00 0E 00 00 00  05 00 00 00 0C
....................................................
    

Sapendo che Eax parte da 0, allora nel primo loop il ESI verrà moltiplicato per B, nel secondo loop Esi verrà moltiplicato per 6, nel terzo per 11, nel quarto per C e così via...Capito?!?!? Facile vero!!! Bene ora analizziamo l'altra parte di codice come viene costruita:

...........................
:0048228D  add ecx, 00000003    
---------> ancora una volta il nome viene preso dalla 3 lettera
:00482290   cmp edx, dword ptr [ebp-0C]
:00482293   jge 004822B8
:00482295   movzx esi, byte ptr [ecx]
----> muove in ESI i caratteri ASCii Esadec. del nome dal 3 in poi
:00482298   movzx edi, byte ptr [ecx-01]
---> muove in EDI i caratteri Ascii Esa del nome dal 2 in poi
:0048229C   imul esi, edi   
--------> moltiplica ESI per EDI e il mette il risultato in ESI
:0048229F   imul esi, dword ptr [4*eax+004BBB44]
-----> moltiplica ESI per il fattore tra le [.....]
:004822A7   add ebx, esi              
--------> somma ESI a EBX e mette il risultato in EBX
:004822A9   inc eax
:004822AA  cmp eax, 00000026
:004822AD  jle 004822B1
:004822AF   xor eax, eax
:004822B1   inc edx
          -----------> incrementa EDX
:004822B2   inc ecx            
----------> incrementa ECX
:004822B3   cmp edx, dword ptr [ebp-0C]
----> ripete il loop se EDX è minore della lunghezza del nome
:004822B6   jl 00482295

    Insomma, anche questa seconda parte del codice ora è svelata. Quando creerete il vostro bel programmino di keygen, ricordatevi bene tutti i percorsi dell'algoritmo di calcolo, nonchè del trattino..... inoltre ricordatevi di citarmi nel programma!!!!!

    Purtroppo io programmo in VB quindi non vi scriverò il programma keygen, questo toccherà a voi implementarlo con il linguaggio che sapete usare di più. A presto miei fidi!!!!

Ringraziamenti: a tutto il gruppo RingZer0 per il supporto Tecnico e Morale, ed a Insanity perchè                          pubblica i miei tutorial.