********************************************                                   
                                            RingZer0 Presents                   
                                              
                                 "Win32asm KEYGEN" by PUSILLUS 
                                                               05/02/1999
                                ********************************************
               
------------------------------------------------------------------------------------------------------------
FAVOLOSO tutorial, se tutti me ne mandate di cos� belli credo che la UIC crescer� come un fungo in una notte nebbiosa ;))))
Battutacce a parte lo scopo della UIC � proprio quello di indirizzare i cracker al.......Reversing di un programma, GRAZIE PUSILLUS
------------------------------------------------------------------------------------------------------------
L'AUTORE DI QUESTO TESTO NON SI PRENDE NESSUNA RESPONSABILITA' PER L'USO
CHE NE VERRA' FATTO POICHE' E' STATO ESPRESSAMENTE CONCEPITO PER PURI
SCOPI DITATTICI.

tools necessari:

WDASM32
SOFTICE
MASM
Scaricate
qui i sorgenti
programma target:
Programmer's IDE for Win95/NT (software by design)

Questo programma e' facilmente crackabile forzando il jump in determinati
punti, ma anche una protezione poco efficente puo' essere un valido esercizio
per le nostre menti bacate! Alla fine la filosofia del cracker non e' solo
quella di riuscire, a tutti i costi, a violare un programma, ma soprattutto
quella di CAPIRE cosa fa una sequenza di codice per il PURO e SEMPLICE
PIACERE di SAPERLO e per ACQUISIRE CONOSCENZE che NON A TUTTI APPARTENGONO
(soprattutto a certi programmatori).
Proprio per questi motivi, A PURO SCOPO DIDATTICO, proveremo a fare un keygen:


Lanciamo il programma ed entriamo nella maschera di registrazione: viene
richiesto il nome dell'utente, il nome della societa' ed un codice di
registrazione.

inseriamo dei valori a caso e prima di dare "ok" entriamo in SoftIce (ctrl-D)
e settiamo un bel : BPX GetDlgItemTextA.
Appena dato l'OK al programma ci si presentera' subito la finestra del SoftIce,
con F12 usciamo dalla API su cui abbiamo settato il break e torniamo nel nostro
progz. Noteremo che la api viene chiamata da "call ebp" .




:0040F939 57 push edi
:0040F93A FFD5 call ebp <---------- getdlgitemtexta
:0040F93C 6A32 push 00000032


Andando avanti con F10 il debugger si blocchera' alle chiamate ad ebp:


:0040F93E 53 push ebx
:0040F93F 6A66 push 00000066
:0040F941 57 push edi
:0040F942 FFD5 call ebp <---------- getdlgitemtexta
:0040F944 8D442410 lea eax, dword ptr [esp+10]
:0040F948 6800010000 push 00000100
:0040F94D 50 push eax
:0040F94E 6A67 push 00000067
:0040F950 57 push edi
:0040F951 FFD5 call ebp <---------- getdlgitemtexta
:0040F953 8D442410 lea eax, dword ptr [esp+10]
:0040F957 50 push eax
:0040F958 E8F3930000 call 00418D50
:0040F95D 83C404 add esp, 00000004
:0040F960 8BE8 mov ebp, eax
:0040F962 56 push esi


Usciti da questa sequenza troviamo la prima cosa interessante: dopo la call
a 00417260 viene confrontato il contenuto di EAX con un certo valore, il fatto che ci
siano dei riferimenti alle stringhe "Gregory Braun" e "Software Design" mi ha incuriosito
molto quando ho disassemblato il programma e ho forzato il programma a non eseguire il
salto alla riga 0040f970. Come risultato ho ottenuto una registrazione con quei
dati! ...megalomania del programmatore?

Comunque il punto che ci interessa ancora non e' arrivato, io voglio registrare il programma
con un qualsiasi nome, non con il nome di chi lo ha fatto! Quindi eseguiamo il salto ed
andiamo avanti:


