Zelix KlassMaster - Documentation

ProGuard Configuration File Translation Tutorial

This tutorial is divided into the following sections:

The Problem

The ProGuard obfuscator is an open source tool. Being open source and freely available, it is often the first obfuscator that a developer might use. However, ProGuard has only limited features. For example, it does not provide Flow Obfuscation, Exception Obfuscation, Reference Obfuscation, AutoReflection™, String Encryption or the "hardening" provided by Method Parameter Changing.

So the situation can arise where a ProGuard user may wish to migrate to Zelix KlassMaster™. This means that they need to translate their existing ProGuard configuration files to ZKM Script.

Also, ProGuard has been built into a number of build environments which have not provided an alternative, generic obfuscator interface. The Android™ Development Tool plugin (ADT) for Eclipse is an example of such a tool. So it would be convenient if a developer wishing to use Zelix KlassMaster™ rather than ProGuard could do a transparent swap.

The Solution

Zelix KlassMaster™ provides broad support for ProGuard configuration files. It does this by translating ProGuard configuration files into ZKM Script on the fly. So you can execute a ProGuard configuration file using Zelix KlassMaster™ just as you would if it was a ZKM Script file.

Incidentally, you can also translate a ProGuard configuration file into ZKM Script using the ProGuard Configuration File Translation Tool.

Output Files

Zelix KlassMaster™'s log files to do not map cleanly to ProGuard's output files. See the table directly below.

Zelix KlassMaster™ file Closest ProGuard file Comment
ZKM_PG_log.txt none This special a log file which Zelix KlassMaster™ uses to write messages relating to the translation of a ProGuard configuration file. It will always be named "ZKM_PG_log.txt". It will be written to the directory specified by the ZKM_DEFAULT_DIR configuration option if it has been set or otherwise the directory specified by the user.dir property in the System properties.
ZKM_log.txt seeds.txt ProGuard has no direct equivalent of Zelix KlassMaster™'s log file. However, a verbose "ZKM_log.txt" file does contain the details of what is matched by the various exclusion statements.

In the context of ProGuard configuration file translation, the name and location of this log file will be set by the ProGuard -printseeds option if it exists. Otherwise, it will be named "ZKM_log.txt" and it will be written to the default directory.
ZKM_TrimLog.txt usage.txt Lists used classes, fields and methods that have been trimmed

In the context of ProGuard configuration file translation, the name and location of this log file will be set by the ProGuard -printusage option if it exists. Otherwise, it will be named "ZKM_TrimLog.txt" and it will be written to the default directory.
ChangeLog.txt mapping.txt Lists the mapping of old class, field and method names to obfuscated names

In the context of ProGuard configuration file translation, the name and location of this log file will be set by the ProGuard -printmapping option if it exists. Otherwise, it will be named "ChangeLog.txt" and it will be written to the default directory.

In the context of ProGuard configuration file translation, the default directory is determined in the following fashion. It has the value of
  • The ZKM_DEFAULT_DIR configuration option if it has been set or otherwise,
  • The -basedirectory option in the ProGuard configuration if it has been set or otherwise,
  • The directory specified by the first encountered -printseeds, -printmapping or -printusage option in the ProGuard configuration if it any have been set or otherwise,
  • The directory specified by the user.dir property in the System properties.

Compatibility

As mentioned above, Zelix KlassMaster™ provides broad support for ProGuard configuration files. However, it doesn't support all ProGuard configuration options. When Zelix KlassMaster™ encounters one of the following options it will simply ignore them after reporting a warning. Similarly, if Zelix KlassMaster™ encounters some aspect of a supported ProGuard option which it doesn't FULLY support then it will again report a warning.

Not supported
-adaptclassstrings
-adaptresourcefilecontents
-adaptresourcefilenames
-allowaccessmodification
-dontnote
-dontoptimize
-dontskipnonpubliclibraryclasses
-skipnonpubliclibraryclassmembers
-dump
-forceprocessing
-keepdirectories
-mergeinterfacesaggressively
-optimizationpasses
-optimizations
-skipnonpubliclibraryclasses
-target
-useuniqueclassmembernames

Not directly supported
-microedition
-printconfiguration
-renamesourcefileattribute
-whyareyoukeeping

Customizing Certain Statements

Zelix KlassMaster™ will construct a ZKM Script based upon the ProGuard configuration options which it is given. However, this will give you just basic trimming and obfuscation without using any of Zelix KlassMaster's special obfuscation features. You will often want to customize certain constructed ZKM Script statements with an alternative statement or to add extra ZKM Script statements for which there is no ProGuard equivalent.

You can do this by putting the customizing or additional ZKM Script statements into a file named "ZKMScript.txt". Note that the content of the "ZKMScript.txt" file is just a list of customizing ZKM Script statements and is not an executable script in the normal sense. It is different in that:
  • Only the first occurence of a particular ZKM Script statement will be used,
  • The order of the ZKM Script statements is not significant and
  • The use of /*...*/ block comments is not supported.
