Stringer Java Obfuscator User Manual

Description

Stringer Java Obfuscator safeguards Java and Android application binaries against reverse engineering and modification. To achieve the highest level of protection, it combines strong encryption of strings and resources with call context checks injection. It also provides an integrity control mechanism that hinders malicious modification of your binaries by third parties. Finally, Stringer's code optimization facilities help you reduce application size.

String Encryption And Call Context Checks

Stringer uses a powerful encryption algorithm derived from AES. The decryption keys are broken into pieces and scattered across the resulting binaries, The keys are different for each package, so as to make the use of statistical analysis for string decryption impossible. By default, Stringer encrypts all encountered strings, but annotations and class name filters can be used for selective protection and creation of dummies — unencrypted copies of stings and resources that are not actually used.

Call context checks ensure that a hacker will not be able to create a malicious class to decrypt a string or resource extracted from your application.

Integrity Control/Tamper Resistance (Android not supported)

A binary processed by Stringer with integrity protection enabled will not function if damaged or deliberately modified. This makes it impossible for hackers to disable a licensing subsystem or inject malicious code in your app, e.g. to obtain sensitive information such as passwords or credit card numbers. Stringer can also hide calls of standard Java APIs and other libraries from plain sight.

Note: When using selective protection, selecting ten or more classes is recommended for best results. At least two classes must be protected in order for integrity control to function correctly.

Application Size Optimization

Stringer Java Obfuscator can optionally optimize the processed class files for size by deleting redundant information such as debugging data, local variable names, etc. These optimizations may effectively nullify the decryption/integrity control overheads.

Resource Encryption (Android not supported)

For extra protection, Stringer may also encrypt resources — images, media clips, and other data files that are part of your application — using the same modified AES algorithm. Encryption keys are different for each application, providing best in class protection. The process is completely transparent to the application and requires no changes to its source code or build steps. You may precisely define the list of resources that should be protected using filters.

General information

Stringer Java Obfuscator takes as input either a folder containing class files or a jar file. The output is respectively a folder with processed files or a jar file. Settings can be specified on the command line or in a configuration file.

IMPORTANT: When used in conjunction with any other class file manipulation tools, such as a name obfuscator, Stringer must be invoked after them all for its call context checks and/or integrity control facilites to work.

You can access all Stringer features from the command line or through a graphical interface, or invoke it from automated build systems such as Ant or Maven. There is also an Eclipse plugin readily available.

Stringer Java Obfuscator is itself written in Java and therefore can be used on any platform for which JRE 6 or higher is available. It can process Java applications compiled for J2SE 5.0 and up.

Package Contents

Stringer is distributed as a zip archive containing the following files:

  • Command-line interface: stringer.jar (executable jar file)
  • Graphical interface: stringer-gui.jar (executable jar file)
  • Application for Mac OS X: Stringer-GUI.app
  • Annotations jar: stringer-annotations.jar
  • Samples folder: samples/
  • License texts: NOTICE, LICENSE

Using CLI and GUI

Downloading

To get the latest version of the obfuscator distribution kit, go to:
Stringer 1.6.10-20140414

Installation

Unpack the zip file to the destination folder.

Obtaining the activation code

To get a fully functional activation code, purchase the required number of licenses. In this case registration is obligatory. You can register by entering your email address when purchasing the license. Further instructions how to set your password and installation directions will be sent to the email address you provided during the checkout process.
When purchasing the product via FastSpring the activation codes are sent within 24 hours after the funds are received. If a contract is signed with a company, the activation codes are sent after receipt on account or after a copy of a payment order is submitted.

The license information will be displayed on your profile, in the Your licenses. The license status will be displayed as: Generated – meaning that the license code is generated but not used or Activated - meaning the activation code is used. Your login is your email you used when ordering Stringer Java Obfuscator.

The activation code is single-use. It means you have to contact the customer support to get a new code if the original license file was lost.