:0040F963 E8F8780000 call 00417260
:0040F968 83C404 add esp, 00000004
:0040F96B 3D92A71901 cmp eax, 0119A792
:0040F970 7518 jne 0040F98A ----------|
|
* Possible StringData Ref from Data Obj ->"Gregory Braun" |
| |
:0040F972 684C734200 push 0042734C |
|
* Reference To: KERNEL32.lstrcpyA, Ord:0296h |
| |
:0040F977 8B2DECB44300 mov ebp, dword ptr [0043B4EC] |
:0040F97D 56 push esi |
:0040F97E FFD5 call ebp |
|
* Possible StringData Ref from Data Obj ->"Software Design" |
| |
:0040F980 683C734200 push 0042733C |
:0040F985 53 push ebx |
:0040F986 FFD5 call ebp |
:0040F988 EB07 jmp 0040F991 |
|
* Referenced by a (U)nconditional or (C)onditional Jump at Address: |
|:0040F970(C) |
| |
:0040F98A 3D3CCE5F0D cmp eax, 0D5FCE3C <--------------|
:0040F98F 750C jne 0040F99D


Incredibile, un'altra comparazione di eax con un valore strano! Ma stavolta non ho
indagato e sono andato avanti. Comunque si e' capito che il prog x verificare l'autenticita'
della chiave confronta EAX con qualcosaltro ;)

Siamo arrivati alla parte di codice che ci interessa: vengono fatte due call a 00416d90 e il
valore di EAX viene confrontato con EBP (indir. 0040f9a7) :

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040F988(U)
|
:0040F991 53 push ebx
:0040F992 56 push esi
:0040F993 E8F8730000 call 00416D90 <------
:0040F998 83C408 add esp, 00000008
:0040F99B 8BE8 mov ebp, eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040F98F(C)
|
:0040F99D 53 push ebx
:0040F99E 56 push esi
:0040F99F E8EC730000 call 00416D90 <------
:0040F9A4 83C408 add esp, 00000008
:0040F9A7 3BC5 cmp eax, ebp <------ controllo codice
:0040F9A9 741E je 0040F9C9 <------ se giusto registra il prog
:0040F9AB 68CFEA0000 push 0000EACF altrimenti viene mostrata
una message box di errore


Ecco la parte di codice che esegue il calcolo della chiave di registrazione:
all'indirizzo 00416d90 viene caricato in EAX l'indirizzo del "nome dell'utente"
all'indirizzo 00416d95 viene caricato in ESI l'indirizzo di una costante
corrispondente al valore "CC0DEFED". Dopo la prima call a 00417260 vengono
esegute alcune operazioni sui registri, dopodiche' alla riga 00416dac viene
caricato in EAX l'offset che punta al "nome dell'organizzazione" e viene eseguita
nuovamente la call a 00417260. Tutti i valori puntati dai registri o presenti ad
un certo indirizzo, sono facilmente ispezionabili con il comado "d" (display)
del softice.




|:0040C722 , :0040F7D9 , :0040F993 , :0040F99F
|
:00416D90 8B442404 mov eax, dword ptr [esp+04] ; EAX <--- nome utente
:00416D94 56 push esi
:00416D95 8B35705D4200 mov esi, dword ptr [00425D70] ; ESI <--- CC0DEFED
:00416D9B 50 push eax
:00416D9C 81CE78030000 or esi, 00000378
:00416DA2 E8B9040000 call 00417260             <-------- 1^ call
:00416DA7 83C404 add esp, 00000004
:00416DAA 03F0 add esi, eax
:00416DAC 8B44240C mov eax, dword ptr [esp+0C] ; EAX <--- nome societa'
:00416DB0 50 push eax
:00416DB1 E8AA040000 call 00417260             <-------- 2^ call
:00416DB6 83C404 add esp, 00000004
:00416DB9 03C6 add eax, esi             <- in EAX c'e' il codice ESATTO
                                per sbloccare il programma
:00416DBB 5E pop esi
:00416DBC C3 ret


Ora non rimane che vedere cosa succede quando viene eseguita la call a 00417260,
quindi disabilitiamo il bpx GetDlgItemTexta e settiamo un bpx 00416da2 e
bpx 00416db1, ridiamo l'OK sulla maschera di registrazione.
Ci troveremo in questa parte di codice che processera' prima il nome dell'utente
e poi, alla seconda call, il nome della societa':

:00417260 53 push ebx
:00417261 56 push esi
:00417262 8B74240C mov esi, dword ptr [esp+0C] <----- ESI addr "nome utente"
:00417266 57 push edi
:00417267 55 push ebp
:00417268 33FF xor edi, edi
:0041726A 56 push esi

