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.
  • 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 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 usefull 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 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 Obfuscate References 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 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
keepInnerClassInfo keepInnerClassInfo=false
keepGenericsInfo keepGenericsInfo=true
obfuscateFlow obfuscateFlow=light
exceptionObfuscation exceptionObfuscation=light
encryptStringLiterals encryptStringLiterals=enhanced
mixedCaseClassNames mixedCaseClassNames=ifInArchive
lineNumbers lineNumbers=delete
localVariables localVariables=delete
methodParameters methodParameters=keepVisible
hideFieldNames hideFieldNames=false
hideStaticMethodNames hideStaticMethodNames=false
legalIdentifiers legalIdentifiers=true
randomize randomize=false
obfuscateReferences obfuscateReferences=none
obfuscateReferenceStructures obfuscateReferenceStructures=inSpecialClass
autoReflectionHandling autoReflectionHandling=none
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
          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")]
["keepInnerClassInfo" "=" ("true" | "false | "ifNameNotObfuscated")]
["keepGenericsInfo" "=" ("true" | "false")]
["obfuscateFlow" "=" ("none" | "light" | "normal" | "aggressive" | "extraAggressive")]
["exceptionObfuscation" "=" ("none" | "light" | "heavy")]
["encryptStringLiterals" "=" ("none" | "normal" | "aggressive" | "flowObfuscate" | "enhanced")]
["obfuscateReferences" "=" ("none" | "normal")]
["obfuscateReferenceStructures" "=" ("inSpecialClass" | "inReferencingClasses")]
["obfuscateReferencesPackage" "=" "\"" someExistingPackageName "\""]
["autoReflectionHandling" "=" ("none" | "normal")]
["autoReflectionPackage" "=" "\"" someExistingPackageName "\""]
["autoReflectionHash" "=" "\"" someAvailableHashAlgorithm "\""]
["collapsePackagesWithDefault=" "=" "\"" someTopLevelPackageName "\""
["mixedCaseClassNames" "=" ("true" | "false" | "ifInArchive")]
["lineNumbers" "=" ("delete" | "scramble" | "keep")]
["localVariables" "=" ("delete" | "keepVisibleMethodParameters") |
    "keepVisibleMethodParametersIfNotObfuscated") | "obfuscate") | "keep")]
["methodParameters" "=" ("delete" | "keepVisible") |
    "keepVisibleIfNotObfuscated") | "obfuscate") | "keep")]
["newNamesPrefix=" "=" "\"" someShortString "\""
["randomize" "=" ("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 Obfuscate References 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".
  • someTopLevelPackageName is the name of the package into which unexcluded packages should be collapsed. Can be "" to specify the Java default package. Otherwise must be a top level package. For example "z" is OK but "z.z" is not. The specified top level package need not already exist.
  • someVersionDigit is the Java version level which should be assumed to be present at runtime. Examples are "6" and "7".
 
ZKM Script resetObfuscateReferenceExclusions statement The ZKM Script Language ZKM Script saveAll statement