Distribute java program with security

K

Kevin

Hello all,

I have a question of how to distribute the java programs (applications)
in a proper way, hope anyone can have some practical suggestion.
Thanks.

The issues are:

1) we don't want the end user to be able to de-compile our program. So
distribute the .jar is a bad choice. By the way, we are using JBuilder,
the JBuilder's "build to .exe" is also a bad choice since I found it
simply wrap the .jar (just change the .exe back to .zip will be able to
see all the class files).

2) since our application may need some pretty frequent update, it would
be nice if the distribution method can help it as well (it would be
hard to keep the list of users who use the program, and email them the
update). PS: the java program is about 2-4M size.

Under these two requirement, what methods are preferred?

I hear java has a WebStart, does it downloads and saves / cache the
..jar files to the client's PC?

Thanks a lot.

Kevin
 
D

Dag Sunde

Kevin said:
Hello all,

I have a question of how to distribute the java programs
(applications) in a proper way, hope anyone can have some practical
suggestion. Thanks.

The issues are:

1) we don't want the end user to be able to de-compile our program. So
distribute the .jar is a bad choice. By the way, we are using
JBuilder, the JBuilder's "build to .exe" is also a bad choice since I
found it simply wrap the .jar (just change the .exe back to .zip will
be able to see all the class files).

2) since our application may need some pretty frequent update, it
would be nice if the distribution method can help it as well (it
would be hard to keep the list of users who use the program, and
email them the update). PS: the java program is about 2-4M size.

Under these two requirement, what methods are preferred?

I hear java has a WebStart, does it downloads and saves / cache the
.jar files to the client's PC?

Yes... That's one of the main thingys about JWS. It checks taht everything
is ok on the client to run it, download the whole caboodle and caches it.

The next time, it just check if anything new is on the server. If not, it
just run from the previous DL. If it is anything new/updated, it downloads
that and start.

So, if you just realise that your app will, and can be "de-compiled" if
someone really wants to, and start ignoring it.... JWS is the way to go.
 
D

ddimitrov

Kevin said:
1) we don't want the end user to be able to de-compile our program. So
distribute the .jar is a bad choice.

I can think of a couple of ways to do this, raging from easy and
unobtrusive to crazy paranoid:

1. Use obfuscation for release builds. There are free obfuscators like
RetroGuard, which will not prevent the potential hacker from
decompiling, but are going to significally increase the effort. Cons:
the stacktraces will be garbled, so you need to use a demangler every
time the client sends you log file with stack trace. Releasing patches
is cumbersome.

2. Use custom class loader. Encrypt the classes before you create the
jar (there are many schemes you can use - i.e. you can use password
based encryption and calculate the pass as a hash of the package name).
You'd need a custom bootstrapper with class loader which decripts the
classes on the fly. Cons: the bootstrapper is a weak link - you have to
combine this with 3 in order to be really effective.

3. Use custom native JVM launcher (check the Invocation API), decoding
the encrypted bootstrapper on the fly, also checking for suspicious
activity (like all the process threads being suspended for more than 10
seconds).

This way you have raised the difficulty of decompiling the Java code
rto that of decompiling native code (which is perfectly doable by the
way - see IDA Pro )

2) since our application may need some pretty frequent update, it would
be nice if the distribution method can help it as well (it would be
hard to keep the list of users who use the program, and email them the
update). PS: the java program is about 2-4M size.

I hear java has a WebStart, does it downloads and saves / cache the
.jar files to the client's PC?

Your requirement sounds like a good candidate for Web Start. Yes, it
downloads and caches jars. I have never used it myself, but I plan to
very soon.

As far as I understand, most of the major complains about JaWs revolve
around the auto-update functionality. What we plan is to use different
links to the different application versions and publish the latest and
greatest link to a common web page. This also has the advantage that
the user can back out or compare versions easily.

An installer might be a good idea if you have problems converting your
app to JaWs. I'd reccomend IzPack + Jaunch4J, but there are other
installers that would work just a s well.

Regarding the distribution, if you use Maven, you can keep track of
your user list inside your pom and then use a simple script to extract
the addresses and send the update email.

cheers,
Dimitar
 
C

Chris Uppal

Kevin said:
1) we don't want the end user to be able to de-compile our program. So
distribute the .jar is a bad choice. By the way, we are using JBuilder,
the JBuilder's "build to .exe" is also a bad choice since I found it
simply wrap the .jar (just change the .exe back to .zip will be able to
see all the class files).