* Reference To: KERNEL32.lstrlenA, Ord:029Ch
|
:0041726B FF15F8B44300 Call dword ptr [0043B4F8] <------ EAX lungh. "nome utente"
:00417271 85F6 test esi, esi <- controlla che ESI non sia 0
:00417273 7432 je 004172A7
:00417275 85C0 test eax, eax             <- contolla che EAX non sia 0
:00417277 742E je 004172A7
:00417279 B900000000 mov ecx, 00000000 <- inizializza ECX a 0 x usarlo come contatore
:0041727E 7E27 jle 004172A7

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004172A5(C)
|
:00417280 0FBE9C08B89B4200 movsx ebx, byte ptr [eax+ecx+00429BB8] <- muove in EBX il contenuto di una particolare locazione di memoria *
:00417288 0FBE2C0E movsx ebp, byte ptr [esi+ecx]         <- usa ECX come puntatore x processare tutti i bytes del "nome Utente"
:0041728C 8D5101 lea edx, dword ptr [ecx+01]
:0041728F 0FAFDD imul ebx, ebp
:00417292 0FBE89F09B4200 movsx ecx, byte ptr [ecx+00429BF0] <- muove in ECX il contenuto di una particolare locazione di memoria *
:00417299 0FAFD9 imul ebx, ecx
:0041729C 0FAFDA imul ebx, edx
:0041729F 03FB add edi, ebx
:004172A1 8BCA mov ecx, edx
:004172A3 3BC2 cmp eax, edx                
:004172A5 7FD9 jg 00417280                 <- esegue il ciclo fino a che non ha processato tutta la stringa

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00417273(C), :00417277(C), :0041727E(C)
|
:004172A7 8BC7 mov eax, edi       
:004172A9 5D pop ebp
:004172AA 5F pop edi
:004172AB 5E pop esi
:004172AC 5B pop ebx
:004172AD C3 ret

* Questa routine esegue dei calcoli sulle stringhe inserite sulla maschera di
registrazione, ma usa anche dei valori particolari presenti agli indirizzi
00429BB8 e 00429BF0, non ci resta che adare a vedere cosa contengono queste
locazioni:


:00429BB8 23 73 65 72 42 26 6E 7A #serB&nz <-------
:00429BC0 7C 6D 66 4D 31 2F 35 28 |mfM1/5(
:00429BC8 21 73 64 24 4D 71 2E 7B !sd$Mq.{
:00429BD0 73 5D 2B 73 46 6A 74 4B s]+sFjtK
:00429BD8 70 7A 53 64 74 7A 6F 58 pzSdtzoX
:00429BE0 71 6D 62 5E 41 6C 40 64 qmb^Al@d
:00429BE8 76 3A 73 3F 78 2F 00 00 v:s?x/..
:00429BF0 7C 62 21 70 7A 2A 6C 73 |b!pz*ls <-------
:00429BF8 3B 72 6E 7C 6C 66 24 76 ;rn|lf$v
:00429C00 69 5E 41 78 70 65 29 72 i^Axpe)r
:00429C08 78 35 61 69 63 26 39 2F x5aic&9/
:00429C10 32 6D 35 6C 73 69 34 40 2m5lsi4@
:00429C18 30 64 6D 5A 77 39 34 63 0dmZw94c
:00429C20 6D 71 70 66 68 77 00 00 mqpfhw..
:00429C28 6D 41 50 49 20 66 75 6E mAPI fun
:00429C30 63 74 69 6F 6E 20 4E 4F ction NO
:00429C38 54 20 73 75 70 70 6F 72 T suppor


A questo punto siamo a conoscenza di tutti i dati che ci occorrono x fare la
nostra keygen. Ho scelto di farla in Win32asm perche' con un semplice
copia ed incolla, ed alcune piccole modifiche, della routine di calcolo del
codice di registrazione e' possibile raggiungere lo scopo, senza neanche
curarsi troppo di tutti calcoli che vengono eseguiti. Se avete gia letto il mio
tute su come fare una patch noterete che lo scheletro e' del tutto analogo
per entrambi i programmi, le cose cambiano quando viene premuto il tasto OK e la
dialogbox e' diversa perche' questa volta dobbiamo inserire dei valori:


---------------------------------------------
.386
.MODEL FLAT, STDCALL
include winicz.inc
includelib user32.lib
includelib kernel32.lib
includelib gdi32.lib

calcolo    PROTO: DWORD

.data
DlgName db "MYDIALOG",0

