Corso UIC Avanzato 02 Int19
From UIC
UIC Lezione 02 (Creare un KeyMaker)
Contents |
| Infos | |
|---|---|
| Author: | Int19 |
| Email: | Int19@hotmail.com, UIN: 4044843 |
| Website: | None |
| Date: | 08/09/1999 (dd/mm/yyyy) |
| Level: |
|
| Language: | Italian |
| 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
- Beh, se state leggendo questo credo che tutti lo conosciate ormai: Template:SERVERÞ
- Questo è la soluzione del Corso UIC Avanzato n°02 disponibile alla pagina Corso UIC Avanzato 02
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
: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
|: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.
|
: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.
|: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'
|: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:
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)
: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 malevoli 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.