|
|
|
|
|
|
|
|
|
|
||
|
||
|
|
There is a crack, a crack in everything. That's how the light gets in. |
|
"JPEG Optimizer is designed
to create the smallest possible JPEG image files. Savings of up to 50%
in file size are possible which can considerably decrease Web Page
download times or save on disc space.
JPEG Optimizer achieves
this by:
· Giving the user
complete interactive control of the JPEG file compression setting and
· The ability to
compress some areas of the image more than others.
JPEG Optimizer is easy to
use. Users familiar with Web graphics should find it intuitive."
|
CODE="XXXXXX"
The X's represent a six digit number.
To enter your registration code you simply select the 'Help' menu
option then the 'Registration' sub option.
For those who are interested, each digit
of our registration code seems to be XOR
with the value of 93h which then gives the true registration code. My knowledge
of Assembler is very rusty but that's what it looks like to me..
|
Once you've unzipped/installed the program run it a few times, make notes on what messages are shown when you try and register the program. These notes will prove very helpful when we come to dead listing the program.
OK, we'll start of with a 'Dead Listing' of this target program, as always I choose W32Dasm to do this job, although some *experienced* crackers seem to prefer a DOS based Disassembler called IDA Pro, each to their own...
Open up the program's String Data Resources and locate the message:-
"Thank you for registering JPEG Optimizer"
Once you've done this you will also see the 'Incorrect Registration Code' message, which some crackers refer to as "The beggar off cracker" message.
Now scroll up your dead listing until you come across one of the following conditions:-
1. A
Conditional jump instruction such as jnz
XXXXXXX or JZ
XXXXXXXX
2.
A RET
instruction, signifying the end of one routine and the start of our routine.
If you understand the above two lines then you will see this code snippet:-
:00427F95
BA02000000 mov edx, 00000002
:00427F9A
E891D10100 call 00445130 ;Check
User's serial no
:00427F9F
59
pop ecx ;fetch
results and put into ecx
:00427FA0
84C9
test cl, cl ;perform AND on
low byte of ecx
:00427FA2
0F84B7000000 je 0042805F ;Show
'Beggar off Cracker' message
;if serial number is invalid.
:00427FA8
66C746102C00 mov [esi+10], 002C ;else
'Good Cracker'
:00427FAE
BA6D9B4700 mov edx, 00479B6D
:00427FB3
8D45F4 lea
eax, dword ptr [ebp-0C]
We're on the right track, it's here the program calls memory location 00445130 where it then saves the results of checking our serial number onto the STACK. When the program returns from calling memory location 00445130 it then fetches this result and places it into the ecx register. The program then checks this register to see if it contains a certain value and if this value is not the right one it knows the serial number check failed.
Some of you will
immediately see that we could simply nop (90h) out this je 0042805F instruction
so that the program will always accept whatever serial number we give it.
This is a good start
and one which I have chosen to do.. When we patch this routine using Nops
(90h) it will look like this:-
:00427F95
BA02000000 mov edx, 00000002
:00427F9A
E891D10100 call 00445130 ;Check
User's serial no
:00427F9F
59
pop ecx ;fetch
results and put into ecx
:00427FA0
84C9
test cl, cl ;perform AND on
low byte of ecx
:00427FA2
90
nop ;Proceed
to register program.
:00427FA3
90
nop
:00427FA4
90
nop
:00427FA5
90
nop
:00427FA6
90
nop
:00427FA7
90
nop
:00427FA8
66C746102C00 mov [esi+10], 002C
:00427FAE
BA6D9B4700 mov edx, 00479B6D
:00427FB3
8D45F4 lea
eax, dword ptr [ebp-0C]
We could now test this patch out and the
program would indeed accept whatever serial number we enter into it.. The
program would also create a new entry at: HKEY_LOCAL_MACHINE\SOFTWARE\XA
Tech\ with Code=XXXXXXX
the X's represent the serial number you might have used to test this patch
out.
If you Lets see if this is permanent...
Exit the program and re-run it. If we now select 'Help' then the
'About Registered Version' the program now tells us that it's disabled
functions (Batch mode etc) are now all enabled, so far so good..
However, if you now select the 'About' screen you'll see the program is
still unregistered.. We've obviously still have some more work to
do...
What's happening is this.. While we've
been able to 'fool' the program into accepting any serial number we give
it, the problem comes when we re-run the program, it's here that the program
reads our fake serial number from the System Registry File then checks
to see if it's valid, and as we know, it isn't so the program assumes it's
still unregistered.. A bug in this program means that although the program
has found our serial number invalid, it does not handle this situation
too well, that's why when we check the 'About
Registered version' screen it still shows that all the disabled
functions are in fact, all enabled, even though the program found our serial
number invalid..
Right, we have a 'dead listing' of this program, but where do we start
looking and more importantly, what do we look for!.
Just think for a moment, try and start thinking like a *cracker*, we
must understand the basics of how most programs work when it comes to Shareware
programs verifying serial numbers in order that it can start running as
a fully registered program.
1.
While loading, the program will either open up the System Registry File
or it's own .ini file and attempt to read your User details including a
serial number.
2.
If no serial number found then the program will assume it's still unregistered.
It will then place in one or more memory locations a value (usually '0'
) which the rest of program will then refer to during the course of you
using it.
In the majority of programs, a value of '0' is usually taken as meaning 'Unregistered', while a value of '1' is usually taken as meaning 'Registered'.
3. If it was able to find a serial number it then creates a real serial number based on your User details (usually based on your name/handle) then check to see if your serial number is the same as the one the program has just created from your name/handle. Again, if the program finds your serial number invalid it will place in one or more memory locations a value (usually '0' ) which the rest of program will then refer to during the course of you using it.
4. If the program gets this far then it's found your serial number as being valid and will again place in one or memory locations a value of '1' which the rest of the program will refer to as during the course of you using it. A value of '1' in certain memory locations chosen by the programmers will mean that the program has been registered.
Can you see which stage we should 'patch' the program yet?. Do you now know 'what' we should be looking for?.
For those who are still a little unsure, we want to attack the program at the 3rd stage, where it has loaded in our User details and checks to see if the serial number is valid or not. By patching the program at this stage we can fool the program into going onto the 4th stage..
Let's go back to our Dead listing, in particular lets have another look
at the 'String Data Resources'.. We are now looking at any Shareware type
messages, those that get displayed if the program is still unregistered..
Now the help file that comes with this program mentions the following items:-
Registered
Version Differences
The
Evaluation Version writes a small advertisement into the JPEG file.
The
Registered Version allows batch processing ie compressing multiple
files at one time.
The Registered Version enables Zoom, Undo and Redo.
Can you see a 'clue'?, the program writes a small 'advertisement' into any JPEG files the User may save.. Lets go fishing..
I came across these String References in
our Dead Listing... Nag256 and Nag16
which smells like 'advertisements' you
would use on 256 colour & 16 colour saved JPEG image files!. so lets
follow these up a little more closely.. Now there are two sets of memory
locations where this text string is used, we will examine the first occurrence
we come across because that's what W32Dasm found first..
*
Referenced by a (C)onditional Jump at Address: :0040361C(C)
*
Possible StringData Ref from Data Obj ->"Nag256"
|
:00403675
BAC5414700
mov edx, 004741C5
:0040367A
8D4584
lea eax, dword ptr [ebp-7C]
:0040367D
E84E180400
call 00444ED0
Ok, so far so good, now W32Dasm tells us that this routine is executed by a conditional jump statement at memory location :004036C so lets take a look at this jump statement and see what trigger's it..
:004035F9
803D00F4470000 cmp byte ptr [0047F400], 00
:00403600
7505
jne 00403607
:00403602
E8E9020000 call 004038F0
:00403607
66C7855CFFFFFF1400 mov word ptr [ebp+FFFFFF5C], 0014
:00403610
E9AE010000 jmp 004037C3
:00403615
83BD44FFFFFF00 cmp dword ptr [ebp+FFFFFF44], 00000000
:0040361C
754E
jne 0040366C ;Display Nag256 advertisement
:0040361E
66C7855CFFFFFF1C01 mov word ptr [ebp+FFFFFF5C], 011C
Take a look at that cmp dword ptr [ebp+FFFFFF44], 00000000 that precedes our conditional Nag256 jump, it's checking for a value of '0' pointed to by the register ebp+FFFFFF44, it could be checking to see if the program is registered or not!. Earlier I said that most programs uses a value of '0' to signify that the program is still unregistered but I also said that these memory locations were specially chosen by the programers themselves. However, the program may use other memory locations for different purposes that may or may not have anything to with the protection system but which ALSO uses either a value of '0' or '1' to signify different things!.. Confused yet?.
Well before making up your mind at this point just take a look a few more lines above this cmp instruction:-
:004035F9
803D00F4470000 cmp byte ptr [0047F400], 00
:00403600
7505
jne 00403607
This also is checking for a memory location that may, or may not have a value of '0'. The reasons why I'm more interested in these two lines than the ones below is because it has the potential to jump over the first sets of Nag256 advertisements if the program finds a value of '1' or more in memory location 0047F400.
At this stage we are still not sure about the importance of memory location 0047F400 other than the program checks to see if it has a value of '0' in it and if it does then it will execute the lines of code that deal with the first of two sets of Nag256 & Nag16 string references. Again, you might ask yourself how can we find out more about this memory location, well, we can do a search of our 'Dead Listing' and try and find out where it gets changed, i.e does it ever get initialized with a value of '1' .
While in our Dead Listing with the cursor at the top of the dead listing do:
search for "0047F400"
The first occurrence found using this memory location is here:
:004035F4
83FB64
cmp ebx, 00000064
:004035F7
7E0E
jle 00403607
:004035F9
803D00F4470000 cmp
byte ptr [0047F400], 00
:00403600
7505
jne 00403607
:00403602
E8E9020000
call 004038F0
Which is where we are already at, so search again for this memory location:-
* Referenced by a CALL at Address: :004045A0
:004043EC
53
push ebx
:004043ED
56
push esi
:004043EE
57
push edi
:004043EF
83C4E8
add esp, FFFFFFE8
:004043F2
C744240801000000 mov [esp+08],
00000001
:004043FA
C744241400F44700 mov [esp+14],
0047F400
:00404402
E940010000
jmp 00404547
Here the program is 'storing' the memory address [0047F400] into another memory address pointed to by the esp+14 instruction!. So from our point of view our target program CAN access memory location [47F400] from two different memory address.. Don't worry if this all sounds confusing, lets keep things nice and easy..
Lets search again for any references to memory location 0047F400:-
*
Referenced by a (C)onditional Jump at Address: 0042A4BD(C)
:0042A4B5
803093 xor
byte ptr [eax], 93 ;xor contents of eax
;with 93h
:0042A4B8
42
inc edx
;Increase count by 1
:0042A4B9
40
inc eax
;get next memory location
:0042A4BA
83FA06 cmp edx, 00000006
;count =6?
:0042A4BD
7CF6 jl 0042A4B5
;no? then loop back
;The
next 18 lines check all six memory locations (there are 6 numbers to our
serial number ) one by one pointed to by the ebx register. After some testing
I found out that the *real* serial number is NOT created in memory but
instead the program checks our serial number one number at a time.
:0042A4BF
0FBE0B movsx ecx, byte
ptr [ebx];Get 1st number of serial
:0042A4C2
83F9D8 cmp ecx, FFFFFFD8
:0042A4C5
7545 jne 0042A50C
;1st number wrong? then 'beggar off'
:0042A4C7
0FBE4301 movsx eax, byte ptr [ebx+01]
:0042A4CB
83F8D9 cmp eax, FFFFFFD9
:0042A4CE
753C jne 0042A50C
;2nd number wrong? then 'beggar off'
:0042A4D0
0FBE5302 movsx edx, byte ptr [ebx+02]
:0042A4D4
83FAA4 cmp edx, FFFFFFA4
:0042A4D7
7533 jne 0042A50C
;3rd number wrong? then 'beggar off'
:0042A4D9
0FBE4B03 movsx ecx, byte ptr [ebx+03]
:0042A4DD
83F9A1 cmp ecx, FFFFFFA1
:0042A4E0
752A jne 0042A50C
;4th number wrong? then 'beggar off'
:0042A4E2
0FBE4304 movsx eax, byte ptr [ebx+04]
:0042A4E6
83F8A7 cmp eax, FFFFFFA7
:0042A4E9
7521 jne 0042A50C
;5th number wrong? then 'beggar off'
:0042A4EB
0FBE5305 movsx edx, byte ptr [ebx+05]
:0042A4EF
83FAA5 cmp edx, FFFFFFA5
:0042A4F2
7518 jne 0042A50C
;6th number wrong? then 'beggar off'
:0042A4F4
C605F0EC470001 mov byte ptr [0047ECF0], 01 ;Serial
OK Reg Flag1=1
:0042A4FB
C60500F4470001 mov byte ptr [0047F400], 01
;Serial OK Reg
Flag2=1
:0042A502
E88993FDFF call 00403890
:0042A507
B001 mov al,
01
:0042A509
5B
pop ebx
:0042A50A
5D
pop ebp
:0042A50B
C3
ret
LOOK! This is the last reference to memory location 0047F400, it's also here that it gets initialized with a value of '1'. That's a good sign.. If you look at the whole routine you'll see many checks on consecutive memory locations pointed to by the ebx register.
In fact, if you do your own tests on this section of code (get softice to break on any bpx messageboxa calls the program might use then type u 0042A4C5 followed by bpx 0042A4C5) you'll see that it involves our six digit serial number, so if you enter more than six numbers these will be ignored. If all six numbers of our serial number pass their checks then, and only then will the program place a value of '1' in the two memory locations shown above. If you do deiced to test this routine out then once you break at 0042A4C5 follow this with r eip= 42A4F4 which is where the program places a value of '1' in memory locations [47ECF0] and [0047F400] then watch what the program does afterwards.
I apologize once again if all this might seem very confusing but it WILL start to make more sense as you get better at *cracking*. Unlike some tutorials on the web that are supposedly written for the newbie *cracker*, I try and explain the 'thinking' that goes behind the decisions I make, rather than say to you do this, do that then do this where all I will achieve is that you can follow simple instructions. It's much better I think, that the quicker you can question my chosen methods in cracking programs the better you'll become *real* crackers.
It's here that I have deiced to create my second and final 'Patch' to this program.
Here's how my second patch works..
THE ORIGINAL CODE (BEFORE)
:0042A4BF
0FBE0B movsx ecx, byte
ptr [ebx];Get 1st number of serial
:0042A4C2
83F9D8 cmp ecx, FFFFFFD8
:0042A4C5
7545 jne 0042A50C
;1st number wrong? then 'beggar off'
THE PATCHED CODE (AFTER)
:0042A4BF
0FBE0B movsx ecx, byte
ptr [ebx];Get 1st number of serial
:0042A4C2
83F9D8 cmp ecx, FFFFFFD8
:0042A4C5
EB2D jmp 0042A4F4
;Jump to: 'Register Program Code' if
;checking 1st number of our serial #
Program
now jumps here... 'Register Program Code'
:0042A4F4
C605F0EC470001 mov byte ptr [0047ECF0], 01
:0042A4FB
C60500F4470001 mov byte ptr [0047F400], 01
:0042A502
E88993FDFF call 00403890
:0042A507
B001
mov al, 01
:0042A509
5B
pop ebx
:0042A50A
5D
pop ebp
:0042A50B
C3
ret
Notice I've changed
a conditional jump on our 1st number check into a full jump instruction
which in effect, tells the program to ignore any further checks on our
serial number and to automatically pass our serial number as valid without
any further checks on it.
Job Done.
|
Load up jpegopt..exe into your favorite
Hex-Editor ( I prefer hexWorkshop-32) but just about any will do..
SEARCH FOR THE FOLLOWING BYTES
: C90F84B700000066
REPLACE WITH HIGHLIGHTED
BYTES : 9090909090909066
SEARCH FOR THE FOLLOWING BYTES
: 0FBE0B83F9D87545
REPLACE WITH HIGHLIGHTED
BYTES : 0FBE0B83F9D8EB2D
|
|
Next | Return to Essay Index | Previous |