2) since our application may need some pretty frequent update, it would
be nice if the distribution method can help it as well (it would be
hard to keep the list of users who use the program, and email them the
update). PS: the java program is about 2-4M size.

Given (2) why are you so worried about (1) ? Probably the best defence there
is against people cracking your software is if the cracked versions quickly
become out-of-date.

Anyway, there are many Java obfusators available, both free and commercial.
Perhaps you could use one of those.

A completely different approach would be to use a native compiler like
Escelsior Jet.

-- chris
 
C

Chris Uppal

ddimitrov said:
2. Use custom class loader. Encrypt the classes before you create the
jar (there are many schemes you can use - i.e. you can use password
based encryption and calculate the pass as a hash of the package name).
You'd need a custom bootstrapper with class loader which decripts the
classes on the fly. Cons: the bootstrapper is a weak link - you have to
combine this with 3 in order to be really effective.

I haven't checked this myself, but a previous poster on a similar subject
asserted that putting a breakpoint on the native DefineClass() function will
trap the bytecode after it has been decoded and before it is used. One could
do something similar with the JNMTI interfaces, or by creating a "dummy"
JVM.DLL.

As Dimitar noted, you can make this technique more robust by using a custom
launcher too.

-- chris
 
K

Kevin

So, for these two methods:
1) obfuscation
2) convert java to real binary code (for me, we need to run it on MS
Win)

which software tools do you guys recommend most? ---- In terms of 1)
how hard it make the un-complie difficult, 2) less harm of the run time
speed.

It can be free ones, or commercial ones.

Thank you a lot!~
 
I

IchBin

Kevin said:
So, for these two methods:
1) obfuscation
2) convert java to real binary code (for me, we need to run it on MS
Win)

which software tools do you guys recommend most? ---- In terms of 1)
how hard it make the un-complie difficult, 2) less harm of the run time
speed.

It can be free ones, or commercial ones.

Thank you a lot!~

1 - Proguard (http://proguard.sourceforge.net/) This is a java shrinker,
optimizer, and obfuscator. I am really happy with this free product.

2 - JSmooth (http://jsmooth.sourceforge.net/) is a Java Executable Wrapper

Thanks in Advance...
IchBin, Pocono Lake, Pa, USA
http://weconsultants.servebeer.com/JHackerAppManager
__________________________________________________________________________

'If there is one, Knowledge is the "Fountain of Youth"'
-William E. Taylor, Regular Guy (1952-)
 
L

ldv

Kevin said:
Hello all,

I have a question of how to distribute the java programs (applications)
in a proper way, hope anyone can have some practical suggestion.
Thanks.

The issues are:

1) we don't want the end user to be able to de-compile our program. So
distribute the .jar is a bad choice. By the way, we are using JBuilder,
the JBuilder's "build to .exe" is also a bad choice since I found it
simply wrap the .jar (just change the .exe back to .zip will be able to
see all the class files).

2) since our application may need some pretty frequent update, it would
be nice if the distribution method can help it as well (it would be
hard to keep the list of users who use the program, and email them the
update). PS: the java program is about 2-4M size.

Under these two requirement, what methods are preferred?

Compile your program to a native code EXE using either Excelsior JET
(http://www.excelsior-usa.com/jet.html) or GCJ
(http://gcc.gnu.org/java/) and use a native Windows setup generator
such as InstallShield to manage automated updates.
I hear java has a WebStart, does it downloads and saves / cache the
.jar files to the client's PC?

Yes, exactly.

See also the article at
http://www.excelsior-usa.com/articles/java-to-exe.html for links to
reference materials and tools

LDV
 
C

Chris Uppal

Kevin said:
which software tools do you guys recommend most? ---- In terms of 1)
how hard it make the un-complie difficult, 2) less harm of the run time
speed.

It can be free ones, or commercial ones.

For compilation, I've already mentioned one name (the only reasonable one as
far as I know). For obfuscation there are many choices, I can't recommend any.
The commercial ones claim to be better than the free ones, and -- who knows --
maybe they are telling the truth...

-- chris
 
L

ldv

ddimitrov said:
Kevin said:
1) we don't want the end user to be able to de-compile our program. So
distribute the .jar is a bad choice.

I can think of a couple of ways to do this, raging from easy and
unobtrusive to crazy paranoid: [skip]
2. Use custom class loader. Encrypt the classes before you create the
jar (there are many schemes you can use - i.e. you can use password
based encryption and calculate the pass as a hash of the package name).
You'd need a custom bootstrapper with class loader which decripts the
classes on the fly. Cons: the bootstrapper is a weak link - you have to
combine this with 3 in order to be really effective.

