UIC Lezione 3
(Codice SMC)
 

08/10/99

by "Int19"

 
 

UIC's Home Page

Published by Quequero

“Use the

Force Luke”

Obi Wan

Complimenti anche stavolta Int19, hai fatto un tutorial davvero impeccabile e spiegato nei più minimi dettagli, bravo

“Quanta legna potrebbe rodere un rroditore…”

Guybrush.

UIC's form

Per chi volesse contattarmi….
E-mail: [email protected]
Nick: Int19 aka Il.Socio, UIN: 4044843

UIC's form

Difficoltà

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

Scaricate qui l'allegato

Questa volta avremo a che fare con codice automodificante, lo crackeremo e creeremo un KeyMaker.


 UIC Lezione 3
 Codice SMC

 
Written by Int19

Introduzione

Ciao a tutti, qui e’ Il.Socio che scrive,

premetto che trattandosi di codice auto-modificante (SMC) un approccio "live" e' quantomeno essenziale, per non lasciarsi ingannare da come il prog. si presenta "in apparenza", quindi scordatevi Win32Dasm e tenete SoftICE sottomano.

Leggete la lezione di Quequero riguardante proprio questo corso per degli approfondimenti relativi al SMC.

Inoltre tutto il codice presentato in questo tute, sara' riferito al codice che viene visualizzato da SoftICE.

Tools usati

Il classico e indispensabile SoftICE 4.0, Hiew 6.16 per patchare l'exe in modo da accettare come valida qualsiasi coppia nome/seriale e il Borland TurboC per il KeyMaker.

Inoltre ho utilizzato Base Calculator http://biosys12.ee.unsw.edu.au/personal/software/basecalc/ per il calcolo del serial.

URL o FTP del programma

Beh, se state leggendo questo credo che tutti lo conosciate ormai : http://quequero.cjb.net seguite i link verso il Terzo Corso e troverete sicuramente il file di esempio

Notizie sul programma 

Il programma presenta due box nei quali inserire nome e numero di serie, ed un bottone per la registrazione, inserendo un

Serial errato non compare nulla, inoltre c’e’ un bottone about che a quanto pare non fa nulla ( Quequero che c’era per caso qualche routine imboscata che mi e’ sfuggita ?  J ) Ecco cosa mi ero dimenticato, il pulsante About, grazie int19 per avermelo ricordato NdQue

Inserendo un serial corretto il prog. mostra un messaggio di congraturazioni.

Essay

Obiettivi:

1) Trovare il codice corrispondente al nostro nick

2) Crackare il programma in modo da ottenere codici sempre validi

3) Analizzare l'algoritmo di generazione del seriale

4) Scrivete un key-maker per il programma

Spero che Que non mi flagelli (splat..splat..splat :)) NdQue) ma personalmente non mi sono attenuto rigorosamente a questo ordine,

quindi vi presentero' l'ordine che a me e' venuto piu' naturale quando ho crackato il prog. di esempio.

1) Individuare la protezione

2) Crackare il programma in modo da ottenere codici sempre validi

3) Trovare il codice corrispondente al nostro nick

4) Analizzare l'algoritmo di generazione del seriale

5) Scrivere un key-maker per il programma

  1) Individuare la protezione

Per conseguire il primo obbiettivo dobbiamo ovviamente come prima cosa individuare la protezione, ovvero il luogo in cui il serial che andremo ad immettere viene confrontato con quello calcolato.

Iniziamo con il piazzare i classici breakpoint "BPX GetDlgItemTextA" e "BPX GetWindowTextA", inseriamo un nome (Int19) e un serial (12244331) ed appena pigiamo il bottone di registrazione arriva SoftICE in nostro aiuto, come potrete notare premendo F5, la funzione viene richiamata per ben quattro volte, ma solo alla quarta viene letto il seriale, le prime tre si riferiscono sempre al nome, e piu' precisamente il nostro codice seriale appena immesso, verra' salvato nella locazione 4020AF (come si deduce dai parametri passati alla funzione).

