not assigned
JavaWorkshop 2.0 cracking
by +Alt-F4, 4 January 1998


Courtesy of Reverser's page of reverse engineering
reverser's comments
That's a good +cracker!
I mildly criticized +Alt+F4 for having written in the previous version of this essay, back in October 97: "If part of the crack is missing, I will probably find out within the next week or so, and will post a new version..." and he sent a more complete essay, which is a state of the art work. I was thinking about including this, together with A+heist's Symantec Visual café essay, in our project1 (tools of the trade), since I feel that Java workshops and compilers are going to be very soon among the most important tools for reverse engineers (which is good: die Gates, die! :-)
We will see, may be we should open a completely new HCU "Java" section. Enjoy (for the second time, but you have gained a lot in comparison with the previous essay) this nice work by +Alt-F4
Cracking Sun's JavaWorkshop 2.0
Written by +Alt-F4 on January 3rd, 1998.
( )Beginner (x)Intermediate ( )Advanced ( )Expert
Part 1 requires understanding of using Softice, and using a dead code listing
Part 2 requires understanding of java.
In this Essay I will show how to crack Sun's Java Workshop 2.0
This is an important target, because (as +Orc says), Java is the future of cracking.
I will show 2 approaches to cracking this program:
Part1 will show how to crack the date using a Live and Dead code approach
Part2 will show how to get a serial number, using pure dead code on a java Dissasembley
Tools Required
Mocha(java Decompiler)
Softice(Windows Debugger)
W32Dasm(Windows Dissasemler)

Don't just use these though, use what ever tools you like(Prehaps IDA?)
Program History
No known(or intersting) history

~Part 1:Cracking the Date Check

The target:
Java Workshop 2.0, trial edition: setupjws.exe	(20303236 bytes)
Where you can get it:

Installing this product, you find a huge monstrosity on your
hard-drive, 50 megs of overbloated, very slow programming.

The first strange thing I noticed was the size of the executable,
jws.exe is only 29696 bytes!

Obviously it is using dll's to do everything, but which ones?
There are 32 dll's in different places in the directory structure.
Using Borland Resource Workshop I found that they don't use standard
windows resources (At least all the dll's I could be bothered 
checking used none)

Obviously, the first approach would be to get a valid serial number

This is hard using Softice and W32Dasm though, so I did a date crack first.

Ok, load up winice 3.0 and bpx on getlocaltime...
Whenever it is executed edit the place where the date is returned
To make this easier, I decided to start learning some of winice's more
useful features.
Use bpx getlocaltime do "p ret"
This returns softice to where getlocaltime was called.

The first one looks like this

call kernel32!GetLocalTime
mov  cx,[esp+12]
mov eax,[esp+04]

