Zelix KlassMaster - Documentation
 

The obfuscate Statement

The ZKM Script obfuscate statement obfuscates all opened classes. Obfuscation includes:
  • Obfuscating the control flow of all methods that have not been excluded by a preceding obfuscateFlowExclude statement.
  • Changing the names of packages, classes, fields and methods that have not been excluded by a preceding exclude statement.
  • Encrypting string literals that have not been excluded by a preceding stringEncryptionExclude statement.
  • Encrypting integer constants that have not been excluded by a preceding integerEncryptionExclude statement.
  • Encrypting long constants that have not been excluded by a preceding longEncryptionExclude statement.
  • Collapsing the package structure. Excludes packages excluded by a preceding exclude statement.
  • Deleting, scrambling or retaining line number tables.
  • Deleting, obfuscating or retaining local variable tables.
  • Automatically handling Java Reflection API calls which may be broken by obfuscation.
  • Obfuscating field or method references that have been specified by a preceding obfuscateReferencesInclude and/or obfuscateReferencesExclude statement by replacing them Java Reflection API calls.
The remainder of this page is organized into the following sections.

Explanation

For a detailed explanation of the effect of the obfuscate statement and its parameters see the documentation for the interactive "Tools Obfuscate" menu option. Functionality that is available only through the ZKM Script interface is documented below.

The broad functionality provided by the changeLogFileIn parameter is available through the GUI interface but the ZKM Script interface allows you to specify more than one input change log. If more than one input change log is specified then the specified change logs are effectively merged. Change logs appearing first in the list have precedence over those appearing later in the list. The changeLogFileIn and looseChangeLogFileIn parameters are mutually exclusive.

The functionality provided by the looseChangeLogFileIn parameter is available only through the ZKM Script interface. The functionality is the same as that provided by the changeLogFileIn except that the name obfuscation exclusion settings (see the exclude statement) take precedence over the input change log mappings. The looseChangeLogFileIn and changeLogFileIn parameters are mutually exclusive.

The functionality provided by the newNamesPrefix parameter is available only through the ZKM Script interface. It allows you to specify a short String prefix which will be prepended to all newly generated package, class, field and method names. It is highly recommended that the prefix be very short so that it doesn't increase the bytecode size any more than necessary.

The functionality provided by the newNameCharacters parameter is available only through the ZKM Script interface. By default, Zelix KlassMaster™ will use only legal ASCII obfuscated names. However, if you specify newNameCharacters=non-ASCII then obfuscated names will make use of the set of legal non-ASCII characters. Note that this feature may cause problems for JVMs prior to version 7. It is your responsibility to test the obfuscated bytecode. Also note that use of non-ASCII characters may cause difficulties in translating stack traces.

The functionality provided by the allClassesOpened parameter is available only through the ZKM Script interface. When set to true, this option tells Zelix KlassMaster™ that not all the classes that make up the application have been opened for obfuscation. If this option is set to false then there must be an input change log specified which contains the mappings for all the unopened classes. Also, the classpath must allow the unobfuscated versions of all the unopened classes of the application to be located

The functionality provided by the deriveGroupingsFromInputChangeLog parameter is available only through the ZKM Script interface. When set to true, this option tells Zelix KlassMaster™ that it should use the information in the input change log to determine the "groupings" of the classes. Normally, Zelix KlassMaster™ would determine the class groupings from the archive structure from which the classes have been opened. If this option is set to true then an input change log must be specified.

The functionality provided by the methodParameters parameter is available only through the ZKM Script interface. There are five ways of dealing with methodParameters attributes. When you specify "delete" all methodParameters attribute information is deleted. You should use this setting in almost all cases. When you specify "obfuscate" all methodParameters attribute information is obfuscated. When you specify "keep" all methodParameters attribute information is retained. This can sometimes be useful for debugging purposes. When you specify "keepVisible" (the default) the methodParameters attribute method parameter variable names of public or protected methods are retained. When you specify "keepVisibleIfNotObfuscated" the methodParameters attribute method parameter variable names of public or protected methods are retained only if
  1. the name of the method is not obfuscated and
  2. the names of the containing class and package are not obfuscated.
