Obfuscating a GWT webapplication with ProGuard - java

I am trying to obfuscate my GWT (Vaadin) application using Proguard. Ive never obfuscated java code before and this is my first attempt using Proguard.
I have my config file set as follows:
-libraryjars JAVA_HOME\rt.jar
-libraryjars MYPATH\test\WebContent\WEB-INF\lib\appfoundation.jar
-libraryjars MYPATH\test\WebContent\WEB-INF\lib\blackboard-2.1.1.jar
-libraryjars MYPATH\test\WebContent\WEB-INF\lib\cssinject-0.9.jar
-libraryjars MYPATH\test\WebContent\WEB-INF\lib\eclipselink.jar
-libraryjars MYPATH\test\WebContent\WEB-INF\lib\eclipselink-jpa-modelgen_2.0.2.v20100323-r6872.jar
-libraryjars MYPATH\test\WebContent\WEB-INF\lib\gwt-visualization.jar
-libraryjars MYPATH\test\WebContent\WEB-INF\lib\iText-5.0.4.jar
-libraryjars MYPATH\test\WebContent\WEB-INF\lib\javax.persistence_1.0.0.jar
-libraryjars MYPATH\test\WebContent\WEB-INF\lib\javax.persistence_2.0.0.v201002051058.jar
-libraryjars MYPATH\test\WebContent\WEB-INF\lib\vaadin-6.4.4.jar
-libraryjars MYPATH\test\WebContent\WEB-INF\lib\vaadin-calendar-0.5.1.jar
-libraryjars MYPATH\test\WebContent\WEB-INF\lib\vaadin-chameleon-theme-1.0.1.jar
-libraryjars MYPATH\test\WebContent\WEB-INF\lib\VisualizationsForVaadin.jar
-libraryjars "C:\Program Files\eclipse\configuration\com.vaadin.integration.eclipse\download\gwt-dev\2.0.3\gwt-dev.jar"
-libraryjars "C:\Program Files\eclipse\configuration\com.vaadin.integration.eclipse\download\gwt-user\2.0.3\gwt-user.jar"
-injars test.war
-outjar test_after.war
-printseeds
-ignorewarnings
-keep public class TestApplication extends com.vaadin.Application {
public void init();
}
I then execute using the proguard command:
java -jar proguard.jar #test.pro
I dont get any errors with the configuration file but i do receive lots of warnings. The output file is created but im concerned about the warnings. Do i need to specify further jar files in my config file? I have listed all the jars that i am using in my application. Is there anything else i am doing wrong?
Below is a snipped of the last 20~ lines of the command line output
Thanks in advance
S.
Maybe this is library method 'sun.jdbc.odbc.JdbcOdbcStatement { java.sql.Connection getConnection(); }'
Maybe this is library method 'sun.jdbc.odbc.ee.CommonDataSource { java.sql.Connection getConnection(); }'
Maybe this is library method 'sun.jdbc.odbc.ee.ConnectionPoolDataSource {java.sql.Connection getConnection(); }'
Maybe this is library method 'sun.jdbc.odbc.ee.DataSource { java.sql.Connection getConnection(); }'
Maybe this is library method 'sun.jdbc.odbc.ee.PooledConnection { java.sql.Connection getConnection(); }'
Maybe this is library method 'sun.rmi.transport.StreamRemoteCall { sun.rmi.transport.Connection getConnection(); }'
Note: org.eclipse.persistence.sdo.helper.DynamicClassWriter accesses a declared method 'writeReplace()' dynamically
Maybe this is program method 'org.eclipse.persistence.sdo.SDODataObject {java.lang.Object writeReplace(); }'
Maybe this is program method 'org.eclipse.persistence.sdo.helper.ListWrapper { java.lang.Object writeReplace(); }'
Maybe this is library method 'com.sun.corba.se.impl.presentation.rmi.InvocationHandlerFactoryImpl$CustomCompositeInvocationHandlerImpl {
Note: there were 4 unresolved dynamic references to classes or interfaces.
You should check if you need to specify additional program jars.
Note: there were 10 accesses to class members by means of introspection.
You should consider explicitly keeping the mentioned class members
(using '-keep' or '-keepclassmembers').
Warning: there were 3649 unresolved references to classes or interfaces.
You may need to specify additional library jars (using '-libraryjars').
Warning: there were 173 unresolved references to program class members.
Your input classes appear to be inconsistent.
You may need to recompile them and try again.
Alternatively, you may have to specify the option
'-dontskipnonpubliclibraryclassmembers'.