Here is why this won't work at all:

http://www.javaworld.com/javaworld/javaqa/2003-05/01-qa-0509-jcrypt.html

LDV
 
D

ddimitrov


I thought I made it clear in my first post, but since everybody feels
obliged to basically repeat my last sentence from point 2, maybe I
should go into more detail.

First things first: if you are going to run this program on your
client's machine and your client is determined (and sufficiently
technically advanced) to reverse engineer it, there is no way to stop
him. Deal with it. If it is really an issue, then think about
implementing the critical parts of your app as a remote service (be it
RMI, web service or plain HTTP requests). Mind that if you charge your
customers fixed price or subscription price and do not limit the number
of calls they can make per second, they can make a clean-room
implementation of your service, which from business POV is just as bad
as reverse engineering (i.e. they stop paying).

Fortunately, it is very easy to make the reverse engineering if not
imposible, then unreasonably hard. As everybody else said, the
obfuscators are the first line of defence - they make your code much
harder to decompile and as bonus it will usually get smaller and faster
due to the shorter symbolic names and some aggressive optimizations
that the compilers are not allowed to make because of the JLS.

The next line is the encryption/signing. Encryption is good especially
when the code goes through third parties. On the other hand, obviously
you need some code to decrypt what is encrypted. As I said, this code
is the weak point of any scheme which relies on encrypted classloaders.
So what do we gain, you might ask?

What we gain is that now we have to cover only one spot and if we
protect it well enough, we can stop worrying about our bytecode being
visible in the wild. What we can do in this case is to implement the
bulk of this decrypting classloader in native code, using native code
the protection techniques which we all undoubtedly know. I've mentioned
some of them, like comparing the API entry points of well known
platform functions, looking at the timer to check that there are no
unreasonable time-lapses and so on. We can even use a dongle, to make
sure that the user has not tampered with the system timer. (essentially
that was 'point three' from my first mail.)

Having done this, we have increased the dificulty of reverse
engineering our Java code to that of any native code. Still it's
doable. There are hardware protocol analyzers which can replay what
went through the buss and take snapshots of the whole system memory
without stopping the CPU. There are enough smart people who can
dissasemble your carefully crafted native code if nessesary make fake
dongles and they are experts in this kind of stuff, just as some people
are in protecting the software.

The key here is to make the reversing not impossible, but unfeasible.
It's all about the balance between the price of the application, effort
to reverse, audience (nobody reverses software for cow milkers),
popularity and probably many other factors.

It is a good idea to decide on a fixed time that you are willing to
invest into protection (that is research + implementation). Otherwise,
you might spend more time working on the protection than on your
application code.

All that said, IMHO the best tradeoff is a simple obfuscator plus
password based encryption (no native launcher). It's easy to implement
and will keep away a good part of the wannabe hackers. It's not worth
trying to stop the other 10% - they are smarter than me anyway.

cheers,
Dimitar
 
L

ldv

ddimitrov said:
What we can do in this case is to implement the
bulk of this decrypting classloader in native code, using native code
the protection techniques which we all undoubtedly know. I've mentioned
some of them, like comparing the API entry points of well known
platform functions, looking at the timer to check that there are no
unreasonable time-lapses and so on. We can even use a dongle, to make
sure that the user has not tampered with the system timer. (essentially
that was 'point three' from my first mail.)

It does not matter how do you implement the decrypting classloader. As
some point the _decrypted_ bytecode must be fed to the JVM, where it is
very easy to intercept. Here is an excerpt from the JavaWorld article I
referred to in my previous post:

"All ClassLoaders have to deliver their class definitions to the JVM
via one well-defined API point: the java.lang.ClassLoader.defineClass()
method. The ClassLoader API has several overloads of this method, but
all of them call into the defineClass(String, byte[], int, int,
ProtectionDomain) method. It is a final method that calls into JVM
native code after doing a few checks. It is important to understand
that no classloader can avoid calling this method if it wants to create
a new Class.

The defineClass() method is the only place where the magic of creating
a Class object out of a flat byte array can take place. And guess what,
the byte array must contain the unencrypted class definition in a
well-documented format (see the class file format specification).
Breaking the encryption scheme is now a simple matter of intercepting
all calls to this method and decompiling all interesting classes to
your heart's desire (I mention another option, JVM Profiler Interface
(JVMPI), later)."

LDV
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top