These two options can be of use when obfuscating a library that will be used within an IDE. Many IDE's will preview a method's signature including its parameter names. However, you should note that method parameter names may also be stored in the local variable tables and these are independently managed by the localVariables parameter.

The functionality provided by the uniqueClassNames parameter is available only through the ZKM Script interface. When set to true, this option tells Zelix KlassMaster™ to not reuse unqualified class names across packages. This option can be useful when a framework uses unqualified class names as identifiers in annotations or XML.

The functionality provided by the uniqueMethodNames parameter is available only through the ZKM Script interface. When set to true, this option tells Zelix KlassMaster™ to not reuse obfuscated method names. This option is intended to be used only in special debugging scenarios in which it could make the interpretation of obfuscated stack traces easier.

The functionality provided by the newPackageNameFile parameter is available only through the ZKM Script interface. It is used to specify a text file in UTF-8 format which specifies a list of possible obfuscated names to be used when renaming packages. If the list is too short then Zelix KlassMaster™ will create the extra package names in the usual way.

The functionality provided by the newClassNameFile parameter is available only through the ZKM Script interface. It is used to specify a text file in UTF-8 format which specifies a list of possible obfuscated names to be used when renaming classes. If the list is too short then Zelix KlassMaster™ will create the extra class names in the usual way.

The functionality provided by the newFieldNameFile parameter is available only through the ZKM Script interface. It is used to specify a text file in UTF-8 format which specifies a list of possible obfuscated names to be used when renaming fields. If the list is too short then Zelix KlassMaster™ will create the extra field names in the usual way.

The functionality provided by the newMethodNameFile parameter is available only through the ZKM Script interface. It is used to specify a text file in UTF-8 format which specifies a list of possible obfuscated names to be used when renaming methods. If the list is too short then Zelix KlassMaster™ will create the extra method names in the usual way.

The functionality provided by the obfuscateReferences parameter is available through the GUI interface but additional functionality provided by the obfuscateReferenceStructures and obfuscateReferencesPackage parameters and the obfuscateReferencesInclude and obfuscateReferencesExclude statements is available only through the ZKM Script interface. A field or method reference is a field access or a method call. See the Reference Obfuscation Tutorial for more detail.

The functionality provided by the autoReflectionHandling parameter is available through the GUI interface but additional functionality provided by the autoReflectionHash and autoReflectionPackage parameters and the accessedByReflection and accessedByReflectionExclude statements is available only through the ZKM Script interface. See the AutoReflection™ Tutorial for more detail.

The functionality provided by the methodParameterChanges parameter is available only through the ZKM Script interface. When set to normal, random or flowObfuscate, this option tells Zelix KlassMaster™ that it may change method parameters in support of the the String Encryption and Reference Obfuscation functions. Method parameters will only be changed in support of the String Encryption function if the enhanced setting has been selected. If methodParameterChanges=normal, methodParameterChanges=random or methodParameterChanges=flowObfuscate then, generally speaking, all methods will be considered as candidates for parameter changes subject to the effects of any preceding methodParameterChangesInclude or methodParameterChangesExclude statements. If there is not an active, preceding methodParameterChangesInclude or methodParameterChangesExclude statement then, again generally speaking, all methods will be considered as candidates for parameter changes.

The random setting is the same as the normal setting but the additional parameters will be of a more random type and will be in a more random position but there may be a slight runtime performance cost. The flowObfuscate setting is the same as the random setting but a special kind of Flow Obfuscation may be applied. Again, there may be a runtime performance cost.

The allowMethodParameterChanges parameter is now deprecated in favor of the methodParameterChanges parameter. The allowMethodParameterChanges=false setting is the equivalent of methodParameterChanges=none. The allowMethodParameterChanges=true setting is the equivalent of methodParameterChanges=normal.

The functionality provided by the obfuscateParameters parameter is available only through the ZKM Script interface. When set to normal this option tells Zelix KlassMaster™ that it may obfuscate method parameters to be a single Object[] parameter. If obfuscateParameters=normal then, generally speaking, all methods that will have their names obfuscated will be considered as candidates for parameter obfuscation subject to the effects of any preceding methodParameterObfuscationInclude or methodParameterObfuscationExclude statements. If there is not an active, preceding methodParameterObfuscationInclude or methodParameterObfuscationExclude statement then, again generally speaking, all methods that will have their names obfuscated will be considered as candidates for parameter changes.

