Zelix KlassMaster - Documentation
 

Obfuscate Options

Overview

Zelix KlassMaster provides the following obfuscation options. Note that there is no name obfuscation option. Generally speaking, all package, class, field and method names not excluded using the Obfuscate Name Exclusions dialog will be obfuscated.
 

Use input change log file

If you select "use input change log file" Zelix KlassMaster will read the name change details from the existing change log file that you named in the input field to the right of the option. This ensures consistent renaming across releases which can be vital in certain situations (e.g. RMI and serialization).

Produce a change log file

If you select "produce a change log file" Zelix KlassMaster will write the name change details to a change log file. The change log file will be given the name that you entered in the input field to the right of the option.
Zelix KlassMaster - Name Obfuscate Options

It is recommended that you always select this option. With a change log, you can use the Stack Trace Translate tool to translate obfuscated stack traces. Without a change log, debugging the stack traces caused by uncaught exceptions is extremely difficult if not impossible. Also, you can use the change log as an input change log when you obfuscate your next release so that the same obfuscated names will be used.

Note that only the latest changes will appear in the file. If you obfuscate twice with the same change log file name then only the second set of name changes will be retained. Also, if the change log out file name is the same as the input change log file name then, after it has been read, the original file will be overwritten with the new change details.
 

Obfuscate Control Flow

If you select light, normal or aggressive in the "Obfuscate Control Flow" list, Zelix KlassMaster will obfuscate most selection (eg. if...else) and loop (eg. while or for) constructs so that they cannot be directly decompiled back to the Java language. Selecting aggressive results in more flow obfuscation than would be done if you selected normal. Selecting normal results in more flow obfuscation than would be done if you selected light.

To switch off flow obfuscation, you should select none in the "Obfuscate Control Flow" list.

The disadvantages of flow obfuscation are that your bytecode will run slower and will be slightly larger. It is a trade off between the degree of protection against decompilation and bytecode size and speed. The table below shows the approximate bytecode size increase that could be expected for typical applications. Note that the size increase will vary from application to application and you should measure the impact on your bytecode.
flow obfuscation
option used
approximate
size increase
light < 1%
normal 1%
aggressive 3%

The performance impact of flow obfuscation varies depending upon
  • the bytecode that is being obfuscated,
  • the JVM used to execute the bytecode,
  • the flow obfuscation option used.
When the HotSpot(TM) JVM is used, the approximate performance impact for general purpose applications is shown in the table below.
flow obfuscation
option used
approximate
performance decrease
light 1%
normal 25%
aggressive 25%
Again, it is recommended that you measure the impact on your classes. If you experience an unacceptable performance impact then you should
  • use light flow obfuscation,
  • use the ZKM Script obfuscateFlowExclude statement to exclude performance critical methods from flow obfuscation.

Also, flow obfuscation can expose bugs in some JVMs and particularly in some JITs. This is more likely to happen if you use the aggressive option and it is much less likely to occur if you use the light option. Be sure to test your code in every environment in which it must run.

Encrypt String literals

When the "Encrypt String literals" option is set to normal, Zelix KlassMaster will replace your string literals with encrypted strings and add instructions to your bytecode that will decrypt the strings at runtime. The aggressive setting goes further by removing any static final String constants that can be left unencrypted when the normal setting is used. The compatibility of the aggressive setting depends upon the compiler that generated the bytecode. It works fine with the Sun, IBM, Symantec, Microsoft and Jikes compilers that we have tested. If you use another compiler and experience problems with your aggressive string encrypted bytecode then use the normal setting instead.

The flow obfuscate setting is the same as the aggressive setting except that it flow obfuscates the decryption methods automatically inserted into your bytecode. This makes the decryption methods harder to decompile but, as with all flow obfuscation, it can expose bugs in some VMs and JITs. Note that the String Encryption flow obfuscate setting is quite independent of the "Obfuscate Control Flow" setting. You can use one without the other.

To switch off String encryption, you should set the "Encrypt String literals" option to none.

The advantage of string encryption is that the Java source produced by a decompiler is much less comprehensible if the string literals are gibberish. The disadvantages are that your code will slightly slower and will be a little larger. Typically, the performance cost is insignificant. The bytecode size increase is typically in the range of about 5% to 10% but it ulimately depends on the number of String literals in your application. It is recommended that you measure the impact on your classes.

Note that the string encryption used by Zelix KlassMaster
  • is cumulative. That is, if you obfuscate more than once with the "Encrypt String literals" option set to normal, aggressive or flow obfuscate then your string literals will be encrypted more than once. Any performance and size penalty will be compounded.
  • is not irreversible. Don't rely on it to protect highly sensitive data.

Collapse packages

When the "collapse packages" box is selected, Zelix KlassMaster will recursively collapse subpackages into their superpackages. Effectively, classes in subpackages will be moved into their superpackages. By reducing the overall length of the package names, this option reduces the length of fully qualified class names and therefore reduces the size of the bytecode.

