|
|
|
|
|
|
|
|
|
|
||
|
||
|
|
There is a crack, a crack in everything. That's how the light gets in. |
|
2. Restores the big
file from the smaller ones."
|
On first running this program the following key is created in your System Registry File.
HKEY_USERS\.Default\Software\Matex Data HB\The File Chopper\
If you use REGMON or REGVIEW then you will discover the following entries that are of interest to us..
HKEY_USERS\.Default\Software\Matex Data HB\The File Chopper\License
ExpireDay = 00008D37
(36151 Decimal) DWORD
LicenseCode=""
UserName =""
The program is able to detect any tampering
you may make to the ExpireDate value,
in which case it will set the 'ExpireDate' so that you have just 1 day
left to evaluate this program if you try and increase this value.. It's
a simple job to do and is a somewhat wasted effort on behalf of the programmer(s)
since if you delete the whole Key then the program then *thinks* it's never
been run before and gives you yet another 30 free days to evaluate this
program with. Obviously they hope you don't think of this simple trick
*grin*
|
This essay is the Third
in a series of tuts based on a program that was featured in the 'Cracking
Challengers For All' forum that shows what can be achieved if
people join together to crack the same program.
OK, lets crack on with this essay...
On running this program you'll see a simple dialog box (a nag screen) showing you how many days you have left to evaluate this program, click OK to this message box. Your now in the main program.. The Registration screen is found by selecting the Help then License Information option.
There's no Cancel button for this screen, so to quit it you need to either enter a valid serial number or click on the 'X' button found at the top right hand corner of the Registration Screen..
The program expects
you, the User, to enter a User Name/Handle and a valid License Code.. One
of the best ways to see if a programs expects an integer number or a alpha-numeric
code is to type in a series of letters for the serial number.. That way,
if the program expects just numbers then it will either crash or give you
an error message stating that the serial number must be within the ranges
of an Integer or words to this effect.. In our particular case, clicking
on the 'Check The Code' button results in the message "Sorry,
the license Code Entered Is Wrong!".
The program uses an Alpha-numeric serial number.
When you try and register this program
you'll see a standard messagebox appear informing you that 'The
license code entered is wrong!" which is ok because we can easily
get softice to break on this function when we fire up Softice a little
later on..
Lets create a Dead Listing of this program using W32Dasm, you can use IDA Pro if you wish but unless your an experienced cracker you might find the output a little hard to follow.
A quick look in our dead listing at the String Data Resources shows that there is a lot of text in both English & German, but lets carry on..
Having viewed the String Data Resources, I tend to then perform a Search for my two favourite text strings:-
The Good Guy Message
The Bad Guy Message
Ok, lets search for the 'Good Guy' text "Thank you"
Remember, we're still in our Dead Listing... You should now see this section of code..:-
*StringData Ref from Data Obj ->"Correct
license code entered. "
->"Thank you for buying this program."
:00412964 BAA33B4800
mov edx, 00483BA3
:00412969 8D85E0FAFFFF
lea eax, dword ptr [ebp+FFFFFAE0]
:0041296F E8288D0600
call 0047B69C
:00412974 FF431C
inc [ebx+1C]
<--------Snip, Snip------------>
:00412A08 BA02000000
mov edx, 00000002
:00412A0D E8E28D0600
call 0047B7F4
:00412A12 66C74310980C
mov [ebx+10], 0C98
*StringData Ref from Data Obj ->"Sorry, the license code entered is wrong!"
:00412A18 BA723C4800
mov edx, 00483C72
:00412A1D 8D85D4FAFFFF
lea eax, dword ptr [ebp+FFFFFAD4]
:00412A23 E8748C0600
call 0047B69C
OK, we've found the Good Guy & Bad
Guy messages very close to each other, so no need to do any more searches..
Normally from here we would be able to back-track our way through the code
to the conditional jump statement that would then decide which of these
messages to display but 'The File Chopper' uses a different method of accessing
routines to ones we're normally used to....
A quick look at the dead listing tells me that this program relies heavily on Memory Address Pointers which means W32Dasm is unable to work out where certain calls to routines are made from.
One of the main reasons for selecting 'The File Chopper' for this project was because of it's use of pointers to locate and execute many of it's internal routines, as well as some German text strings thrown in for good measure. So often we read about and rely on Text strings to guide us around unfamiliar code, that when a program such 'The File Chopper' uses a different method of executing the code then we too must adopt a new perspective to this problem. For many of you, this is perhaps the first time you've come across a program that uses pointer addresses to move around the code with.
While our dead listing may at first seem
somewhat hard to understand, we mustn't forget that the information we
want is still being shown to us and we can still see some *possible* places
to use some softice BPX's on. With programs that use pointers we will come
to rely more and more on Softice's ability to show us where the program
reads the pointer addresses from and where the program goes once it has
read a pointer address. Our dead listing shows us possible places to place
a bpx so make as many as you feel is necessary. I find that the 'RET'
instruction at the end of routines are extremely helpful, since they will
automatically help us to 'back-track' through the code without worrying
about where to Jump/Call the previous routine.
Using Memory pointers is a simply way to make life hard for newbie crackers when they try and follow the program's flow in their dead listings. They are also very useful from the programmer's point of view because it's quite easy to perform 'self modifying' code techniques on the program itself, now that would make things very interesting indeed but that's a totally different story!.
Here's a simple overview how Memory Address Pointers work..
The programmer sets aside an area of memory that he will use to hold the locations where some of his routines can be found. Lets call this area Table 1.
These memory addresses will be stored side-by-side and don't contain any assembler instructions such as jmp, jnz etc.
Suppose the target program has three routines, Routine 1, Routine 2, Routine 3 which the programmer wants to place their memory locations in a Table 1 then here's how it could be achieved..
Routine 1.
Begins at memory address 4703ED32
Routine 2.
Begins at memory address 416EDD00
Routine 3.
Begins at memory address 445F3400
OK, we have three routine and we know where the begin, normally a program would use CALL 4703ED32 to execute the first routine or perhaps use a JNZ 4703ED32 which we all should be familiar with by now.. However, the programmer doesn't want you to see this in your dead listing so he will replace the normal Call and JNZ statements with ones that cannot be calculated easily by W32Dasm.
The programmer will 'take' the memory address of the above three routines and store them in an area within the program which we've called Table 1.
TABLE 1.
32ED0347 00DD6E41 00345F44
:
:
:
:
:
:------------Routine 3
:
:-----------------------------Routine 2
:---------------------------------------------Routine
1
Notice how the routine addresses are 'reversed',
that's how they are stored in PC's and other computer systems and dates
back to the early days of computers..
OK, now the programmer has created a kind
of look-up table but the rest of his program now need to be told WHERE
and HOW to 'find' the addresses for Routine 1,
Routine 2, Routine
3
First, the programmer will use one of the PC's internal registers to 'point' to Table 1.
Mov EAX,40100000 <------- Set Register EAX to point to Table 1
If you type d EAX then you'll see this:-
XXXXXXXX:40100000 32ED034700DD6E4100345F44
EAX is 'Pointing' to Table 1
XXXXXXXX:40100000 32
XXXXXXXX:40100000 ED
XXXXXXXX:40100000 03
XXXXXXXX:40100000 47
XXXXXXXX:40100000 00
XXXXXXXX:40100000 DD
XXXXXXXX:40100000 6E
XXXXXXXX:40100000 41
....<Snip>....
Now in order for the program to execute
say, Routine 2 then it has to give
the computer a little math's sum to tell it where to find the start of
Routine 2.
CALL ptr [EAX+00000004]
|---||-------|
: :
: :--------Memory offset =Routine
2 Address
:---------------EAX
=Table 1
Table 1.
XXXXXXXX:40100000
00 --- First Memory address at 40100000 offset 00 - Routine
1
XXXXXXXX:40100001
CD :
XXXXXXXX:40100002
67 :
XXXXXXXX:40100003
46 ------------
XXXXXXXX:40100004
56 --- Second Memory address at 40100004 offset 04 - Routine
2
XXXXXXXX:40100005
EF :
XXXXXXXX:40100006
32 :
XXXXXXXX:40100007
41 -----------
....<Snip>....
Looking at the above Call ptr [EAX+00000004] instruction we can see that the program will take the address of Routine 2 out of Table 1 by adding the offset value [00000002] in order to retrieve the memory address stored in this table.
Since memory addresses are stored in REVERSE order we need to reverse the order of these four bytes to get the correct address.
Does this make any sense?
Don't worry too much if it doesn't yet,
it will one day when your ready..:)
OK, back to cracking File Chopper....
We're going to crack this babe via two different methods, the first
method we will choose is the nop'ing of a conditional jump, a classic newbie
crack and the other way we shall sniff out the *real* serial number so
that we can *register* this program with whatever Name/Handle we choose..
Interestingly, when we come to sniffing out the serial number we will come
across an interesting 'bug' in the program, more of this later...
CRACK
METHOD ONE - A Classic Newbie Patch
One of the most popular methods a program can use to determine how many
days you have left to evaluate the program is to read the PC's internal
clock and then take this date from the date of the file itself..
In fact, the program could use an entry in your System Registry file but
it doesn't matter what it uses, for us all we need to know right now is
that we can get Softice to trap this process using the function found in
Kernel32!GetLocalTime.
Why would we use GetlocalTime and
how does this help us?.. Well, before a program is able to determine
if it's been 'registered' or not or that you've 'run of of time' for evaluating
the software with the program must carry a set of steps that we can make
use of.. This knowledge comes from experience and a dash of logic..
Here's a simple overview of what I mean..
On start-up the program obtains the pc's internal date. It then checks this date against an entry stored in your System Registry File or with the program's .EXE file itself. If, by subtracting the 'current' pc's date by the date stored in your system registry file or from the date assigned to the program's .EXE file produces a 'negative' number then the program will now check to see if it has been 'Registered' or not. It does this by trying to retrieve the user's details from the System Registry file, or even from a hidden file stored someone on the User's hard disk. If this checks out ok then the program will insert a value of '1' into a memory location that signifies to to the rest of the program that it has been registered, if not then a value of '0' will be inserted into this same memory location..
At this point if the program has not been registered and the User has 'run out of' credit then a messagebox, the first sign of any activity from the program appears, informing the User they have no more 'free' time, after which the program will exit back to windows. If the User does have some 'free' time left and the program has not been registered then a 'Nag Screen' appears before the main program has had chance to be displayed.
If the program has been registered then the Nag Screen is bypassed and the main program is executed...
All this sounds very complicated but in reality it's just a set of logical steps that makes sense if you give this matter some further thought...
OK, we have a general idea of the processes involved before the Nag Screen is displayed, so lets see how this looks in 'The File Chopper'...
Before running The File Chopper, lets fire up Softice (Ctrl & D keys together) and type: bpx getlocaltime then x to exit Softice..
Now start up File Chopper..
Softice breaks at: KERNEL32!SetFileTime :BFF7717D
Type: bd 00 to disable the GetLocalTime breakpoint, it's done it's job so we don't need it anymore.
Press F11 once to allow Softice to finish executing this function and break once again at the point where File Chopper originally called this function,,
We should now see this snippet of code...
:00467905 668B4C240E
mov cx, word ptr [esp+0E] ;cx= current day
:0046790A 668B54240A
mov dx, word ptr [esp+0A] ;dx= current month
:0046790F 668B442408
mov ax, word ptr [esp+08] ;ax= current year
:00467914 E81FFEFFFF
call 00467738
:00467919 DD1C24
fstp qword ptr [esp] ;esp=036134h
:0046791C 9B
wait
:0046791D DD0424
fld qword ptr [esp]
:00467920 83C418
add esp, 00000018
:00467923 C3
ret
;this RETurns us to 0047BD30
OK, the above code snippet simply assigns the cx,dx,ax registers with the current date from our PC's local clock, which is stored at ESP+0E,ESP+)A, and ESP+08 respectively.. F10 through this code and you will be RETurned to this code block:-
:0047BD30 5D
pop ebp ;F10 through these two instructions.
:0047BD31 C3
ret ;this RETurns us to
00403E2E
Once you F10 on the RET instruction we are now taken to this
large code block... Now some of you have commented on some of my tuts that
they don't always show the 'thinking' behind the tracing of code blocks
so here's what I did..
:00403E2E DD9D28FFFFFF
fstp qword ptr [ebp+FFFFFF28] ;We land here...
:00403E34 DD8528FFFFFF
fld qword ptr [ebp+FFFFFF28]
:00403E3A E841000700
call 00473E80
:00403E3F 898530FFFFFF
mov dword ptr [ebp+FFFFFF30], eax
:00403E45 8D5720
lea edx, dword ptr [edi+20]
:00403E48 8D8314030000
lea eax, dword ptr [ebx+00000314]
:00403E4E E8D1790700
call 0047B824
:00403E53 8B55FC
mov edx, dword ptr [ebp-04]
:00403E56 8D4DFC
lea ecx, dword ptr [ebp-04]
:00403E59 52
push edx
:00403E5A 51
push ecx
:00403E5B 66C74610A400
mov [esi+10], 00A4
:00403E61 BA0BD64700
mov edx, 0047D60B
:00403E66 8D45C0
lea eax, dword ptr [ebp-40] ;Type: edx = UserName
:00403E69 E82E780700
call 0047B69C
:00403E6E FF461C
inc [esi+1C]
:00403E71 8B08
mov ecx, dword ptr [eax]
:00403E73 51
push ecx
;Type: ecx = UserName
:00403E74 8B8314030000
mov eax, dword ptr [ebx+00000314]
:00403E7A 50
push eax
;Type: eax = License
:00403E7B 57
push edi
:00403E7C E84FC50100
call 004203D0
:00403E81 83C414
add esp, 00000014
:00403E84 FF4E1C
dec [esi+1C]
:00403E87 8D45C0
lea eax, dword ptr [ebp-40]
:00403E8A BA02000000
mov edx, 00000002
:00403E8F E860790700
call 0047B7F4
:00403E94 66C74610B000
mov [esi+10], 00B0
:00403E9A BA20D64700
mov edx, 0047D620
:00403E9F 8D45BC
lea eax, dword ptr [ebp-44] ;Type: edx =
ExpireDay
:00403EA2 E8F5770700
call 0047B69C
:00403EA7 FF461C
inc [esi+1C]
:00403EAA BA14D64700
mov edx, 0047D614
:00403EAF 8B08
mov ecx, dword ptr [eax] ;Type:
edx = LicenseCode
:00403EB1 8D45F8
lea eax, dword ptr [ebp-08]
:00403EB4 51
push ecx
:00403EB5 50
push eax
:00403EB6 8D45B8
lea eax, dword ptr [ebp-48]
:00403EB9 E8DE770700
call 0047B69C
:00403EBE FF461C
inc [esi+1C]
:00403EC1 8B10
mov edx, dword ptr [eax]
:00403EC3 52
push edx
;Type: edx =
LicenseCode
:00403EC4 8B8B14030000
mov ecx, dword ptr [ebx+00000314]
:00403ECA 51
push ecx
;Type: ecx =
License
:00403ECB 57
push edi
:00403ECC E8FFC40100
call 004203D0
:00403ED1 83C414
add esp, 00000014
:00403ED4 FF4E1C
dec [esi+1C]
:00403ED7 8D45B8
lea eax, dword ptr [ebp-48]
:00403EDA BA02000000
mov edx, 00000002
:00403EDF E810790700
call 0047B7F4
:00403EE4 FF4E1C
dec [esi+1C]
:00403EE7 8D45BC
lea eax, dword ptr [ebp-44]
:00403EEA BA02000000
mov edx, 00000002
:00403EEF E800790700
call 0047B7F4
:00403EF4 8D8D3CFFFFFF
lea ecx, dword ptr [ebp+FFFFFF3C]
:00403EFA 6A00
push 00000000
:00403EFC 51
push ecx
:00403EFD BA21D64700
mov edx, 0047D621
:00403F02 66C74610BC00
mov [esi+10], 00BC
;Type: edx =
ExpireDay
:00403F08 8D45B4
lea eax, dword ptr [ebp-4C]
:00403F0B E88C770700
call 0047B69C
:00403F10 FF461C
inc [esi+1C]
:00403F13 8B08
mov ecx, dword ptr [eax]
:00403F15 51
push ecx
:00403F16 8B8314030000
mov eax, dword ptr [ebx+00000314]
:00403F1C 50
push eax
:00403F1D 57
push edi
:00403F1E E811C70100
call 00420634
:00403F23 83C414
add esp, 00000014
:00403F26 FF4E1C
dec [esi+1C]
:00403F29 8D45B4
lea eax, dword ptr [ebp-4C]
:00403F2C BA02000000
mov edx, 00000002
:00403F31 E8BE780700
call 0047B7F4 ;Check if this is the first time
we are running
;this program for the first time.
; Check if
memory address ebp+FFFFFF3C = 0.
; If it does
then this is the first time this program has been run on the User's computer.
:00403F36 83BD3CFFFFFF00
cmp dword ptr [ebp+FFFFFF3C], 00000000
:00403F3D 0F85CF000000
jne 00404012 ;jump
if not equal to 0, program has already been
;run
At this point if the program is being run for the FIRST time, (we can stimulate this by deleting the whole registration entry at: HKEY_CURRENT_USER\Software\Matex Data HB ) then the program WON'T jump to 0040412 but continue to execute the code following this jump. In your dead listing you will see that the program now begins to create the nessasary entries in our System Registry file for this program to use later on.
Since NOP'ing the jne 00404012 serves no purpose other than giving us unlimited evaluation period with Nag Screen we must follow the jump instead to the code block at 00404012.
We arrive now to our final block of code,
which accesses the System Registry file and attempts to fetch and User
Registration details. I know this because as I executed each instruction
I displayed the contents of the most recently changed registers.
:00404012 66C74610EC00
mov [esi+10], 00EC
:00404018 33C9
xor ecx, ecx
:0040401A 894DA4
mov dword ptr [ebp-5C], ecx
:0040401D 8D4DA4
lea ecx, dword ptr [ebp-5C]
:00404020 FF461C
inc [esi+1C]
:00404023 B850A54900
mov eax, 0049A550
:00404028 8B55FC
mov edx, dword ptr [ebp-04] ;edx = User Name from
registry file
:0040402B E854D50100
call 00421584
;See if User Name exits
;If no
User Name exist, then
;User
Name =""
:00404030 8D55A4
lea edx, dword ptr [ebp-5C]
:00404033 8D45F8
lea eax, dword ptr [ebp-08] ;eax = Serial No from
registry file
:00404036 E89D780700
call 0047B8D8
;See if Serial # exists
;If no
Serial # exists, then
;serial=""
:0040403B 50
push eax
:0040403C FF4E1C
dec [esi+1C]
:0040403F 8D45A4
lea eax, dword ptr [ebp-5C]
:00404042 BA02000000
mov edx, 00000002
:00404047 E8A8770700
call 0047B7F4
:0040404C 59
pop ecx
:0040404D 84C9
test cl, cl
;does cl = 0?
:0040404F 740C
je 0040405D
;Jump and place a '0' in the
;Shareware/Registration
Flag
;If serial from your system registry file matches the one the program has created then place ;the value '1' into memory location [0047D320].
:00404051 C60520D3470001
mov byte ptr [0047D320], 01 ;Our Registration
Flag!
:00404058 E95C020000
jmp 004042B9
;Ignore Nag Screen Reminder
:0040405D C60520D3470000
mov byte ptr [0047D320], 00 ;Our Shareware Flag!
I know what your thinking, we could NOP
out the je 0040405D instruction and then the program will always be Registered
each time it is run!.. Well although it does look promising we have to
remember that once this jump is patched and run for the FIRST time then
the program WON'T come here!. Remember, this program detects if it has
not been run and then directs the program away from the above routine where
it will display that horrible "You have 30 days to evaluate this software
bla bla bla".. If you didn't want this then you would then also have to
change the:
:00403F3D jne 00404012
to
:00403F3D jmp 00404012
Now we are begin to patch this program in two different places... To add to this mess, unless you now go into the System Registry file and enter your User Name/Handle and a fake serial directly into the System registry file then this program will show that it's been registered by someone with no name using no registration code!. It's getting to be a messy job already!..
Is there another way we could 'crack' this program without any patching of the code and which makes use of the knowledge we've already gained?
As a matter of fact this is...
CRACK
METHOD TWO - Sniffing Out A Valid Serial
Ok, where would we begin?...
Well if you've *tried* to patch this program and as a rule, Newbies tend to try this out first then you will already have covered most of the ground work leaving you now to fish out the serial number.. Easier said than done at this stage so lets see what we can do..
Lets just re-cap on what we've already covered..
The program must at least, generate a valid serial number for our User Name at least twice, once at run time when it tries to fetch the User's Details from the System Registry file and once when the User tries to register the program. The work we've already covered concentrated on the routines that are executed at start up time. Don't ask me why, but I always feel that a program is at it's weakest at run-time rather than trying to go through it once it's fully loaded into memory.. Perhaps because at run-time we can get a lock on any of it's nag screens/dialog boxes etc..
Anway...
Go back to the 'final' stage of the above
crack, just from what details we got from some of the registers and the
fact that if we forced Softice to skip over the je
0040405D instruction we could fool the program into registering
this program then we would know (feel) that the *real* serial was close
by.. Lets take a closer look at this routine a little more
closer, in fact just the top half of it...
:00404012 66C74610EC00
mov [esi+10], 00EC
:00404018 33C9
xor ecx, ecx
;At this point Register ECX has just been zero'd out by the XOR instruction on it's self...
If at this point we now type: d ebp-5c
we should see something like this in Softice's Hex/ASCII Code Window:-
XXXX:006EFCC0:
00 17 17 00 00 00 XX XX XX XX XX XX XX XX XX XX XX
*Address in blue may be different on your computer *** These numbers don't mean much to us at
this point but if we remember that this program relies heavily on
|
:0040401A 894DA4
mov dword ptr [ebp-5C], ecx
After executing the above instruction
the bytes shown in Softice Hex/ASCII Code Window show this:-
XXXX:006EFCC0:
00 17 17 00 00 00 00 XX XX XX XX XX XX XX XX XX XX
*Address in blue may be different on your computer *** The program has in effect, made sure it
starts off with a 'clean' slate. It's good programming policy
|
:0040401D 8D4DA4
lea ecx, dword ptr [ebp-5C] ;ecx now = XXXX:006EFCC0:
:00404020 FF461C
inc [esi+1C]
:00404023 B850A54900
mov eax, 0049A550
:00404028 8B55FC
mov edx, dword ptr [ebp-04] ;edx = User Name from
registry file
:0040402B E854D50100
call 00421584
;See if User Name exits
;If no
User Name exist, then
;User
Name =""
After executing the Call 00421584 instruction
the bytes shown in Softice Hex/ASCII Code Window show this:-
XXXX:006EFCC0:
B0 AA C1 00 00 00 00 XX XX XX XX XX XX XX XX XX XX
OK, the Call to 00421584 has updated the
first four bytes pointed to by [EBP-5C], so lets take a look
Type: d 00C1AABO notice I've 'reversed' their order, you must remember to do this. Hey, whats this! XXXX:00C1AABO
34302D34312D3632-2d30332D35320000
40-41-62-03-52..
This looks like a serial number but their
isn't any User Names in the System registry file for this program
If the abov serial number you can now go
into the Registration Screen and simply type in this serial
Having a Registered Program that does not
have our User Name/Handle feels like we've only done half
Fire up REGEDIT and go to this entry:- HKEY_CURRENT_USER\Software\Matex Data HB\The File Chopper\License For the UserName type in: Pirate Copy Close REGEDIT Create a Softice breakpoint: Type: BPX getlocaltime then x to leave Softice Run 'The File Chopper' Softice Breaks at the start of the GetLocalTime system function.... Press F11 once.. Keep pressing F10 UNTIL you land here:- :00404030 8D55A4 lea edx, dword ptr [ebp-5C] Type: d ebp-5c Take the first four bytes you see in Softice's Hex/ASCII Code Window in reverse order and type: D XXXXXXXX We should see something like this:- XXXX:00C1AABO
39382D31312D3335-2D30302D31360000
98-11-35-00-16..
Now we can fully register File Chopper with our User Name of 'Pirate Copy' using the serial of: 98-11-35-00-16 |
Job Done.
|
|
My thanks and gratitude goes to:-
Fravia+ for providing possibly the greatest
source of Reverse Engineering
knowledge on the Web.
+ORC for showing me the light at the end
of the tunnel.
Everyone who took part in the 'Cracking Challenges For All' forum.
|
Ripping off software through serials
and cracks is for lamers..
If your looking for cracks or serial
numbers from these pages then your wasting your time, try searching elsewhere
on the Web under Warze, Cracks etc.
Next | Return to Essay Index | Previous |