The functionality provided by the makeClassesPublic parameter is available only through the ZKM Script interface. When set to true this option tells Zelix KlassMaster™ to make all classes public and not final. This can make it harder to analyze the structure of an application.

The functionality provided by the legalIdentifiers parameter is available only through the ZKM Script interface. If you specify legalIdentifiers=false then Zelix KlassMaster™ will use numeric identifiers which would not be legal in the Java language. However, this could cause your bytecode to fail verification. The parameter is provided only for backwards compatibility reasons. It is recommended that you do NOT use this option.

The functionality provided by the hideFieldNames and hideStaticMethodNames parameters are available only through the ZKM Script interface. Prior to Zelix KlassMaster™ v2.3.1, field and static method names were hidden by default. However, because of changes in the second edition of the Java Language Specification, the default was changed in Zelix KlassMaster™ v2.3.1 so that the names are not hidden. These parameters are provided to allow you to override the defaults for compatibility reasons. It is recommended that you do NOT use this option.

The obfuscate statement has useful defaults which are as follows:

Omitted parameter Effect
changeLogFileOut changeLogFileOut="ChangeLog.txt"
aggressiveMethodRenaming aggressiveMethodRenaming=false
newNameCharacters newNameCharacters=ASCII
keepInnerClassInfo keepInnerClassInfo=false
keepGenericsInfo keepGenericsInfo=true
obfuscateFlow obfuscateFlow=light
exceptionObfuscation exceptionObfuscation=light
encryptStringLiterals encryptStringLiterals=enhanced
encryptIntegerConstants encryptIntegerConstants=none
encryptLongConstants encryptLongConstants=none
mixedCaseClassNames mixedCaseClassNames=ifInArchive
lineNumbers lineNumbers=delete
localVariables localVariables=delete
methodParameters methodParameters=keepVisible
hideFieldNames hideFieldNames=false
hideStaticMethodNames hideStaticMethodNames=false
legalIdentifiers legalIdentifiers=true
randomize randomize=false
uniqueClassNames uniqueClassNames=false
uniqueMethodNames uniqueMethodNames=false
obfuscateReferences obfuscateReferences=none
obfuscateReferenceStructures obfuscateReferenceStructures=inSpecialClass
autoReflectionHandling autoReflectionHandling=none
methodParameterChanges methodParameterChanges=none
obfuscateParameters obfuscateParameters=none
makeClassesPublic makeClassesPublic=false
allClassesOpened allClassesOpened=true
deriveGroupingsFromInputChangeLog deriveGroupingsFromInputChangeLog=false
keepBalancedLocks keepBalancedLocks=false
preverify preverify=true

Examples

obfuscate;                       //Obfuscate using the defaults

obfuscate changeLogFileOut=""    //Don't write to a change log file
          lineNumbers=scramble   //Scramble and keep the line number tables
          obfuscateFlow=none;    //Don't obfuscate control flow

obfuscate changeLogFileIn="ChangeLogIn.txt"   //Use ChangeLogIn.txt as the input change log
          changeLogFileOut="ChangeLog.txt"    //Write to change log file ChangeLog.txt
          obfuscateFlow=light                 //Light control flow obfuscation
          encryptStringLiterals=flowObfuscate //Encrypt String literals using a flow obfuscated decrypt method
          encryptIntegerConstants=normal //Encrypt integer constants
          collapsePackagesWithDefault="foo"   //Collapse packages into package "foo"
          newNamesPrefix="Z";                 //Prepend "Z" to every new obfuscated name

          //Use ChangeLogIn0.txt and ChangeLogIn1.txt as loose input change logs
obfuscate looseChangeLogFileIn="ChangeLogIn0.txt","ChangeLogIn1.txt";

Syntax

