Capire un generatore di chiave: primo approccio
Salve a tutti, eccomi di nuovo all'opera per spiegare le basi di un generatore di chiavi. Iniziamo dal principio: Che vuol dire generatore di chiavi? Immaginiamo di avere tra le mani un bel programma che richiede l'immissione di 2 campi: un nome e un codice. Molto presumibilmente questi 2 valori saranno legati tra di loro, ovvero il programmatore avrà pensato:"perchè non usiamo i valori esadecimali delle lettere che compongono il nome e li utilizziamo come cifre da usare in qualche funzione che calcola il codice seriale?!?!?!". Le domande da porsi è: come fa la funzione a generare il codice seriale, ovvero quali sono le operazioni che vengono effettuate dalla funzione con i valori di partenza che sono dati dal nome che noi abbiamo immesso? Quando riuscirete a rispondere a questa domanda sarete pronti a creare il vostro generatore di chiavi.
Per introdurvi su questo argomento ho preso come esempio un programmino DLLSHOW ( a dir la verità in questo caso non si può parlare di una vera funzione che calcola il codice partendo dal nome inserito, in quanto i due campi sono separati tra loro, cioè il programma è vero che richiede 3 codici, 2 nomi e un codice numerico, ma fa un controllo solo sul primo nome tralasciando i valori che sono stati inseriti negli altri campi; ciò che a me interessa è comunque farvi capire come viene generato un numero da un nome attraverso qualche funzione). Ok siamo pronti per partire: avete caricato Softice, avete lanciato DllShow, benissimo ora andate nel menù HELP|REGISTER, scrivete il vostro nome (io userò Furb3T), la vostra Organizzazione e il codice numerico... VI RICORDO che in questo caso non hanno importanza cosa mettete nel campo dell'Organizzazione e del codice numerico, ciò che conta è cosa inserite nel campo del nome... e CONTATE soprattutto quanto è lungo il nome che avete inserito (il mio è 6 come potete vedere). Prima di premere OK, entrate in Softice con il classico Ctrl-D, scrivete BPX HMEMCPY, e poi con F5 ritornate su DLLSHOW. Ora premete il bottone dell'OK e.......VOILA' eccovi dentro Softice. Premete F12 fino a quando non entrerete con lo stack su DLLSHOW (basterà guardare la finestra di softice). Ok ci siete arrivati, qualcuno di voi però si domanderà :"Come faccio a sapere che sono nel punto giusto?". Facile, vi ricordate che vi ho detto di contare di quante lettere è formato il nome che avete inserito, ebbene se siete dentro DllShow e il registro EAX=00000006 ( 6 perchè è la lunghezza del mio nome) allora vuol dire che siete "atterrati" nel punto giusto ( RICORDATEVELO!!!!). Bene adessiamo facciamo un bel TRACE con F10 ( trace vuol dire tracciare, cioè scorrere il programma istruzione dopo istruzione seguendo ciò che le istruzioni prevedono) fino ad arrivare qui:
:0040F2CE 6A67 push 00000067
:0040F2D0 57 push edi
:0040F2D1 FFD5 call ebp
:0040F2D3 8D442410 lea eax, dword ptr [esp+10]
:0040F2D7 50 push eax
:0040F2D8 E8F3840000 call 004177D0
:0040F2DD 83C404 add esp, 00000004
:0040F2E0 8BE8 mov ebp, eax
:0040F2E2 56 push esi ------> provate a fare qui d esi comparirà
:0040F2E3 E808720000 call 004164F0 il vostro nome
:0040F2E8 83C404 add esp, 00000004
:0040F2EB 3D92A71901 cmp eax, 0119A792
:0040F2F0 7518 jne 0040F30A
Analizziamo quello che succede a 0040F2E2; viene salvato un valore che è il nostro nome e subito dopo c'è una CALL, la cosa vi dovrebbe puzzare!!!! Andiamo a spulciare dentro la call utilizzando il tasto F8 quando stiamo sull'istruzione 0040F2E3 ( F8 serve per fare un trace entrando però nelle call a differenza di F10 che non vi entra):
:004164F0 53 push ebx
:004164F1 56 push esi
:004164F2 8B74240C mov esi, dword ptr [esp+0C]
:004164F6 57 push edi
:004164F7 55 push ebp
:004164F8 33FF xor edi, edi
:004164FA 56 push esi ----------> viene salvato il ns nome
* Reference To: KERNEL32.lstrlenA, Ord:029Ch -----> calcola la lunghezza
| del nome e mette il
:004164FB FF15AC454300 Call dword ptr [004345AC] risultato in EAX
:00416501 85F6 test esi, esi | verifica che sia il nome che la
:00416503 7432 je 00416537 | lunghezza non sia un campo nullo
:00416505 85C0 test eax, eax |
:00416507 742E je 00416537 |
:00416509 B900000000 mov ecx, 00000000 -------> azzera il contatore ECX
:0041650E 7E27 jle 00416537 per iniziare il loop
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00416535(C)
|
:00416510 0FBE9C0828604200 movsx ebx, byte ptr [eax+ecx+00426028]
:00416518 0FBE2C0E movsx ebp, byte ptr [esi+ecx]
:0041651C 8D5101 lea edx, dword ptr [ecx+01]
:0041651F 0FAFDD imul ebx, ebp
:00416522 0FBE8960604200 movsx ecx, byte ptr [ecx+00426060]
:00416529 0FAFD9 imul ebx, ecx
:0041652C 0FAFDA imul ebx, edx
:0041652F 03FB add edi, ebx
:00416531 8BCA mov ecx, edx
:00416533 3BC2 cmp eax, edx
:00416535 7FD9 jg 00416510
Il codice che ci interessa analizzare e che genera un numero è da 00416510 a 00416535. Vediamo insieme che fa:
movsx ebx, byte ptr [eax+ecx+00426028], muove il byte che si trova in EAX+ECX+00426028 in EBX. Ricordate che in EAX si trova la lunghezza del vostro nome, mentre ECX è il contatore, 00426028 invece è una locazione fissa di DLLSHOW dove prende i numeri esadecimali:
movsx ebp, byte ptr [esi+ecx], muove il byte di ESI+ECX in EBP. In ESI c'è registrato il vostro nome, quindi in EBP ci sarà ogni volta del loop una lettera del vostro nome:
lea edx, dword ptr [ecx+01], carica in EDX il valore di ECX+1, quindi incrementa il contatore:
imul ebx, ebp, moltiplica i valori di EBP * EBX, ponendo il risultato in EBX:
imul ebx, edx, moltiplica EBX*EDX e mette il risultato in EBX:
add edi, ebx, aggiunge EDI a EBX e mette il tutto in EDI:
mov ecx, edx, riporta il contatore su ECX:
cmp eax, edx, confronta la lunghezza del nome con il contatore per vedere se ripetere il loop o uscirne.
Penso che avrete capito in che modo dal vostro nome viene generato un numero. Alla fine del loop la call ritornerà in EAX il valore che si trova in EDI, ossia il valore che è stato calcolato dal loop. Se osservate l'istruzione 0040F2EB CMP EAX,0119A792, voi sapete che in EAX c'è il codice generato dal vostro nome (nel mio caso è 00EA6634), allora cosa è 0119A792....non è altro che il codice che da l'accesso alla registrazione del programma. Basta cambiare il JNE in JE e sarete registrati, REGGETEVI FORTI, come gli autori del programma!!!!! Bè bisogna fare un applauso al programmatore di DLLSHOW per questa protezione sciocca.
Spero che adesso le cose siano più chiare su come viene generato un numero da un nome, pensate però che questa è solo uno dei molti algoritmi che ci possono essere, l'importante è non disperare e se vi accorgete che la funzione è troppo complicata...USATE LA FORZA BRUTA!!!!
Ringraziamenti : A tutto il gruppo di RingZer0, ed in particolare a |Scacco| per avermi indicato questo programma.