Zoom Icon

Corso UIC Avanzato 02 Int19

From UIC Archive

UIC Lezione 02 (Creare un KeyMaker)

Contents


Corso UIC Avanzato 02 Int19
Author: Int19
Email: [email protected], UIN: 4044843
Website: None
Date: 08/09/1999 (dd/mm/yyyy)
Level: Working brain required
Language: Italian Flag Italian.gif
Comments: Que: Ottimo questa soluzione la ritengo il migliore, leggetelo perché è veramente chiaro ed esauriente




By Int19 aka Il.Socio: Scaricate qua l'allegato
Cercheremo di creare un KeyMaker per l'esercizio proposto.


Introduction

Ciao a tutti, questo è il mio primo tute, quindi non siate troppo spietati nel giudicarlo, io cercherò di farmi capire il più possibile, se vi restano dei dubbi siete liberi di contattarmi.


Tools

Il classico e indispensabile SoftICE 4.0, W32Dasm 8.93, e il Borland TurboC per il KeyMaker.


Link e Riferimenti


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 compare un messagebox che riporta l'errore.


Essay

Eccoci qui….

Dunque, tanto per iniziare piazzo gli usuali breakpoint "BPX GetDlgItemTextA" e "BPX GetWindowTextA", inserisco un nome (Int19) e un serial (12345) pigio il bottone e Bang! ecco la finestrella di SoftICE che poppa sullo schermo. Pigiando "F12" mi ritrovo al punto dal quale è stata chiamata la GetWindowTextA, dando un'occhiata agli argomenti passati alla funzione scopro l'indirizzo dove è stato memorizzato il nome che ho inserito più precisamente alla locazione 40219F


:004011F2   push 00000019              
:004011F4   push 0040219F     Buffer dove viene salvato il nome
:004011F9   push dword ptr [004020D7]
* Reference To: USER32.GetWindowTextA, Ord:0000h
|
:004011FF   Call 004013B3
:00401204   xor ecx, ecx
:00401206   mov al, byte ptr [0040219F]         Preleva il primo char del nome
:0040120B   test al, al
:0040120D   je 00401371       Salta se il testo è vuoto
:00401213   xor eax, eax

ED ORA VIENE IL BELLO, ANALIZZIAMO LA ROUTINE DI CRITTOGRAFIA DEL NOME

* Jump at Address:
|:00401277
|
:00401215   mov al, byte ptr [ecx+0040219F]    Preleva il prossimo char del nome
:0040121B   test eax, eax
:0040121D   je 00401279     Salta se siamo giunti alla fine del nome ed esce dal ciclo di 

crittografia

:0040121F   xor al, cl       xor tra il char e la sua posizione all'interno del nome…  Nel mio 

caso sarà "I" xor 0 al 1° passaggio poi "n" xor 1 al 2° passaggio ecc..

:00401221   mov edi, ecx     ora edi contiene la posizione del char corrente                  
:00401223   mul edi          il char viene moltiplicato per la posizione
:00401225   sub al, 25       ora il char viene decrementato di 25h
:00401227   add al, cl       e sommato con la sua posizione
:00401229   xor al, byte ptr [ecx+00402000]    xor tra il char e dei valori costanti

La locazione 402000 contiene i seguenti valori: 12 45 D1 FF quindi verrà effettuato l'xor con 12 al 1° passaggio con 45 al 2° passaggio ecc.. Come vedremo alla fine del tute sono rilevanti solo i primi 4 bytes del nome quindi prendiamo in considerazione solo 4 bytes della locazione 402000. A questo punto vengono effettuati una serie di operazioni matematiche che coinvolgono Il registro ebx, la cosa importante da notare è che il valore finale di ebx NON viene in alcun modo salvato in memoria, NÈ modifica il valore di al (il nostro char) Inoltre il contenuto di ebx viene SOVRASCRITTO ad ogni ciclo dall'istruzione alla linea 401234, quindi è molto probabile che tutte le operazioni che vengono effettuate su di esso siano li solo per confonderci, se così non fosse ebx assumerebbe un valore significativo che dipenderebbe solo dal valore dell'ultimo char (a causa della linea 401234) Le istruzioni che ho marcato con *** sono molto probabilmente delle istruzioni inutili, utilizzate per confondere un po' le idee e confesso che per quel che mi riguarda inizialmente ci è riuscito benissimo, ho iniziato ad avere dei sospetti quando ho incontrato l'istruzione 40125A:rol bl,08 che lascia praticamente invariato il registro.