GWT generates code in two parts.
Client side code. This is what runs in your browser and consists of the user interface plus any async calls to the server. While you write Java source it is transformed from the source straight into Javascript. i.e. the GWT compiler doesn't even look at the class files. To obfuscate the generated JS, use the GWT compiler flags (see below)
Server side code. The server code would be the end points your client app calls. e.g. you might invoke GWT RPC calls and have GWT servlets as end point. Obfuscate your web app like you would any other - trial and error through Proguard or similar. Start off with a simple configuration that lightly obfuscates and then proceed from there.
As the GWT client side is generated from Java source code there is no easy way to obfuscate before feeding to GWT. I suppose you could somehow obfuscate through Proguard and then decompile that and feed it to the GWT compiler. It seems like overkill but it may be possible.
The normal way to obfuscate is to specify -style OBF to the GWT compiler. This will thoroughly obfuscate your code. You could probably go further and run it through another JS obfuscator though the law of diminishing returns, bugs etc. applies.
I suggest you understand what gets generated when you supply OBF as the style. It's probably quite sufficient for your purposes. Obviously the more stuff you put on the server side (e.g. security, cookie validation etc.) the less it matters what code is in the client.

Related

Android, Proguard & XmlPullParser: NoSuchMethodError

I am using XmlPullParser and when the app pass throught the Proguard, and the apk is running on device, it give me the following error:
08-06 17:10:26.717: E/AndroidRuntime(2527):
Caused by: java.lang.NoSuchMethodError: org.xmlpull.v1.XmlPullParser.d
I have added -ignorewarnings in my proguard.cfg or otherwise there is no way to pass the Proguard.
Here is a link to my proguard.cfg file.
You obfuscated away a method you shouldn't have. You need to keep the pull parser code intact. Add:
-keep public class org.xmlpull.**
to your proguard.cfg file.
what you want in your proguard config file is -keep instead of -ignorewarnings
-keep class org.xmlpull.** { *; }
See the following url for some more details
http://android-developers.blogspot.com/2010/09/proguard-android-and-licensing-server.html
But Wait, My App is Crashing Now
Most crashes happen because Proguard has obfuscated away something that your application needs,
such as a class that is referenced in the AndroidManifest or within a
layout, or perhaps something called from JNI or reflection. The
Proguard configuration provided here tries to avoid obfuscating most
of these cases, but it’s still possible that in edge cases you’ll end
up seeing something like a ClassNotFoundException.
You can make edits to the procfg.txt file to keep classes that have
been obfuscated away. Adding:
-keep public class * [my classname]
should help. For more information about how to prevent Proguard from
obfuscating specific things, see the Proguard manual. Specifically,
the keep section. In the interest of security, try to keep as little
of your application unobfuscated as possible.
The standard settings provided in procfg.txt will be good for many
applications, and will catch many common cases, but they are by no
means comprehensive. One of the things that we’ve done is had Proguard
create a bunch of output files in the obf directory to help you debug
these problems.
The mapping.txt file explains how your classes have been obfuscated.
You’ll want to make sure to keep this around once you have submitted
your build to Market, as you’ll need this to decipher your stack
traces.

Proguard issues with jar files, how to find the missing jar?