Ora la logica suggerisce di piazzare un bel BPM 4020AF 4020AF+8 rw, ma se date ancora un'ulteriore sguardo al codice che segue, vedrete che il serial inserito viene immediatamente manipolato...

:0040132D      push 00000018

:0040132F      push 004020AF                           <--- Locazione nella quale sara' salvato il serial inserito

:00401334      push dword ptr [00402050]

* Reference To: USER32.GetWindowTextA, Ord:0000h

                                  |

:0040133A      Call 0040165B

:0040133F      xor ecx, ecx                                  <--- Azzera la posizione per analizzare il primo char del serial

:00401341      xor eax, eax

:00401343      mov al, byte ptr [ecx+004020AF] <--- Preleva un char dal serial inserito usando ecx

                                                                                   come contatore

:00401349      xor al, 81

:0040134B      xor al, 40

:0040134D      mov bl, byte ptr [ecx+004020C7] <--- Preleva un char dalla locazione 4020C7 usando ecx

          come contatore

:00401353      cmp al, bl                                      <--- Esegue il confronto tra il char del serial e il char

                   della locazione 4020C7

:00401355      jne 00401170                               <--- e salta se sono diversi

:0040135B      inc ecx                                         <--- incrementa il contatore (fino a qui sono stati

       analizzati ecx chars del serial)

:0040135C      cmp ecx, 00000004                     <--- Se non sono stati ancora analizzati i primi 4 chars

:0040135F      jne 00401341                               <--- allora salta

:00401361      nop

:00401362      nop

Il ciclo qui sopra (da 401343 a 40135F) esegue un confronto ad uno ad uno dei primi 4 chars del serial opportunamente manipolati, con i primi 4 chars della locazione 4020C7 (nel mio caso questa locazione contiene i seguenti valori F9 F3 F5 F1 3A 34 essi sono certamente ricavati da una codifica del nome inserito poiche' variano al variare del nome, vedremo in seguito) e se tutti i quattro confronti della linea 401353 hanno avuto successo allora si continua alla linea 401361 (Se ne deduce che il serial dovra' avere almeno 4 chars).

Per forzare il successo di questo check e' sufficiente sostituire il cmp al, bl con un cmp al, al

:00401363      mov esi, 004015C3

:00401368      mov edi, 00401374

:0040136D     mov ecx, 00000049

:00401372      repz movsb

Le linee qui sopra servono per poter sovrascrivere 49hex bytes della zona di codice a partire dalla locazione 401374 con il codice presente alla locazione 4015C3, infatti se lo aprite con Win32Dasm osserverete il codice seguente...

:00401374      mov eax, 00000008

:00401379      xor edx, eax

:0040137B      mov bl, byte ptr [ecx+0040209B]

:00401381      cmp edx, dword ptr [0040209B]