Also Zelix KlassMaster™ will only process the following statements in the "ZKMScript.txt" file. All others will be ignored.
If a customizing classpath statement is found then all paths that it specifies will be appended to the end of the classpath specified by the ProGuard configuration. Similarly, if a customizing exclude, unexclude, trimExclude, trimUnexclude, ignoreMissingReferences, removeMethodCallsInclude or removeMethodCallsExclude statement is found then all the parameters that they specify will be appended to the end of any corresponding specifications made by the ProGuard configuration.

In all other cases, the customizing statement will override any equivalent configuration in the ProGuard configuration.

Zelix KlassMaster™ will look for the "ZKMScript.txt" file in the following directories.
  • In the directory specified by the ZKM_DEFAULT_DIR configuration option if it has been set,
  • In the directory specified by the -basedirectory option in the ProGuard configuration if it has been set,
  • In the directory specified by the first encountered -printseeds, -printmapping or -printusage options in the ProGuard configuration if any have been set,
  • Finally, in the directory specified by the user.dir property in the System properties.

Zelix KlassMaster™ adds the following three convenience properties to the System properties that you are able to use as system variables in your customizing ZKM Script statements in addition to the System user.dir property.

PROGUARD_LOG_DIR The absolute directory specified by the ProGuard -printseeds, --printusage or -printmapping command if present. Otherwise it will be the directory specified by the ProGuard -basedirectory command if present. Otherwise it will be the directory specified by the System user.dir property.
ZKM_LOG_DIR Same as PROGUARD_LOG_DIR except that the ZKM_DEFAULT_DIR System property if it is present will take precedence over the ProGuard -basedirectory command if present.
PROGUARD_SAVE_DIR The absolute directory specified by the first ProGuard -outjars command if any are present.

Example ZKMScript with customizing statements

The contents of a basic example ZKMScript file appears below. It contains just a ZKM Script obfuscate statement. It specifies light flow and exception obfuscation with relatively safe settings and that Strings should be encrypted. Note that it makes use of the PROGUARD_LOG_DIR System property mentioned above.
//Start ZKMScript.txt with customizing statements
obfuscate   keepGenericsInfo=false
            keepInnerClassInfo=false
            methodParameters=keepVisibleIfNotObfuscated 
            changeLogFileOut="%PROGUARD_LOG_DIR%\ChangeLog.txt"
            obfuscateFlow=light
            encryptStringLiterals=flowObfuscate
            exceptionObfuscation=light 
            autoReflectionHandling=none 
            obfuscateReferences=none
            randomize=true 
            preverify=false
            mixedCaseClassNames=false
            keepBalancedLocks=true
            ;
//End ZKMScript.txt
		 

How to use Zelix KlassMaster™ in an environment expecting ProGuard

If the environment calls ProGuard through a batch or shell script file then you could directly edit that file to point to Zelix KlassMaster™ instead. That is, a reference in the file to proguard.jar could simply be replaced with a reference to ZKM.jar. Of course, you should back up the file before editing it and you would need to ensure that ZKM.jar can be found.

For example

call java -jar proguard.jar %*

would become

call java -jar ZKM.jar %*

Another option in the same scenario would be to replace the original proguard.jar with a dummy version which simply calls Zelix KlassMaster™. For example, you could replace proguard.jar with proguardStub_6.0.3.2.jar. Again, you should back up the original proguard.jar before replacing it and you would need to ensure that ZKM.jar is in the the same directory as proguardStub_6.0.3.2.jar.

If you need to replace ProGuard in an Apache Ant build XML then, as mentioned above, you could replace the reference to proguard.jar with proguardStub_6.0.3.2.jar. You can also simply change the reference to proguard.ant.ProguardTask to com.zelix.ZKM_PG_Task but note that com.zelix.ZKM_PG_Task does not support the more complicated and verbose XML configuration. Again you would need to ensure that ZKM.jar is in the classpath so that com.zelix.ZKM_PG_Task can be found.

In either case, you should back up the original build XML before editing it,

How to use Zelix KlassMaster™ with the Android™ Development Tool

The Eclipse ADT plugin calls ProGuard via the <SDK>\tools\proguard\bin\proguard.bat file in Windows™ or the <SDK>/tools/proguard/bin/proguard.sh file in Linux. These files can be directly edited to specify ZKM.jar rather than proguard.jar.

Note that when using the Android™ Development Tool you do not manually translate any ProGuard configuration into ZKM Script. Rather, when ProGuard is replaced with Zelix KlassMaster™, Zelix KlassMaster™ will automatically translate the ProGuard configuration passed to it by the Android™ Development Tool.

How to use Zelix KlassMaster™ with the Android™ Studio