Stringer Java Obfuscator support two activation methods: online and offline. If you have an active Internet connection you may use online activation. If you have not Internet connection, or if it is limited by various traffic filter systems you should use offline activation. In this case it is necessary to generate activation request code using CLI or GUI, and send it to stringer@licelus.com via email. You can do it from another comuter or a device which has an active Internet connection.

CLI

Activation via CLI
Online activation via CLI

To activate Stringer Java Obfuscator online in the console mode, run the following command:

java -jar stringer.jar -activate

and follow the instructions.

After successful activation the license file stringer.licel will be created in the user's home folder.
To use a license file located in a different folder and not in the same folder with stringer.jar, it is necessary to specify the path to the license file.

Offline activation via CLI

In order to activate license offline run the following command:

java -jar stringer.jar -activationRequest

After you enter an activation code a request code will be generated. You should email this code to stringer@licelus.com. In 24 hours you will receive response code, then run the following command:
java -jar stringer.jar -activationResponse

Enter the code you have received. After successful activation the license file stringer.licel will be created in the user's home folder.
To use a license file located in a different folder and not in the same folder with stringer.jar, it is necessary to specify the path to the license file.
Options and parameters

java -jar stringer.jar <options> <src> <dest>
Valid values <src>:

The original jar file or folder path

Valid values <dest> (may be the same as <src>):

Path to destination jar file or folder. If the <dest> doesn't exists it will be created. By default, type of <dest> is equal to <src>. The <dest> type can be changed with the -outputType dir/jar option.

Valid values <options>:

  • -activate - activate the license
  • -activationRequest - generate request code for offline activation
  • -activationResponse - finish offline activation process, enter response code
  • -info - license status
  • -licenseFile filename - path to license file
  • -configFile filename - use the configuration parameters from the specific file (Configuration file format)
  • -outputType dir/jar - select <dest> type (folder or jar file)
  • -checkCaller - turn on call context check (default: off)
  • -integrityProtection - turn on protection against modification (default: off)
  • -resourceEncryption - turn on resource encryption (default: off)
  • -optimize - turn on size optimization of the class files (default: off)
  • -osgiCompatibility - turn on OSGI containers compatibility mode (default: off)
  • -proguardMapFile - path to ProGuard’s map file
  • -target 1.7|1.8 - force to generate specific bytecode version (by default the original bytecode version of class files is used)
  • -nameGenMethod latin|utf - method name generation algorithm (utf by default)
  • -verbose - print verbose log to stdout (default: off)

Input files filter:

  • -include <pattern> include class files and resource files by <pattern>
  • -exclude <pattern> exclude class files and resource files by <pattern>

GUI

Activation via graphic interface
Online activation via graphic interface

To activate license online in the GUI double-click on stringer-gui.jar (Windows/Linux) or Stringer-GUI.app (MacOS).
Click the License Info in the application window.


Then click Activate, enter the activation code and click Activate online.

After successful activation file stringer.licel will be created in the user's home folder.
Offline activation via graphic interface

In order to activate license offline in the GUI double-click on stringer-gui.jar (Windows/Linux) or Stringer-GUI.app (MacOS).
Click the License Info in the application window.


Click the Activate, enter the activation code and click Generate activation request.


You should email this code to stringer@licelus.com. In 24 hours you will receive reply with a activation response. It is necessary to enter the code in a field which will appear after clicking Enter activation response. In case if you turned Stringer Java Obfuscator off, run it again and follow License Info -> Activate -> Enter activation response.


After successful activation file stringer.licel will be created in the user's home folder.
Options and parameters

Source - the original jar file or folder path.
Destination - the jar file or folder path at the output. May be equal to the Source. If Destination does not exist it will be created. By default type of Destination is the same as Source.

Configuration

  • Include class file filter - include class files and resource files by <pattern>
  • Exclude class file filter - exclude class files and resource files by <pattern>
  • Check call context - turn on call context check (default: off)
  • Class file integrity protection - turn on protection against modification (default: off)
  • Resource encryption - turn on resource encryption (default: off)
  • Optimize - turn on size optimization of the class files (default: off)
  • OSGI compatibility - turn on OSGI containers compatibility mode (default: off)
  • Print verbose output to console - display a detailed operation log (default: off)