* Possible StringData Ref from Data Obj ->"77103798325"
|
:0040122F   mov edx, 00402193                   ***
:00401234   mov ebx, dword ptr [0040219F]       ***
:0040123A   xor ebx, edx                        ***
* Possible StringData Ref from Data Obj ->"34065479327"
|
:0040123C   mov edx, 00402183                   ***
:00401241   xor ebx, edx                        ***
:00401243   add ebx, ecx                        ***
:00401245   add al, byte ptr [ecx+00402000]    Viene sommato un valore (12 45 D1)
:0040124B   xor bl, byte ptr [ecx+00402000]     ***
:00401251   shl al, 02        shift a sinistra di 2 bit
:00401254   ror al, 04        rotazione a destra di 4 bit
:00401257   shr bl, 03                          ***
:0040125A   rol bl, 08                          ***
:0040125D   xor bl, al                          ***
:0040125F   xor bl, byte ptr [00402002]         ***
:00401265   xor bl, cl                          ***
:00401267   rol bl, 08                          ***
:0040126A   add bl, al                          ***
:0040126C   sub al, 05        decrementa il char di 5
:0040126E   sub bl, al                          ***
:00401270   mov byte ptr [ecx+0040218F], al    salva il risultato a partire 

dalla locazione 40218F

:00401276   inc ecx           incrementa la posizione corrente per poter esaminare il 

prossimo char

:00401277   jmp 00401215

Ora la crittografia del nome è stata compiuta ed il risultato salvato nella locazione 40218F, adesso viene eseguita un'ulteriore conversione.


* Jump at Address:
|:0040121D
|
:00401279   xor ecx, ecx 
* Jump at Address:
|:004012A0
|
:0040127B    mov al, byte ptr [ecx+0040218F]  Carica in al un char dal nome crittografato
:00401281    test al, al
:00401283    je 00401331     Salta se siamo alla fine del nome crittografato ed esce 

dal ciclo di conversione

:00401289    cmp al, 66       
:0040128B    jg 0040131B     Salta se il char è > di 66 ‘f'
* Jump at Address:
|:00401321
|
:00401291    cmp al, 30      Salta se il char è < di 30 ‘0'
:00401293    jl 00401326

A questo punto il nostro char crittografato sarà compreso tra il set di caratteri che vanno Da ‘0' a ‘f'

* Jump at Address:
|:0040132C
|
:00401299    inc ecx         incrementa la posizione per passare al prossimo char
:0040129A    mov byte ptr [ecx+004021A7], al   salva il risultato a partire 

dalla locazione 004021A8

:004012A0    jmp 0040127B    continua la conversione
* Jump at Addresses:
|:0040128B, :0040131F
|
:0040131B    sub al, 12      decrementa il char di 12
:0040131D    cmp al, 66      finche' non è <= di 66  "f"
:0040131F    jg 0040131B          
:00401321    jmp 00401291
* Jump at Addresses:
|:00401293, :0040132A
|
:00401326    add al, 18      incrementa il char di 18
:00401328    cmp al, 30      finche' non è >= di 30  "0"
:0040132A    jl 00401326
:0040132C    jmp 00401299

Nella locazione 4021A8 ora c'è il nostro numero di serie tanto cercato (Int19/97EY) infatti se lo utilizziamo ci compare il tanto amato messaggino di successo.

E ADESSO CREIAMO IL NOSTRO KEYMAKER. Dunque, Eliminando le istruzioni inutili che operavano sul registro ebx (quelle marcate con gli asterischi) rimane ben poco codice, ed è possibile tradurlo in C in questo modo:

#include <stdio.h> void ror4(char *num) Esegue la rotazione di 4 bits verso destra {

 char tmp=(*num & 0x0F);
 tmp=tmp << 4;
 *num=(*num >> 4) & 0x0F;
 *num=*num | tmp;

}

int c; const loc402000[4]={0x12, 0x45, 0xD1, 0xFF}; char serial[6]={" "}; char name[6]={" "};

void main(void) {

 printf("Second Lesson KeyMaker by Int19\n");
 printf("Name : ");
 scanf("%s",name);
 c=0;
 while ((name[c]!='\0') && (c<4)) {        40121D
   serial[c]=((name[c] ^ c)*c - 0x25 + c);  da 40121F a 401227
   serial[c]= (serial[c] ^ loc402000[c]) + loc402000[c];  istruzioni 401229 e 401245
   serial[c]= serial[c] << 2;               401251
   ror4(&serial[c]);                        401254
   serial[c]=serial[c] - 5;                 40126C
   c++;
 };
 c=0;                         
 while ((name[c]!='\0') && (c<4)) {         401283
   while (serial[c]>0x66)  serial[c] = serial[c] - 0x12;  da 40131B a 401321
   while (serial[c]<0x30)  serial[c] = serial[c] - 0x18;  da 401326 a 40132C
   c++;
 };
 printf("S/N  : %s\n", serial);

}