When I try to export my apk with Proguard I get a lot of errors (over 400) similar to:
Warning: org.codehaus.jackson.jaxrs.JsonMappingExceptionMapper: can't find superclass or interface javax.ws.rs.ext.ExceptionMapper
and
org.codehaus.jackson.xc.DataHandlerJsonDeserializer$1: can't find superclass or interface javax.activation.DataSource
I am using the Jackson Json library, and the errors seem related to that.
Researching this error I found the following from Proguards FAQ:
If there are unresolved references to classes or interfaces, you most likely forgot to specify an essential library. For proper processing, all libraries that are referenced by your code must be specified, including the Java run-time library. For specifying libraries, use the -libraryjars option.
Searching around on SO I found a lot of unanswered questions related to this, but the general sense was that the jar file I am using (in this case Jackon JSON) is relying on more libraries and they need to be added to Proguard's config file some how.
However, I can't figure out how to determine what jars are needed and where they are. The warnings mention a lot of different packages such as javax.ws.rs.ext, org.joda.time, org.codehaus.stax2, javax.xml.stream, etc.
How do I determine what jars contain those packages? For example, what jar is required for the javax.ws.rs.ext.** classes?
How do I figure out where those jars are and what path would be used with -libraryjars in Proguard?
Thanks much
Edit: I should also mention that I am using an Android Library Project setup. The jars are in the main Library project, and the actual working project has their build paths including the jars in the Library project. Don't know if that makes a difference but thought I should mention it.
Update Just to test, I completely removed the jackson far from the build path and from my code and now Proguard completes successfully. The questions still remain... What is the correct approach for handling these errors?
Does the Android export wizard in Eclipse automatically add the /lib/ jars to proguard or do they all have to be added manually in the proguard config file like this:
-libraryjars C:/Project/lib/somjar.jar
I did try that for the jackson one but it didn't make any difference. Does this mean I also have to find all of the jars that are needed for the classes mentioned in the warnings and add those? Would they be in the sdk or in the java installation?
Sorry if these are stupid questions, but I have been trying to figure this out for the last couple hours and have no idea what to do.
Thanks again
Update Again
So more searching, combined with Benjamin's suggestion, I found some of the missing classes were in rt.jar, which is in the jdk's lib folder. So I ended up adding
-libraryjars <java.home>/lib/rt.jar
To the proguard.cfg file and brought the warnings from 485 down to 204. Hey I guess that's something... The remaining warnings describe classes that I cannot find at all. The app works just fine without running proguard, so these classes must be somewhere right? Or are these warnings that I should use -dontwarn with?
The remaining classes are in these packages:
org.joda.time.
org.codehaus.stax2.
javax.ws.rs.
So now I just need a way to figure out:
What jars have these classes
Where are these jars so I can include them in the proguard config file
I've had similar problems with Proguard and similar errors I was using an osmdroid.jar which built OK unobfuscated. This jar must have had external dependencies which my application didn't need. Fortunately the authors listed the jars needed and once I downloaded them and told Proguard via the -libraryjars option, the Proguard build was OK.
Re your missing jars (which you probably don't really need, but Proguard thinks you might!), you should find them at:
org.joda.time
(The jar's inside the zip)
org.codehaus.stax2.
javax.ws.rs.
I only can provide an answer for the first part:
Give
http://www.findjar.com
a try, there you might find the names of the needed jar files
like so
You don't need to include the libraries for Proguard; you need to instead instruct Proguard to keep the class names and some other stuff. I toyed around with it a bit myself, and I ended up with something similar to this discussion:
-keepnames class org.codehaus.** { *; }
-keepattributes *Annotation*,EnclosingMethod
-dontwarn org.codehaus.jackson.**
If you're still experiencing crashes—and I would suggest testing vigorously!—you might want to keep Jackson completely intact with:
-keep class org.codehaus.** { *; }
-keepattributes *Annotation*,EnclosingMethod
-dontwarn org.codehaus.jackson.**
(Note that the latter produces a larger file.)

How to decompile obfuscated java programs avoiding class/package name collisions

I want to decompile a java program and recompile the derived (obfuscated) source. I unpacked the .jar archive and got a directory structure like that:
com/
com/foo/A/
com/foo/A/A.class
com/foo/A/B.Class
com/foo/B/A.class
...
com/foo/A.class
com/foo/B.class
org/foo/Bar.class
...
The problem is that there are name collisions between packages and classes, which makes it impossible to recompile the decompiled class files.
A decompiled class will look like this:
package org.foo;
import com.foo.A; // <-- name collision error
class Bar {
...
}
Is there any way to resolve those naming issues, without renaming the class files?
EDIT:
This is not a decompiler problem, but the question how it is possible to have a working .jar file with classes that violate naming conventions.
EDIT2:
Okay, i guess on bytecode level such naming is possible, so with a smarter decompiler (who automatically renames the classes and fixes their references) this problem could be solved.
Do you really need to unpack the entire jar and recompile everything? Instead of recompiling the entire decompiled source by itself, use the original jar as the classpath, and extract and recompile only those classes that you need to modify. Then, when you need to package up your recompiled code, just copy the original jar and use jar -uf to replace the modified class files in place:
jar -uf ./lib/copy_of_original_jar_file.jar -C ./bin com/foo/A.class com/foo/B.class [...]
...and ./lib/copy_of_original_jar_file.jar becomes your new library.
One thing is for sure, and that is that the original jar must work properly with a Java classloader in order for the program to run. It should work just as well for compiling your one-off .class files.
You should experience much fewer naming collision issues by using the original jar because you keep the same classpath scanning order that the running application would use. Not only that, but Java decompilers aren't perfect. By eliminating the majority of the decompiled code from recompilation, you avoid the majority of issues that decompilers have with things like exception handler overlaps, special characters in obfuscated symbols, variable scoping issues, etc.
Java's import mechanism provides a shorthand for naming things, but you obviously cannot use it when there are collisions. You can always use the fully qualified name in your code, e.g.
package org.foo;
class Bar {
private com.foo.Bar aDifferentBar;
...
}
EDIT:
I suppose there could be class files that comply with the JVM spec but which cannot be produced by a Java program that complies with the JLS spec. If so then you'll definitely need a smarter decompiler.
You can not import packages in Java, so why should this be a name collision? Which error message do you get from the compiler?
If there would be a name collision in the obfuscated code, the code would not run. So the decompiled code should be collision free.

How to obfuscate Java code quickly?

How to obfuscate code quickly. I have a very small Java App and I want to deliver the obfuscated code to my client. I have heard a lot about ProGuard to obfuscate code and have downloaded it but doesn't know how to obfuscate my "abc.jar" file.
I checked out its website but it contains a lot of material to read. I don't need heavy obfuscation. I just need a obfuscate that simply changes the name of variables, methods and classes to some unreadable ones. I know ProGuard provide all of this with a ton of other functionalities too.
Q1. So could anyone tell me please some simple obfuscators or some simple steps to use proguard so that I can just input "abc.jar" and it outputs "obfuscate_abc.jar" or something simple like that.
Q2. One more thing, as my Java program uses external libraries, so should I need to obfuscate those libraries too?
Q3. Is there any Eclipse or NetBeans plugin availabe to this obfuscation?
I have also heard that we should retain the mapping table file with us so that in future we can debug or edit that obfuscated code by first de-obfuscating with the help of that mapping-table which was created at the time of obfuscation.
Q4. So, one more question is Why do we need to keep that mapping-table with us? We can simply retain a copy of un-obfuscated application so as to make changes in that (if required in future). Is there any reason to retain that mapping-table file with us?
Q1. So could anyone tell me please some simple obfuscators or some simple steps to use proguard so that I can just input "abc.jar" and it outputs "obfuscate_abc.jar" or something simple like that.
Just go for ProGuard, it's definitely a good tool (recommended in many answers here on SO like this one, this one and this one).
Q2. One more thing, as my java program uses external libraries, so should i need to obfuscate those libraries too?
No need IMHO (not even mentioning that you may not).
Q3. Is there any eclipse or netbeans plugin availabe to this obfuscation?
I'd rather suggest to use the Ant Task or the proguard-maven-plugin. See this question about the maven plugin if required.
Q4. So, one more question is Why do we need to keep that mapping-table with us. We can simply retain a copy of un-obfuscated application so as to make changes in that (if required in future). Is there any reason to retain that mapping-table file with us?
Yes, to "translate" stacktrace.
I tried this from scratch. It should get you started. I think the key will be to understand the "keep options" in the configuration file.
Using this code:
import java.util.*;
public class Example {
public static void main(String... args) {
Example ex = new Example();
ex.go();
}
public void go() {
String[] strings = { "abc", "def", "ijk" };
for (String s : strings) {
System.out.println(s);
}
}
}
I created an Example.jar. I copied the proguard.jar from the ProGuard lib directory, and ran this command-line
java -jar proguard.jar #myconfig.pro
where myconfig.pro contains:
-injars Example.jar
-outjars ExampleOut.jar
-libraryjars <java.home>/lib/rt.jar
-keep public class Example {
public static void main(java.lang.String[]);
}
This produces ExampleOut.jar which contains the same functionality and is obfuscated (verified with JAD). Note that I did not use a manifest, so to test functionality, I unjarred and tested the class. Execution entry-points within jars are left to the reader.
There are many more keep options listed in the Usage section.
You only need to obfuscate the other libraries in the case where you need to protect them against whatever you think obfuscation is doing for your code. However you should read the licences for those other libraries to see whether they restrict you from distributing modified versions.
regarding Q4: The mapping is used when users send you bug reports that contain exception stacktraces from the obfuscated code. ProGuard allows you to translate these stacktraces back to the original class names and line numbers if you have the mapping.
Just answering Q4…
There is a good reason to keep the mapping. If the client ever sends you a stacktrace, it can be very useful to know where in the code that stacktrace came from. The purpose of an obfuscator is to get rid of that information ;-) By keeping the mapping, you enable the conversion of the stacktrace into where the problem occurred in the original code.
I can answer question 4. You should retain it for debugging. Say you have a bug in function "printTheAlphabet()" on line 23, after obfuscating the stack trace might say something like "Error in j6z9r() on line 27" which makes it pretty impossible to locate the error in your source code.
How to obfuscate code quickly & dirty:
Try it: http://www.daftlogic.com/projects-online-javascript-obfuscator.htm or it: http://javascriptobfuscator.com/default.aspx or Google "javascript obfuscator online".
I know it is for Javascript, but you can get the
function result using a Javascript eval for Java (have a look at: https://stackoverflow.com/a/2605051/450148)
It is not the best aprouch, but it can be useful if you are really in a hurry and you are not a paranoic about security.
EDIT: The next piece of code uses the simple ROT13 to not expose directly your password. The good thing is the "hacker" do not know which algorithm you are using (you can replace ROT13 for which algorithm you like), but it is still very easy to break it down:
static String password;
static {
password = a("NXVNWQX5CHXRWTKGDMHD");
}
private static String a(String b) {
String c = "eval(function(p,a,c,k,e,d){e=function(c){return c.toString(36)};if(!''.replace(/^/,String)){while(c--){d[c.toString(a)]=k[c]||c.toString(a)}k=[function(e){return d[e]}];e=function(){return'\\\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\\\b'+e(c)+'\\\\b','g'),k[c])}}return p}('k a(b){2 5=\\'\\';o(2 i=0;i<b.e;i++){2 c=b.g(i);2 1=b.f(i);4(c>=\\'a\\'&&c<=\\'m\\')1+=3;6 4(c>=\\'n\\'&&c<=\\'9\\')1-=3;6 4(c>=\\'7\\'&&c<=\\'h\\')1+=3;6 4(c>=\\'7\\'&&c<=\\'p\\')1-=3;2 d=8.l(1);5+=d}j 5}',26,26,'|charcode|var|13|if|sb|else|A|String|z|||||length|charCodeAt|charAt|M||return|function|fromCharCode|||for|Z'.split('|'),0,{}));";
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
Object z = "";
//noinspection EmptyCatchBlock
try {
z = engine.eval(c + " a('" + b + "');");
} catch (ScriptException e) {}
return z.toString();
}
I have had a quick look at yGuard before and liked the fact that you could integrate the obfuscation steps into an Ant script. This allows you to use it very easily in Eclipse etc if you want.
The documentation it comes with provide a number of ready made Ant scripts to get you started. These just need to be modified to work with your projects layout, ie setting the correct package names etc.
If your not clear on how to get Ant going in Eclipse, you pretty much just need to add a build.xml file to the project, copy the example script that comes with yGuard into it, modify the script to work with your project and run the yGuard task from the Ant view.
With regards to your mapping table question. The only reason I can think you might need something like this would be if you can't replicate a bug your obfuscated jar exhibits, from your original code. At this point you might need to work with the obfuscated version, maybe to determine if the obfuscation has caused a problem.
-injars Decryption.jar (input .jar file that you want to obfuscate)
-outjars DecryptionOut.jar (output .jar file that you get after obfuscate)
-libraryjars '<java.home>\lib\rt.jar'
#-dontwarn javax.crypto.** only if it gives any warnings in import
-dontshrink
-keep class Decryption{ *; }
Try to copy these rules in your myconfig.pro rules and then save it and run the command java -jar proguard.jar #myconfig.pro on cmd
Download proguard.jar from https://sourceforge.net/projects/proguard/

Netbeans Obfuscation

I'm very new to obfuscation and don't have a lot of experience with ant. Come someone provide me a way to obfuscate a regular Java application with ProGuard (or any other open source obfuscator). Currently I'm using NetBeans 6.5.1, and only see the obfuscation ability if I create a JAVA ME, and not a Java Application like I have. I've looked at http://wiki.netbeans.org/DevFaqModuleObfuscation, but don't understand what they're saying.
Thanks for any input.
The FAQ you point to is for obfuscating NetBeans modules. This is quite a complicated use case, so I will assume that it is not the regular application you are interested in.
Very briefly: the obfuscation process changes the names of classes, methods and fields to make it more difficult to reverse engineer your application.
This causes some issues:
the JVM requires your application to have a public static void main( String args[] ) in a public class, so you must tell proguard not to change this name
if you are using any sort of introspection, you have to protect the relevant names from being changed
other cases, as explained in the manual
Additionally, proguard strips out unused code. If you have any classes that are used but not referenced directly, you have to -keep them as well.
The proguard documentation includes an example of how to obfuscate a simple application. Here is the example explained (with some less confusing names):
-injars application.jar # obfuscate all the classes in the named jars
-outjars obfuscated.jar # save all the obfuscated classes to the named jar
-libraryjars <java.home>/lib/rt.jar # these are all the libraries that the application uses
-printmapping obfuscation.map # save a file linking the original names to the obfuscated ones
# this helps understanding stack traces from the obfuscated application
# we need to keep our main class and the application entry point
-keep public class com.mycompany.Application {
public static void main(java.lang.String[]);
}
Unless you specify -dontshrink, proguard will remove any code not kept or not referenced from any kept code. So in the above configuration, any code not referenced (indirectly) by the main method will be removed.
Proguard includes an Ant task that can be used to integrate with the NetBeans workflow. I would suggest experimenting manually first though, without Ant, as that takes one of the complicating factors out of the process. Build your application jar with NetBeans and then try to obfuscate with the above configuration (fleshed out if necessary). Make sure to test the obfuscated application, as innumerable things can go awry. Once you have a working proguard configuration, try adding an Ant task to your build file to automate the obfuscation process within NetBeans.
Another solution than -dontskipnonpubliclibraryclasses is to use the same JDK for running proguard as you used for compiling the code in the JAR file.
For example, instead of
java -jar ../proguard3.8/lib/proguard.jar
use
/usr/local/jdk1.5.0/bin/java -jar ../proguard3.8/lib/proguard.jar
Jacob

Categories