(NOTA: Essendo questo un esempio e trattandosi di zone di codice relativamente piccole in un codice complessivo di dimensioni esigue, il reversing non risulta particolarmente ostico e fortunatamente Que non ha voluto renderci le cose troppo difficili, purtroppo pero' non credo vi capitera' mai ad aver a che fare con codice di 8kb. Lascio a voi immaginare le potenzialita' del SMC quando implementato in un bel eseguibile da 2Mega e magari con qualche parte crittografata qua e la. Vi assicuro che fa girare altamente le palle il fatto di aspettarsi un certo comportamento dal programma e rimanerne delusi)

Ma dopo l'esecuzione runtime della linea 401372 il codice si e' "magicamente" trasformato in questo modo...

:00401374      mov ecx, 00000004                <--- I primi 4 chars sono gia' stati analizzati

:00401379      xor eax, eax                             <--- Credo non sia indispensabile

:0040137B      mov al, byte ptr [ecx+004020AF] <--- Carica il prossimo char dal serial immesso

        (dal 5° char in poi)

:00401381      cmp ecx, dword ptr [0040210F]  <--- Se ha analizzato lunghezza_nome+1 chars

:00401387      je 004013A5                                <--- Allora salta a MessageBoxA "Successo"

:00401389      xor al, 82                                      <---| Esegue alcune

:0040138B      shl al, 02                                             | manipolazioni sul char

:0040138E      ror al, 02                                      <---| corrente

:00401391      mov bl, byte ptr [ecx+004020C7]  <--- Lo confronta con un char del nome codificato

:00401397      cmp al, bl                                      <--- della locazione 4020C7 usando ecx come contatore

:00401399      jne 00401170                               <--- e salta se sono diversi

:0040139F      inc ecx                                          <--- passa al prossimo char

:004013A0      cmp ecx, 00000008                     <--- se non ha ancora analizzato 8 chars

:004013A3      jne 00401379                              <--- allora continua il ciclo alla linea 401379

* Referenced by a Jump at Address 004015D6

|

:004013A5      push 00000020

* Possible StringData Ref ->"SMC - - by Quequero for UIC"

                                  |

:004013A7      push 00402061

* Possible StringData Ref ->"Serial esatto....Bravo!!!!"

                                  |

:004013AC      push 00402113

:004013B1      push 00000000

:004013B3      call USER32!MessageBoxA

:004013B8      jmp 00401170

Osservate che la locazione [40210F] contiene la lunghezza del nome inserito + 1 quindi... se e' stato inserito un nome di 3 chars il check della linea 401381 sara' verificato al primo ciclo (poiche' inizialmente ecx=4) ed il prog. saltera' all'indirizzo 4015D6 che come potete vedere mostra il messagebox di successo. Da questo deduciamo che il serial da inserire dovra' essere piu' lungo di un char rispetto alla lunghezza del nome.

Se forziamo il confronto della linea 401397 con cmp al, al potremo finalmente vedere il MessageBoxA...

Nel mio caso la locazione 4020C7 contiene i seguenti valori F9 F3 F5 F1 3A 34 quindi la linea 40137B con [ecx+4020C7] fa riferimento al valore 3A inizialmente, poi 34 al secondo ciclo ed esce al terzo ciclo poiche' ecx=6 ed e' uguale a lung_nome+1.

Bene, ora abbiamo individuato la protezione e patchato il prog. in modo da ottenere seriali sempre validi...PERO' se ora premiamo nuovamente il pulsante di registrazione non comparira' piu' alcun messaggio di congraturazioni, questo a causa del SMC di Que, in pratica il prog si e' "Aggiustato" e il cmp al,al che noi avevamo inserito e' nuovamente tornato cmp al,bl  (Ecco un esempio di quando ho detto che il prog. non si comporta come ci si aspetterebbe)

Adesso possiamo passare al punto successivo...

  2) Crackare il programma in modo da ottenere codici sempre validi

Come abbiamo visto il prog. si "corregge" o meglio si auto-modifica appunto...

Come possiamo procedere ?  Dunque, l'idea e' quella di individuare le locazioni di memoria "sorgente" dalle quali vengono copiati i bytes che vanno a sovrascrivere le nostre locazioni incriminate, modificarle, e incrociando le dita sperare che le cose non siano piu' complicate (ad esempio le locazioni "sorgente" potrebbero a loro volta essere modificate prima di essere copiate, vi dico subito che non e' il nostro caso quindi rilassatevi)

Il codice che vi presento qui' sotto e' il codice che precede la chiamata alla GetWindowTextA che legge il seriale, ed ecco li la locazione "sorgente" 4014E5.

Esso copia 22hex bytes da 4014E5 a 40133F (sovrascrivendo il nostro primo check)

:0040131C      mov esi, 004014E5

:00401321      mov edi, 0040133F

:00401326      mov ecx, 00000022

:0040132B      repz movsb

Quindi andando alla locazione 4014E5 troviamo la routine di check dei primi 4 chars e ora possiamo cambiare la locazione "sorgente"

:004014F9      cmp al, bl

con

:004014F9      cmp al, al

