Zelix KlassMaster - Documentation

Change Logs and Incremental Obfuscation Tutorial

This tutorial is organized into the following sections.

Change Logs

Change logs record the mapping of:
  • old names to new names,
  • original source line numbers to scrambled line numbers (if you used Line Number Scrambling),
  • flow obfuscation data (if you used flow obfuscation).
You should always let Zelix KlassMaster™ produce a change log when you perform your final obfuscation and then store it a safe place. You will need it:
  • to translate any stack trace you might get if your bytecode contains some bugs,
  • to use as an input change log when you obfuscate future releases so that objects are consistently renamed. This is called incremental obfuscation.
This is the kind of stack trace you may get from an obfuscated application.
java.lang.NullPointerException: 
        at a.a.b.gp.a(gp.java:101)
        at a.a.b.gp.a(gp.java:457)
        at a.a.b.gp.b(gp.java:13)
        at a.a.b.gp.a(gp.java:501)
        at a.a.b.b.a(b.java:4)
        at a.a.b.b.a(b.java:98)
        at Main.main(Main.java:433)
Without the change log that was produced when the application was obfuscated, the stack trace will be close to indecipherable. Note that if you have a change log, you can use the Stack Trace Translate tool to help you decipher stack traces.

Input Change Logs

You can specify that a change log should be used as a guide when assigning new names to packages, classes, fields and methods. When a change log is used in this way it is refered to as an input change log. Input change logs are the basis of Zelix KlassMaster's incremental obfuscation.

When you are using the ZKM Script obfuscate statement, you can specify more than one input change log. If more than one input change log is specified then the change logs are effectively merged. Change logs appearing first in the list have precedence over those appearing later in the list.

By default, Zelix KlassMaster™ will honour the mappings in an input change log and it will give those mappings precedence over any name obfuscation exclusion settings that may be in place. So input change log mappings overrule your exclusion settings. This strictness is essential for incremental obfuscation.

However, the obfuscate statement also allows you to specify "loose" input change logs. An input change log is specified as "loose" if the looseChangeLogFileIn rather than the changeLogFileIn parameter is used with the obfuscate statement. Loose input change logs are different in that your exclusion settings take precedence over the change log mappings. They are typically only usefull when you need to produce a slightly different for some special purpose. They are not suitable for incremental obfuscation because the slight changes that can result could break compatability with previous releases.

Incremental Obfuscation

Incremental Obfuscation is the ability to consistently obfuscate subsequent versions of your bytecode such that:
  • the same new names are assigned to each particular package, class, field and method in all releases,
  • flow obfuscation is consistent across releases.
This consistency is necessary:
  • for Java Serialization support,
  • if you wish to release just a subset of your application's classes in the form of a patch.

Zelix KlassMaster™ supports incremental obfuscation through its input change log functionality. The change log generated when the previous version was obfuscated is specified as the input change log when the next release is obfuscated. However, note that it is recommended that:
  • you always open and obfuscate all of the classes of your application even if you intend to release just the changed subset,
  • your output and input change logs have different names so that one does not overwrite the other. You don't want to accidentally loose your only copy of a change log.
Having said the above, Zelix KlassMaster™ does provide a limited ability to open only part of an application and successfully obfuscate it. To do this, you would need to
  • specify allClassesOpened=false on your obfuscate statement,
  • set the classpath so that the unobfuscated versions of all the unopened classes of the application can been located,
  • specify an input change log which contains mappings for all the unopened classes of the application.
Zelix KlassMaster™ will automatically update references in opened classes to the names of objects that have not been opened using the input change log as a guide. However, this automatic processing applies to name obfuscation and not to the Trim function. If you are using the Trim function and opening just a subset of your application then you must explicitly set your trim exclusions to reflect this. Zelix KlassMaster™ will not trace for accesses to opened classes from classes which have not been opened.

Similarly, some advanced features such as AutoReflection, Reference Obfuscation and Method Parameter Changing do not support the allClassesOpened=false setting.

Finally, it is recommended that if you are not opening the application as a whole then you should at least open archive files as complete units. So, if your application consists of three archive files A.jar, B.jar and C.jar then it is recommended that you open or not open each of the three archives as a whole and not open just a subset of the classes in any of the archives.
 
Documentation Table of Contents