Packages whose names have been excluded from being changed are never collapsed. So packages with excluded superpackages will be collapsed into the nearest excluded superpackage. If a package has no excluded superpackage then it will be collapsed into the package specified in the "Default name" field that appears to the immediate right of the "Collapse packages" box. If the "Default name" field is empty then packages with no excluded superpackage will be collapsed into the Java default package "" (which is no package at all). If a default package name is specified then it must be a top level package. For example "foo" is OK but "foo.bar" is not. The specified top level package need not already exist.

Remember that one of the purposes served by package names is to ensure that fully qualified class names are unique. If you collapse your packages into the Java default package (ie. no package) then Zelix KlassMaster will ensure that your class names are unique within your application. However, you must be sure that there will be no runtime name clashes with other default package classes in the runtime classpath.

Take as an example the following set of packages.
com
com.mycompany
com.mycompany.package1
com.mycompany.package2
com.yourcompany
com.yourcompany.package1

If you
1. select the "Collapse packages" box
2. exclude the com.mycompany package name from being excluded
3. enter foo into the "Default name" field

then the packages will be collapsed as follows
com=>com
com.mycompany=>com.mycompany
com.mycompany.package1=>com.mycompany
com.mycompany.package2=>com.mycompany
com.yourcompany=>foo
com.yourcompany.package1=>foo

giving the result
com
com.mycompany
foo

Typically you would only collapse the package structure if your obfuscated classes were self contained. The following settings are typical for the different application types.
Application type Ok to collapse packages?
Non-extensible library No
Extensible framework No
J2ME MIDlet Yes
Self contained application or applet Yes

Aggressive method renaming

If you select this option, Zelix KlassMaster will rename your methods more aggressively. The resulting bytecode will run without problem but you may have difficulties compiling Java source against your obfuscated bytecode.

Select this option only if your application is stand-alone and self-contained. Do not select this option if your classes make up an extensible framework or a class library.

Keep inner class information

The JDK 1.1 introduced inner classes. At the level of the bytecode, inner classes are distinguished by the structure of their names and by the presence of a few attributes. This inner class information is not critical to the running of your bytecode. It is provided for the use of compilers and debuggers and similar utilities.

If you select "true" in the "keep inner class information" list then Zelix KlassMaster will retain this inner class information in all inner classes. If you select "false" then Zelix KlassMaster will delete this inner class information from all inner classes. Finally, if you select "ifNameNotObfuscated" then Zelix KlassMaster will retain this information in all inner classes that do not have their names obfuscated and it will delete it in all others. The rationale of the "ifNameNotObfuscated" setting is that you are unlikely to have changed the name of an inner class that needs to be accessed by a compiler or utility.

Because inner class information is not used at runtime, it is generally suggested that you select "false". However, if you or your customers must compile classes against your obfuscated inner classes then you must select "true" or at least "ifNameNotObfuscated".

Keep generics information

The JDK 1.5 introduced generics. At the level of the bytecode, generics information is stored in special attributes. As in the case of inner class information, generics information is not critical to the running of your bytecode but is provided for the use of compilers and debuggers and similar utilities.

If you select "true" in the "keep generics information" list then Zelix KlassMaster will retain this information in all classes. If you select "false" then Zelix KlassMaster will delete this information from all classes.

Because generics information is not used at runtime, it is generally suggested that you select "false". However, if you or your customers must compile classes against your obfuscated classes that make use of the genericity of those classes then you must select "true". Some JEE environments may also require that generics information be retained.

Line number tables

Java compilers can include line number tables in your bytecode that map bytecode instructions to source code line numbers. If your code contains line number information and it experiences an uncaught exception at runtime then the corresponding source code line number is displayed by the Virtual Machine. However, line number tables can also provide clues to decompliers.

Zelix KlassMaster gives you three ways of dealing with line number tables. These options appear in the drop down list. If you select delete, Zelix KlassMaster will remove all line number debugging information. This reduces the size of your bytecode but it can make it difficult to analyze the stack traces produced by uncaught exceptions. This is especially the case in obfuscated code where many methods share the same name.

If you select scramble, Zelix KlassMaster will mix-up the line number table entries and write the mapping of the new to original line numbers to the nominated change log file. This gives decompilers little extra information while allowing you to determine the source code line numbers in stack traces. The Stack Trace Translate tool makes the translation of scrambled to original line number easy. However, scrambled line numbers will make your bytecode larger.

The third choice is to select keep. Zelix KlassMaster will leave the existing line number tables as they are. Any stack traces will give the original source line numbers and your bytecode will be slightly smaller than if you had scrambled the line numbers. However, unscrambled line number tables can give decompilers valuable information about the structure of your original code.

In all cases, if there is no line number information in the bytecode, this option will have no effect.

Default exclusions

Zelix KlassMaster excludes some class, method and field names by default ( see "Default Name Exclusions"). For example it supports RMI, JavaBeans™ and EJBs™ by:
  • not changing the "_Stub", "_Skel", "BeanInfo" or "Customizer" class name suffixes and by maintaining the necessary class name correspondence.
  • not changing the names of your RMI remote methods.
  • automatically adjusting the values of your BeanInfo
    • Class beanClass
    • Class customizerClass
    static fields to reflect the new class names.
  • not changing the static long serialVersionUID field name.
  • not changing the names of critical EJB methods such as create(*) and ejbCreate(*).
 
Tools | Obfuscate