dati1    db "#serB&nz|mfM1/5(!sd$Mq.{s]+sFjtKpzSdtzoXqmb^Al@dv:s?x/",0,0 ; dati estratti dalla locazione 00429BB8
dati2    db "|b!pz*ls;rn|lf$vi^Axpe)rx5aic&9/2m5lsi4@0dmZw94cmqpfhw",0,0 ; dati estratti dalla locazione 00429BF0

formato db "%lu",0
.data?
nome db 40 dup(?),0
societa db 40 dup(?),0
codice    db 40 dup(0),0

hInstance HINSTANCE ?
hInstance1 HINSTANCE ?


.const
IDC_EDIT2 equ 3003
IDC_EDIT1 equ 3004
IDC_EDIT3 equ 3005
IDC_BUTTON2 equ 3007
IDC_EXIT equ 3000

.code

start:

invoke GetModuleHandle, NULL
mov hInstance,eax
invoke WinMain, hInstance,NULL,NULL, SW_SHOWDEFAULT
invoke ExitProcess,eax
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:SDWORD
mov eax, OFFSET DlgProc
invoke DialogBoxParam, hInst, ADDR DlgName,NULL,eax,NULL
ret
WinMain endp
DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
mov eax,hWnd
mov hInstance1,eax
mov eax,uMsg
.IF eax==WM_INITDIALOG
invoke SetFocus,eax
.ELSEIF eax==WM_CLOSE
invoke EndDialog, hWnd,NULL
.ELSEIF eax==WM_COMMAND
mov eax,wParam
.IF ax==IDC_BUTTON2
shr eax,16
.IF ax == BN_CLICKED

                invoke GetDlgItemTextA,hInstance1,IDC_EDIT1,addr nome,40
                invoke GetDlgItemTextA,hInstance1,IDC_EDIT2,addr societa,40
   
                mov esi, 0cc0defedh        ; valore estratto dalla loc. 00425D70
                or esi, 00000378h
                invoke calcolo, addr nome    ; prima chiamata calcolo sul "nome utente"
                add esi, eax
                invoke calcolo, addr societa ; seconda chiamata calcolo sul "nome                                                               ; societa"
                add eax, esi
                invoke wsprintfA,addr codice, addr formato,eax ; il valore HEX viene                                                                                            ; convertito in decimale
                invoke SetDlgItemText,hInstance1,IDC_EDIT3,addr codice                                                                                       ;visualizzazione del codice
                invoke UpdateWindow, hInstance1
.ENDIF
.ELSEIF ax == IDC_EXIT
shr eax,16
.IF ax==BN_CLICKED
invoke EndDialog, hWnd,NULL
.ENDIF
.ENDIF
.ELSE
mov eax,FALSE
ret
.ENDIF
mov eax,TRUE
ret
DlgProc endp

calcolo proc aVariabile:dword
   
    push ebx
    push esi
    mov esi, aVariabile
    push edi
    push ebp
    xor edi, edi
    invoke lstrlen, aVariabile
    test esi, esi
    je @@salto1
    test eax, eax
    je @@salto1
    mov ecx, 00000000
    jle @@salto1
@@salto2:   
    movsx ebx, byte ptr [eax+ecx+dati1]
    movsx ebp, byte ptr [esi+ecx]
    lea edx, dword ptr [ecx+01]
    imul ebx, ebp
    movsx ecx, byte ptr [ecx+dati2]
    imul ebx, ecx
    imul ebx, edx
    add edi, ebx
    mov ecx, edx
    cmp eax, edx
    jg @@salto2
@@salto1:   
    mov eax, edi
    pop ebp
    pop edi
    pop esi
    pop ebx
   
    ret
calcolo endp

end start

---------------------------------------------

Non credo che il keygen abbia bisogno di particolari spiegazioni bastera'
confrontare la parte di codice che esegue le call a "calcolo" con qella del
programma preso in esame alla locazione 00416D90 e la routine "calcolo"
con la parte di programma che parte dall'indirizzo 00417260.


Un ringraziamento ad Iczelion x i suoi tutes sul win32asm e a tutti i membri
di RingZero!! (Hei Pusi e la UIC dove la lasci? ;))) NdQ)

============================================================================
Copyright:

Questo testo pu� essere liberamente divulgato a patto di non essere modificato in nessuna sua parte.
La presente copia in particolare � riservata al progetto UIC su richiesta di Quequero.
============================================================================

Pusillus.