Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Before introducing Crema, we will walk through an example using Mocha. The following simple program displays the string "Hi there" on the screen:
class test {
public static void main(String argv[]) {
System.out.println("Hi there");
}
}
If the above four lines were saved in a file, test.java, then compiling test.java would generate a new file, test.class, that contains the Java bytecodes representing that Java source code. Now let's run Mocha on the class file and see the Mocha
output:
% java mocha.Decompiler test.class // the % is my C shell prompt on UNIX.
The above command generates a file called test.mocha, which contains the Java source code generated by Mocha:
% more test.mocha
/* Decompiled by Mocha from test.class */
/* Originally compiled from test.java */
import java.io.PrintStream;
class test
{
public static void main(String astring[])
{
System.out.println("Hi there");
}
test()
{
}
}
As you can see from the example above, Mocha has given us Java source code that is easy to read and understand. If you copy
this file to test.java, compile it again, and run it, it will compile and run just fine.
So how can you protect your classes from being decompiled? One answer is Crema. Crema scrambles the symbolic information in
your .class files so that they will become less vulnerable to decompilation. The symbolic information that Crema scrambles includes the
name of the class, its superclass, interfaces, variable names, methods, and so on. These symbolic names are needed by the
Java virtual machine (JVM) to link your classes with library packages. Crema scrambles these symbolic names and makes references
to them in the same way so that the JVM can still achieve the correct linking between classes and packages.
So how does Crema work? Basically, before distributing your class files on the Internet, run Crema on them. Crema will scramble
the symbolic information contained in them, and will place each new class in the file 1.crema. Your job then is to rename 1.crema to something like filename.class before distributing it on the Internet.
Let's run Crema on our test.class example shown above, and then try to decompile it with Mocha:
% java Crema -v test.class // -v is an option to turn the verbose
// mode on. There are many more options.
CREMA - The Java Obfuscator - EVALUATION VERSION
Copyright (c) 1996 Hanpeter van Vliet
Loading test.class
Obfuscating test
Saving test as 1.crema
NOTE: Classes processed with the evaluation version of Crema can only
be used locally, as most browsers will refuse to load them. For
the full version of Crema, point your browser to:
http://www.inter.nl.net/users/H.P.van.Vliet/crema.html (see Resources)
The above command has generated a new file, 1.crema, which contains the bytecodes with scrambled symbolic information. Note that Crema has many command-line option parameters
that you can use; for more information on Crema, see the Resources section.
Now let's move that file into test.class again and decompile it using Mocha:
% mv 1.crema test.class
% java mocha.Decompiler test.class
java.lang.NullPointerException
SIGSEGV 11* segmentation violation
si_signo [11]: SIGSEGV 11* segmentation violation
si_errno [0]: Error 0
si_code [1]: SEGV_ACCERR [addr: 0x0]
stackbase=EFFFF35C, stackpointer=EFFFF040
Full thread dump:
"Finalizer thread" (TID:0xee3003b0, sys_thread_t:0xef490de0) prio=1
"Async Garbage Collector" (TID:0xee300368, sys_thread_t:0xef4c0de0) prio=1
"Idle thread" (TID:0xee300320, sys_thread_t:0xef4f0de0) prio=0
"clock handler" (TID:0xee3001f8, sys_thread_t:0xef5b0de0) prio=11
"main" (TID:0xee3000a0, sys_thread_t:0x835a0) prio=5 *current thread*
java.lang.Throwable.printStackTrace(Throwable.java)
java.lang.ThreadGroup.uncaughtException(ThreadGroup.java)
java.lang.ThreadGroup.uncaughtException(ThreadGroup.java)
Monitor Cache Dump:
Registered Monitor Dump:
Finalize me queue lock: unowned
Thread queue lock: unowned
Class lock: unowned
Java stack lock: unowned
Code rewrite lock: unowned
Heap lock: unowned
Has finalization queue lock: unowned
Monitor IO lock: unowned
Child death monitor: unowned
Event monitor: unowned
I/O monitor: unowned
Alarm monitor: unowned
Waiting to be notified:
"clock handler"
Sbrk lock: unowned
Monitor cache lock: unowned
Monitor registry: monitor owner: "main"
Thread Alarm Q:
Abort (core dumped)
As you can see in the code above, the first thing Mocha complains about is a NullPointerException because it was confused about the symbolic information. Hence, our goal of making it difficult to decompile our code is achieved.
It should be noted that the author of Mocha, Hanpeter van Vliet, is also the author of Crema! Mocha is distributed without charge. An evaluation copy of Crema is available without charge, but the full version is a commercial product.
When distributing Java classes over the Internet, you can protect your Java bytecode from the risk of being reverse-engineered. The code examples above show how Mocha is used to effect decompilation and how Crema can come to the rescue by preventing such activity.