La prossima volta che verra' eseguito il codice SMC verra' copiato il codice da noi gia' patchato.

Procedendo in modo analogo per il secondo check (che controlla dal 5° char in poi)

:00401363      mov esi, 004015C3

:00401368      mov edi, 00401374

:0040136D      mov ecx, 00000049

:00401372      repz movsb

Andiamo alla locazione 4015C3 e cambiamo la locazione "sorgente"

:004015E6      cmp al, bl

con

:004015E6      cmp al, al

Ora premendo il pulsante di registrazione piu' volte il progr. da sempre esito positivo.

Modificando il programma con un editor esadecimale le modifiche saranno permanenti ed il programma accettera' qualunque coppia nome/seriale come esatta. Sicuramente si sarebbe potuto crackare in  altri modi, ma questo e' quello che personalmente mi e' sembrato il piu' "elegante" e meno invasivo.

  3) Trovare il codice corrispondente al nostro nick

Bene, per questa parte vi consiglio di munirvi di calcolatrice e del codice che ho presentato poco sopra (mi riferisco a quello che parte da 40133F ovviamente)

Io ho inserito "Int19" come nome ed ho ottenuto i seguenti valori alla locazione 4020C7: F9 F3 F5 F1 3A 34

Ed ora diamo un'occhiata al primo check (quello relativo ai primi 4 chars del serial)

Indichero' con n_serial l'n-esimo char del seriale immesso quindi 1_serial si riferira' al 1°char del seriale 2_serial al secondo char ecc..

Prendendo in considerazione le manipolazioni che vengono effettuate sui char del seriale immesso concludiamo che per soddisfare il primo check si devono verificare le seguenti condizioni:

(1_Serial xor 81) xor 40 deve essere uguale a F9

Per le proprieta' dell'xor (vedi il tute di Quequero sullo xor per ulteriori approfondimenti) possiamo convertirlo nel seguente modo...

(1_Serial xor 81) xor 40  =  1_Serial xor (81 xor 40)  =  1_Serial xor (C1)  qiundi...

1_Serial xor C1 deve essere uguale a F9

2_Serial xor C1 deve essere uguale a F3

3_Serial xor C1 deve essere uguale a F5

4_Serial xor C1 deve essere uguale a F1

Sempre grazie alle proprieta' dell'xor deduciamo che...

1_Serial dovra' essere uguale a F9 xor C1   ->   1_Serial=38 "8"

2_Serial dovra' essere uguale a F3 xor C1   ->   2_Serial=32 "2"

3_Serial dovra' essere uguale a F5 xor C1   ->   3_Serial=34 "4"

4_Serial dovra' essere uguale a F1 xor C1   ->   4_Serial=30 "0"

Infatti se inseriamo questo come seriale "8240" riusciamo a passare il primo check con successo.

Adesso vediamo il secondo...

Vengono effettuate queste operazioni sul char in al...

((al xor 82) shl 02) shr 02

Che come ora vedremo possono essere ricondotte ad

(al xor 02) and 3F

Quando viene eseguito lo shift a sinistra di 2 bit, i 2 bit piu' significativi di al vengono persi quindi qualunque sia il loro valore e' ininfluente, da questo deriva che xor al,82  (82 = 10000010) puo' essere ridotto

ad xor al,2 ( 2 = 00000010) e l'operazione di shift e rotate in un And 3F (per azzerare i 2 bit piu' significativi

ricapitolando      *** ((al xor 82) shl 02) shr 02 ***

lo trasformiamo in *** (al xor 2) and 3F ***

Quindi per passare il 2° check dovranno essere verificate queste condizioni:

5_Serial dovra' essere uguale a (3A xor 2) and 3F  ->  5_Serial=38="8"

6_Serial dovra' essere uguale a (34 xor 2) and 3F  ->  6_Serial=36="6"

Infatti se inseriamo questo come seriale "824086" riusciamo a passare entrambi i check.

Ecco trovato il seriale per il mio nick.

NOTA:

