Feb 052009
 

One way to protect Java software from casual reverse engineering is obfuscation. Essentially, an obfuscator renames classes, variables, and packages with random/meaningless names. The application still functions correctly; the decompiled code becomes difficult to read.

There are quite a few obfuscators for Java — at least a dozen when I looked — most of which are easily used from an Ant script.

For my use I selected one with a ready-to-use Ant task: yGuard. Unfortunately, yGuard operates on .jar files only, not individual .class files or webapp .war files. Thus, I have written my own Ant script which uses yGuard and built-in Ant tasks to obfuscate .war files.

Update 2009-12-11: If I had to do it over again, I would obfuscate my classes/jars before creating the .war file.

Before you try using my Ant script, read yGuard’s documentation and be sure you fully understand how it works. You should pay special attention to the inoutpairs, keep, and hints and troubleshooting sections.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<!-- prepare a temporary directory in which the war file is expanded and obfuscated -->
<tempfile property="unwar.dir" destdir="${java.io.tmpdir}" deleteonexit="yes"/>
<mkdir dir="${unwar.dir}"/>
<unwar src="webapp.war" dest="${unwar.dir}"/>
 
<!-- create a jar of webapp classes (required by yguard) for obfuscation -->
<jar destfile="${unwar.dir}/WEB-INF/lib/webapp.jar" whenempty="fail">
    <zipfileset dir="${unwar.dir}/WEB-INF/classes"/>
</jar>
<delete dir="${unwar.dir}/WEB-INF/classes"/>
 
<!-- create a fileset of internal libraries to be obfuscated -->
<fileset dir="${unwar.dir}/WEB-INF/lib" id="internal.lib.set">
    <include name="myLibrary.jar"/>
    <include name="myOtherLibrary.jar"/>
</fileset>
 
<!-- move the internal libraries to a temporary directory and make a fileset out of them -->
<tempfile property="obfuscation.dir" destDir="${java.io.tmpdir}" deleteonexit="yes"/>
<mkdir dir="${obfuscation.dir}"/>
<move todir="${obfuscation.dir}">
    <fileset refid="internal.lib.set"/>
</move>
 
<!-- create a jar of web.xml (required by yguard) for obfuscation -->
<jar destfile="${obfuscation.dir}/web.xml.jar" whenempty="fail">
    <zipfileset dir="${unwar.dir}/WEB-INF" includes="web.xml"/>
</jar>
<delete file="${unwar.dir}/WEB-INF/web.xml"/>
 
<!-- make a fileset of all jars to be obfuscated -->
<fileset dir="${obfuscation.dir}" includes="*.jar" id="in-out.set"/>
 
<!-- make a fileset of the remaining libraries, these are not obfuscated -->
<path id="external.lib.path">
    <fileset dir="${unwar.dir}/WEB-INF/lib" includes="*.jar"/>
</path>
 
<taskdef name="yguard"
    classname="com.yworks.yguard.YGuardTask"
    classpath="yguard.jar"/>
 
<yguard>
    <inoutpairs>
        <!-- these filesets are inputs to be obfuscated -->
        <fileset refid="in-out.set"/>
    </inoutpairs>
    <externalclasses refid="external.lib.path"/>  <!-- external libs, not obfuscated -->
    <rename>
        <adjust replaceContent="true">
            <include name="web.xml"/>  <!-- modified to reference the obfuscated Servlet -->
        </adjust>
        <keep>
            <!-- classes, packages, methods, and fields which should not obfuscated are specified here -->
        </keep>
    </rename>
</yguard>
 
<!-- move our newly obfuscated classes back into the lib area -->
<move todir="${unwar.dir}/WEB-INF/lib">
    <fileset dir="${obfuscation.dir}" includes="*_obf.jar"/>
</move>
 
<!-- unjar the adjusted web.xml --> 
<unzip dest="${unwar.dir}/WEB-INF/" src="${unwar.dir}/WEB-INF/lib/web.xml_obf.jar">
    <patternset includes="web.xml"/>
</unzip>
<delete>
    <fileset dir="${unwar.dir}/WEB-INF/lib" includes="web.xml*.jar"/>
</delete>
 
<!-- rebuild the war file -->
<war destfile="webapp_obf.war" basedir="${unwar.dir}"/>

yWorks, the creator of yGuard, is perhaps best known for yDoc a UML diagram generator for JavaDocs.

  11 Responses to “Obfuscating a webapp .war file with yGuard and Ant”

  1. Thanks Mike, that was really helpful – we were in quite a hurry and (once I had my head wrapped around obfuscation/yGuard) this script worked smoothly.

    Cheers

  2. Hi Alex, I’m glad you found this post useful.

    When I created the script, I needed to obfuscate a .war file that was already created. As you can see this makes for a somewhat confusing and complex script.

    If I had to do it over again, I would obfuscate my classes/jars before creating the .war file. Maybe someone else will read this and do it that way instead!

  3. Hi Mike,
    Thanks for this script. This is what I was expecting and it is really very helpful for me.

    Thanks.

  4. Hi Mike I am very thankful to what you have posted on your site….it’s been very tidy and explained very smoothly….!!thanks a lottt dude….!

  5. Hi Mike,
    How does yGuard obfuscate your jsp files?

    I’ve tried to do it, but only imports were obfuscated:

  6. @Sergey, I don’t know, perhaps someone else visiting my blog will be able to help you. You might also consider contacting yWorks.

  7. Hi Mike,

    thanks for this really useful script. I was struggling with obfuscation and this script has helped. However my class files are not being obfuscated. If I decompile the classes in webapp.jar they are as before.

    Any idea as to what I am doing wrong?

    Thanks

  8. Please ignore my previous comment. I realised that i needed to specify the created jar or classes within the fileset of internal libraries to be obfuscated.

    Thanks

    S.

  9. Hi Mike,

    Thanks, this script is very helpful for me. I did spend time creating one, but yours is perfect!

    Thanks

  10. Hey mike,

    Thanks for the script. But when i saw the obfuscated war file, the jsps are all unobfuscated.

    Thanks

  11. Hi Mike.

    Can you give hint to obfuscate war file using Proguard?

    Thanks

Leave a Reply