Jpeg Optimizer v3.03
[Reversing essay]

Subject: Cracking
Target: JPEG Optimizer 3.03 (but also valid for 3.07)
Author: BlackB
Date: 1999-03-03
Tools used: W32DSM89, HIEW 6.01
Difficulty (scale 1-5): 2
Requirements: Basic knowledge of cracking

Before starting!
This essay is for knowledge purposes only!!
Software developers spend much time in making their programs. They live from the money we give them!
Please buy good software!!
I. Introduction
Well well, here I am again.....with a second tut. This time on JPEG Optimizer. Becoz I'm also kind-of-a-webdesigner (hehehe), I use this program a lot......and I think it's good (u may have another opinion). However, I didn't wrote this tut to argue if the program is good or not. ;-) Useful remark: if u tried to crack this program but u didn't manage and if u read this tut, you may ask yourself: "Oh, I didn't know it was that easy!". And sometimes it's frustrating if u see it was thát easy. No, let me say u, it is not easy:) Before I wrote this tut, I tried about everything that was possible to crack JPEG Opt. And of course, I don't mention the things that didn't work. ;-) Okay, enough, I just wanted u to know u'r not the only one with difficulties cracking programs:-/ Note: cracking with some music rulez.....especially Metallica :))
II. About the protection
Time trial
III. Cracking it
JPEG Opt. has a registration function where it asks to fill in a serial,
but I didn't manage finding the code (or I was too lazy)...so I disassembled
it in W32DSM89 :) When done I tried to find the string "Invalid registration"
but couldn't find it. It's probably encrypted....so no luck ;-(
I re-ran JPEG........yes u re-run it too.....and on the top of the window
u can see the string "Unregistered". So, let's try if we can find that!
Search for "Unregistered" and......yes here we are:

-------------------------Start of partial code-------------------------------
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00404078(U)
|
:0040407F 51                      push ecx
:00404080 E8AB590200              call 00429A30 	<- call 1
:00404085 59                      pop ecx
:00404086 84C0                    test al, al
:00404088 0F85D4010000            jne 00404262
:0040408E 66C78550FFFFFF6401      mov word ptr [ebp+FFFFFF50], 0164
:00404097 33C0                    xor eax, eax
:00404099 894580                  mov dword ptr [ebp-80], eax
:0040409C 8D5580                  lea edx, dword ptr [ebp-80]
:0040409F FF855CFFFFFF            inc dword ptr [ebp+FFFFFF5C]
:004040A5 8B1D54404800            mov ebx, dword ptr [00484054]
:004040AB 8BC3                    mov eax, ebx
:004040AD E832DC0300              call 00441CE4 	<- call 2
:004040B2 8D5580                  lea edx, dword ptr [ebp-80]
:004040B5 52                      push edx

* Possible StringData Ref from Data Obj ->" - Unregistered"
-------------------------End of partial code---------------------------------

So, there are 2 calls :-) With a (very) little bit of brains u should know
what call could be important.....yes call 1. Why? Coz after the call there's
a 'jne' instruction. 
Nopes I didn't change the 'jne' instruction, becoz it would just avoid
displaying the "Unregistered" string (btw, I didn't try it out, so I'm not
sure!). Follow my reasoning: 

		-To NOT displaying the "Unregistered" string, there has to 
		 be a check, if the program is registered.
		-As the checking procedure 'll be called several times, it
		 will be harder to change all the jump instructions
		-Conclusion: let's patch the call which checks the registered
		 -or-not flag.

As I said before, the first call is most obvious......let's go to call 1 :-)