Una conseguenza del fatto che i 2 bit significativi non vengono presi in considerazione diviene evidente perche' ad uno stesso nome vi possono essere abbinati piu' numeri di serie ad esempio prendendo il seriale "824086" e settando ad 1 il secondo bit piu' significativo dei numeri coinvolti nel 2° check si ottiene un nuovo seriale (8240xv) che e' anch'esso considerato come valido...

Poiche' i 2 bit significativi saranno scartati (riconducendo "8240xv" a "824086")

Mi rendo conto che queste manipolazioni sui bit possano sembrare un po' ostiche per i principianti, ma e' fondamentale sapersi "destreggiare" tra i vari xor shift ecc... per poter affrontare schemi di "crittografia" sempre piu' complessi.

Ora che abbiamo qualche elemento possiamo iniziare ad abbozzare quello che sara' il nostro keymaker...

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

char name[9]={"Int19"};

char cryptname[9]={0xF9, 0xF3, 0xF5, 0xF1, 0x3A, 0x34};

int c;

int namelength;

void main(void)

{

  randomize();

  namelength=strlen(name);

  printf("Third Lesson Pre-KeyMaker by Int19\n");

  c=0;

  for (c=0; c<4; c++)

    printf("%c", cryptname[c]^0xc1);

  for (c=4; c<namelength+1; c++)

  {

    if (random(2)==1) // per rendere la generazione degli ultimi chars del seriale semi-casuale

      printf("%c", (cryptname[c]^2)& 0x3f);

    else

      printf("%c", (cryptname[c]^2)& 0x3f | 0x40 );

  }

}

Questo programma si limita a stampare il numero di serie per il mio nick.

L'ultimo if.then.else e' "facoltativo", esso si limita a settare ad 1 il secondo bit piu' significativo, in modo da generare seriali diversi per lo stesso nome.

  4) Analizzare l'algoritmo di generazione del seriale

Quello che faremo in questa parte sara' scoprire il modo in cui vengono generati i bytes della locazione 4020C7 (quella che ho chiamato cryptname) in modo da cambiare i valori di cryptname a seconda del nome inserito, cosi' da realizzare un keymaker.

Iniziamo pure piazzando un "BPR 4020C7 4020C7+6 rw" pigiamo il bottone di registrazione e SoftICE poppa all'interno di questo ciclo

:00401277      mov dword ptr [0040210F], eax

:0040127C      xor ecx, ecx

* Referenced by a Jump at Address 004012A9

|

:0040127E      mov al, byte ptr [ecx+0040209B] <--- Carica il prossimo char del Nome

:00401284      mov edi, 0000000B                      <--- si prepara per la divisione

