Autokeygen
e Keygen per Winzip Self-Extractor 2.2
|
Data
|
by Graftal
|
|
14/novembre/2003
|
UIC's
Home Page
|
Published by
Quequero
|
If freedom is outlawed...
|
Cooooosa
volevo dire? Non lo so... Ma c'ho ragione! FATTI NON PUGNETTEEE! :P grazie
Graft e complimenti pure per il progetto |
...only outlaws will have freedom
|
....
|
- E-mail:
[email protected]
-
#asm, #cpu, #crack-it, #cryptorev, #focushack, #folli, #gamesradar, #graftal,
#informazionelibera, #nsh, #pmode, #programming, #slipknot, #spippolatori
|
....
|
Difficoltà
|
(X)NewBies ( )Intermedio ( )Avanzato ( )Master
|
|
Benissimo, oggi ci accingeremo a fare un semplice
autokeygen per mezzo di una messagebox, toglieremo sia la schermata di errore
più altre eventuali scocciature, ci analizzeremo l'algo che genera il serial e
ci faremo pure un bel keygen (semplicissimo) sotto windows in C :)))
- Autokeygen e Keygen
per Winzip Self-Extractor 2.2
Written by Graftal
-
Allegato
- Bene bene, buon giorno a tutti :) Questo è il primo tutorial che invio alla UIC
e spero che sia di vostro gradimento. Oggi vedremo un po di vedere come
funziona
- il Winzip SE e vediamo cosa possiamo fare per prendercene gioco (ma
soprattutto per imparare qualcosa di nuovo :))
- Spiegherò per prima cosa come
fare l'autokeygen e successivamente il keygen. Buona lettura :)))
- I tools sono i soliti:
-
Ollydbg (o qualsiasi
altro debugger che più vi piace)
-
IDA Pro (o
qualsiasi altro disasm che più vi piace)
-
Hiew (o qualsiasi
altro editor esadecimale che più vi piace)
- Tenetevi pure una calcolatrice, un
notepad e un po di musica vicino, non si sa mai :)
- www.winzip.com
- Il programma in questione è utile nel caso abbiamo
bisogno di farci un programma di installazione per dei file zippati che
dobbiamo magari inviare a degli amici che non hanno il winzip, altri possibili
utilizzi non me ne vengono in mente :)
- Appena
finiamo di installarlo e lo apriamo, si apre una succulenta MessageBox che ci
avverte che il programma non presenta suddetto messaggio una volta
registrato...ma bene bene :) Clicchiamo su ok e successivamente su Enter
Registration Code e siamo pronti per leggere il tute.
- Allora, per prima cosa dobbiamo trovare un punto d'attacco. In questo caso,
a noi serve il momento in cui un registro in memoria contiene il serial
esatto (attenti però perché solo nei programmi meno protetti i programmatori
non cercano di "nascondere" il serial ai nostri occhi, e questo è uno di quelli
:))) quindi diamoci da fare. Perfetto, settiamo i soliti breakpoint su GetDlgItemTextA
e vediamo che il debugger poppa :) Guardiamoci quindi un po il codice
per trovare il punto favorevole per fare l'autokeygen. Ci possono essere molte
alternative, aggiungere una sezione al file per esempio, ma perché dovremmo
andarci a complicare la vita quando possiamo semplicemente trovare un paio di
istruzioni che non servono a nulla o un po di spazio libero? :)
- Io ho trovato questo (ci troviamo all'offset 95AA):
-
-
-
-
- :00409F99 lea eax, [ebp+var_104]
- :00409F9F push eax
- :00409FA0 push offset byte_43E640
- :00409FA5 call sub_409D1E
- :00409FAA push offset byte_43E520 ;
Noi siamo qua
- :00409FAF lea eax, [ebp+var_104]
- :00409FB5 push eax
- :00409FB6 call __strcmpi
- :00409FBB pop ecx
- :00409FBC pop ecx
- :00409FBD neg eax
- :00409FBF sbb eax, eax ;almeno
fino a qui è tutto inutile
- :00409FC1 inc eax ;quindi
possiamo modificare tutto
Come vedete, ci troviamo giusto giusto sotto una call (attenzione perché quella
call è fondamentale, quindi non fateci pasticci!). Apriamo il nostro hiew, F5 e
scriviamo l'offset (95AA), quindi F3. Ora scrivete gli opcode che seguono:
- opcode ------------- azione
- 6A20 push
20h ;pusha lo stile della msgbox, in questo caso è un MB_OK e un
MB_ICONASTERISK
- 50 push
eax ;pusha il titolo della msgbox
- 50 push
eax ;pusha il testo della msgbox
- FF7508 push
d,[ebp][00008] ;pusha l'hWnd
- FF1574234200 call
MessageBoxA ;chiama la msgbox :)
- --------------------------------------------
E' di vitale importanza che facciate attenzione a ciò che trovate, perché dovete
noppare una istruzione (che ora vi segnalo all'interno del codice):
- :00409F99 lea eax, [ebp-104h]
-
:00409F9F push eax
- :00409FA0 push
offset byte_43E640
- :00409FA5 call
sub_409D1E
- :00409FAA push 20h
- :00409FAC push eax
-
:00409FAD push eax
- :00409FAE push
dword ptr [ebp+8]
- :00409FB1 call
ds:MessageBoxA
- :00409FB7 push ebp
- :00409FB8 push ebp
-
:00409FB9 add [eax], eax ;noppiamo
questo!!!!!!!!
- :00409FBB pop ecx
- :00409FBC pop ecx
-
:00409FBD neg eax
- :00409FBF sbb eax,
eax
- :00409FC1 inc eax
Ocio quindi all'offset 95B9 ke senno da errore! :) Perfetto,
possiamo ora testare la nostra "creatura" :) Scriviamo un User e
un serial a caso e vediamo ke ci poppa la nostra msgbox con il seriale giusto!
EVVAI! Ma...hehe, gia, non è ancora mica finita! Io penso sia davvero poco
professionale, non trovate? Prima di tutto, vediamo di zittire quella msgbox di
errore: non andiamo a trovare il salto ke ci porta alla msgbox,
semplicemente CANCELLIAMOLA! (mi è sempre piaciuta la forza bruta :) Come?
Prima di tutto dopo che abbiamo inserito user e serial, steppiamo fino a quando
non troviamo la call dove sta la masgbox, e piano piano entriamo nella call e
analizziamo di nuovo il tutto, finché non la troviamo. Ecco quindi che ci
troviamo all'offset 9940: noppate tutto di sana pianta (ci vanno 6 nop ;)
Eccovi il codice:
- :0040A32E push 10h
-
:0040A330 push 0
- :0040A332 push 12FCh
- :0040A337 call sub_406CC7
-
:0040A33C push eax
- :0040A33D push
[ebp+arg_0]
- :0040A340 call
ds:MessageBoxA ;noppiamolo!
Ora però, andiamo a provare. Vediamo che la msgbox di errore non compare,
perfetto! Si ma, uff, dopo 3 volte che sbagliamo, ci esce e dobbiamo rientrare
nella finestra che chiede il serial... Vediamo di farla finita una volta per
tutte. Andiamo all'offset 9958 (cioe subito dopo la msgbox di errore ke abbiamo
appena cancellato) e vediamo di cambiare il jnz in un jmp. Infatti se fate
attenzione, vediamo che compara una varaibile (che si incrementa ogni volta che
sbagliamo serial) con il numero 3: se sono uguali ci chiude la finestra :) Ecco
qua, abbiamo terminato (o quasi :)! Ora andiamo a farci il patcher, pelandroni!
:) Ho messo qui il sorgente, voi fateci le modifiche che volete. Io l'ho
compilato con dev-cpp 4.8 e va alla grande, comunque la sostanza è questa.
- ----------------------------cutehere-----------------------------------------
-
#include <windows.h>
- #include
<stdio.h>
- #include
<stdlib.h>
-
#define NOP 0x90
-
#define JMP 0xEB
- #define PUSH_EAX 0x50
- #define PUSH_6A 0x6A
-
#define PUSH_20 0x20
- #define HWinDFF
0xFF
- #define HWinD75 0x75
-
#define HWinD08 0x08
- #define MSGBOXAFF
0xFF
- #define MSGBOXA15 0x15
- #define MSGBOXA74 0x74
-
#define MSGBOXA23 0x23
- #define
MSGBOXA42 0x42
- #define MSGBOXA00 0x00
- int WINAPI WinMain(HINSTANCE hInst, HINSTANCE
hPrevInst, LPSTR lpCmdLine, int nCmdShow)
-
{
- FILE *fl_open;
-
char *s,*k;
- long z,a;
-
if (!(fl_open=fopen("WZIPSE32.EXE","rb")))
-
{
- MessageBox(0, "Non posso aprire il
file", "Errore", MB_OK + MB_ICONHAND);
-
exit(0);
- }
-
fseek(fl_open,0,SEEK_END);
- z=ftell(fl_open);
- fseek(fl_open,0,SEEK_SET);
-
s=k=(char*)malloc(z);
- if (!k)
- {
- MessageBox(0,
"Non posso allocare la memoria", "Errore", MB_OK + MB_ICONHAND);
-
exit(0);
- }
-
while (!feof(fl_open))*(s++)=fgetc(fl_open);
-
*(k+0x95AA)=PUSH_6A;
- *(k+0x95AB)=PUSH_20;
- *(k+0x95AC)=PUSH_EAX;
-
*(k+0x95AD)=PUSH_EAX;
- *(k+0x95AE)=HWinDFF;
- *(k+0x95AF)=HWinD75;
-
*(k+0x95B0)=HWinD08;
- *(k+0x95B1)=MSGBOXAFF;
- *(k+0x95B2)=MSGBOXA15;
-
*(k+0x95B3)=MSGBOXA74;
- *(k+0x95B4)=MSGBOXA23;
- *(k+0x95B5)=MSGBOXA42;
-
*(k+0x95B6)=MSGBOXA00;
- *(k+0x95B9)=NOP;
- *(k+0x95BA)=NOP;
-
*(k+0x9864)=JMP;
- *(k+0x98A0)=JMP;
- *(k+0x9940)=NOP;
-
*(k+0x9941)=NOP;
- *(k+0x9942)=NOP;
- *(k+0x9943)=NOP;
-
*(k+0x9944)=NOP;
- *(k+0x9945)=NOP;
- *(k+0x9958)=JMP;
-
if (!(fl_open=fopen("WZIPSE32Crk.exe","wb")))
-
{
- MessageBox(0, "Non posso creare il
file", "Errore", MB_OK + MB_ICONHAND);
-
exit(0);
- }
-
for (a=0;a<z;a++)
- fputc(*(k++),fl_open);
- fflush(NULL);
-
fclose(fl_open);
- MessageBox(0, "Crack
completato con successo!", "Congratulazioni!!", MB_OK + MB_ICONASTERISK);
- free(fl_open);
-
exit(0);
- }
-
---------------------------------------cuthere-------------------------------
-
Devo dire ke l'ho fatto un po "alla mia", nel senso
che ho un gusto particolare nel fare i sorgenti, quindi modificatevelo quanto
vi pare, la sostanza, come dicevo prima, rimane la stessa! :) Attenzione perché
il patcher e il file originale vanno nella stessa cartella e soprattuto il file
WZIPSE32Crk.exe che viene creato, lo dovete rinominare in WZIPSE32.exe perché
funzioni!
Ok, direi che la prima parte del tutorial è fatta,
passiamo quindi a crearci il keygen! :))
- Allora, questa volta abbiamo ovviamente un approccio
diverso da prima, e invece di andare a trovare un punto in cui il programma fa
qualcosa di inutile (o proprio non fa nulla :)) andiamo ad analizzarci tutto
l'algo che genera il serial :)
- Mettiamo
nuovamente i breakpoint su GetDlgItemTextA e analizziamo il codice che ci
compare una volta che il debugger poppa:
:0040A1D7 call ds:GetDlgItemTextA ;qui
prende l'username
--------snip----tanto non ci interessa------
:0040A22F call ds:GetDlgItemTextA ;qui
invece il serial da noi immesso
-------snip----tanto non ci interessa di nuovo
:)------
Arriviamo invece al primo vero check:
- :0040A260 pop ecx
-
:0040A261 cmp eax, 8
- :0040A264 jnz
short loc_40A296
Che cosa fa qui? semplicemente prende il nostro serial e lo compara con 8: se
sono uguali (se l'user insomma è lungo 8 caratteri) ci fa comparire una
messagebox di errore che ci avvisa del fatto che il serial di winzip e di
winzip SE sono diversi (il serial di winzip è lungo 8 caratteri, quello di
winzip SE invece 6 :)). A questo punto quindi, attenti a mettere un serial più
corto o più lungo. Avvenuto il salto, vediamo cosa troviamo:
- :0040A2FC movzx eax, byte_43E640
-
:0040A303 test eax, eax
- :0040A305 jnz
short prima_della_call ;qui
c'è un altro dei check, saltiamo alla label da me rinominata prima_della_call
:)
- :0040A307 movzx eax, byte_43E520
- :0040A30E test eax, eax
-
:0040A310 jz short loc_40A369
- :0040A312
;arriviamo quindi qui
- :0040A312 prima_della_call: ; CODE XREF:
sub_40A09E+267j
- :0040A312 push 0
- :0040A314 call sub_409F35 ;call
FONDAMENTALE :)
- :0040A319 test eax,
eax
- :0040A31B jnz short loc_40A369
Ora entriamo nella call che ci porta a 409F35 e dobbiamo un po vedere come
muoverci...Analizzando un po il codice iniziale vediamo che sono tutti dei
check (molti inutili e ripetitivi, come troverete anche più avanti nell'algo) e
arriviamo ad una call...Proprio quello che cercavamo:
:00409FA5 call sub_409D1E
Entriamoci e vediamo che sorprese ci aspettano :) Inizialmente ci sono un po di
call e check vari, l'unica cosa davvero fondamentale qui è che il nostro user
viene salvato in lowercase (con tutte le lettere minuscole insomma, e qui c'è
una grande differenza, perché voi ovviamente sapete che il codice ascii di una
lettera maiuscola e diversa da una minuscola :)). Ecco quindi che ci troviamo
di fronte al nostro primo loop, analizziamolo:
- :00409D66 mov eax, [ebp+var_4]
-
:00409D69 inc eax
- :00409D6A mov
[ebp+var_4], eax
- :00409D6D
-
:00409D6D loc_409D6D: ; CODE XREF: sub_409D1E+46j
-
:00409D6D mov eax, [ebp+var_4]
- :00409D70
movzx eax, byte ptr [eax]
- :00409D73
test eax, eax
- :00409D75 jz loc_409DFB
- :00409D7B cmp cchMultiByte, 1
-
:00409D82 jle short loc_409D9F
- :00409D84
push 103h ; int
- :00409D89 mov eax,
[ebp+var_4]
- :00409D8C movzx eax, byte
ptr [eax]
- :00409D8F push eax ; int
- :00409D90 call __isctype
-
:00409D95 pop ecx
- :00409D96 pop ecx
- :00409D97 mov [ebp+var_118], eax
-
:00409D9D jmp short loc_409DBA
- :00409D9F
; ---------------------------------------------------------------------------
- :00409D9F
-
:00409D9F loc_409D9F: ; CODE XREF: sub_409D1E+64j
-
:00409D9F mov eax, [ebp+var_4]
- :00409DA2
movzx eax, byte ptr [eax]
- :00409DA5
mov ecx, dword_427710
- :00409DAB movzx
eax, word ptr [ecx+eax*2]
- :00409DAF
and eax, 103h
- :00409DB4 mov
[ebp+var_118], eax
- :00409DBA
- :00409DBA loc_409DBA: ; CODE XREF:
sub_409D1E+7Fj
- :00409DBA cmp
[ebp+var_118], 0
- :00409DC1 jz short
loc_409DF6
- :00409DC3 mov eax,
[ebp+var_4] ;per noi,
il loop comincia da qui, perché il resto non ci interessa :)
-
:00409DC6 movzx eax, byte ptr [eax] ;mette
la prima lettera dell'user
- :00409DC9
movzx ecx, [ebp+var_114] ;mette
la sua posizione all'interno dell'username
-
:00409DD0 imul eax, ecx ;li
moltiplica con risultato in eax
- :00409DD3
mov cx, [ebp+var_110] ;il
risultato...
- :00409DDA add cx, ax ;...viene
aggiunto in cx...
- :00409DDD mov
[ebp+var_110], cx ;...per
essere poi messo in una variabile (di vitale importanza :))
-
:00409DE4 mov ax, [ebp+var_114] ;ora
incrementa ax in modo che alla prossima moltiplicazione...
-
:00409DEB add ax, 1 ;...ci
sia la posizione successiva della lettera all'interno dell'username...
- :00409DEF mov [ebp+var_114], ax ;...e
quindi salva il tutto...
- :00409DF6
- :00409DF6 loc_409DF6: ; CODE XREF:
sub_409D1E+A3j
- :00409DF6 jmp
loc_409D66 ;ricomincia
il ciclo :)
Ok, per essere maggiormente chiaro vorrei ripetere tutta questa prima parte in
modo un po più concreto, usando degli esempi. Noi abbiamo come username
"graftal" (attenti eh, lowercase), vediamo cosa fa il prog: prende la prima
lettera (la "g"), prende la sua posizione all'interno dell'username (è la prima
lettera, quindi prende il numero 1); ora li moltiplica e il risultato lo
AGGIUNGE in una variabile. Incrementa l'indice per passare alla seconda lettera
e per fare quindi la moltiplicazione tra "r" (2° lettera) e 2 (perché è questa
la sua posizione nell'username). In poche parole, moltiplica il carattere e il
suo indice e aggiunge il risultato in una variabile, semplice no? :))) Teniamo
d'occhio la variabile nella quale i vari risultati sono aggiunti perché come
dicevo nel codice commentato, è di vitale importanza. Ora non pensiate sia
finita eh, abbiamo da analizzare la seconda e ultima parte dell'algo :)
- :00409E10 loc_409E10: ; CODE XREF:
sub_409D1E+167j
- :00409E10 mov eax,
[ebp+var_4]
- :00409E13 inc eax
- :00409E14 mov [ebp+var_4], eax
-
:00409E17 .text:00409E17 loc_409E17: ; CODE XREF: sub_409D1E+F0j
-
:00409E17 mov eax, [ebp+var_4]
- :00409E1A
movzx eax, byte ptr [eax]
- :00409E1D
test eax, eax
- :00409E1F jz short
loc_409E87
- :00409E21 cmp cchMultiByte,
1
- :00409E28 jle short loc_409E45
- :00409E2A push 103h ; int
-
:00409E2F mov eax, [ebp+var_4]
- :00409E32
movzx eax, byte ptr [eax]
- :00409E35
push eax ; int
- :00409E36 call
__isctype
- :00409E3B pop ecx
- :00409E3C pop ecx
-
:00409E3D mov [ebp+var_11C], eax
- :00409E43
jmp short loc_409E60
- :00409E45 ;
---------------------------------------------------------------------------
- :00409E45
-
:00409E45 loc_409E45: ; CODE XREF: sub_409D1E+10Aj
-
:00409E45 mov eax, [ebp+var_4]
- :00409E48
movzx eax, byte ptr [eax]
- :00409E4B
mov ecx, dword_427710
- :00409E51 movzx
eax, word ptr [ecx+eax*2]
- :00409E55
and eax, 103h
- :00409E5A mov
[ebp+var_11C], eax
- :00409E60
.text:00409E60 loc_409E60: ; CODE XREF: sub_409D1E+125j
-
:00409E60 cmp [ebp+var_11C], 0
- :00409E67
jz short loc_409E85
- :00409E69 push
1021h ;da qui comincia
il vero loop: anche questo valore (che chiameremo "mask") è importante, è usato
nella call dopo
- :00409E6E mov eax,
[ebp+var_4] ;prende
l'username
- :00409E71 movzx ax, byte
ptr [eax] ;prende la
prima lettera in AX, attenti!
- :00409E75
push eax
- :00409E76 push [ebp+var_8]
- :00409E79 call sub_409ECF ;una
call che analizzeremo di seguito e che è importantissima
-
:00409E7E add esp, 0Ch
- :00409E81 mov
word ptr [ebp+var_8], ax
- :00409E85
- :00409E85 loc_409E85: ; CODE XREF:
sub_409D1E+149j
- :00409E85 jmp short
loc_409E10 ;riparte il
loop
Ok, qui non fa molto come potete vedere, è infatti quella call a 409ECF che è
importantissima: salto la parte prima del loop e ve la spiego qua a parole,
perché fa praticamente una sola cosa: shifta il carattere dell'username preso
prima di 8 verso sinistra (shl carattere, 8 ;in asm) e cosi se prima avevamo in
ax "67" ora abbiamo "6700". Perfetto, passiamo al loop:
- :00409ECF push ebp
-
:00409ED0 mov ebp, esp
- :00409ED2 push
ecx
- :00409ED3 mov ax, [ebp+arg_4] ;mette
il primo carattere dell'user in ax (se è la prima volta che viene eseguito il
loop, se è la seconda allora è il secondo carattere dell'user che viene messo
in ax ecc)
- :00409ED7 shl ax, 8 ;shifta
il carattere di 8, in modo da avere in ah il carattere e 00 in al
-
:00409EDB mov [ebp+arg_4], ax ;salva
ax e poi si comincia il vero loop da 409EE5
-
:00409EDF and [ebp+var_4], 0
- :00409EE3
jmp short loc_409EEC
- :00409EE5 ;
---------------------------------------------------------------------------
- :00409EE5
-
:00409EE5 loc_409EE5: ; CODE XREF: sub_409ECF+5Ej
-
:00409EE5 mov eax, [ebp+var_4] ;questa
parte viene saltata la prima volta...
- :00409EE8
inc eax ;qui
incrementa l'indice...
- :00409EE9 mov
[ebp+var_4], eax ;...e
lo salva :)
- :00409EEC
-
:00409EEC loc_409EEC: ; CODE XREF: sub_409ECF+14j
-
:00409EEC cmp [ebp+var_4], 8 ;lo
compara quindi con 8...in pratica è un loop che si ripete per 8 volte...
- :00409EF0 jge short loc_409F2F ;se
siamo arrivati a 8, allora esci dal loop e vai a 409F2F dove si esce dalla call
- :00409EF2 movzx eax, [ebp+arg_0] ;prende
una variabile che nel keygen noi chiameremo "value"
-
:00409EF6 movzx ecx, [ebp+arg_4] ;ora
prende il carattere (che nel keygen si chiamerà "ch") che nelle istruzioni
seguenti verra manipolato molto :)
- :00409EFA
xor eax, ecx ;li xorra
con risultato in eax (nel keygen creeremo una variabile per questo e la
chiameremo "eax")
- :00409EFC and eax,
8000h ;ora fa un and
tra eax e 8000h...
- :00409F01 test eax,
eax ;...se fa 0...
- :00409F03 jz short loc_409F17 ;...allora
saltiamo a 409F17...
- :00409F05 movzx
eax, [ebp+arg_0] ;altrimenti
prende "value" (la variabile di prima)...
-
:00409F09 shl eax, 1 ;...la
raddoppia grazie al shift left di 1...
-
:00409F0B movzx ecx, [ebp+arg_8] ;...ora
prende la "mask" che vale 1021h dal ciclo che abbiamo analizzato prima...
- :00409F0F xor eax, ecx ;...li
xorra con risultato in eax...
- :00409F11
mov [ebp+arg_0], ax ;ora seleziona
solo la word del risultato di prima, in C sarebbe eax &= 0xFFFF;
-
:00409F15 jmp short loc_409F22 ;e
ora passiamo a 409F22 per continuare il loop...
-
:00409F17 ;
---------------------------------------------------------------------------
- :00409F17 ;nel
caso prima eax and 8000h facesse 0, allora capiteremmo qui...vediamo cosa
ci attende...
- :00409F17 loc_409F17: ;
CODE XREF: sub_409ECF+34j
- :00409F17
mov ax, [ebp+arg_0] ;prende
"value" e lo mette in ax...
- :00409F1B
shl ax, 1 ;...lo
raddoppia...
- :00409F1E mov
[ebp+arg_0], ax ;...e
lo salva di nuovo...
- :00409F22 ;dal
jmp di poco fa capitiamo qui...
- :00409F22
loc_409F22: ; CODE XREF: sub_409ECF+46j
-
:00409F22 mov ax, [ebp+arg_4] ;prende
il carattere e...
- :00409F26 shl ax, 1
;...lo raddoppia...
- :00409F29 mov [ebp+arg_4], ax ;...lo
salva e...
- :00409F2D jmp short
loc_409EE5 ;...riparte
il loop :) ...
- :00409F2F ;
---------------------------------------------------------------------------
- :00409F2F
-
:00409F2F loc_409F2F: ; CODE XREF: sub_409ECF+21j
-
:00409F2F mov ax, [ebp+arg_0] ;una
volta finito il loop di 8 iterazioni, si salva "value" in ax e si esce dalla
call
- :00409F33 leave
-
:00409F34 retn
-
- A questo punto esce dalla call, rientra nel loop di
prima, e si rifà tutto daccapo con il carattere successivo dell'username :)
- Vediamo
solo di fare il punto della situazione riguardo a questa call, giusto per
essere sicuri che abbiate le idee chiare:
- prende il carattere dell'username, lo
shifta a sinistra di 8 così da avere in ah il carattere (e non più in al) e di
avere in al 00. Se per esempio l'username da noi immesso è "graftal", avremo in
ax questo: 6700. 67 sarà quindi ah, e 00 al, mi sembra oltremodo semplice :)
- Ora
invece comincia il loop vero e proprio che si rifarà per 8 volte (a causa di
quel check presente all'inizio del loop a 409EEC): prima di tutto prende una
variabile che all'inizio di tutto varrà ovviamente 0, poi prende
il carattere (il famoso 6700 di prima :)) e li xorra con risultato in eax.
Fa quindi l'and logico tra eax e il numero 8000h (attenti che è esadecimale eh!
;)) e se il risultato fa 0 allora il salto ci porta a 409F17, altrimenti si
continua il loop normalmente; prendiamo il caso in cui si continua normalmente
e vediamo che prima raddoppia "value" tramite un altro shift left e poi prende
quel numero 1021h di prima e lo xorra con "value": attenti però perché questa
volta il risultato viene salvato (sempre di word si parla!) in "value"! A
questo punto salta alla fine del loop dove "ch" viene shiftato di 1 a sinistra
e viene ovviamente salvata (come sempre) solo la word.
- Nel caso il jz di prima
fosse saltato, avevamo il raddoppiamento di "value" e il salvataggio del
risultato sempre sottoforma di word all'interno di "value" e quindi quel
raddoppiamento di "ch" che viene eseguito in ogni loop.
- Quando anche questi
loop sono finiti, abbiamo in "value" il risultato della seconda parte
dell'algo: ecco quindi che facendo il punto della situazione, sappiamo
finalmente che nella prima parte dell'algo abbiamo il numero che ci serve in
"multot" mentre nella seconda parte in "value"; il programma in seguito
aggiunge 9DDh a "value", fa uno sprintf per fare in modo che il risultato
da noi ottenuto sia unsigned, ma a noi non interessa particolarmente. Ci
interessa invece il fatto che alla fine, il serial viene creato dal programma
prendendo i primi 3 numeri di multot CONCATENATI ai primi 3 di value :))))
- Huh,
spero di essere stato almeno chiaro :)))
- Arrivati qui pero non abbiamo ancora
finito, ci manca il keygen! Allora, io ho deciso di farlo sotto windows
utilizzando una semplicissima DialogBox e il Visual C++ .NET: vi metto in
allegato al tutorial il file sorgente comunque, magari dateci un'occhiata, e se
di programmazione sotto windows non sapete nulla, chissà che non vi
dia l'ispirazione per cominciare :)
- Ok, non mi rimane altro da dire
riguardo al tutorial e/o al programma, quindi penso proprio di aver (finalmente
;p) finito :)) E mo beccatevi i ringraziamenti!! :P
Byez,
Graftal
Ommadonna, questa è la parte più difficile di tutto il
tute, ricordarsi tutte le innumerevoli persone da ringraziare è sempre arduo,
ma cercherò di scrivere i loro nomi in ordine puramente casuale: se per caso mi
scordo di qualcuno non abbiatemene :)
kOrn[CsA] che è un mio grande amico e mi ha sempre
aiutato e sostenuto :), Eimiar che è pure lui un grande amico e che almeno
conosco di persona (:P), Ntoskrnl che è un grande (sisi, proprio cosi =)),
evilcry che mi ha sempre aiutato a imparare nuove cose nell'arte del reversing
e che io stimo moltissimo :), Quake2^AM pure, mi ha dato un po di dritte molte
volte ;), AndreaGeddon, unrelated, cyberdude, active85k[], Kitsune-San (aka
Xargon :)(o viceversa, non so, gh :P)), Ch4osm4n, SeiF3r, SiberianSTAR, [igor],
Caligola (che sembra si sia volatilizzato :)), N0bodY88, blacksword, ZaDoK,
Akagi, cHr, Dejavu, jhon[array] e ultimo nella lista (e non per ordine di
importanza ;)) il nostro GRANDE Quequero che mi ha pubblicato questa "patacata"
(come direbbe Palmiro Cangini :P) :))) Thx que! =)
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.