Control elements:

  • License Info - the license status and activation
  • Load config - load settings from the configuration file
  • Save config - save settings to the configuration file
  • Run - run obfuscation

After execution, displayed if Print verbose output to console is enabled, information about obfuscation and the debugging information is dispplayed. You can click Save to file button to save the log to a file.

Using as Ant-task

NOTE: To use Stringer Java Obfuscator as an Ant task, it is necessary to download the obfuscator distribution kit, complete installation, receive the activation code and use it for obtaining your license following the instructions Using CLI and GUI. The license can be activated via GUI or CLI.

To add Stringer Java Obfuscator task to an Ant script, add the following to your ant script (build.xml by default):

<taskdef name="stringer" classname="com.licel.stringer.AntTask" classpath="lib/stringer.jar"/>

To call a stringer task:
<stringer srcFile="${src.jar}" destFile="${dest.jar}"/>

You can also use the srcDir and destDir parameters to specify the source and the output folders respectively. You can input a jar file and get encoded source files in a folder as the output and vice versa.
Example:
<stringer srcDir="${src.dir}" destFile="${dest.jar}"/>

The additional parameters can be specified in the outer configuration file:
<stringer srcFile="${src.jar}" configFile="${stringer.config}" destFile="${dest.jar}"/>

Or you can specify it inside the task:

<stringer srcFile="${src.jar}" destFile="${dest.jar}" 
         checkCaller="true|false"
         integrityProtection="true|false"
         resourceEncryption="true|false"
         optimize="true|false"
         verbose="true|false"
         osgiCompatibility="true|false"
         proguardMapFile="${proguard.map.file}"
         target="1.7|1.8"
         nameGenMethod="latin|utf"
         licenseFile="${stringer.license}">
  <include name="mypackage/p1/**"/>
  <exclude name="mypackage/p1/testpackage/**"/>
</stringer>


Android obfuscation and Ant

1) Make sure Android SDK and ANT are properly installed.
2) If you already have build.xml then skip steps 3-5 and start with step 6.
3) Go to the project folder:

    $ cd HelloWorldAndroid
 

4) Execute the following command:
    $ android-sdk-home/tools/android update project --path .
 

5) Check the correctness of build.xml with the ant command; the output should be like this:
help:
     [echo] Android Ant Build. Available targets:
     [echo]    help:      Displays this help.
     [echo]    clean:     Removes output files created by other targets.
     [echo]               The 'all' target can be used to clean dependencies
     ......
BUILD SUCCESSFUL

6) Create file custom_rules.xml with the following content:
<?xml version="1.0" encoding="UTF-8"?>
<project name="stringer_rules" default="debug">
 
<taskdef name="stringer" classname="com.licel.stringer.AntTask"
classpath="${stringer.home}/stringer.jar"/>
 
 <target name="-obfuscate" depends="android_rules.-obfuscate">
 	<if condition="${proguard.enabled}">
    	<then>
    		<property name="stringer.jar.file" value="${out.dex.input.absolute.dir}"/>
        </then>
        <else>
            <!-- Secondary dx input (jar files) is empty since all the
                     jar files will be in the obfuscated jar -->
            <path id="out.dex.jar.input.ref" />
            <property name="stringer.absolute.dir" location="${out.absolute.dir}/stringer" />
            <property name="stringer.jar.file" value="${stringer.absolute.dir}/project-all.jar"/>
            <property name="out.dex.input.absolute.dir" value="${stringer.jar.file}" />
            <delete file="${stringer.jar.file}"/>
            <script language="javascript"><![CDATA[
              println("Merging all jars in single jar");
              importClass(java.io.File); 
              var zipTask = project.createTask("zip");
              zipTask.setDestFile(new File(project.getProperty("stringer.jar.file")));
              var fileSet = project.createDataType("fileset");
              fileSet.setDir(new File(project.getProperty("out.classes.absolute.dir")));
              zipTask.addFileset(fileSet);
              println("input: "+project.getProperty("out.classes.absolute.dir"));
              var allPath = project.getReference("project.all.jars.path");
              if(allPath!=null) {
              	var paths = allPath.list();
                for (i=0; i<paths.length; i++) {
                	println("input: "+paths[i]);
                	fileSet = project.createDataType("fileset");
                	fileSet.setFile(new File(paths[i]));
                        fileSet.setExcludes("META-INF/**");
                	zipTask.addZipGroupFileset(fileSet);
		        }
              }
              zipTask.execute();
             ]]></script>
        </else>
 	</if>           
 	<stringer verbose="true" checkCaller="true"
 		srcFile="${stringer.jar.file}"
 		destFile="${stringer.jar.file}">
 	</stringer>
 </target>
 
