Menu

Win32asm KEYGEN by PUSILLUS

*****************************************
*                                       *
*         RingZer0   Presents           *
*                                       *
*       Win32asm KEYGEN by PUSILLUS     *
*                                       *
*****************************************
05/02/1999
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
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                   ----------|
1000
|
* 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 <--- CC0D
1000
EFED
: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
1000
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
mo
399
v 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!!
Pusillus.
SORGENTI

Top: Sicurezza su Internet - Back
Previous: The Italian CRaCKiNG Encyclopedia vol. 4 - Up: Sicurezza su Internet - Next: Reverse Engeneering di Babylon Translator

This page last updated: Friday 08 November 2002 at 3:59pm

Please send any comments on this page to Astalalista.

Labelled with ICRA

This page is powered by Copyright Button(TM).
Click here to read how this page is protected by copyright laws.

Use this button to
NOT browser button


begin banner Exchange zone

Member of BannerPower Rotation System

Home Main Portal Translate Tell A Friend Create Page Create Site Search Site Search WWW E-mail Login Insert A Link Free for All Free Dating Forum disabled-come soon Guestbook Links Vote For Us disabled-come soon Necklace | Income for Websites | Team Building Camps and Seminars | Black Jack Game | Arcade Games