Ok, The date is returned above esp, so edit esp
e esp
Look for the year, which will be CD07 (1997 in Hex format, Don't
forget Intel's use reverse format so CD07 really is 0x07CD)
Change it to CE, and then continue.

After doing this a few times, you find the nag does not pop up, so
obviously it is not using getlocaltime for this purpose.

Looking in the windows help for getlocaltime, I found a link to
getsystemtime. Lets see if this is what the target is using.
bpx getsystemtime.
Whenever it breaks, set the year to 07CE as above.

Wow! Hundreds of calls!

After a while I realised that one place in particular was getting a
lot of calls, (possibly a timer?), so I told winice to only snap when
the location wasn't this one,(So I could continue..)
But first I typed stack to see where I was


bpx getlocaltimer if *esp != 2264717
(I did this, because when called, getsystemtime has the return address
in esp, so this will only break when the return address is not

After doing this, there are a lot more calls from a different location.
Calling stack again I see


I then extend the breakpoint to not include this one
bpe 0
change to
bpx getlocaltime if *esp!= 2264717 && *esp!= 10030FD9
It now goes into the program, so one of those two locations must be
used to check the date, or it is using some other different procedure.

Testing our theory

Lets  check if it really is using getsystemtime...
Clear all breaks (bc *)
and bpx getsystemtime

Now trace through getsystemtime, until you get here...
BFF9B2FC	push esi
BFF9B2FD	call BFF76920
BFF9B302	mov ax, [esi]
BFF9B305	mov cx, [esi+02]
BFF9B309	mov dx, [esi+04]

Ok, on 302 type "d esi", and you can see it is
getting the year.
Now for some fun, lets do a temporary patch on Win 95!
"a BFF9B302", and change
mov ax, [esi] to
mov ax, 07CE	

We are now forcing getsystemtime to always return 1998, so if the nag
screen appears
we know it is using getsystemtime.

Now clear all breakpoints and go.
Hurrah, the nag has appeared, now we can be certain that it is using
Of course we can't patch Win95 like this (Although other more useful 
patches might be an interesting idea! Prehaps a future +HCU project!)
We had better find where getsystemtime is being used. First we should
clean up our patch, by either changing it back, or resetting 
the computer.

Homing in for the kill

Ok, we now know it is using getsystemtime, and we have narrowed it down to
only two locations (It couldn't be any of the other locations that
use getsystemtime, as we were editting the year that they were
We also know which dll's the target is using now, so we can dissassemble 
Load up Wdasm8.9 (Search for the full registered version)
and dissassemble Javai.dll and winawt.dll

Javai gets called first, then winawt, then javai again, so lets look
at javai first:

Here is the code for Javai.dll

* Reference To: KERNEL32.SystemTimeToFileTime, Ord:023Fh
:10030FC8 8B3DD8520610            mov edi, dword ptr [100652D8]
:10030FCE 8D442418                lea eax, dword ptr [esp+18]
:10030FD2 50                      push eax

* Reference To: KERNEL32.GetSystemTime, Ord:0134h
:10030FD3 FF15D0520610            Call dword ptr [100652D0]
:10030FD9 8D4C2410                lea ecx, dword ptr [esp+10]
:10030FDD 8D442418                lea eax, dword ptr [esp+18]
:10030FE1 51                      push ecx		;Output date in file format
:10030FE2 50                      push eax		;Input date in normal format
:10030FE3 FFD7                    call edi		;SystemTimeToFiletime
:10030FE5 B120                    mov cl, 20
:10030FE7 8B442414                mov eax, dword ptr [esp+14]
:10030FEB 33D2                    xor edx, edx
:10030FED E8AEA70100              call 1004B7A0
:10030FF2 8B4C2410                mov ecx, dword ptr [esp+10]
:10030FF6 83CA00                  or edx, 00000000
:10030FF9 0BC1                    or eax, ecx
:10030FFB 8B2D180A0610            mov ebp, dword ptr [10060A18]
:10031001 2BC5                    sub eax, ebp
:10031003 8B351C0A0610            mov esi, dword ptr [10060A1C]
:10031009 1BD6                    sbb edx, esi
:1003100B 6A00                    push 00000000
:1003100D 6810270000              push 00002710
:10031012 52                      push edx
:10031013 50                      push eax
:10031014 E8D7A60100              call 1004B6F0
:10031019 5D                      pop ebp
:1003101A 5F                      pop edi
:1003101B 5E                      pop esi
:1003101C 5B                      pop ebx
:1003101D 83C418                  add esp, 00000018
:10031020 C3                      ret

According to the Win32 online help that comes with BC++ 4.5
systemfiletofiletime converts an ordinary time to a "64-bit value
representing the number of 100-nanosecond intervals since 
January 1, 1601"

Hmm this:
:10030FFB 8B2D180A0610            mov ebp, dword ptr [10060A18]
:10031001 2BC5                    sub eax, ebp
:10031003 8B351C0A0610            mov esi, dword ptr [10060A1C]
:10031009 1BD6                    sbb edx, esi

looks encouraging!
Retreiving a global variable, followed by an operation that compares it
with another variable. Could well be dates stored in those variables!

I played around with these locations in winice, and found that esi
ends up with the installation date, and edx has
todays date.
After the sbb edx stores a number that is the difference
between the two dates.

Patching Javai.dll

I found a value of edx when the program was ok(1F19DF), and then changed the
code to this:

:10031003 BADF191F00              mov edx, 001F19DF
:10031008 50			  push eax
:10031009 90			  nop
:1003100A 58                      pop  eax
After this, EDX will always have a valid number, regardless of the
date, so 
JWS will never expire.

This works for a date crack, but I still wan't happy.

There must have been a way to get a serial number.....

~Part 2:Getting a serial number

The intersting thing about Java Workshop, is that a LOT of it is written in Java(I would like to thank panoramix^impact97 for pointing this out)
This is good for sun, because they can make versions for different platforms very easily.
It is even better for us, because java can be diss-assembled until it almost looks like source code!(As you will soon see)

Unzipping, an intersting class is found, License.class
Dissasembling this file(Either with mocha or IDA), we see that it uses another class(base.LicenseUtils) to do all it's dirty work.

Running mocha on this new class, we find the source code for the Registration checking!

Look at some of these interesting functions!
private static boolean validateSerialNo(String serial)
public static boolean validateVersion(String serialno)
public static boolean checkSerialNo()
public static boolean isGoldScholarSerial(String serial)

I won't bother you with all the details, but the basic checking is:
-Must be 23 characters long
-Must Contain "-" in position 6 and 13
-Searches for certain text strings at certain positions(Such as JWS200 at the start)
-Uses the last 2 characters as a check-sum

Thanks to Mocha, we have source code for the check-sum:

 private static String generateCheck(String b)
        String ret;
        int x0 = b.charAt(0) - 65 + 1;
        int x1 = b.charAt(1) - 65 + 1;
        int x2 = b.charAt(2) - 65 + 1;
        int v0 = b.charAt(3) - 48;
        int v1 = b.charAt(4) - 48;
        int v2 = b.charAt(5) - 48;
        int z0 = b.charAt(7) - 97;
        int z1 = b.charAt(8) - 97;
        int z2 = b.charAt(9) - 97;
        int check = x0 + (27 - x1) + x2;
        check += v0 + (9 - v1) + v2;
        if (newVersion(b))
            check += z0 + (13 - z1) + z2;
        check += b.charAt(14) - 48;
        check += 9 - (b.charAt(15) - 48);
        check += b.charAt(16) - 48;
        check += 9 - (b.charAt(17) - 48);
        check += b.charAt(18) - 48;
        check += 9 - (b.charAt(19) - 48);
        check += b.charAt(20) - 48;

	//Strange code here! Just turns check into a string padded with 0's
        for (ret = Integer.toString(check % 100); ret.length() <2; ret="new" StringBuffer("0").append(ret).toString()) /* null body */ ; return ret; } 
(Quite amazing how well mocha works, isn't it?)

I then made a little java program, that takes an input string, and displays the expected
checksum(Source code not included, it only took 5 minutes)
Ok, looking at the isGoldScholarSerial fucntion , we see it checks for "sungld" at position 7
I enter this into my program...
Get the checksum, and then paste the whole thing as my serial number

Wow, I am a golden scholar, with a license that never expires!

Standard Disclaimer
I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer period than the allowed one. Should you want to STEAL this software instead, you don't need to crack its protection scheme at all: you'll find it on most Warez sites, complete and already regged, farewell.
Final Notes
An easy crack, but intersting in that it uses java. As you can see, we can crack java even easier than we can crack normal code!
This doesn't mean we should get complacent and assume all java cracks will be easy!
Java makes Network programming extremely easy, so we can expect a lot of protections in the future that will test your serial number on the server...
Should be FUN. I can't wait!
(c) +Alt-F4 3 Jan 1998 All rights reversed.
way out
You are deep inside reverser's page of reverse engineering, choose your way out:

redhomepage redlinks redanonymity +ORC redstudents' essays redacademy database
redtools redcocktails redantismut CGI-scripts redsearch_forms redmail_reverser
redIs reverse engineering legal?