</project>

7) In the local.properties file add property stringer.home, and set the property to the Stringer's installation path, for example stringer.home=/usr/local/stringer.

IMPORTANT! Do not place Stringer's jar libraries in libs of your project.

Save file and execute the command ant release.

Using as Maven-plugin

NOTE: To use Stringer Java Obfuscator's Maven plugin, it is necessary to download the obfuscator distribution kit, install the Stringer, get the activation code and use it for obtaining your license following the instructions here: Using CLI and GUI.

First you need to specify Licel Plugin Repository in pom.xml:

    <pluginRepositories>
        <pluginRepository>
            <id>licel</id>
            <url>https://licel.ru/m2</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

Stringer is executed at the package phase of a lifecycle of a project build. To use it, it is necessary to add a plugin definition to the build/plugins pom.xml section.

<project>
  ...
  <build>
    <plugins>
            ...
            <plugin>            
                <groupId>com.licel</groupId>
                <artifactId>stringer-maven-plugin</artifactId>
                <version>1.6.7</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>stringer</goal>
                        </goals>
                        <configuration>
                           <!-- put your configurations here -->   
                        </configuration>
                    </execution>
                </executions>
            </plugin>
           ...
      </plugins>
  </build>
  ...
</project>

The additional parameters can be set by specifying external configuration file:

<configuration>
    <configFile>${stringer.config}</configFile>
</configuration>

Or by adding configuration in the plugin section:

<configuration>
    <verbose>true</verbose>
    <checkCaller>true</checkCaller>
    <integrityProtection>true</integrityProtection>
    <resourceEncryption>true</resourceEncryption>
    <optimize>true</optimize>
    <osgiCompatibility>true</osgiCompatibility>
    <proguardMapFile>${proguard.map.file}</proguardMapFile>
    <target>1.7|1.8</target>
    <nameGenMethod>latin|utf</nameGenMethod>
    <licenseFile>${stringer.license}</licenseFile>
    <includes>
        <include>mypackage/p1/**</include>
    </includes>
      <excludes>
        <exclude>mypackage/p1/testpackage/**</exclude>
    </excludes>    
</configuration>

Using as Eclipse plugin

Install using Eclipse Marketplace

1. Open Eclipse Marketplace (if MPC not installed, please install in accordance with http://www.eclipse.org/mpc/)


2. Type Stringer in the search field, select Stringer Java Obfuscator and then click Install

Manual installation

Repository location: https://jfxstore.com/stringer/eclipse
1. Run Eclipse
2. Click Help -> Install New Software


3. Click Add in the Install window and add a repository; use a convenient name, for example Stringer and location - https://jfxstore.com/stringer/eclipse

4. Select Stringer from the Developer Tools category and click Next. Then you will see an installation report, click Next. If you do not see Stringer in the installation window, uncheck Group items by category

5. Confirm that you agree with the license and click Finish
6. After installation you need to restart Eclipse. The best option is Restart Now

Using Eclipse-plugin

1. Open or create a Java/Android project, go to its Properties. Select Builders and add Stringer.


2. After you add Stringer builder you will see the plugin configuration screen

If you do not have a valid license file or activation code, follow the instructions here: Receiving an activation code. After getting the activation code, click the Activate button and enter your activation code.


3. Slide Stringer to the position right after Java Builder

NOTE: Use Export Android Application with Stringer Protection to export Android projects.

Adding Stringer Annotations Library

To use annotations in Eclipse IDE, it necessary to add Stringer Annotations Library to the project Build Path.
Go to the project Properties, select Java Build Path, open the Libraries tab and click Add Library..., add Stringer Annotations Library:

Protection of Eclipse RCP projects

To protect RCP projects, it is necessary to enable Use class files compiled in the workspace option inside the Options tab of export section (Export Dialog Wizard):

Now you can protect your Android and Java projects using Eclipse IDE!

NOTE: Stringer Java Obfuscator will be run only if you build or run manually.

Using in NetBeans

1. To protect your class files in NetBeans, you can use the stringer Ant task
2. Edit build.xml of the project you want to protect. And add the stringer Ant task defenition:

<taskdef name="stringer" classname="com.licel.stringer.AntTask"
classpath="${stringer.home}/stringer.jar"/>

3. Add the stringer call after project compilation:
<target name="-post-compile">
    <stringer srcDir="${build.classes.dir}" destDir="${build.classes.dir}"/>
</target>

Additional settings described in Using as Ant-task.

If you use Maven to build a project in NetBeans then follow the instructions Using as Maven-plugin.

Configuration file format

The syntax of configuration file:

    <stringer  checkCaller="true|false"
                   integrityProtection="true|false" 
                   resourceEncryption="true|false" 
                   optimize="true|false"  
                   verbose="true|false"  
                   osgiCompatibility="true|false"   
                   proguardMapFile="/home/user/build/proguard.map" 
                   target="1.7|1.8" 
                   nameGenMethod="latin|utf" 
                   licenseFile="/home/user/stringer.licel">
    	<include name="mypackage/p1/**"/>
    	<exclude name="mypackage/p1/testpackage/**"/>
    </stringer>


Annotations

To fine tune your protection process, you can use annotations. By default if there are no @secured annotations in a project then all class files meeting filter requirements are protected. If there are the @secured annotations in a project then class files and/or their elements marked @secured will be protected.
The @secured annotation can be used at the following hierarchy levels:

Class - all contents of the class are protected:

...
import com.licel.stringer.annotations.secured;
 
@secured 
public class Test {
   ....
}
Class field - a specified class field is protected:

import com.licel.stringer.annotations.secured;
 
public class Test {
 @secured
  final String SOME_TEXT="12345678";
   ....
}
Class method - a body of class method is protected:

import com.licel.stringer.annotations.secured;
 
public class Test {
   ....
  @secured
  public void someMethod(){
     ...
  }
   ....
}

In some cases it could be comfortably to protect all classes with an exception. The @insecure annotation is suitable for this. Similar to the @secured annotation you can use @insecure for classes, class fields and class methods.

To use @secured and @insecure annotations in your projects, add the stringer-annotations.jar library from the distribution kit to the project classpath.

If using Eclipse follow the instructions of section Eclipse: Adding Stringer Annotations Library.

If working with a Maven project: add a Maven repository Stringer Java Obfuscator and specify project dependence on the com.licel.stringer-annotations artifact:

   <repositories>
     <repository>
         <id>licel</id>
         <url>https://licel.ru/m2</url>
         <snapshots>
            <enabled>false</enabled>
         </snapshots>
     </repository>
   </repositories>
 
   <dependencies>
       <dependency>
           <groupId>com.licel.</groupId>
           <artifactId>stringer-annotations</artifactId>
           <version>1.0.3</version>
           <scope>compile</scope>
       </dependency>
   </dependencies>

An example of using annotations is available in the samples/HelloWorldAnnotations folder of the distribution kit.

Samples

To build the samples you can use either Ant or Maven.

Ant:

$ cd samples/HelloWorld
$ ant
$ java -cp dist/HelloWorld.jar test.App

Maven:
$ cd samples/HelloWorld
$ mvn package 
$ java -cp target/HelloWorld-1.0-SNAPSHOT.jar test.App