Il confronto tra il seriale immesso e quello calcolato in base al nome viene effettuato immediatamente dopo la seconda chiamata alla GetWindowTextA (legge il seriale immesso)

:004012C8   push 00000019
:004012CA   push 004021A3
:004012CF   push dword ptr [004020DB]
* Reference To: USER32.GetWindowTextA, Ord:0000h
|
:004012D5   Call 004013B3
:004012DA   xor ecx, ecx
:004012DC   mov eax, dword ptr [ecx+004021A3]   Seriale immesso
:004012E2   mov ebx, dword ptr [ecx+004021A8]   Seriale calcolato
:004012E8   inc ecx
:004012E9   cmp eax, ebx     Confronta i 2 seriali
:004012EB   jne 004012A2     Serial errato
:004012ED   mov al, byte ptr [ecx+004021A3]
:004012F3   mov bl, byte ptr [ecx+004021A8]
:004012F9   test al, al      Serve solo a confondere le idee
:004012FB   je 00401303     
:004012FD   cmp al, bl       È un compare ridondante perché confronta il 2° char
                                 dei due seriali, ma l'intruzione 4012E9 ha già effettuato
                                 il confronto dei primi 4 chars e se siamo qui significa che i
                                 primi 4 chars sono uguali.
:004012FF   jne 004012A2     Serial errato (non eseguirà mai questo salto)
:00401301   jmp 00401303     Serial corretto

Come potete notare il confronto tra i due seriali avviene facendo un compare dei primi quattro caratteri, alla linea 4012E9 tutto il codice che viene dopo la linea 4012EB e' inutile perché in ogni caso si eseguirà un jump alla locazione 401303


Note Finali

Un saluto a tutti i compagni di classe, è da un pezzo che non faccio un salto in IRC, magari un giorno di questi rispolvero l'mirc e ci si incontra sul canale. Ed ora qualche ringraziamento a… Phobos, Catlike, Mojo, Mark, Machine Head, Kermit, Dyntro, Horse, Grave, Joe, Pab Gamer, Emesis, Sherlox, Andy, Quake, Stood, Ozone, Plucky. PDM, OGN, RZR, DOD, PWA, PC, UCF… nonché tutti quelli che hanno pubblicato tutorial riguardanti cracking/hacking, se non fosse per loro non sarei mai stato in grado di svolgere questo lavoro, un ringraziamento in particolare a tutti coloro che hanno reso possibile l'UIC, byez Il.Socio.


Disclaimer

I documenti qui pubblicati sono da considerarsi pubblici e liberamente distribuibili, a patto che se ne citi la fonte di provenienza. Tutti i documenti presenti su queste pagine sono stati scritti esclusivamente a scopo di ricerca, nessuna di queste analisi è stata fatta per fini commerciali, o dietro alcun tipo di compenso. I documenti pubblicati presentano delle analisi puramente teoriche della struttura di un programma, in nessun caso il software è stato realmente disassemblato o modificato; ogni corrispondenza presente tra i documenti pubblicati e le istruzioni del software oggetto dell'analisi, è da ritenersi puramente casuale. Tutti i documenti vengono inviati in forma anonima ed automaticamente pubblicati, i diritti di tali opere appartengono esclusivamente al firmatario del documento (se presente), in nessun caso il gestore di questo sito, o del server su cui risiede, può essere ritenuto responsabile dei contenuti qui presenti, oltretutto il gestore del sito non è in grado di risalire all'identità del mittente dei documenti. Tutti i documenti ed i file di questo sito non presentano alcun tipo di garanzia, pertanto ne è sconsigliata a tutti la lettura o l'esecuzione, lo staff non si assume alcuna responsabilità per quanto riguarda l'uso improprio di tali documenti e/o file, è doveroso aggiungere che ogni riferimento a fatti cose o persone è da considerarsi PURAMENTE casuale. Tutti coloro che potrebbero ritenersi moralmente offesi dai contenuti di queste pagine, sono tenuti ad uscire immediatamente da questo sito.

Vogliamo inoltre ricordare che il Reverse Engineering è uno strumento tecnologico di grande potenza ed importanza, senza di esso non sarebbe possibile creare antivirus, scoprire funzioni malevole e non dichiarate all'interno di un programma di pubblico utilizzo. Non sarebbe possibile scoprire, in assenza di un sistema sicuro per il controllo dell'integrità, se il "tal" programma è realmente quello che l'utente ha scelto di installare ed eseguire, né sarebbe possibile continuare lo sviluppo di quei programmi (o l'utilizzo di quelle periferiche) ritenuti obsoleti e non più supportati dalle fonti ufficiali.