Android™ Studio 3.6 no longer allows you to use ProGuard. You must use R8. So unfortunately you cannot use Zelix KlassMaster™ in place of ProGuard in this version. Everything set out below assumes that you are using a version of Android™ Studio prior to 3.6.

Newer versions of the Android™ Studio (prior to 3.6) treat ProGuard as a dependency of the Android Gradle plugin and will automatically upgrade it. That is not what you want if you want to replace ProGuard. So the recommended approach is to first configure Android™ Studio so that it is successfully using a local copy of ProGuard that you have downloaded and then make changes so that it uses Zelix KlassMaster™ instead.

Step 1 is to configure Android™ Studio so that it is using a local copy of ProGuard. You do this by adding two lines to your build.gradle file as is shown below.
buildscript {  
    repositories {
        flatDir { dirs '/proguard' }
    }
    dependencies {
        classpath ':proguard:'
    }
}
The flatDir specifies a flat directory repository in your project directory. Download the latest version of ProGuard and place the proguard.jar file into the proguard directory that you have created in your project directory.

Also, Android Studio 3.4 or better now uses the R8 compiler rather than ProGuard. So, to use Zelix KlassMaster rather than R8, you need to set android.enableR8=false in your gradle.properties file.

Check that ProGuard is being called successfully before going on to the next step.

Step 2 is to use Zelix KlassMaster™ rather than ProGuard.
  • Rename the local proguard.jar JAR file just so that you have it backed up,
  • Download the proguardStub_6.0.3.2.jar JAR to the local proguard directory and rename it to proguard.jar
  • Put your ZKM.jar JAR file into a location where the renamed ProGuard Stub can find it.

The renamed ProGuard Stub will look in the following places.
  • The directories specified by the System java.library.path property which would normally be based upon the PATH environmental variable,
  • The directory specified by the System user.home property,
  • The directory specified by the System user.dir property,
  • The directories specified by the System java.class.path property,
  • The directories specified by the System java.endorsed.dirs property and
  • The directories specified by the System java.ext.dirs property.
Typically it would be easiest to put your ZKM.jar file in a folder that is specified by your PATH environmental variable.

Note that when using the Android Studio you do not manually translate any ProGuard configuration into ZKM Script. Rather, when ProGuard is replaced with Zelix KlassMaster™, Zelix KlassMaster™ will automatically translate the ProGuard configuration passed to it by the Android Studio.

How to translate a ProGuard configuration file to a ZKM Script file

The com.zelix.ZKMProGuardTranslate class appears in the Zelix KlassMaster™ JAR file distribution. It provides a command line alternative to the ProGuard Configuration Translate tool GUI tool. It is used as follows to translate a ProGuard configuration file into ZKM Script format.

java -cp ZKM.jar com.zelix.ZKMProGuardTranslate <proguardConfigFileName> <outputFileName>

How to translate a Zelix KlassMaster™ change log into ProGuard mapping file format

The com.zelix.ZKMChangeLogConvert class appears in the Zelix KlassMaster™ JAR file distribution. It provides a command line tool to translate a Zelix KlassMaster™ change log into ProGuard mapping file format. This can be useful when a third party tool supports only the ProGuard mapping file format. The usage is as follows.

java -cp ZKM.jar com.zelix.ZKMChangeLogConvert <changeLogFileName> <outputFileName> [<pathToObfuscatedClasses>]

If the optional third parameter specifying the path to the obfuscated classes (e.g. the obfuscated JAR file) is specified then Zelix KlassMaster will include line number mappings for those methods in the obfuscated JAR that have a LineNumberTable attribute. Note that these line number mappings will be overlapping across methods if the "lineNumbers=scramble" setting has been specifed at the time of obfuscation.

Troubleshooting

If you are replacing ProGuard with Zelix KlassMaster™ in some environment that uses ProGuard by default then the very first step should be to make sure that you are successfully obfuscating using ProGuard. Obviously if ProGuard is not being successfully called by the environment then attempts to replace ProGuard with Zelix KlassMaster™ will be ineffective.

In the context of translating a ProGuard configuration, if you are having problems then the first place to look is in the ZKM_PG_log.txt file. If no ZKM_PG_log.txt file is being produced then Zelix KlassMaster™ is not being called to translate the ProGuard configuration. As mentioned above, ZKM_PG_log.txt file will be written to the directory specified by the ZKM_DEFAULT_DIR configuration option if it has been set or otherwise the directory specified by the user.dir property in the System properties. The ZKM_PG_log.txt file will show
  • The full ProGuard configuration that is to be translated,
  • The detail of any messages and warnings,
  • The default directory for subsequent processing,
  • The name and the location of the Zelix KlassMaster™ log file.
You can then look in the Zelix KlassMaster™ log file named in the ZKM_PG_log.txt file to see if there are any further warning and error messages.
 
Documentation Table of Contents
Zelix KlassMaster - Java Obfuscator