WinImage ovvero uno schema di protezione deludente -D |
||
Data |
by "Evilcry" |
|
15/09/2002 |
Published by Quequero |
|
Sr |
W la marshall allora :P, grazie per il tute, ben scritto, la protezione davvero deludente :) |
Stronzio a chi? :-P |
.... |
|
.... |
Difficoltà |
(Poco più che->) NewBies (*) Intermedio ( )Avanzato ( )Master |
Introduzione |
Tools usati |
URL o FTP del programma |
Notizie sul programma |
Essay |
Iniziamo il nostro viaggio nelle viscere di WinImage :)). Dopo aver installato il programma, una simpatica NagScreen ci avvisa che il programma non è registrato, e dopo 30 giorni smetterà di funzionare :)). Le vie per evitare la sua morte sono tante, si potrebbero rimuovere il/ i jump che decidono se sono passati i 30 giorni (metodo mooolto lamero ed antipatico), o trovarci un seriale valido (è la via che preferisco :)). Facciamo partire il programma ed andiamo sull' Item 'Options', nel quale troveremo 'Registering'. Ora avremo davanti a noi il classico Name/Serial :)), quindi inseriamo un nome a caso (io ho messo evilcry) ed un serial a caso (io ho scritto triton). Settiamo ora i canonici (ma come parlo oggi??? ihihi) bpx GetDlgItemTextA e bpx GetWindowTextA poi usciamo da SICE con F5 e clickiamo su 'Register'. Il Sice poppa :)), ora premiamo una volta F12 e ci troveremo davanti, qualcosa del genere:
0042204A mov ebx, 00453B90 ; Viene messo in ebx l' indirizzo del buffer che riceverà il nome
0042204F push ebx
00422050 push 00000816
00422055 push [ebp+08]
00422058 call esi ;Call a Getdlgitemtexta
0042205C mov edi, 00453F00 ;In edi avremo l' indirizzo del buffer per il serial
00422061 push edi
00422062 push 00000817
00422067 push [ebp+08]
0042206A call esi ;Chiamata a getdlgitemtexta
0042206C push 0045386C
00422071 push edi ;Salva il puntatore al serial nello stack
00422072 push ebx ;Salva il puntatore al nome nello stack
00422073 call 0044208A ; Questa call la analizzeremo in seguito... dato che è fondamentale
Fin qui non ci dovrebbero essere problemi :)) , il programma non fa altro che prendere il nome ed il serial inserito (d ebx e d edi per credere), e passarli alla call 00422073. Dopo essere arrivati su questa call premiamo F8 per entrarci dentro. La prima parte della call non è molto utile ai nostri scopi quindi la tralascerò:
/**** CUTTED CALL ****/
004420A2 lea eax, dword ptr [ebp+FFFFFF00] ; Carica in eax il serial
004420A8 push eax ; Salva il serial nello stack , questo perchè sarà il parametro della seguente call
004420A9 call 00441F90
004420AE push [ebp+08]
004420B1 call 00441FBC ;Questa call la analizzeremo a parte
Quando ci troveremo su questa call, premiamo nuovamente F8 per entrarci.
00441F90 mov eax, dword ptr [esp+08] ;Mette in eax il serial
00441F94 jmp 00441F97
Referenced by a (U)nconditional or (C)onditional Jump at Address:
00441F96 inc eax
Referenced by a (U)nconditional or (C)onditional Jump at Address:
00441F97 cmp byte ptr [eax], 20 ;Controlla che l' ennesimo char puntato da eax sia 20 (quindi ne un numero ne una lettera)
00441F9A je 00441F96 ; Se è uguale a 20 salta su ed incrementa di 1 il puntatore al serial
00441F9C push eax ;In caso contrario usa il nostro serial come parametro di lstrcpy
00441F9D push [esp+08] ;Questo è l' output buffer di lstrcpy
Reference To: KERNEL32.lstrcpyA,
00441FA1 Call dword ptr [00446260] ; Chiamata a lstrcpy
Chi conosce un pò di C sicuramente avrà capito cosa fa quest' API, in pratica copia una stringa (il nostro serial :-P), in un' altra locazione (variabile per gli amici :-D).
00441FA7 push [esp+04]
Reference To: USER32.CharUpperA
00441FAB Call dword ptr [004464E4] ;Rende maiuscola una stringa
00441FB1 push [esp+04]
00441FB5 call 00415B9C ;Eccovela spiegata qui di seguito ---->
*****************************************
00415B9C push esi
00415B9D mov esi, dword ptr [esp+08] ;Muove in esi il nome
00415BA1 push esi ;Lo salva nello stack (per poi essere usato come parametro di strlen)
Reference To: KERNEL32.lstrlenA
00415BA2 Call dword ptr [0044625C]
00415BA8 jmp 00415BB5
Referenced by a (U)nconditional or (C)onditional Jump at Address:
00415BAA dec eax ;Decrementa di uno la lunghezza
00415BAB cmp byte ptr [eax+esi], 20 ;Controlla che l' ennesimo char puntato da eax sia 20
00415BAF jne 00415BB9 ;Salta se è diverso da 20
00415BB1 and byte ptr [eax+esi], 00
Referenced by a (U)nconditional or (C)onditional Jump at Address:
00415BB5 test eax, eax ;La lunghezza del nome è 0???? (cioè esiste :-D)???
00415BB7 ja 00415BAA ;Se è più grande di zero salta sopra
Referenced by a (U)nconditional or (C)onditional Jump at Address:
00415BB9 pop esi
00415BBA ret
Anche questa call non fa altro che controllare se i caratteri siano uguali a 20. Adesso dopo il RET a 00415bba, entreremo nella call più importante cioè quella che calcola il serial (in parte).
00441FDD lea eax, dword ptr [ebp+FFFFFEF8] ;Viene caricato in eax il nome
00441FE3 push eax ;Il nome è passato come parametro
Reference To: KERNEL32.lstrlenA
00441FE4 Call dword ptr [0044625C]
00441FEA xor ecx, ecx ;Azzera ecx che in futuro sarà usato come contatore
00441FEC test eax, eax ;Controlla che il nome quanto meno esista
00441FEE mov dword ptr [ebp-08], eax ;Mette il nome in ebp-08
00441FF1 jle 00442039 ;Salta se il numero di lettere del nome e minore o uguale a 0
00441FF3 push ebx
00441FF4 push esi
00441FF5 mov esi, dword ptr [ebp-08] ;Muove in esi il nome
00441FF8 push edi ;Salva edi
00441FF9 lea edi, dword ptr [ebp+FFFFFEF8] ;Carica in edi l' indirizzo relativo al nome
00441FFF sub edi, 00000003 ;Sottrai 3 alla locazione del nome
Referenced by a (U)nconditional or (C)onditional Jump at Address:
00442002 mov eax, ecx
00442004 push 0000000E ; passa questo numero ad ebx
00442006 cdq ;Azzera edx
00442007 pop ebx ;adesso abbiamo in ebx 0000000Eh
00442008 idiv ebx ;dividi eax per ebx
0044200A test edx, edx ; controlla che il resto della divisione sia 0
0044200C jne 00442011 ;se il resto è diverso da 0 salta
0044200E push 00000027 ; | equivale a mov esi,00000027h
00442010 pop esi ; | vedi sopra
Referenced by a (U)nconditional or (C)onditional Jump at Address:
00442011 lea eax, dword ptr [ecx+03]
00442014 movzx edx, byte ptr [edi+eax]
00442018 imul edx, esi
0044201B add dword ptr [ebp-04], edx ; In ebp-04 abbiamo dei valori costanti (almeno la prima volta)
0044201E push 0000000E ;Mette E in ebx con il solito metodo
00442020 cdq ;Azzera edx, e si prepara alla divisione
00442021 pop ebx
00442022 idiv ebx ;Divide eax per ebx
00442024 test edx, edx ;Controlla che il resto sia uguale a 0
00442026 je 0044202D ;Se lo è salta
00442028 lea esi, dword ptr [esi+2*esi] ;Carica in esi l' indirizzo relativo a [esi+2*esi]
0044202B jmp 00442030 ;Salta alla prossima semi-routine
Referenced by a (U)nconditional or (C)onditional Jump at Address:
0044202D imul esi, 00000007 ;Moltiplica esi per 7
Referenced by a (U)nconditional or (C)onditional Jump at Address:
00442030 inc ecx ;Incrementa ecx,vi ricordo funge da contatore
00442031 cmp ecx, dword ptr [ebp-08] ;Controlla che ecx sia uguale ad ebp-08, cioè alla variabile dove è stato salvato il valore di ritorno di strlen
00442034 jl 00442002 ;Se ecx è minore di questo valore, ripeti nuovamente il ciclo
00442036 pop edi
00442037 pop esi
00442038 pop ebx
Referenced by a (U)nconditional or (C)onditional Jump at Address:
00442039 mov eax, dword ptr [ebp-04] ;Sposta in eax il seriale parzialmente lavorato
0044203C leave ;Rimette a posto lo stack
0044203D ret ;Esce fuori dalla call
Come avrete visto, la routine non è un granchè di difficile, ma per agli ultra-newbies potrebbe creare un pò di confusione. Dopo una serie di divisioni e moltiplicazioni, otteniamo in ebp-04, il seriale parzialmente lavorato ed anche in chiaro, infatti se fate d ebp-04, lo vedrete il bella mostra, il mio serial è 007EEA66. Fermiii! , non ditemi che siate già andati a provarlo ihihi, se lo avete messo cosi com' è otterrete un messagio d' errore. Perchè mai?, semplice... andate a vedere cosa succede dopo il ret.Inizialmente al serial vengono tolti i primi 2 caratteri, di conseguenza il mio serial corretto è 7EEA66, poi avremo il canonico repz e cmp tra serial correto e quello che abbiamo messo noi, ed un salto condizionato ;-P.
Note per chi vuole fare un keygen.
Per ragioni di spazio non ho messo il keygen che avevo fatto (in masm). Se qualcuno di voi volesse fare un keygen, ricordi che: c'è un valore costante precisamente quello in ebp-04 che è 4c694700 (se non ricordo male) quindi state attenti :)), inoltre come avete potuto vedere, almeno nella prima parte EAX non viene usato quindi se usate qualche API abbiate l' accortezza di fare uno xor eax,eax (ovviamente dopo che vi siete salvati il suo contenuto :-P). Ricordate in oltre la routine che toglie i primi 2 char. Creare un keygen per questo programma è molto semplice (soprattutto se usate Masm/Tasm :-D).Spero di essere stato sufficentemente chiaro ed esauriente, se così non è stato, siete liberi di maillarmi :)).
Note finali |
In fine colgo l' occasione per salutare:Quequero, AndreaGeddon, e4m, Slash, Vinci,Quake2^AM, albe, Ntoskrnl, BIGAlex, Littleluk, Speed Strid. I chan #crack-it #asm #pmode e #twotux. E la marshall per i suoi grandiosi ampli :)).
Disclaimer |
Vorrei ricordare che il software va comprato e non rubato, dovete registrare il vostro prodotto dopo il periodo di valutazione. Non mi ritengo responsabile per eventuali danni causati al vostro computer determinati dall'uso improprio di questo tutorial. Questo documento è stato scritto per invogliare il consumatore a registrare legalmente i propri programmi, e non a fargli fare uso dei tantissimi file crack presenti in rete, infatti tale documento aiuta a comprendere lo sforzo immane che ogni singolo programmatore ha dovuto portare avanti per fornire ai rispettivi consumatori i migliori prodotti possibili.
Noi reversiamo al solo scopo informativo e di miglioramento del linguaggio Assembly .
Capitoooooooo????? Bhè credo di si ;))))