-------------------------Start of partial code-------------------------------
* Referenced by a CALL at Addresses:
|:00404080   , :00428D89   
|
:00429A30 55                      push ebp
:00429A31 8BEC                    mov ebp, esp
:00429A33 83C4F8                  add esp, FFFFFFF8
:00429A36 53                      push ebx
:00429A37 8B4508                  mov eax, dword ptr [ebp+08]
:00429A3A 8D5DF8                  lea ebx, dword ptr [ebp-08]
:00429A3D 8A10                    mov dl, byte ptr [eax]    
:00429A3F 8813                    mov byte ptr [ebx], dl
:00429A41 8A4801                  mov cl, byte ptr [eax+01]
:00429A44 884B01                  mov byte ptr [ebx+01], cl
:00429A47 8A5002                  mov dl, byte ptr [eax+02]
:00429A4A 885302                  mov byte ptr [ebx+02], dl
:00429A4D 8A4803                  mov cl, byte ptr [eax+03]
:00429A50 884B03                  mov byte ptr [ebx+03], cl
:00429A53 8A5004                  mov dl, byte ptr [eax+04]
:00429A56 885304                  mov byte ptr [ebx+04], dl
:00429A59 8A4005                  mov al, byte ptr [eax+05]
:00429A5C 884305                  mov byte ptr [ebx+05], al
:00429A5F 0FBE0B                  movsx ecx, byte ptr [ebx]
:00429A62 51                      push ecx
:00429A63 E858570400              call 0046F1C0
:00429A68 59                      pop ecx
:00429A69 83F846                  cmp eax, 00000046
:00429A6C 7547                    jne 00429AB5
:00429A6E 0FBE4301                movsx eax, byte ptr [ebx+01]
:00429A72 50                      push eax
:00429A73 E848570400              call 0046F1C0
:00429A78 59                      pop ecx
:00429A79 83F859                  cmp eax, 00000059 <- verify 1st serial no
:00429A7C 7537                    jne 00429AB5      <- jump to "bad boy" 
:00429A7E 0FBE5302                movsx edx, byte ptr [ebx+02]
:00429A82 83FA39                  cmp edx, 00000039 <- verify 2nd serial no
:00429A85 752E                    jne 00429AB5	    <- jump to "bad boy" 
:00429A87 0FBE4B03                movsx ecx, byte ptr [ebx+03]
:00429A8B 83F932                  cmp ecx, 00000032 <- verify 3th serial no
:00429A8E 7525                    jne 00429AB5      <- jump to "bad boy"
:00429A90 0FBE4304                movsx eax, byte ptr [ebx+04]
:00429A94 83F838                  cmp eax, 00000038 <- verify 4th serial no
:00429A97 751C                    jne 00429AB5      <- jump to "bad boy"
:00429A99 0FBE5305                movsx edx, byte ptr [ebx+05]
:00429A9D 83FA31                  cmp edx, 00000031 <- verify 5th serial no
:00429AA0 7513                    jne 00429AB5      <- jump to "bad boy"
:00429AA2 C705E44748001443FC69    mov dword ptr [004847E4], 69FC4314
:00429AAC E8ABA8FDFF              call 0040435C
:00429AB1 B001                    mov al, 01        <- "01" flag=registered!
:00429AB3 EB1B                    jmp 00429AD0      <- jump to "good boy" 

-------------------------End of partial code---------------------------------

So, now it's very easy -> make the first "jne" at 00429A7C jump to
00429AB1 so it's always registered!! :)

So "jne 00429AB5" becomes "jmp 00429AB1". Do this with HIEW becoz u can
typ in assembler code....much easier then seeking out the hex code of it;)

If u don't know what HIEW is, don't now how to change the "jne" in the "jmp",
JPEG Opt. gives errors afterwards, etc... LEARN HOW TO CHANGE PROPERLY!!!
I suppose u can work with those programs, and know how to patch! If u don't:
learn. There are plenty of good tut's on the net.

Okay, if everything worked out well, u should be able to start JPEG Opt. 
immediately as a registered user!
IV. In the end

If u have any questions, comments, etc... mail me on cracking@softhome.net U can also visit my other homepage at http://myplace.to.be/blackb. It's an anti- virus site....no cracking stuff. Thanks goto: +ORC, tKC, Qapla and all other fantastic tutorial writers who taught me cracking! :-)

Endnote:
Essay written by The Blackbird © 1999-2000
This essay can be freely distributed/ published/ printed etc... as long as no modifications are made.