:00401289      cdq                                               <--- azzera edx (che conterra' il resto della divisione)

:0040128A      idiv edi                                         <--- esegue la divisione del char per 0B (edx contiene il resto)

:0040128C      add eax, edx                                <--- somma il resto della divisione al risultato

:0040128E      shl eax, 1

:00401290      mov dl, al

:00401292      call 0040160C                              <--- "Normalizza" il char contenuto in dl

        (routine analizzata sotto)

:00401297      xor eax, eax

:00401299      mov al, dl                                      <---| Manipola il char

:0040129B      xor al, 81                                            |

:0040129D      xor al, 40                                     <---|

:0040129F      mov byte ptr [ecx+004020C7], al <--- Il char manipolato viene salvato

       (ed e' qui' che poppa SoftICE)

:004012A5      inc ecx                                         <--- Incrementa la posizione corrente per

       convertire il prossimo char

:004012A6      cmp ecx, 00000004                    

:004012A9      jne 0040127E                              <--- salta se non sono ancora stati convertiti i primi 4 chars

:004012AB      nop

:004012AC      nop

… … … …

… … … …

… … … …

Ecco qui la routine di "normalizzazione" che prende un char tramite dl e fa in modo che all'uscita dalla routine il char in dl sia compreso tra "0" e "z"

:0040160C      cmp dl, 7A

:0040160F      jg 00401617        <--- salta se il char e' > "z"

:00401611      cmp dl, 30

:00401614      jl 00401621          <--- salta se il char e' < "0"

* Referenced by Jump at Addresses 0040161F, 00401629

|

:00401616      ret                        <--- all'uscita il char e' per forza compreso tra "0" e "z"

* Referenced by a Jump at Addresses 0040160F, 0040161D

|

:00401617      sub dl, 0A             <---|

:0040161A      cmp dl, 7A                  |

:0040161D      jg 00401617        <---| Sottrae 0A al char fino a che non e' <= di "z"

:0040161F      jmp 00401616

* Referenced by a Jump at Addresses 00401614, 00401627

|

:00401621      add dl, 0A            <---|

:00401624      cmp dl, 30                   |

:00401627      jl 00401621          <---| Somma 0A al char fino a che non e' >= di "0"

:00401629      jmp 00401616

Adesso che abbiamo analizzato il modo in cui vengono generati i primi 4 chars di cryptname andiamo a vedere come si comporta con i restanti dando uno sguardo al codice che si presenta poche linee dopo

:004012C0      mov ecx, 00000004

* Referenced by a Jump at Address 00401315

|

:004012C5      xor eax, eax

:004012C7      mov al, byte ptr [ecx+0040209B]            <--- carica un char dal nome (a partire dal 5°)

:004012CD      cmp ecx, dword ptr [0040210F]             <--- 40210F contiene lung_nome+1

:004012D3      je 0040131C                                           <--- Salta se sono gia' stati convertiti

        lung_nome+1 chars

:004012D5      mov edi,00000008           <--- si prepara per la divisione per 8

:004012DA      cdq                                 <--- azzera edx che conterra' il resto

:004012DB      idiv edi                            <--- divide il char per 8

:004012DD      add al, dl                         <--- somma il risultato della divisione ed il resto

:004012DF      shl al, 03                          <---| varie

:004012E2      ror al, 1                                   | manipolazioni

:004012E4      add al, 06                                | aritmetiche

:004012E6      shl al, 1                             <---| sul char

:004012E8      xor al, byte ptr [0040210F]                      <--- xor con lung_nome+1

                   (variando la lunghezza del nome

                                                                                               veriera' anche il nome crittografato)

:004012EE      mov edi,00000003           <---| una ulteriore

:004012F3      cdq                                         | divisione per 3

:004012F4      idiv edi                                    |

:004012F6      add al, dl                          <---|

:004012F8      mov dl, al

:004012FA      call 0040160C                 <--- "normalizza" il char contenuto in dl

:004012FF      mov al, dl

:00401301      xor al, 82                          <---|

:00401303      shl al, 02                                  |  manipolazioni finali del char

:00401306      ror al, 02                          <---|

:00401309      mov byte ptr [ecx+004020C7], al <--- salva il risultato

:0040130F      xor eax, eax

:00401311      inc ecx                              <--- incrementa la posizione corrente per analizzare il prossimo char

:00401312      cmp ecx, 00000008

:00401315      jne 004012C5                  <--- se non sono stati esaminati ancora 8 chars continua il ciclo

:00401317      nop

:00401318      nop

:00401319      nop

:0040131A      nop

:0040131B      nop

:0040131C    <---- arriveremo qui se sono stati convertiti 8 chars del nome oppure

                      se ne sono stati convertiti lung_nome+1 (se ne deduce che se il nome e'

                      piu' corto di 8 chars allora anche il char di fine stringa 0 verra' convertito)

  5) Scrivere un key-maker per il programma

Vorrei farvi notare la forte analogia che esiste tra le operazioni

aritmetiche che vengono effettuate dopo la chiamata alla funzione di normalizzazione

e le operazioni che troviamo nella routine di check del seriale....

Come potete vedere per quel che riguarda i primi 4 chars

vi sono queste operazioni in comune

   xor al, 81          <---| Ed abbiamo visto che possono essere

   xor al, 40          <---| unificate con "al xor C1"

Mentre per i restanti chars sono queste le operazioni in comune

   xor al, 82          <---| Che abbiamo

   shl al, 02                  | trasformato

   ror al, 02          <---| in "(al xor 2) and 0x3f"

In effetti il codice corretto lo otteniamo gia' al termine delle call alla routine di normalizzazione,

"scartando" i 2 bit piu' significativi, l'xor serve solo per "mascherare" ulteriormente il codice corretto,

quindi eliminando le operazioni inutili il nostro keygen possiamo scriverlo cosi'....

// Iniziamo con il tradurre la routine di normalizzazione....

void normalize(char *ch)              <--- Call dell'indirizzo 40160C

{

  while (*ch>'z') *ch = *ch - 0x0a;

  while (*ch<'0') *ch = *ch + 0x0a;

}

char name[10]={"Int19"};

char serial[10]={0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

int c;

int namelength;

char currchar;

div_t res;

void main(void)

{

  printf("Third Lesson KeyMaker by Int19\n");

  printf("Name: ");

  scanf("%s", name);

  namelength=strlen(name);

// Ora traduciamo la routine che crittografa i primi 4 chars del nome...

  for (c=0; c<4; c++)                               <--- Ciclo 40127E...4012A9

  {

    currchar=name[c];

    res=div(currchar, 0x0b);                      <--- 401284...

    currchar= res.quot + res.rem;               <--- ...40128C

    currchar= currchar << 1;                     <--- 40128E

    normalize(&currchar);                          <--- 401290...401297

    serial[c]=currchar;                               <--- 40129F

  }

// E adesso occupiamoci dei restanti

  c=4;

  while ((c<8) && (c<namelength+1))   <--- Ciclo 4012C5...401315

  {

    currchar=name[c];

    res=div(currchar, 0x08);                      <--- 4012D5...

    currchar= res.quot + res.rem;               <--- ...4012DD

    currchar= (currchar<<2) & 0x7c;        <--- 4012DF...4012E2            shl 3 ror 1 --> 0xxxxx00

    currchar= currchar+6;                          <--- 4012E4

    currchar= currchar<<1;                       <--- 4012E6

    currchar= currchar^(namelength+1);    <--- 4012E8

    res=div(currchar, 0x03);                      <--- 4012EE...

    currchar= res.quot + res.rem;               <--- ...4012F6

    normalize(&currchar);                          <--- 4012F8...4012FF

    if (random(2)==1)      // Rende la generazione degli ultimi chars del seriale semi-casuale

      currchar=(currchar & 0x3f);               <--- 401301...401306

    else

      currchar=(currchar & 0x3f) | 0x40;

    serial[c]=currchar;                               <--- 401309

    c++;

  }

  // Ora stampiamo il serial

  printf("S/N:  %s\n", serial);

}

Di cosa trattera’ il quarto corso ? mah!

Note finali

Leggiti tutti i saluti del mio ultimo tute (mqmc4) ed aggiungi questi… George Lucas: Per le grandi sage che e’ riuscito a sfornare, da Indy a Monkey a StarWars. Dagolith perche’ e’ un buon-uomo. +Xoanon perche’ anche se non lo sa, e’ grazie a lui che mi sono avvicinato al mondo del cracking o meglio, grazie alla sua guida per aspiranti crackers, tnx Xoa.                                                                                                                                                     C’entra un caxxo col cracking ma … un grande fanculo al gruppo Twilight CD poiche’ non sprecano uno straccio di righe per ringraziare i gruppi (leggasi pdm rzr ogn ecc..) grazie ai quali hanno potuto guadagnare un bel po’ di soldoni, byez Il.Socio.

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.

Capitoooooooo????? Bhè credo di si ;)))) 


UIC's page of reverse engineering, scegli dove andare:

Home   Anonimato   Assembly    ContactMe  CrackMe   Links   
NewBies   News   Forum   Lezioni  
Tools   Tutorial 

UIC