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 local variable tables.
The remainder of this page is organized into the following sections.
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 randomize parameter is available only through the ZKM Script interface.
When set to true, this option tells Zelix KlassMaster to generate new obfuscated names in a random fashion.
By default, if the opened classes are unchanged, Zelix KlassMaster will generate the same obfuscated names.
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 localVariables parameter is available only through the ZKM Script interface.
It can bet set to either "delete" or "keepVisibleMethodParameters".
When set to "delete" (the default) all local variable information is deleted. You should use this setting in almost all cases.
When set to "keepVisibleMethodParameters" the method parameter variable names of public or protected methods are retained.
This 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.
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 functionality provided by the addCorruptInfo parameter is available only through the ZKM Script interface.
When the option is set to
"light", Zelix KlassMaster will add corrupt debugging information to
every class which implements methods. Setting the parameter to "heavy" options results
in additional corrupt pool information being added to every class. This corrupt information can confuse or crash
some decompilers.
The "light" setting has
the following properties:
- it crashed some early decompilers but is ineffective against the newer versions
- is easily removed by freely available utilities
- it didn't have any problems with the JDK 1.1 bytecode verifiers but is caught by the JDK 1.2 verifier
The "heavy" setting has the following properties:
- it used to crash most decompilers but is becoming increasingly ineffective
- it is harder to remove from the bytecode.
- it will not pass bytecode verification.
- it will not run on the Microsoft VM.
It is recommended that you do NOT use this option. This is especially the case if there is any chance that
your bytecode must pass verification now or in the future.
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
|
encryptStringLiterals
|
encryptStringLiterals=flowObfuscate
|
lineNumbers
|
lineNumbers=delete
|
localVariables
|
localVariables=delete
|
hideFieldNames
|
hideFieldNames=false
|
hideStaticMethodNames
|
hideStaticMethodNames=false
|
legalIdentifiers
|
legalIdentifiers=true
|
randomize
|
randomize=false
|
allClassesOpened
|
allClassesOpened=true
|
deriveGroupingsFromInputChangeLog
|
deriveGroupingsFromInputChangeLog=false
|
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";
"obfuscate"
|
["changeLogFileIn" "=" "\"" changeLogFileNameIn "\"" ("," "\"" changeLogFileNameIn "\"")*]
|
|
|
["looseChangeLogFileIn" "=" "\"" changeLogFileNameIn "\"" ("," "\"" changeLogFileNameIn "\"")*]
|
|
|
["changeLogFileOut" "=" "\"" changeLogFileNameOut "\""]
|
|
|
["aggressiveMethodRenaming" "=" ("true" | "false")]
|
|
|
["keepInnerClassInfo" "=" ("true" | "false | "ifNameNotObfuscated")]
|
|
|
["keepGenericsInfo" "=" ("true" | "false")]
|
|
|
["obfuscateFlow" "=" ("none" | "light" | "normal" | "aggressive")]
|
|
|
["encryptStringLiterals" "=" ("none" | "normal" | "aggressive" | "flowObfuscate")]
|
|
|
["collapsePackagesWithDefault=" "=" "\"" someTopLevelPackageName "\""
|
|
|
["lineNumbers" "=" ("delete" | "scramble" | "keep")]
|
|
|
["localVariables" "=" ("delete" | "keepVisibleMethodParameters")]
|
|
|
["newNamesPrefix=" "=" "\"" someShortString "\""
|
|
|
["randomize" "=" ("true" | "false")]
|
|
|
["allClassesOpened" "=" ("true" | "false")]
|
|
|
["deriveGroupingsFromInputChangeLog" "=" ("true" | "false")]
|
|
|
["legalIdentifiers" "=" ("true" | "false")]
|
|
|
["hideFieldNames" "=" ("true" | "false")]
|
|
|
["hideStaticMethodNames" "=" ("true" | "false")]
|
|
|
["addCorruptInfo" "=" ("light" | "heavy")] ";"
|
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.
- 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.
|