-
Program generates
two valid serial numbers.
-
First serial contians
numbers and letters (HEX format), and second serial contains only numbers
(DECIMAL format).
-
Each serial number
is generated with two calculation routines.
-
First calc routine generates
first four characters and second one generates second four characters of
serial.
-
That means that serials
has eight characters!
-
-
Let's start...
-
-
When you run Winzip,
you'll see nag screen that pops up.
-
Press ' Enter Registration
Code' button and enter your handle and any random serial number.
-
For example here is
what entered:
-
-
Name:
Borna Janes
-
Registration #:
998899
-
-
-
Press CTRL-D to
pop up Softice and type bpx GetDlgItemTextA, then hit CTRL-D
again to leave Softice.
-
-
Press 'OK' button.
-
Softice now breaks on
GetDlgItemTextA function, hit ' F11'
to return to Winzip code and 'BD
0' for disable breakpoint.
-
You can now see this
section of code:
-
-
:00408014
FF150C844600 Call dword ptr [0046840C]
-
:0040801A
53
push ebx
;We
are here
-
:0040801B
E879160200 call 00429699
-
:00408020
59
pop ecx
;ECX = Name
-
:00408021
53
push ebx
-
:00408022
E89B160200 call 004296C2
-
:00408027
59
pop ecx
-
:00408028
BE58D94700 mov esi, 0047D958
-
:0040802D
6A0B
push 0000000B
-
:0040802F
56
push esi
-
:00408030
68810C0000 push 00000C81
-
:00408035
57
push edi
-
:00408036
FF150C844600 Call dword ptr [0046840C]
-
:0040803C
56
push esi
-
:0040803D
E857160200 call 00429699
-
:00408042
59
pop ecx
;ECX
= fake serial
-
:00408043
56
push esi
-
:00408044
E879160200 call 004296C2
-
:00408049
803D28D9470000 cmp byte ptr [0047D928], 00
;Check
lenth of name
-
:00408050
59
pop ecx
;ECX
= fake serial
-
:00408051
745F
je 004080B2
;If
0 then display error
-
:00408053
803D58D9470000 cmp byte ptr [0047D958], 00
;Check
lenth of serial
-
:0040805A
7456
je 004080B2
;If
0 then display error
-
:0040805C
E8EAFAFFFF call 00407B4B
;Create
and compare serials
-
:00408061
85C0
test eax, eax
;EAX
0 = Wrong serial, EAX 1 = Good serial
-
:00408063
744D
je 004080B2
;If
wrong serial display error
-
:00408065
53
push ebx
-
:00408066
BBB80C4700 mov ebx, 00470CB8
-
-
How we can see there
are two calls to GetDlgItemTextA function.
-
One for name and one
for serial. After that calls program puts locations of name and serial
in ECX.
-
There are also two compare
functions at 00408049 and 00408053.
-
They checks lenth of
name and serial. If there is no name or serial then display error message.
-
For us is only important
call at 0040805C witch create real and compare fake and real serial.
-
If number is wrong then
EAX = 0 if number is good then EAX = 1.
-
If you anywhere inside
the call at 40805C see XOR EAX,EAX it's bad because it indicates that serial
is wrong!
-
Now press 'F10'
until you step on 0040805C then
press 'T'
to trace the code inside the call.
-
-
You'll now see this
piece of code:
-
-
-
:00407B4B
55
push ebp
-
:00407B4C
8BEC
mov ebp, esp
-
:00407B4E
81EC08020000 sub esp, 00000208
-
:00407B54
53
push ebx
-
:00407B55
56
push esi
-
:00407B56
33F6
xor esi, esi
;ESI
= 0
-
:00407B58
803D28D9470000 cmp byte ptr [0047D928], 00
;Check
lenth of name
-
:00407B5F
57
push edi
-
:00407B60
0F84A1000000 je 00407C07
;If
0 then display error
-
:00407B66
8D45EC
lea eax, dword ptr [ebp-14] ;Memory
location for next string
-
:00407B69
50
push eax
-
:00407B6A
6860F44600 push 0046F460
-
:00407B6F
E84F9CFFFF call 004017C3
;Save
"MuradMeraly" to EAX
-
:00407B74
59
pop ecx
-
:00407B75
8D85F8FDFFFF lea eax, dword ptr [ebp+FFFFFDF8]
;Memory
location for next string
-
:00407B7B
59
pop ecx
;ECX=
"MuradMeraly"
-
:00407B7C
BF28D94700 mov edi, 0047D928
;EDI
= Name
-
:00407B81
50
push eax
-
:00407B82
57
push edi
-
:00407B83
E8A9020000 call 00407E31
;Make
second copy of name
-
:00407B88
59
pop ecx
-
:00407B89
8D85F8FDFFFF lea eax, dword ptr [ebp+FFFFFDF8]
-
:00407B8F
59
pop ecx
;ECX
= Second copy of name
-
:00407B90
50
push eax
-
:00407B91
8D45EC
lea eax, dword ptr [ebp-14] ;EAX
= "MuradMeraly"
-
:00407B94
50
push eax
-
:00407B95
E866FD0400 call 00457900
;Compare
"MuradMeraly" and second copy of
-
name
-
:00407B9A
59
pop ecx
;If
they are the same then EAX = 0, else EAX = 1
-
:00407B9B
59
pop ecx
-
:00407B9C
6A01
push 00000001
-
:00407B9E
85C0
test eax, eax
;Check
EAX
-
:00407BA0
5B
pop ebx
-
:00407BA1
7502
jne 00407BA5
;If
EAX= 0 then then then ESI = 1
-
:00407BA3
8BF3
mov esi, ebx
-
:00407BA5
8D45EC
lea eax, dword ptr [ebp-14]
-
-
What progarm does
program do here?
-
First program makes
second copy of name without spaces, numbers... (only with letters)
-
You can see second
copy of name by typeing "D ECX" when you standing on 407B91
-
You can also see
"MuradMeraly" string at 407B91 by typing "D EAX"
-
-
If you don't know
"D" command display(dump) memory location,
-
in our case we dump
memory location witch is situated in eax (ecx)
-
-
Then program compare
"MuradMeraly" with second copy of name.
-
If you are "MuradMeraly"
then EAX = 0, if you're not then EAX = 1.
-
If EAX = 0(if you
are Murad Meraly) then program sets ESI to 1, else ESI = 0.
-
-
:00407BA8
50
push eax
-
:00407BA9
6870F44600 push 0046F470
-
:00407BAE
E8109CFFFF call 004017C3
-
:00407BB3
59
pop ecx
-
:00407BB4
8D45EC
lea eax, dword ptr [ebp-14]
-
:00407BB7
59
pop ecx
-
:00407BB8
50
push eax
-
:00407BB9
57
push edi
-
:00407BBA
E841FD0400 call 00457900
-
:00407BBF
59
pop ecx
-
:00407BC0
85C0
test eax, eax
-
:00407BC2
59
pop ecx
-
:00407BC3
750C
jne 00407BD1
-
:00407BC5
FF15C4814600 Call dword ptr [004681C4]
-
:00407BCB
84C3
test bl, al
-
:00407BCD
7402
je 00407BD1
-
:00407BCF
8BF3
mov esi, ebx
-
:00407BD1
6A14
push 00000014
-
:00407BD3
8D45EC
lea eax, dword ptr [ebp-14]
-
:00407BD6
6A00
push 00000000
-
:00407BD8
50
push eax
-
:00407BD9
E872E50400 call 00456150
-
:00407BDE
83C40C
add esp, 0000000C
-
:00407BE1
8D85F8FDFFFF lea eax, dword ptr [ebp+FFFFFDF8]
-
:00407BE7
68C8000000 push 000000C8
-
:00407BEC
6A00
push 00000000
-
:00407BEE
50
push eax
-
:00407BEF
E85CE50400 call 00456150
-
:00407BF4
83C40C
add esp, 0000000C
-
:00407BF7
85F6
test esi, esi
;Check
ESI
-
:00407BF9
7413
je 00407C0E
;If
ESI = 0 then skip next few lines
-
:00407BFB
E89C060000 call 0040829C
-
:00407C00
83257CB0470000 and dword ptr [0047B07C], 00000000
-
:00407C07
33C0
xor eax, eax
;EAX
= 0
-
:00407C09
E9B3000000 jmp 00407CC1
;Jump
to end of the routine
-
-
If ESI = 1 (if you
are Murad Meraly) then set EAX to 0 (if you remember it indicates bad serial),
-
jump to the end
of the routine, and display error message!
-
If ESI = 0 (if you
are not Murad Meraly) then skip next few lines and jump to 407C0E
-
Why Murad Meraly
can't register Winzip?
-
Murad Meraly is
first cracker who sucessfuly cracked WinZip and he is in the Nico Mak Computing
blacklist
-
Now here is the
most important part of code.
-
Program here generates
two valid serial numbers:
-
:00407C0E
8D85C0FEFFFF lea eax, dword ptr [ebp+FFFFFEC0]
;Memory
location for first serial
-
:00407C14
50
push eax
-
:00407C15
57
push edi
-
:00407C16
E8AB000000 call 00407CC6
;Generate
first serial
-
:00407C1B
59
pop ecx
-
:00407C1C
BE58D94700 mov esi, 0047D958
-
:00407C21
59
pop ecx
;ECX
= First serial
-
-
Type "D ECX"
here to see first valid serial number
-
-
:00407C22
8D85C0FEFFFF lea eax, dword ptr [ebp+FFFFFEC0]
-
:00407C28
56
push esi
-
:00407C29
50
push eax
-
:00407C2A
E8D1FC0400 call 00457900
;Compare
first serial with *fake* serial
-
:00407C2F
F7D8
neg eax
-
:00407C31
1BC0
sbb eax, eax
-
:00407C33
59
pop ecx
-
:00407C34
40
inc eax
-
:00407C35
59
pop ecx
-
:00407C36
A37CB04700 mov dword ptr
[0047B07C], eax ;Save
registration result 1 = Good serial
-
:00407C3B
7569
jne 00407CA6
;into
memory
0 = Bad serial
-
:00407C3D
8D85C0FEFFFF lea eax, dword ptr [ebp+FFFFFEC0]
;Memory
location for second serial
-
:00407C43
50
push eax
-
:00407C44
57
push edi
-
:00407C45
E820010000 call 00407D6A
;Generate
second serial
-
:00407C4A
59
pop ecx
-
:00407C4B
8D85C0FEFFFF lea eax, dword ptr [ebp+FFFFFEC0]
-
:00407C51
59
pop ecx
;ECX
= Second serial
Type "D ECX"
here to see second valid serial number
-
:00407C52
56
push esi
-
:00407C53
50
push eax
-
:00407C54
E8A7FC0400 call 00457900
;Compare
second serial with *fake* serial
-
:00407C59
F7D8
neg eax
-
:00407C5B
1BC0
sbb eax, eax
-
:00407C5D
59
pop ecx
-
:00407C5E
40
inc eax
-
:00407C5F
59
pop ecx
-
:00407C60
A37CB04700 mov dword ptr
[0047B07C], eax ;Save
registration result 1 = Good serial
-
:00407C65
753F
jne 00407CA6
;into
memory
0 = Bad serial
-
-
Now we can see that
program generates two valid serial numbers, and compare it with our *fake*
serial!
-
First valid serial
number contain letters and numbers (HEX format),
-
and second serial
contain only numbers (DECIMAL format).
-
If our serial is
same as one of two valid serial numbers, then program set eax to 1.
-
If our serial is
not same as any of two valid serials then eax is 0.
-
Program also save
registration result (EAX) into memory.
-
After this only
is important call at 407CB4 witch clear the part of memory where correct
serial was saved!
-
If we want to make
KeyGen we must trace the code inside calls witch generates correct serials!
-
(If you are not
going to make KeyGen, you have two correct serials and you can register
Winzip with one of them)
-
Press "F10"
until you get to 407C16 CALL 407CC6
, here program generates first serial.
-
Now type "T"
to trace the code inside the call
|
First
valid serial number
|
-
-
You'll now see this
part of code:
-
-
Looking at the following
generation routine we can see that it include two calculation routines
-
-
:00407CC6
55
push ebp
-
:00407CC7
8BEC
mov ebp, esp
-
:00407CC9
51
push ecx
-
:00407CCA
8B4D08
mov ecx, dword ptr [ebp+08] ;ECX
= Name
-
:00407CCD
8365FC00
and dword ptr [ebp-04], 00000000 ;Clear
memory for first
-
:00407CD1
53
push ebx
;four
characters of serial
-
:00407CD2
56
push esi
-
:00407CD3
8A11
mov dl, byte ptr [ecx]
;EDX(DL)
= First character of name
-
:00407CD5
57
push edi
;EDI
= Name
-
:00407CD6
33C0
xor eax, eax
;EAX
= 0
-
:00407CD8
8BF1
mov esi, ecx
;ESI
= Name
-
:00407CDA
33FF
xor edi, edi
;EDI
= 0
-
:00407CDC
84D2
test dl, dl
;Check
EDX(DL)
-
:00407CDE
7413
je 00407CF3
;If
end of name then exit calculation routine
-
:00407CE0
660FB6D2
movzx dx, dl
;EDX(DX)
= EDX(DL)
-
:00407CE4
8BDF
mov ebx, edi
;EBX
= EDI
-
:00407CE6
0FAFDA
imul ebx, edx
;EBX
= EBX * EDI
-
:00407CE9
015DFC
add dword ptr [ebp-04], ebx ;Add
EBX to [EBP-04]
-
:00407CEC
8A5601
mov dl, byte ptr [esi+01]
;Next
character to EDX(DL)
-
:00407CEF
47
inc edi
;EDI
= EDI + 1
-
:00407CF0
46
inc esi
;ESI
= ESI + 1
-
:00407CF1
EBE9
jmp 00407CDC
;Loop
this [lenth of name] times
-
-
Here is the end
of first calculation routine.
-
We can see that
program takes character from name (EDX) and multiply it with EBX witch
is growing up by one
-
every next character
(starting with zero).
-
Every time when
program get the result of multiplying it adds it to [EBP-04]
-
Here is exemple:
My handle is "Borna Janes"; EBX
is 0
-
1. char of name is "B"(42h) program multiplys it with EBX witch is 0;
EBX grows by 1 -- EBX is 1
-
Result of multiply is 0, program saves it to [EBP-04]
-
2. char of name is "o"(6Fh) program multiplys it with EBX witch is 1;
EBX grows by 1 -- EBX is 2
-
Result of multiply is 6F, program saves it to [EBP-04]
-
3. char of name is "r"(72h) program multiplys it with EBX witch is 2;
EBX grows by 1 -- EBX is 3
-
Result of multiply is E4, program saves it to [EBP-04]
-
.....and so on!
-
When calculation
routine ends, when there is no more characters to multiply type "D EBP-04"
and you'll see the sum of
-
all multiplys in
data window. Thats second four characters of serial but in REVERSE
FORM !!
-
In my case sum is
"9F 14" but my serial ends with "149F".
-
-
Let's take a look
how program generates first four characters of serial
-
-
Here is second calculation
routine:
-
-
-
:00407CF3
C705ECD3470001000000 mov dword ptr [0047D3EC], 00000001
-
:00407CFD
8BF1
mov esi, ecx
;ESI
= Name
-
:00407CFF
8A09
mov cl, byte ptr [ecx]
;ECX(CL)
= First character of name
-
:00407D01
84C9
test cl, cl
;Check
ECDX(CL)
-
:00407D03
7419
je 00407D1E
;If
end of name then exit calculation routine
-
:00407D05
660FB6C9
movzx cx, cl
;ECX(CX)
= ECX(CL)
-
:00407D09
6821100000
push 00001021
;Save
"1021" onto the stack
-
:00407D0E
51
push ecx
;Save
ECX
-
:00407D0F
50
push eax
;Save
EAX
-
:00407D10
E82A000000
call 00407D3F
;Call
calculation subroutine
-
:00407D15
8A4E01
mov cl, byte ptr [esi+01]
;Next
character to ECX(CL)
-
:00407D18
83C40C
add esp, 0000000C
;ESP
= ESP - 0C
-
:00407D1B
46
inc esi
;ESI
= ESI + 1
-
:00407D1C
EBE3
jmp 00407D01
;Loop
this [lenth of name] times
-
-
Here is the end
of second calculation routine.
-
-
What can we see
here?
-
1. Program takes
one character user name and saves it on the stack(ECX).
-
2. Program saves
"1021" onto the stack.
-
3. Program calls
calculation subroutine, and result of calculation adds in EAX.
-
-
Program loops this
calculation routine for every character of name.
-
When the routine
ends sum of calculations is in EAX.
-
This number is very
close with our second four chars of serial.
-
You'll see later
how program make from number in EAX, our second piece of serial.
-
Now let's see what
program do in calculation routine called at 407D10
call 407D3F!
Here is the code:
-
:00407D3F
55
push ebp
;Save
EBP
-
:00407D40
8BEC
mov ebp, esp
;EBP
= ESP
-
:00407D42
8B4508
mov eax, dword ptr [ebp+08] ;Load
EAX from the stack (EAX stays same)
-
:00407D45
56
push esi
;ESI
= Name
-
:00407D46
33C9
xor ecx, ecx
;ECX
= 0
-
:00407D48
6A08
push 00000008
;Save
"00000008" onto stack
-
:00407D4A
8A6D0C
mov ch, byte ptr [ebp+0C] ;CH
= Next char of name; ECX = Char + "00"
-
:00407D4D
5A
pop edx
;Loads
"8" from stack and puts it to EDX
-
:00407D4E
8BF1
mov esi, ecx
;ESI
= ECX
-
:00407D50
33F0
xor esi, eax
;ESI
= ESI XOR EAX
-
:00407D52
66F7C60080
test si, 8000
;Check
SI (first four chars of ESI)
-
:00407D57
7407
je 00407D60
;If
less then 8000 then jump to 407D60
-
:00407D59
03C0
add eax, eax
;EAX
= EAX + EAX
-
:00407D5B
334510
xor eax, dword ptr [ebp+10] ;EAX
= EAX XOR "1021"
-
:00407D5E
EB02
jmp 00407D62
;Jump to 407D62
-
:00407D60
D1E0
shl eax, 1
;Shift EAX
left by one bit
-
:00407D62
D1E1
shl ecx, 1
;Shift
ECX left by one bit
-
:00407D64
4A
dec edx
;EDX
= EDX - 1
-
:00407D65
75E7
jne 00407D4E
;Loop
this until EDX = 0 (eight times)
-
:00407D67
5E
pop esi
-
:00407D68
5D
pop ebp
-
:00407D69
C3
ret
-
What program do
here?
-
It takes char from user name and
puts it to CH (ECX = Char + "00")
-
Then puts number eight to EDX,
and loop this function eight times:
-
-
1. ESI = ECX ( first time it's
char of name + "00")
-
2. Xor ESI with EAX
-
3. Check is SI (first four chars
of ESI) less then 8000
-
4. If yes then jump to 8
-
5. Adds EAX to EAX (EAX = EAX
* 2)
-
6. Xor EAX with 1021
-
7. Jump to 9
-
8. Shift EAX left by one bit,
it's same as EAX = EAX *
2
-
9. Shift ECX left by one bit,
it's same as ECX = ECX *
2
-
Result of this subroutine
routine is located in EAX!
-
-
Ok, that was calculation
subroutine called from main calc routine at 407D10
call 407D3F!
-
How I already say
when main calc routine ends result of all calculation is located in EAX!
-
You are probably
thinking that our second piece of serial is EAX, ok it's very close but
it's not!
-
Where the hell are
our second piece of serial?
-
Let's see...
-
-
Here is continue
of code cuted at 407D1C:
-
:00407D1E
0FB74DFC
movzx ecx, word ptr [ebp-04] ;ECX
= First piece of our serial
-
:00407D22
83C063
add eax, 00000063
;EAX
= EAX + 63
-
:00407D25
51
push ecx
;Save
ECX
-
:00407D26
0FB7C0
movzx eax, ax
;EAX
= AX; EAX = First four char of EAX
-
:00407D29
50
push eax
;Save
EAX
-
-
We'll stop here
for a moment!
-
Now take a look
at EAX after adding "63", IT'S SECOND PIECE OF SERIAL!
-
Also take a look
at ECX, that is FIRST PIECE OF SERIAL!
-
If you connect these
two pieces, you'll get CORRECT SERIAL!
-
-
:00407D2A
6884F44600
push 0046F484
-
:00407D2F
FF750C
push [ebp+0C]
;Memory
location to save serial
-
:00407D32
E869E20400
call 00455FA0
;Save
serial to memory
-
:00407D37
83C410
add esp, 00000010
-
:00407D3A
5F
pop edi
-
:00407D3B
5E
pop esi
-
:00407D3C
5B
pop ebx
-
:00407D3D
C9
leave
-
:00407D3E
C3
ret
-
-
-
We came to the end
of routine that generates first valid serial number.
-
Let's see how program
generates second serial...
|
Second
valid serial number
|
-
-
Program generates
second valid serial number on the very similar way.
-
I'll don't write
all code here because it's almost same, i'll explain how program do that!
-
-
First, program generates second
valid serial from second copy of our name in lower
case!
-
If you don't remember second copy
of name is without spaces, numbers... ONLY LETTERS!
-
Calculation routines for second
serial are same!
-
But here is the difference:
-
Second four characters of serial
are decimal value of result of first calculation routine!
-
First four characters of serial
are decimal value of result of second calculation routine!
-
-
Here is exemple:
-
-
My name is "Borna Janes"
-
Program generates second serial
from second copy of name in lower case, It's "bornajanes"!
-
Result of first calculation routine
is "12AE", decimal value of "12AE" is "4782".
-
"4782" are second four characters of my second
valid serial number
-
-
Result of second calculation routine
is "1B9C", decimal value of "1B9C" is "7068".
-
"7068" are first four characters of my second
valid serial number.
-
-
The most easiest way to found
second serial is to enter second copy of your name( lower case),
-
for USER NAME, and any random
serial!
-
Then trace the code just how I
explain before, and when you step on 407D2A you'll see
-
first piece of serial in EAX,
and secod piece in ECX.
-
You can also put breakpoint at
407D2A with "BPX 407D2A"
-
-
Now only what you must do
is to convert them to decimal and you have your second serial!!
|