Universe 1.61 |
|
|
30/04/2000 |
by "AndreaGeddon" |
|
|
Published by Quequero |
|
Qualche mio eventuale commento sul tutorial :))) Allora io qui non ci devo scrivere, giusto??? :-P Esatto! :))))) Bravo Andrea che continua a cimentarsi in programmi con routine pallosissime :)...Bravo, fa bene al cervello, ma questo form NON � degno di nota, insisto nel dire che il Notepad (oppure QuePad? :) ed il courier new per il codice sarebbero un'ottima accoppiata :))) |
||
UIC's form |
|
UIC's form |
Difficolt� |
( )NewBies (x)Intermedio ( )Avanzato ( )Master |
Vediamo come si trova il seriale di Universe 1.61, poi cerchiamo di capire come vegono generati i seriali.
Introduzione |
Fiiiico! Un programmillo per disegnare sfondi stellati con tanto di galassie, nebulose, nane bianche e chi pi� ne ha pi� ne metta. Peccato che alcuni pulsanti di disegno siano disattivati nella demo.... attiviamoli! Una volta tanto so a che cosa serve il prog che voglio reversare :-)
Tools usati |
- SoftIce
URL o FTP del programma |
http://www.diardsoftware.com
Notizie sul programma |
Nome e serial number.
Essay |
PARTE PRIMA: L' OSSERVAZIONE
Questa secondo me � la parte pi� importante di tutte, infatti vi permette di partire con informazioni preziose e vi fa risparmiare parecchio tempo. Ricordatevi, quindi, di cercare di scoprire pi� cose possibili invece di buttarvi subito sul SoftIce. Okay, iniziamo.
Andiamo su Help->Register, voil�, il dialog con Nome e Key. Prima osservazione: notate che nel campo del serial � gi� presente uno 0. Bene, questo ci fa pensare che il serial debba essere un numero. Un qualsiasi numero? Vediamo... Proviamo ad inserire un numero compreso di lettere, tipo: 114455AABB. Che succede? Oltre che a dire che il serial � sbagliato, dice anche che il numero deve essere un intero! Grazie! Quindi probabilmente il meccanismo di calcolo non deve essere molto complesso, si baser� sui numeri gestibili da un registro, cio� da 0 a 2^32. Bene, per adesso abbiamo parecchie informazioni. Quindi procediamo con il softice.
PARTE SECONDA: L'ATTACCO
Okay, adesso partiamo col Sice. Inserisco il mio nome (AndreaGeddon) ed un intero, cio� 123456789, e tanto per comodit� segnamoci il corrispondente hexa, cio�: 75BCD15. Ricordatelo. Adesso settiamo un breakpoint su GetWindowTextA. Premete invio e ...pop... ecco il sice; premete ctrl-d cos� ripopperete sulla seconda chiamata a getwindowtexta. Ora possiamo iniziare lo stepping. La prima cosa che facciamo e steppare conn F10 per cercare la call che ci spara il messagebox di errore. Dove la troviamo? Alla riga:
0040AE15 CALL 00464957
Quindi dobbiamo trovare unn jump che ci permetta di evitare questa parte di codice. Se risteppate daccapo trovere che alla riga:
0040ADD2 JZ 0040AE0C
il jump ci spara alla call di errore. Se provate ad invertire il jump il prog non mostrer� il messagebox di errore, ma rimarrete non registrati. Va bene. Diamo uno sguardo pi� attento all'intorno del JZ:
0040ADC6 CALL 004167EB | che succede qui dentro?
MOV [ebp-04|, eax | praticamente controlla se il valore restituito dalla call
CMP dword ptr [ebp-04|, 00 | in eax � 0
0040ADD2 JZ 0040AE0C | se lo �, salta al messaggio di errore
� chiaro che la call decide se il prog deve andare al messaggio di errore oppure no. Quindi � proprio nella call che andremo a cercare. Risteppiamo fino alla call, ed entriamoci con F8. Qui ci aspetteremo quindi di trovare la routine di controllo del seriale. Sappiamo che il valore di controllo sar� restituito in eax, quindi andremo a cercare qualche istruzione XOR o SETZ dopo unn call, probabilmente verso la fine della routine. Infatti andiamo alla linea:
00416938 CALL 00428D20 strana call... restituisce in eax un numero strano
XOR ecx, ecx azzeriamo ecx
CMP [ebp-38|, eax in ebp-38 c'� il numero che abbiamo messo, ma in hexa (quindi eax sar� il giusto serial?)
SETZ cl se sono uguali setta il flag cl
MOV eax, ecx metti ecx in eax, che verr� usato come flag di controllo fuori dalla call
....
RET
okay. Dopo la call in EAX ci troveremo uno strano numero. Poi viene azzerato ecx. Viene effettuato il compare di una locazione di memoria con eax. Se andiamo a vedere la locazione di memoria (ebp-38) ci troveremo un valore in hexa, una dword, che connvertita in decimale ci dar� il numero che avevamo inserito. Bene. Allora anche eax sar� il corrispondente decimale del giusto seriale? Proviamo... Io in eax ci ho trovato il valore 2F9C56D4 che in decimale sarebbe 798774996, che infatti � il serial valido per il nome AndreaGeddon. Ecco come trovare il seriale. Adesso vogliamo vedere come viene generato.
PARTE TERZA: CAPIAMO L'ALGORITMO
Se entriamo nella call precedentemente citata, troveremo dei calcoli effettuati con dei valori di cui non sappiamo la provenienza, per cui dobbiamo rivedere l'intera routine dalla riga 004167EB. Iniziamo a vedere quali sono i punti importanti.
:004167EB push ebp
... sniip 8< qui inizia il primo ciclo... :00416874 mov edx, dword ptr [ebp-18]:00416877 add edx, 00000001
:0041687A mov dword ptr [ebp-18], edx
:0041687D mov ecx, dword ptr [ebp+08] mette in ecx il puntatore al nome
:00416880 call 00403530 ottiene la lunghezza del nome (in eax)
:00416885 cmp dword ptr [ebp-18], eax la confronta con il valore inn ebp-18, che � il contatore
:00416888 jge 004168D9 salta se abbiamo finito il ciclo
:0041688A mov eax, dword ptr [ebp-18]
:0041688D push eax
:0041688E mov ecx, dword ptr [ebp+08] di nuovo inn ecx il puntatore al nome
:00416891 call 00416C70 ottiene l' n-esimo char in al
:00416896 movsx ecx, al mette al in ecx
:00416899 mov dword ptr [ebp-20], ecx salva il char attuale in ebp-20
:0041689C mov edx, dword ptr [ebp-10] mette in edx le somme delle eguenti moltiplicazioni
:0041689F add edx, dword ptr [ebp-20] gli aggiunge il char corrente
:004168A2 mov dword ptr [ebp-10], edx aggiorna la variabile con la nuova somma
:004168A5 mov eax, dword ptr [ebp-18] mette in eax il contatore
:004168A8 cdq azzera edx
:004168A9 xor eax, edx alcuni calcoli...
:004168AB sub eax, edx ... che portano...
:004168AD and eax, 00000001 ... a decidere...
:004168B0 xor eax, edx ...se per la moltiplicazione....
:004168B2 sub eax, edx ... useremo il fattore...
:004168B4 test eax, eax
:004168B6 je 004168C1
:004168B8 mov [ebp-1C], FFFFFFFF ... FFFFFFFF...
:004168BF jmp 004168C8 ...oppure...
:004168C1 mov [ebp-1C], 00000001 ... 00000001.
:004168C8 mov eax, dword ptr [ebp-1C] prende in eax il fattore (00000001 oppure FFFFFFFF)
:004168CB imul eax, dword ptr [ebp-20] lo moltiplica per il char corrente
:004168CF mov ecx, dword ptr [ebp-10] mette in ecx il valore dei precedenti risultati
:004168D2 add ecx, eax gli aggiunge il fattore precedentemente usato
:004168D4 mov dword ptr [ebp-10], ecx salva il nuovo valore
:004168D7 jmp 00416874 loop per tutti i char del nome
... e qui finisce. Alla fine in ebp-18 avremo il totale di tutto questo calcolo. Nel mio caso sar� il numero 448.
:004168D9 mov edx, dword ptr [ebp-10] mette in edx il totale
:004168DC mov dword ptr [ebp-14], edx lo salva nella locazione ebp-14
:004168DF mov eax, dword ptr [ebp-10] mette anche in eax il totale
:004168E2 imul eax, dword ptr [ebp-10] | ebp-10 = (totale)^2
:004168E6 mov dword ptr [ebp-10], eax | adesso ebp-10 contiene il totale^2
:004168E9 mov ecx, dword ptr [ebp-10] metti in ecx totale^2
:004168EC add ecx, dword ptr [ebp-14] ecx = totale^2+totale
:004168EF mov dword ptr [ebp-10], ecx salva il tutto in ebp-10
:004168F2 mov edx, dword ptr [ebp-10] prepara il totale^2+totale
:004168F5 push edx per la call che segue
:004168F6 call 00428D00 copia il valore totale^2+totale in eax e nella locazione 004906F8
:004168FB add esp, 00000004
:004168FE mov [ebp-18], 00000000
:00416905 jmp 00416910
secondo piccolo ciclo...
:00416907 mov eax, dword ptr [ebp-18] mette in eax il contatore
:0041690A add eax, 00000001 lo incrementa
:0041690D mov dword ptr [ebp-18], eax lo salva
:00416910 mov ecx, dword ptr [ebp-2C] mette in ecx il puntatore al numero di iterazioni
:00416913 mov edx, dword ptr [ebp-18] mette in edx il contatore
:00416916 cmp edx, dword ptr [ecx] controlla quante volte abbiamo eseguito il ciclo
:00416918 jge 00416921 se il contatore � uguale al valore puntato da ecx, abbiamo finito
:0041691A call 00428D20 vedi SUB-CALL pi� sotto
:0041691F jmp 00416907 loop
... che dura fin qui
:00416921 cmp dword ptr [ebp+0C], 00000000 ebp+0c = nostro serial, lo confronta con 0
:00416925 jle 0041692F salta se � 0 (ma noi mica abbiamo messo 0!)
:00416927 mov eax, dword ptr [ebp+0C] metti il serial in eax
:0041692A mov dword ptr [ebp-38], eax e poi mettilo in ebp-38
:0041692D jmp 00416938 e salta alla call!
:0041692F mov ecx, dword ptr [ebp-2C]
:00416932 mov edx, dword ptr [ecx+10]
:00416935 mov dword ptr [ebp-38], edx
:00416938 call 00428D20 di nuovo: vedi SUB-CALL pi� sotto
finalmente alla fine!
:0041693D xor ecx, ecx azzera ecx
:0041693F cmp dword ptr [ebp-38], eax confronta il giusto serial (eax) con il nostro (ebp-38)
:00416942 sete cl se sono uguali setta il flag cl
:00416945 mov eax, ecx metti il flag cl in eax
:00416947 mov ecx, dword ptr [ebp-0C]
:0041694A mov dword ptr fs:[00000000], ecx
:00416951 mov esp, ebp
:00416953 pop ebp
:00416954 ret 0008 torna indietro!
SUB-CALL per comodit� ho esploso direttamente qui le due ulteriori sub-call, che trovate spostate pi� a destra :-)
:00428D20 mov eax, dword ptr [004906F8]
che � sto valore? � totale^2+totale, rivedete la riga 004168F6!:00428D25 push 78B30C40
salva il valore 78B30C40 (!):00428D2A cdq
azzera edx:00428D2B push 00000000
pusha 0:00428D2D push 25A2A40D
salva il valore 25A2A40D (!):00428D32 push edx
pusha edx (zero):00428D33 push eax
pusha eax (totale^2+totale):00428D34 call 00440590
:00428D39 add eax, 00000001 aggiungi 1 al risultato "parte bassa"
:00428D3C adc edx, 00000000 aggiungi con riporto 0 al risultato "parte alta"
:00428D3F push edx pusha la parte alta
:00428D40 push eax pusha la parte bassa
:00428D41 call 00428DA0
:00428DA0 push ebp |
:00428DA1 mov ebp, esp | crea nuovo stack
:00428DA3 push ebx ebx = contatore
:00428DA4 mov eax, dword ptr [ebp+08] metti in eax il valore che gi� ha
:00428DA7 mov edx, dword ptr [ebp+0C] metti in ecx il valore che gi� ha
:00428DAA mov ebx, dword ptr [ebp+10] richiama in ebx 78B30C40, valore pushato alla riga 428D25
:00428DAD div ebx dividi eax (parte bassa) per 78B30C40
:00428DAF mov eax, edx copia il resto di questa divisione in eax
:00428DB1 pop ebx
:00428DB2 pop ebp
:00428DB3 ret
:00428D46 add esp, 0000000C
:00428D49 mov dword ptr [004906F8], eax metti il resto salvato poco fa nella locazione 004906F8
:00428D4E ret attenzione perch� al prossimo ciclo la locazione 004906F8
non contiene pi� il valore totale^2+totale ma il nuovo valore!
Fiuu! Che faticaccia commentare questa luuuuunghissima routine. Ho ricontrollato pi� volte, ma potrebbe esserci scappato qualche errore, ma comunque in generale adesso la routine che crea il seriale giusto dovrebbe essere chiara. Di scriverci un keymaker non se ne parla, non ho n� il tempo n� la voglia, ma visto che ora sapete come fare, potete provarci. Calcolarsi un serial valido a mano sarebbe stato abbastanza complicato, fortuna che i programmatori ci hanno risparmiato il lavoro e ci hano lasciato il bel compare in chiaro! Alla proxima.
AndreaGeddon
|
Saluto tutti gli amici della mailing list. Saluto pure GiOcRaCk che ho conosciuto da poco, ma sembra uno in gamba. Pare che per� abbia lo stesso accento di Zoa (voi leim... roba da leim....) hahahaha!
Disclaimer |
UIC's page of reverse engineering, scegli dove andare: |
Home Anonimato Assembly CrackMe ContactMe Forum Iscrizione |
Lezioni Links Linux NewBies News Playstation |
Tools Tutorial Search UIC Faq |
UIC |