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


Courtesy of Fravia's page of reverse engineering
fravia'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 winawt!+3717 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 2264717) After doing this, there are a lot more calls from a different location. Calling stack again I see javai!.text+2FFD9 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 getsystemtime. 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 returning) We also know which dll's the target is using now, so we can dissassemble them. 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 fravia'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_fravia+
redIs reverse engineering legal?