"obfuscate" ["changeLogFileIn" "=" "\"" changeLogFileNameIn "\"" ("," "\"" changeLogFileNameIn "\"")*]
["looseChangeLogFileIn" "=" "\"" changeLogFileNameIn "\"" ("," "\"" changeLogFileNameIn "\"")*]
["changeLogFileOut" "=" "\"" changeLogFileNameOut "\""]
["aggressiveMethodRenaming" "=" ("true" | "false")]
["newNameCharacters" "=" ("ASCII" | "non-ASCII")]
["keepInnerClassInfo" "=" ("true" | "false | "ifNameNotObfuscated")]
["keepGenericsInfo" "=" ("true" | "false")]
["obfuscateFlow" "=" ("none" | "light" | "normal" | "aggressive")]
["exceptionObfuscation" "=" ("none" | "light" | "heavy")]
["encryptStringLiterals" "=" ("none" | "normal" | "aggressive" | "flowObfuscate" | "enhanced")]
["encryptIntegerConstants" "=" ("none" | "normal" | "aggressive"]
["encryptLongConstants" "=" ("none" | "normal"]
["obfuscateReferences" "=" ("none" | "normal")]
["obfuscateReferenceStructures" "=" ("inSpecialClass" | "inReferencingClasses")]
["obfuscateReferencesPackage" "=" "\"" someExistingPackageName "\""]
["autoReflectionHandling" "=" ("none" | "normal")]
["autoReflectionPackage" "=" "\"" someExistingPackageName "\""]
["autoReflectionHash" "=" "\"" someAvailableHashAlgorithm "\""]
["collapsePackagesWithDefault=" "=" "\"" somePackageName "\""
["mixedCaseClassNames" "=" ("true" | "false" | "ifInArchive")]
["newPackageNameFile" "=" "\"" nameListFileName "\""]
["newClassNameFile" "=" "\"" nameListFileName "\""]
["newFieldNameFile" "=" "\"" nameListFileName "\""]
["newMethodNameFile" "=" "\"" nameListFileName "\""]
["lineNumbers" "=" ("delete" | "scramble" | "keep")]
["localVariables" "=" ("delete" | "keepVisibleMethodParameters" |
    "keepVisibleMethodParametersIfNotObfuscated" | "keepMethodParametersIfNotObfuscated" |     "obfuscate" | "keep")]
["methodParameters" "=" ("delete" | "keepVisible" |
    "keepVisibleIfNotObfuscated" |     "keepIfNotObfuscated" | "obfuscate" | "keep")]
["newNamesPrefix=" "=" "\"" someShortString "\""
["randomize" "=" ("true" | "false")]
["uniqueClassNames" "=" ("true" | "false")]
["uniqueMethodNames" "=" ("true" | "false")]
["methodParameterChanges" "=" ("none" | "normal" | "random" | "flowObfuscate")]
["allowMethodParameterChanges" "=" ("true" | "false")] (deprecated)
["methodParameterChangesPackage" "=" "\"" somePackageName "\""
["obfuscateParameters" "=" ("none" | "normal")]
["makeClassesPublic" "=" ("true" | "false")]
["allClassesOpened" "=" ("true" | "false")]
["deriveGroupingsFromInputChangeLog" "=" ("true" | "false")]
["keepBalancedLocks" "=" ("true" | "false")]
["preverify" "=" ("true" | "false")]
["legalIdentifiers" "=" ("true" | "false")]
["assumeRuntimeVersion" "=" "\"" someVersionDigit "\""]
["hideFieldNames" "=" ("true" | "false")]
["hideStaticMethodNames" "=" ("true" | "false")] ";"

Where
  • changeLogFileNameIn is the name of the existing change log file from which the previously used name mapping details are to be read.
  • changeLogFileNameOut is the name of the file to which the new change details are to be written.
  • someExistingPackageName is the name of some package existing within your classes. If it is required, an AutoReflection™ or Reference Obfuscation lookup class will be put into this package.
  • someAvailableHashAlgorithm is the name of some hash algorithm which will be available at runtime. Examples are "SHA-512", "SHA" and "MD5".
  • somePackageName is the name of the package into which unexcluded packages should be collapsed. Can be "" to specify the Java default package. The specified package need not already exist.
  • nameListFileName is a path to a text file in UTF-8 format specifying a list of obfuscated names to be used.
  • someVersionDigit is the Java version level which should be assumed to be present at runtime. Examples are "6" and "7".
ZKM Script resetMethodParameterObfuscationExclusions statement The ZKM Script Language ZKM Script saveAll statement
Zelix KlassMaster - Java Obfuscator