DexProtector User Manual

Description

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

DexProtector is the security solution for Android and iOS (Enterprise) platforms.

DexProtector works directly (post-processing, no coding required) with APKs, AARs, AABs, IPAs and iOS Frameworks bringing the unbeatable integrity control.

  • It applies the one and only true multi-layer protection (Native/Byte-code)

  • Successfully prevents Static Analysis, Dynamic Analysis and Tampering

  • Effortless integration (Gradle, Ant, Maven)

  • Supported languages: Java, Kotlin, C/C++, C#, Objective-C, Swift, HTML/JS

  • Supported platforms: Android, Android Wear, Android TV, Android Auto, iOS, WatchOS, tvOS, FireOS, YunOS

  • Supported Application Development Frameworks: Adobe PhoneGap, Apache Cordova, B4X, Cocos2d, Ionic, ReactNative, Titanium, Unity, Xamarin

Features

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

  • Encryption of strings
  • Encryption of classes
  • Support for multidex applications
  • Hiding method calls, field types and field access with use of the DexProtector's native invokedynamic engine
  • Integrity control: certificate checks, APK's content checks
  • Tamper notifications
  • Native code obfuscation
  • Native code encryption
  • Native code anti-debugging (gdb)
  • Encryption of resources and assets
  • Resource name obfuscation (resources.arsc)
  • Obfuscation of AndroidManifest: Applications/ActivityNames/ContentProviders/Receivers class names mangling
  • Transparent SSL Pinning / HTTP Public Key Pinning (HPKP)
  • Environment checks: Emulator/Root/Debug/Hooks/Jailbreak detection, custom firmware detection, wireless status monitoring
  • Secure Execution Environment and CryptoModule

Note: Some of the features are available in the Enterprise version only. Please see the feature matrix here.

String Encryption

Encryption of strings is used to hide the contents of string constants in mobile applications. It is based on a strong cryptographic algorithm with the dynamic keys or White-Box Cryptography. The dynamic keys are calculated during the work of the protected application based on many parameters (context-sensitive), and they can't be extracted from the application's code. As a result, if the code is decompiled, the contents of strings will be hidden and will be inaccessible for static analysis and decryption.

Note: We recommend to encrypt strings that contain sensitive data (logins, passwords, API credentials, keys, and so on), it’s also useful to encrypt some more strings in order to knock a malicious person out of the way, and to make the reverse engineering task much more complicated. A good approach is to have as many strings encrypted as possible until it's ok for the performance of the application. We do not recommend to use String Encryption for strings in open source libraries and for insensitive strings, because it may lead to a negative performance impact.

Class Encryption

DexProtector allows you to encrypt entire classes.dex including Application, Activities, ContentProviders, Receivers. It also supports multidex configurations (Enterprise version only). Classes protected by this function are encrypted and moved from all original classes.dex files (common storage of all classes of an application in the APK-file). Thus they become "invisible" to APK-file decompiling tools, for example: apktool, dex2jar.

Note: Decryption of classes is an expensive operation. We recommend to use this feature for all your critical classes where you have valuable logic, and other sensitive things you want to hide from third eyes. As the decryption operation takes time, having all the classes encrypted may lead to significant performance impact. But you can easily avoid it by adding only critical classes to the filter, or excluding insensitive. For example, it is not necessary to have open source, or uncritical classes encrypted.

Hide Access

Hiding of method calls allows protecting the critical places of an application from the analysis and modification. This mechanism masks the calls of library methods and application methods with the dynamic functions constructed in a special way. It also hides field types and accesses to fields.

Note: It is recommended using this function only for classes which logic must be protected from analysis and modification, for example, work with the license, mechanism of In-App purchases, etc.

Note: This technique allows you to hide Google API calls or third-party API calls you use in your project, it hides calls to methods with use of our native 'invokedynamic' engine, so that it is almost impossible to decompile protected code, and to figure out which method is going to be called in a certain place. It is also a part of our anti-decompiler technique.

Native Library Protection

DexProtector Enterprise allows you to protect native libraries of all kinds: libraries with JNI functions and regular native libraries. The following protection methods are available:

  • Encryption of native libraries
  • Obfuscation of JNI-method names inside of the libraries and in Dalvik bytecode
  • Protection against debugging of native libraries

Content Protection

Our solution allows protecting the content of APK files and AAR libraries to prevent malicious copying and modification:

  • Encryption of res folder contents (APK only)
  • Encryption of assets folder contents
  • Resource name obfuscation for resources.arsc (APK only)
  • Applications/ActivityNames/ContentProviders/Receivers class names mangling in AndroidManifest.xml (DexProtector Enterprise only)

Note: With the use of this function you can easily encrypt an application's internal resources, WebView resources (html, js, css), Cordova/PhoneGap resources (html, js, css). DexProtector Enterprise also supports encryption of game engines resources, video and audio resources, and allows you to access the encrypted resources from external applications.

Integrity Control

Integrity control, or tamper resistance is a mandatory part of the protection DexProtector provides and it is turned on automatically; it prevents the protected APK-file from modification. DexProtector Enterprise allows you to manually configure the integrity control function: enable/disable the certificate check. It also allows you to fire a notification of any kind if the application has been tampered with. Still, the low-level integrity checks are performed first. If they are bypassed, which is barely possible, a notification will be fired.

Tamper Notifications

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

DexProtector Enterprise allows you to set actions that will be performed when there have been attempts to modify applications' content and/or the signature.

Every single integrity check consists of two phases:

Probe - at this phase, the integrity of the apk file is being checked

Callback - processing of the check's results

For each check, it is needed to set its own Probe and Callback methods and DexProtector will automatically handle them.

The Probe setting requires a method that has android.content.Context as a parameter. The function that checks the integrity of the apk will be automatically embedded in the beginning of the method.

Note: This method must be called in your application prior to using the checks' results.

In order to configure the Callback, it is needed to set two methods: the first one will be called when the application has been tampered with. The second one will be called when the integrity checks have passed successfully. These methods should have public static modifier and (Object data) signature.

For example:

    public static positiveIntegrityCheckCallbackApkTampered(Object o){
        // report the fact of tampering to corporate servers
    }

    public static negativeIntegrityCheckCallbackApkOk(Object o){
        // everything is fine
    }

Please see details of how to configure Tamper Notifications in the Configuration File Format section.

Note: We recommend to process the results of the check function both on the client side (device) and on the server side. Sample: GitHub

Note: You can specify a set of files that are to be controlled by the Integrity Control. If you do not set the filters, the default filter is:

APKs:

<dexprotector>
...
    <detects>
        <integrity>
            <filters>
                <filter>glob:**</filter>
                <filter>glob:!META-INF/**</filter>
                <filter>glob:!AndroidManifest.xml</filter>
            </filters>
        </integrity>
        ...
        ...
    </detects>
...
</dexprotector>

AABs:

<dexprotector>
...
    <detects>
        <integrity>
            <filters>
                <filter>glob:classes*.dex</filter>
                <filter>glob:assets/**</filter>
            </filters>
        </integrity>
        ...
        ...
    </detects>
...
</dexprotector>

AARs:

<dexprotector>
...
    <detects>
        <integrity>
            <filters>
                <filter>glob:assets/**</filter>
            </filters>
        </integrity>
        ...
        ...
    </detects>
...
</dexprotector>

Transparent SSL Pinning / HTTP Public Key Pinning (HPKP)

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

Important: DexProtector secures URL.openConnection(), which can be invoked directly, or via loadUrl, loadData, loadDataWithBaseURL, evaluateJavascript, postUrl in case of WebView/okhttp, etc.

DexProtector Enterprise allows you to securely and transparently protect your Android applications that use HTTPS communication against MITM attacks (Man-in-the-middle). It is not needed to modify the source code and implement SSL Pinning / HPKP (HTTP Public Key Pinning) manually. The following components and frameworks are supported: WebView, Cordova/PhoneGap, Http/sURLConnection.

In order to perform all the checks, DexProtector Enterprise uses a clean room implementation of getting a server SSL certificate chain and performing its validation. It is important to highlight that OpenSSL and Android Security API are not used in these processes, thus your application will be resistive to attacks aimed to bypass HTTPS certificate validation: modification of OpenSSL, replacing/adding forged CA certificates into TrustStore, replacing TrustManager in Android Security API, imposition of a forget certificate chain when Android Security API is used.

DexProtector Enterprise supports the standard approach of configuring SSL Pinning/HTTP Public Key Pinning - Network Security Configuration, which is available for Android N (see details here) What is crucial, DexProtector Enterprise works with a standard configuration and it works for all the Android versions that are supported by DexProtector, not only for Android N.

An important measure of fighting against MITM-attacks is monitoring of checks that are being executed on HTTPS certificates and HTTPS connections. For that purpose the Reporting Pin Validation Failure mechanism was implemented in DexProtector Enterprise - RFC7469 - Public Key Pinning Extension for HTTP (see details here). If an anomaly is detected the module that is injected into your application could send reports in JSON format to a server that is set in your configuration.

Please see configuration details here.

Environment checks and device attestation

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

DexProtector Enterprise allows using different environment and device checks in protected applications. The following checks are supported:

  • Emulator Detection
  • Root Detection
  • Root Cloaking Detection
  • Debug Detection
  • Hooks Detection (xposed, luckypatcher)
  • Custom Firmware Detection
  • Wireless Security Status Monitoring

Every single check consists of two phases:

Probe - at this phase the device/environment data is being collected

Callback - processing of the check's results

For each check it is needed to set its own Probe and Callback methods and DexProtector will automatically handle them.

The Probe setting requires a method that has android.content.Context as a parameter. The function that collects and processes environment/device data will be automatically embedded in the beginning of the method.

Note: This method must be called in your application prior to using the checks' results.

In order to configure the Callback it is needed to set two methods: the first one will be called when the check has been successful, for example the Root Detection detected that the device was rooted. The second one will be called when the check was unsuccessful, i.e. the Root Detection did not find that the device was rooted. These methods should have public static modifier and (Object data) signature. Depending on the types of checks the required data will be passed as data parameter.

For example:

    public static positiveCheckCallback(Object o){
        // store information or call network service
    }

    public static negativeCheckCallback(Object o){
        // store information or call network service
    }

Please see details of how to configure these checks in the Configuration File Format section.

Note: We recommend to process the results of the check functions both on the client side (device) and on the server side.

Sample: GitHub

Performance Tuning

In order to eliminate the negative performance impact, it is needed to consider which classes/strings and resources should be protected. The set of classes/resources that should be protected can be specified with the help of a filter (filter format). If you need more detailed adjustment, for example, protection of class methods or individual fields, you can use the annotations mechanism (annotations). We recommend to set filters for classes where you have sensitive strings for String Encryption, classes where you have valuable logic - Class Encryption and Hide Access, and add filters for valuable resources in the assets folder. And we would also recommend to exclude all the open source libraries.

If no filters specified, DexProtector protects all the strings in all the classes (String Encryption), all the classes and method calls, fields (removes types) and field accesses in all the classes (Class Encryption, Hide Access), encrypts resources (Resource Encryption).

There is a reference configuration file dexprotector.xml in the root folder of the distribution kit. It has exclusions for widespread open source libraries. String Encryption, Class Encryption and Hide Access are enabled in this configuration. If you do not have your own configuration yet, we recommend to start with the reference configuration and then add settings that are relevant to your Android applications.

General information

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

As an input, DexProtector receives an application APK/AAB-file or Android Library AAR-file. An output is the protected APK/AAB-file, and protected AAR-file respectively. The output APK can be signed in the Debug mode (it is intended for debugging in the emulator), Release mode, or None - the signing can be postponed, for example for Platform/Vendor signed applications. The settings can be specified either in the external configuration file (format) if you use DexProtector via the CLI or its plugins, or in the DexProtector Studio.

In the APK/AAB protection mode DexProtector automatically finds places inside of the Dalvik bytecode where to put its protection initialisation methods, this is achieved owing to the fact that DexProtector works with a final application and its lifecycle is known. There is a special initialization mechanism for AARs, please see Configuration file format and Protecting Android Libraries sections.

The following protection mechanisms are available for Android Libraries:

  • String Encryption
  • Class Encryption
  • Assets Encryption
  • Hide Access
  • Native Code Encryption
  • Native Code Obfuscation
  • Environment checks and device attestation

Note: As Android Libraries provide a public API that should be available on the build stage, Class Encryption can be used only for inner classes and packages of the library.

DexProtector can be used as a console application, GUI-application (DexProtector Studio), Ant-task, Maven-plugin or Gradle-plugin if you protect APK files, and CLI/Gradle-plugin if you protect AAR files.

DexProtector works under JRE ≥ 1.7. Protected Android applications and libraries are compatible with Android ≥ 2.3 (API Level 9).

Important: If you use a name obfuscator alongside DexProtector, for example, ProGuard, in your build chain, it is needed to follow the requirements below:

  1. DexProtector must be the last step of your build chain
  2. If you use annotations to configure DexProtector they should be preserved, here is an example for ProGuard:

    -keepattributes SourceFile, LineNumberTable, *Annotation*
    -keep @interface com.dexprotector.annotations.** { *; }
    
  3. To be able to use original class names in the configuration, instead of using obfuscated names, you might set proguardMappingFile in DexProtector's configuration.

  4. If you use an AAR protected with DexProtector in your APK it is needed to disable ProGuard for all the AAR's packages. For example:

    -keep class com.mylibrary.** { *;}
    

Distribution kit contents

Distribution kit is a zip archive containing the following files:

  • Executable jar file - dexprotector.jar
  • Annotations library - dexprotector-annotations.jar
  • Maven plugin - dexprotector-maven-plagin.jar
  • Gradle plugin - dexprotector-gradle-plugin.jar
  • Default config - dexprotector.xml
  • Ant settings file – custom_rules.xml
  • License texts - NOTICE, LICENSE

Using the console mode and DexProtector Studio

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

Downloading

The download links with DexProtector and DexProtector Studio will be sent with an activation code via email after requesting a trial license, or after purchasing a full license(s).

In order to get the latest version of DexProtector Enterprise, please request it via the contact form.

Note: You should have a valid license activation code in order to get DexProtector working in full or trial mode. If you do not have a license activation code, please either get a trial activation code, or purchase your DexProtector license(s).

Installation

Unpack the zip file to the destination folder.

Obtaining the activation code

To get the trial activation code, please use the following link: https://dexprotector.com/trial-request

To get a fully functional activation code, purchase the required number of licenses. In this case, registration is obligatory. Your email will be registered automatically during the purchasing process. Further instructions (how to set your password and so on) will be sent to the specified email address.

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 the cash receipt to account or after a copy of a payment order is submitted.

E-mail address you have provided in the order, or when getting the trial license, may be used as login to client’s area on the DexProtector’s site. There is information about all your licenses in this area. 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.

The activation codes are single-use. It means that in case the original license file was lost, or if the hardware or software configuration was changed, you have to contact the customer support to get a new code.

Note: DexProtector supports two activation methods: online and offline. If you have an active Internet connection, you may use online activation. Otherwise, if you do not have 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 an activation request code using CLI or GUI (Command Line or Dexprotector Studio), and send it to dexprotector@licelus.com via email. You can do it from another computer or a device which has an active Internet connection.

Console mode

Online activation via CLI

To activate DexProtector online via the command line, run the following command, then follow the instructions generated:

java -jar dexprotector.jar -activate

After successful activation, the license file dexprotector.licel will be created in the user's home folder.

To use a license file located in a different folder from dexprotector.jar, specify the path to the license file via the special option provided in the CLI.

Offline activation via CLI

To activate DexProtector offline via the command line, run the following command:

java -jar dexprotector.jar -activationRequest

Enter your activation code as prompted. When you have entered a valid activation code, a request code will be generated. Email this request code to primary@licelus.com.

You will receive a response code as soon as possible, within a maximum of 24 hours.

When you have received the response code, run the following command and then enter the response code when prompted:

java -jar dexprotector.jar -activationResponse

After successful activation, the license file dexprotector.licel will be created in the user's home folder.

To use a license file located in a different folder from the dexprotector.jar, it is necessary to specify the path to the license file.  

Options and parameters
java -jar dexprotector.jar <options> <src> <dest>

Here <src> is a path to the original APK-file, <dest> is a path to the destination APK-file (it may be the same as <src>).

Valid values of <options>:

-activate
Activate the license online

-activationRequest Generate a request code for offline activation

-activationResponse Finish the offline activation process by entering a response code

-info License status

-licenseFile filename Path to license file

-verbose Print the verbose log to stdout (default: off)

-configFile filename Use the configuration parameters from the specified file (see the Configuration file format)

-signMode debug|release Mode of signing the output APK-file (default: debug)

-keystore path Path to the file with the signing keys (for the release mode only)

-alias name Key alias for signing (for the release mode only)

-storepass password Password to the file with the signing keys (for the release mode only)

-keypass password Password to the signing key (for the release mode only)

-proguardMapFile path Path to the ProGuard map file

DexProtector Studio

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

DexProtector Studio is our desktop application, included with every DexProtector license. Studio offers a straightforward GUI where you can control every aspect of the DexProtector protection process. Studio allows you to:

  • activate your DexProtector license
  • observe DexProtector’s analysis of your input file
  • configure the protection settings for your project
  • create protection profiles
  • visualize exactly how DexProtector’s protection mechanisms are applied to your code and resources
  • manage your ALICE integration
Online activation via Studio
  1. When you have also downloaded DexProtector, save the DexProtector Studio zip file to your destination folder.

    Note: You can find a download link for DexProtector Studio in the same email as your DexProtector download link and activation code. For DexProtector Studio to function at its best, the latest version of DexProtector is required.

  2. Extract the contents of the zip file.

    Note: DexProtector Studio comes already bundled with the required JRE.

  3. Double-click to open DexProtector Studio.

  4. Click on ‘License Info’ to the right of the bar at the bottom of the window.
  5. Click ‘Activate License’ and follow the instructions in the new window. To activate your license and obtain a license file online, simply enter the unique, single-use activation code provided in the email with your download links. If you don’t have an active Internet connection, or have problems with the online activation, see how to Activate via DexProtector Studio (offline) below.
  6. After successful activation, the license file dexprotector.licel will be created in the user's home folder.

Offline activation via Studio
  1. When you have also downloaded DexProtector, save the DexProtector Studio zip file to your destination folder.

    Note: You can find a download link for DexProtector Studio in the same email as your DexProtector download link and activation code. For DexProtector Studio to function at its best, the latest version of DexProtector is required.

  2. Extract the contents of the zip file.

    Note: DexProtector Studio comes already bundled with the required JRE.

  3. Double-click to open DexProtector Studio.

  4. Click on ‘License Info’ to the right of the bar at the bottom of the window.
  5. Click ‘Activate License’ and follow the instructions in the new window. If you don’t have an active Internet connection, or have problems with the online activation, enter the unique, single-use activation code provided in the email with your download links, and then click ‘Generate activation request’.
  6. When you have entered a valid activation code, a request code will be generated. Email this request code to primary@licelus.com. You will receive a response code as soon as possible, within a maximum of 24 hours.
  7. When you have received your response code, return to the same ‘Activate License’ window, and click ‘I Already Have My Activation Response Code’. In the following window, enter the response code you’ve received and click ‘Activate’ to complete the license activation procedure.
  8. After successful activation, the license file dexprotector.licel will be created in the user's home folder.    

Using as Ant-task

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

Note: To use DexProtector as an Ant-task, it is necessary to download the distribution kit, complete the installation, receive the activation code and use it for obtaining your license following the instructions here: Using the console and graphic modes. There are two ways to activate your license: Activation via CLI or Activation via GUI.

  1. Make sure that Android SDK and ANT are properly installed.

  2. If you already have build.xml, then skip the steps 3-5 and start with the step 6.

  3. Go to the project folder:

    $ cd android-project 
    
  4. Execute the following command:

    $ android-sdk-home/tools/android update project --path .  
    
  5. Check the correctness of build.xml with the help of 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. Copy the custom_rules.xml file to the project folder from the DexProtector distribution kit.

  7. In the local.properties file add a property dexprotector.home and set its value to the DexProtector distribution kit path, for example: dexprotector.home=/usr/local/dexprotector.

    IMPORTANT! Do not place DexProtector's jar libraries in the libs folder of your project.

  8. Create the settings file dexprotector.xml in the project folder either manually, or via the DexProtector.

  9. Run the command ant release. An example of ANT-task usage is available in the samples folder of the DexProtector distribution kit.

Note: Parameters that were set in the Ant-task has higher priority than parameters set in the configuration file, for example if there is password to keystore – keypass defined in Ant task, than its value will be used instead of the value of keypass tag from the configuration file. 

Using as Maven-plugin

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

DexProtector is designed for Maven-projects which use Android Maven Plugin for compilation.

Note: To use DexProtector as Maven-plugin, it is necessary to download the distribution kit, get the activation code and use it for obtaining your license following the instructions here: Using the console and graphic modes. There are two ways to activate your license: Activation via CLI or Activation via GUI.

First it is needed to install all the required artifacts (POM files are shipped within the distribution package):

mvn install:install-file -Dfile=$DEXPROTECTOR_HOME/dexprotector.jar -DpomFile=$DEXPROTECTOR_HOME/dexprotector.pom
mvn install:install-file -Dfile=$DEXPROTECTOR_HOME/dexprotector-maven-plugin.jar -DpomFile=$DEXPROTECTOR_HOME/dexprotector-maven-plugin.pom
mvn install:install-file -Dfile=$DEXPROTECTOR_HOME/dexprotector-annotations.jar -DpomFile=$DEXPROTECTOR_HOME/dexprotector-annotations.pom

Example:

mvn install:install-file -Dfile=`pwd`/dexprotector.jar -DpomFile=`pwd`/dexprotector.pom
mvn install:install-file -Dfile=`pwd`/dexprotector-annotations.jar -DpomFile=`pwd`/dexprotector-annotations.pom
mvn install:install-file -Dfile=`pwd`/dexprotector-maven-plugin.jar -DpomFile=`pwd`/dexprotector-maven-plugin.pom

DexProtector replaces maven-jar-signer plugin and is executed at the package phase of a lifecycle of a project build. To use it, it is necessary to replace the current maven-jar-signer plugin, or add the definition of dexprotector if maven-jar-signer is absent in the pom.xml/plugins section.

    <plugin>
        <groupId>com.licel</groupId>
        <artifactId>dexprotector-maven-plugin</artifactId>
        <version>${dexprotector.version}</version>
         <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>dexprotector</goal>
                </goals>
                <configuration>
                    <keystore>..</keystore>
                    <storepass>android</storepass>
                    <keypass>..</keypass>
                    <alias>..</alias>
                    <configFile>dexprotector.xml</configFile>
                </configuration>
            </execution>
        </executions>  
    </plugin>

An example of Maven-plugin usage is available in the samples folder of the DexProtector distribution kit. Priority of the parameters that are being set with Maven configuration is similar to Ant-task (see note in the Using as Ant-task section).

Using as Gradle-plugin

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

Note: To use DexProtector as Gradle-plugin, it is necessary to download the distribution kit, get the activation code and use it for obtaining your license following the instructions here: Using the console and graphic modes. There are two ways to activate your license: Activation via CLI or Activation via GUI.

  1. Set the path to DexProtector in your buildscript.repositories (main build.gradle of your project), for example:

    flatDir { dirs '/Users/developer/DexProtector' }
    

    alternatively, you can use a Maven repository which has the DexProtector's artifacts installed, for example:

    mavenLocal()
    

    In order to install DexProtector's artifacts, please follow instructions below:

    mvn install:install-file -Dfile=$DEXPROTECTOR_HOME/dexprotector.jar -DpomFile=$DEXPROTECTOR_HOME/dexprotector.pom
    mvn install:install-file -Dfile=$DEXPROTECTOR_HOME/dexprotector-gradle-plugin.jar -DpomFile=$DEXPROTECTOR_HOME/dexprotector-gradle-plugin.pom
    

    Example:

    mvn install:install-file -Dfile=`pwd`/dexprotector.jar -DpomFile=`pwd`/dexprotector.pom
    mvn install:install-file -Dfile=`pwd`/dexprotector-gradle-plugin.jar -DpomFile=`pwd`/dexprotector-gradle-plugin.pom
    

    Note: When you use a Maven repository, we would recommend to add additional variable in your main build.gradle which points to a version of DexProtector, for example:

    buildscript {
        ext {
            dexProtectorVersion = '10.0.1'
        }
    
  2. Add the following dependencies:

    buildscript {
        dependencies {
            classpath ':dexprotector-gradle-plugin:'
            classpath ':dexprotector:'
        }
    }
    

    or for the Maven approach:

    buildscript {
        dependencies {
            classpath 'com.licel:dexprotector-gradle-plugin:' + rootProject.ext.dexProtectorVersion
            classpath 'com.licel:dexprotector:' + rootProject.ext.dexProtectorVersion
        }
    }
    
  3. Add into an Android Application or Android Library project’s build.gradle file the following line after apply plugin: 'com.android.application' or apply plugin: 'com.android.library':

    apply plugin: 'dexprotector'
    
  4. Add into the desired buildType’s section the following line:

    ext.set("dexprotector.configFile", "${projectDir}/dexprotector.xml")
    
  5. Set up signingConfigs:

    signingConfigs {
        release {
            storeFile file("config/release.keystore")
            storePassword RELEASE_STORE_PASSWORD
            keyAlias RELEASE_KEY_ALIAS
            keyPassword RELEASE_KEY_PASSWORD
        }
    }
    
  6. Thus, it should look like this:

    apply plugin: 'com.android.application'
    apply plugin: 'dexprotector'
        ...
        ...
        ...
    android {
        signingConfigs {
            release {
                storeFile file("config/release.keystore")
                storePassword RELEASE_STORE_PASSWORD
                keyAlias RELEASE_KEY_ALIAS
                keyPassword RELEASE_KEY_PASSWORD
            }
        }
        ...
        ...
        ...
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
                ext.set("dexprotector.configFile", "${projectDir}/dexprotector.xml")
                signingConfig signingConfigs.release
             }
        }
        ...
        ...
        ...
    }
    
  7. In order to build a protected APK or AAB file in Android Studio, launch Build - Generate Signed Bundle / APK ... and select the appropriate application container format.

Using as Gradle-plugin (Kotlin DSL)

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

Note: To use DexProtector as Gradle-plugin, it is necessary to download the distribution kit, get the activation code and use it for obtaining your license following the instructions here: Using the console and graphic modes. There are two ways to activate your license: Activation via CLI or Activation via GUI.

  1. Set the path to DexProtector in your buildscript.repositories (main build.gradle.kts of your project), for example:

    flatDir(new File("/Users/developer/DexProtector"))
    

    alternatively, you can use a Maven repository which has the DexProtector's artifacts installed, for example:

    mavenLocal()
    

    In order to install DexProtector's artifacts, please follow instructions below:

    mvn install:install-file -Dfile=$DEXPROTECTOR_HOME/dexprotector.jar -DpomFile=$DEXPROTECTOR_HOME/dexprotector.pom
    mvn install:install-file -Dfile=$DEXPROTECTOR_HOME/dexprotector-gradle-plugin.jar -DpomFile=$DEXPROTECTOR_HOME/dexprotector-gradle-plugin.pom
    

    Example:

    mvn install:install-file -Dfile=`pwd`/dexprotector.jar -DpomFile=`pwd`/dexprotector.pom
    mvn install:install-file -Dfile=`pwd`/dexprotector-gradle-plugin.jar -DpomFile=`pwd`/dexprotector-gradle-plugin.pom
    

    Note: When you use a Maven repository, we would recommend to add additional variable in your main build.gradle.kts which points to a version of DexProtector, for example:

    buildscript {
        val dexprotectorVersion by extra { "12.1.43" }
    
  2. Add the following dependencies:

    buildscript {
        dependencies {
            classpath(":dexprotector-gradle-plugin:")
            classpath(":dexprotector:")
        }
    }
    

    or for the Maven approach:

    buildscript {
        dependencies {
            classpath("com.licel:dexprotector-gradle-plugin:$dexprotectorVersion")
            classpath("com.licel:dexprotector:$dexprotectorVersion")
        }
    }
    
  3. Add into an Android Application or Android Library project’s build.gradle.kts file the following line after id("com.android.application") or id("com.android.library"):

        id("dexprotector")
    
  4. Add into the desired buildType’s section the following line:

        require(this is ExtensionAware)
        extra["dexprotector.configFile"] = project.file("dexprotector.xml").path
    
  5. Set up signingConfigs:

    signingConfigs {
        create("release") {
            keyAlias = "RELEASE_KEY_ALIAS"
            keyPassword = "RELEASE_KEY_PASSWORD"
            storeFile = project.file("release.keystore")
            storePassword = "RELEASE_STORE_PASSWORD"
        }
    }
    
  6. Thus, it should look like this:

    plugins {
        id("com.android.application")
        id("dexprotector")
    }
        ...
        ...
        ...
    android {
        signingConfigs {
            create("release") {
                keyAlias = "RELEASE_KEY_ALIAS"
                keyPassword = "RELEASE_KEY_PASSWORD"
                storeFile = project.file("release.keystore")
                storePassword = "RELEASE_STORE_PASSWORD"
            }
        }
    
        ...
        ...
        ...
        buildTypes {
            getByName ("release") {
                isMinifyEnabled = false
                proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
                signingConfig = signingConfigs.getByName("release")
                require(this is ExtensionAware)
                extra["dexprotector.configFile"] = project.file("dexprotector.xml").path
            }
        }
        ...
        ...
        ...
    }
    
  7. In order to build a protected APK or AAB file in Android Studio, launch Build - Generate Signed Bundle / APK ... and select the appropriate application container format.

Protecting iOS Applications (IPAs) and Frameworks

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

Important: The iOS protection functionality is available in DexProtector Enterprise.

iOS applications usually consist of the main binary, resources, and frameworks. The App Store publishing policy imposes a set of limitations on the ability to protect components of iOS applications. At the moment, DexProtector Enterprise allows you to protect the main binary and the frameworks which the application is using. You also can separately protect your frameworks (binary form) which are distributed and then used in your customers' applications. The following protection mechanisms are supported (Objective-C, Swift):

CODE PROTECTION

  • WhiteBox String Encryption
  • WhiteBox HideAccess (selectors)
  • Code Obfuscation
  • Anti-Debugging

ENVIRONMENT CHECKS

  • Jailbreak detection

TRANSPARENT SSL PINNING/ HTTP Public Key Pinning (HPKP)

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

Important: To protect iOS applications and Frameworks you must have the latest version of XCode installed on the machine where you will be protecting the application or framework. Or the version of XCode must match the version the application or framework was built with. All the required signing certificates (iOS Development or iOS Distribution) must be in place as well.

DexProtector takes original IPA files or Framework directories as the input and produces protected and signed IPA files and Framework directories on the output.

Important: Input IPA files and Frameworks must contain bitcode. IPAs must be exported from the iOS Apps archive for the distribution via App Store (Method of distribution: App Store). Frameworks must be exported from the Frameworks archives for the Built Products distribution (Method of distribution: Built Products). It is also required to set the Deployment - Skip Install option to No.

Protected IPA files are built with no bitcode. Frameworks are built with bitcode enabled.

iOS Protection Settings

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

Protection Configuration

You can use a configuration file, or set the protection configuration via the GUI.

Note (applicable only to IPAs): If you wish frameworks to be protected which are located in your application (IPA), you can use filters of the frameworks element (Configuration File), or use the special form in the GUI (iOS Project Settings view) to set which frameworks must be protected.

Signing Certificate Name

The identity of the signing certificate can be iOS Development or iOS Distribution. For example, iPhone Distribution: Licel Corporation (1NKDRJYKBE). If you have more than one signing certificate with the same name but different validity period, you can use its ID. The ID can be gotten via the following console command:

   $ security find-identity -v -p codesigning

      1) 869B7011A78D50FFD7B9F9488A18BE8A5F1500A1 "iPhone Distribution: Licel Corporation (1NKDRJYKBE)"   

The value of 869B7011A78D50FFD7B9F9488A18BE8A5F1500A1 is the certificate ID.

According to Apple's iOS Framework distribution rules your Framework must be signed.

Provision Profile (Optional)

Note: This is not applicable to Frameworks.

If you would like to use your protected IPA not only for distribution via App Store, you can set a corresponding Provision Profile. For example, you can set a Development Provision Profile to be able to install a protected application on a device. The Provision Profiles can be generated via Apple Developer Portal or XCode. If the Provision profile is not set, DexProtector takes the original Provision Profile and Entitlements from the IPA that was passed as the input. Otherwise, if you set a Provision Profile, the corresponding Provision Profile will be used alongside its Entitlements.

iOS Configuration File Format

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

The format of the configuration file corresponds to the description of the Configuration File Format section. Please note that Android-related tags will be ignored.

Example for Frameworks:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<dexprotector>
    <verbose>true</verbose>
    <optimize>false</optimize>
    <signMode>debug</signMode>
    <certificate>iPhone Developer: Licel Corporation (1NKDRJYKBE)</certificate>
    <stringEncryption mode="all">
        <filters>
            <filter><![CDATA[glob:ClassA:methodA*]]></filter>
            <filter><![CDATA[glob:ClassB:methodB*]]></filter>
            <filter><![CDATA[glob:ClassC]]></filter>
        </filters>
    </stringEncryption>
    <hideAccess mode="all">
        <filters>
            <filter><![CDATA[glob:ClassA:methodA*]]></filter>
            <filter><![CDATA[glob:ClassB:methodB*]]></filter>
            <filter><![CDATA[glob:ClassC]]></filter>
        </filters>
    </hideAccess>
    <ios mode="all">
        <bitcodeObfuscation>
            <filters>
                <filter><![CDATA[glob:ClassA:methodA*]]></filter>
                <filter><![CDATA[glob:ClassB:methodB*]]></filter>
                <filter><![CDATA[glob:ClassC]]></filter>
            </filters>        
        </bitcodeObfuscation>
    </ios>
</dexprotector>

Note: The glob:ClassA:methodA*, glob:ClassB:methodB* and glob:ClassC filters in this example instruct DexProtector to process classes that match the pattern.

Example for IPAs:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<dexprotector>
    <verbose>true</verbose>
    <optimize>false</optimize>
    <signMode>debug</signMode>
    <certificate>iPhone Distribution: Licel Corporation (1NKDRJYKBE)</certificate>
    <stringEncryption mode="all">
        <filters>
            <filter><![CDATA[glob:ClassA:methodA*]]></filter>
            <filter><![CDATA[glob:ClassB:methodB*]]></filter>
            <filter><![CDATA[glob:ClassC]]></filter>
        </filters>
    </stringEncryption>
    <hideAccess mode="all">
        <filters>
            <filter><![CDATA[glob:ClassA:methodA*]]></filter>
            <filter><![CDATA[glob:ClassB:methodB*]]></filter>
            <filter><![CDATA[glob:ClassC]]></filter>
        </filters>
    </hideAccess>

    <ios mode="all">
        <mobileProvisionFile>/Users/Developer/IOSDevelopmentLicel.mobileprovision</mobileProvisionFile>
        <frameworks mode="all">
            <filters>
                <filter><![CDATA[glob:AppCore.framework/*]]></filter>
            </filters>
        </frameworks>
        <bitcodeObfuscation>
            <filters>
                <filter><![CDATA[glob:ClassA:methodA*]]></filter>
                <filter><![CDATA[glob:ClassB:methodB*]]></filter>
                <filter><![CDATA[glob:ClassC]]></filter>
            </filters>        
        </bitcodeObfuscation>
    </ios>
</dexprotector>

Note: The names of frameworks are set using the root of Frameworks folder of an IPA. For example, if you have an AppCore.framework in your app, the filter will be AppCore.framework/* not including Frameworks or any other folder names. You can use the standard DexProtector's filtering rules - Filter Format.

Console Mode
java -cp dexprotector.jar com.licel.dexprotector.ios.ConsoleTask <options> <src> <dest>

Example for an IPA:

java -cp dexprotector.jar com.licel.dexprotector.ios.ConsoleTask -configFile SampleApplication_dexprotector.xml Sample.ipa ProtectedSample.ipa

Example for a Framework:

java -cp dexprotector.jar com.licel.dexprotector.ios.ConsoleTask -configFile SampleFramework_dexprotector.xml Sample.framework ProtectedSample.framework

Valid values of <options>:

-activate Activate the license online

-activationRequest Generate a request code for offline activation

-activationResponse Finish the offline activation process by entering a response code

-info License status

-licenseFile filename Path to the license file

-verbose Print the verbose log to stdout (default: off)

-configFile filename Use the configuration parameters from the specified file (see the Configuration file format section)

-signMode debug|release Mode of signing of the output IPA-file or Framework

EnvChecks for iOS Applications/Frameworks (Objective-C projects)

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

DexProtector Enterprise allows you to use Environment Checks mechanisms in a secured application/Framework to determine the presence of JailBreak and a connected Debugger. The architecture of the detect call and the processing of results is similar to the Android approach.

Please use the <root/> and <debug/> nodes to configure JailBreak and Debug checks accordingly.

At the moment, you must specify the same probeMethod, negativeCallback, positiveCallback methods both for the <root/> / <debug/> nodes when it comes to iOS applications or Frameworks (please see an example below).

To specify the probeMethod, negativeCallback, positiveCallback method names, the following format must be used: objc_class.method_name.

Just like for Android, negativeCallback / positiveCallback methods must be static (class method according to the Objective-C terminology).

Please find an example of using doProbe and callbacks for Objective-C code below:

DexProtector settings:

<detect>
    <root>
        <positiveCheckCallback>ProbeCallbacks.positiveCallback</positiveCheckCallback>
        <negativeCheckCallback>ProbeCallbacks.negativeCallback</negativeCheckCallback>
        <probeMethod>MainProbeClass.probeMethod</probeMethod>
    </root>
    <debug>
        <positiveCheckCallback>ProbeCallbacks.positiveCallback</positiveCheckCallback>
        <negativeCheckCallback>ProbeCallbacks.negativeCallback</negativeCheckCallback>
        <probeMethod>MainProbeClass.probeMethod</probeMethod>
    </debug>
</detect>

Objective-C code:

@interface MainProbeClass : NSObject
+(void) probeMethod;
@end

@implementation MainProbeClass

+(void) probeMethod {
    NSLog(@"Main probeMethod was called");
}
@end

@interface ProbeCallbacks : NSObject
+(void) positiveCallback : (NSString*) json_str;
+(void) negativeCallback : (NSString*) json_str;
@end

@implementation ProbeCallbacks
+(void) positiveCallback : (NSString*) json_str {
    NSLog(@"Call positiveCallback with: %@", json_str);
}
+(void) negativeCallback : (NSString*) json_str {
    NSLog(@"Call negativeCallback with: %@", json_str);
}
@end

- (void)viewDidLoad {
    [super viewDidLoad];
    [MainProbeClass probeMethod];
    // Do any additional setup after loading the view.
}

The JSON string that comes to the input positive / negative callback methods has the following structure:

{
  "DetectCydia" : 0,
  "CheckForSandBox" : 0,
  "DetectDebuggerHasTracerPid" : 0,
  "DetectPotentiallyDangerousApps" : 0,
  "CheckForRWPaths" : 0
}

where DetectDebuggerHasTracerPid is a sign of a connected Debugger, and the remaining fields are signs of a JailBreak.

EnvChecks for iOS Applications/Frameworks (Swift projects)

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

In your Swift project, create new Objective-C and Header files. Choose Create Bridging Header when prompted Would you like to configure an Objective-C bridging header?

Add the following code to the Objective-C file:

@interface MainProbeClass : NSObject
+(void) probeMethod;
@end

@implementation MainProbeClass

+(void) probeMethod {
    NSLog(@"Main probeMethod was called");
}
@end

@interface ProbeCallbacks : NSObject
+(void) positiveCallback : (NSString*) json_str;
+(void) negativeCallback : (NSString*) json_str;
@end

@implementation ProbeCallbacks
+(void) positiveCallback : (NSString*) json_str {
    NSLog(@"Call positiveCallback with: %@", json_str);
}
+(void) negativeCallback : (NSString*) json_str {
    NSLog(@"Call negativeCallback with: %@", json_str);
}
@end

Then add a call of the probe method in your Swift code:

    override func viewDidLoad() {
        super.viewDidLoad()

        MainProbeClass.probeMethod();
    }

Protecting Android Libraries (AARs)

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

At first it is needed to set a Gradle configuration. It is absolutely the same as for APKs, please see the Using as Gradle-plugin section for details.

The next step is to create a DexProtector configuration for the Android Library Project and add initialisation methods if you are planning to use Class Encryption, Hide Access or Resource Encryption mechanisms, after that you are all set and ready to protect your Android Library.

Note: From the version 8.1.39, DexProtector has an automatic initialisation mode, so you do not have to manually specify any initClasses or initMethods. In order to enable this mode, please use:

<aar autoInit="on" autoInitAuthorities="${applicationId}"/>

Important: (if you use DexProtector older than 8.1.39) If you have ClassEncryption and/or HideAccess and/or ResourceEncryption functions enabled it is needed to set an initMethod. Thus, DexProtector will be able to inject its initialisation method that is needed for the initialisation of the above-mentioned functions. One of its/their parameters must be Context. The format is FQCN.methodName, for example licel.com.mylibrary.Library.init, You do not have to set a method’s signature, DexProtector will find all the methods that have Context in their signature and inject its initialisation method into them. These initMethod(s) are basically entry-points of your AAR. The method(s) must be called first (before invoking any other methods of the AAR). If you would like to protect broadcast receiver classes or other classes which might be referenced before the init method(s) is called, it is needed to list those classes within the initClass tag as follows:

<aar>
    <initMethod>com.mylibary.EntryPointClassA.initMethod</initMethod>
    <initClass>com.mylibary.MainReceiver</initClass>    
</aar>

In order to set multiple initMethods/initClasses for AAR initialisation it is needed to create a section in your configuration file that looks like the following one:

<aar>
    <initMethod>com.mylibary.EntryPointClassA.initMethod</initMethod>
    <initMethod>com.mylibary.EntryPointClassB.initMethod</initMethod>
    <initMethod>com.mylibary.EntryPointClassB.initMethodC</initMethod>
    <initMethod>...</initMethod>
    <initClass>com.mylibary.MainReceiver</initClass>
    <initClass>com.mylibary.AnotherReceiver</initClass>
    <initClass>...</initClass>
</aar>

Tip: The best and the most reliable option will be adding a dummy content provider with the maximal priority (AndroidManifest.xml) and setting it as the initClass.

For example:

 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.engine.extra.securelib">
...
...
...
        <provider
        android:name="com.engine.extra.securelib.StubProvider"
        android:authorities="com.example.android.datasync.provider"
        android:exported="false"
        android:syncable="true"
        android:priority="2147483647"
        />
...
...
...
    </application>
</manifest>

In the DexProtector’s configuration file, it is needed to add an initClass element (within the aar node):

<dexprotector>
    ...
    <aar>
        <initClass>com.engine.extra.securelib.StubProvider</initClass>
        ...
    </aar>
...

If you already have a ContentProvider in your AAR, you might set a maximal priority to it and add an initClass element with a corresponding value.

DexProtector’s logs will be available at build/outputs/dexprotector/<builtType>/log.txt file.

Configuring Environment Checks

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

The way you configure the environment checks is similar to the APK's one (see Configuration File Format section). You can also set no specific Probe/Callback methods, in case of the AAR protection DexProtector handles this automatically. For example:

<detect>
    <root/>
    <debug/>
    <emulator/>
</detect>

All the checks are being performed during the library's initialisation process. In case of a positive result there will be an exception (RuntimeException) thrown containing all the information regarding the anomalies detected.

Protecting Dynamically Loadable Modules

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

Many Android applications use dynamically loadable modules or plugins, so-called external APKs or dynamic APKs. They are used to extend the functionality of an application, to add an ability to be updated without reinstalling the entire application or to decrease the size of the main application and so on.

It is as important to protect these dynamic APKs as taking care of protection of the main application. Or even more important - usually these dynamic APKs are very sensitive and carry the real value of an application. The crucial thing is integrity control of the dynamic module. To meet these requirements we implemented the ability to protect dynamic APKs in DexProtector Enterprise. The following mechanisms can be used for external APK protection, at the moment:

CODE PROTECTION

  • Secure String Encryption
  • Secure Class Encryption
  • CallHiding via Native invokedynamic Engine
  • Field Access and Field Types Hiding via Native invokedynamic Engine
  • Native Code Obfuscation (for non-public JNI methods)
  • Native Code Encryption
  • Native Code Anti-Debugging (gdb)

CONTENT PROTECTION

  • Assets Encryption

INTEGRITY CONTROL

  • Certificate Checks
  • APK Content Checks

Important:
1. When you protect an external APK it is needed to set the following tag in your configuration file: <mainAPK>false</mainAPK>
2. All the APKs: main and dynamic must be signed with the same key (DexProtector’s signature mode must be release).

Sample: GitHub

Configuration file format

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<dexprotector>
    <verbose/>
    <licenseFile/>
    <optimize/>
    <signMode/>
    <keystore/>
    <storepass/>
    <alias/>
    <keypass/>
    <certificate/>
    <sha256CertificateFingerprint/>
    <v1SigningEnabled/>
    <v2SigningEnabled/>
    <mainAPK/>
    <proguardMapFile/>
    <rngSeedFile>...</rngSeedFile>
    <stripLogging>...</stripLogging>
    <stripMethodCalls>
        <filters>
            <filter>...</filter>
        </filters>
    </stripMethodCalls>
    <abiFilter>...</abiFilter>
    <platformApplicationSupport/>
    <aar>
        <initMethod>...</initMethod>
        <initClass>...</initClass>
    </aar>
    <ios>
        <mobileProvisionFile>...</mobileProvisionFile>
        <frameworks>
            <filters>
                <filter>...</filter>
            </filters>
        </frameworks>
        <bitcodeObfuscation>
            <filters>
                <filter>...</filter>
            </filters>        
        </bitcodeObfuscation>        
    </ios>
    <stringEncryption>
        <filters>
            <filter>...</filter>
        </filters>
    </stringEncryption> 
    <classEncryption>
        <filters>
            <filter>...</filter>
        </filters>
    </classEncryption> 
    <hideAccess>
        <filters>
            <filter>...</filter>
        </filters>
    </hideAccess>
    <resourceEncryption>
        <assets>
            <filters>
                <filter>...</filter>
            </filters>
        </assets>    
        <res>
            <filters>
                <filter>...</filter>
            </filters>
        </res>    
        <strings>
            <filters>
                <filter>...</filter>
            </filters>
        </strings>
        <androidManifestMangling>
            <filters>
                <filter>...</filter>
            </filters>
        </androidManifestMangling>
        <unityManagedCode/>
        <xamarinAssemblies/>
    </resourceEncryption>  
    <nativeLibraryEncryption>
        <filters>
            <filter>...</filter>
        </filters>
    </nativeLibraryEncryption>
    <jniObfuscation>
        <filters>
            <filter>...</filter>
        </filters>
    </jniObfuscation>       
    <integrityControl>
        <checkCertificate/>
    </integrityControl>
    <publicKeyPinning>
        <reportUri>...</reportUri>
        <actions>...</actions>
        <reportMethod>...</reportMethod>
        <cacheTTL>...</cacheTTL>
        <network-security-config>
            ...
        </network-security-config>
    </publicKeyPinning>     
    <detect>
        <root>
            <positiveCheckCallback>...</positiveCheckCallback>
            <negativeCheckCallback>...</negativeCheckCallback>
            <probeMethod>...</probeMethod>
        </root>
        <debug>
            <positiveCheckCallback>...</positiveCheckCallback>
            <negativeCheckCallback>...</negativeCheckCallback>
            <probeMethod>...</probeMethod>
        </debug>
        <emulator>
            <positiveCheckCallback>...</positiveCheckCallback>
            <negativeCheckCallback>...</negativeCheckCallback>
            <probeMethod>...</probeMethod>
        </emulator>
        <integrity>
            <positiveCheckCallback>...</positiveCheckCallback>
            <negativeCheckCallback>...</negativeCheckCallback>
            <probeMethod>...</probeMethod>
            <filters>
                <filter>...</filter>
            </filters>
        </integrity>
        <hooks>
            <positiveCheckCallback>...</positiveCheckCallback>
            <negativeCheckCallback>...</negativeCheckCallback>
            <probeMethod>...</probeMethod>
        </hooks>
        <customFirmware>
            <positiveCheckCallback>...</positiveCheckCallback>
            <negativeCheckCallback>...</negativeCheckCallback>
            <probeMethod>...</probeMethod>
        </customFirmware>
        <wirelessSecurity>
            <positiveCheckCallback>...</positiveCheckCallback>
            <negativeCheckCallback>...</negativeCheckCallback>
            <probeMethod>...</probeMethod>
            <filters>
              <filter/>
            </filters>          
        </wirelessSecurity>
    </detect> 
</dexprotector>


NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

Element: verbose
Description: Sets verbosity level to maximum
Format: boolean
Default value: false
Example: <verbose>true</verbose>

Element: licenseFile
Description: Path to the license file
Format: string
Default value: ${user.home}/dexprotector.licel
Example: <licenseFile>/Users/developer/dexprotector.licel</licenseFile>

Element: optimize
Description: Enables the class optimisation mode
Format: boolean
Default value: false
Example: <optimize>true</optimize>

Element: signMode
Description: Sets mode of signing of the output APK file
Format: string
Valid values: debug - signature is performed with a debug-key, release - signature is performed with the developer's key, google - signing mode to be used with Google Play App Signing (see Google Play App Signing), amazon - signing mode to be used for Amazon App Store (see Amazon App Signing), none - postponed signature, for example for signing later with a platform vendor key (Enterprise only)
Default value: no default value / DexProtector Gradle Plugin: the mode is set automatically
Example: <signMode>release</signMode>

Element: keystore (only for signMode == release, signMode == google (upload key), signMode == amazon (any key))
Description: Path to the keystore
Format: string
Default value: no default value / DexProtector Gradle Plugin: the value is set automatically
Example: <keystore>/Users/developer/.keystore</keystore>

Element: storepass (only for signMode == release, signMode == google, signMode == amazon)
Description: Password for the keystore
Format: string
Default value: no default value / DexProtector Gradle Plugin: the value is set automatically
Example: <storepass>android</storepass>

Element: alias (only for signMode == release, signMode == google, signMode == amazon)
Description: Key alias in the keystore
Format: string
Default value: no default value / DexProtector Gradle Plugin: the value is set automatically
Example: <alias>android</alias>

Element: keypass (only for signMode == release, signMode == google, signMode == amazon)
Description: Password for the key
Format: string
Default value: no default value / DexProtector Gradle Plugin: the value is set automatically
Example: <keypass>android</keypass>

Element: certificate (only for signMode == none) (Enterprise only)
Description: Path to the certificate file of the signature key
Format: string
Default value: no default value / DexProtector Gradle Plugin: the value is set automatically
Example: <certificate>/Users/developer/vendor.cert</certificate>

Element: v1SigningEnabled
Description: Use the v1 signing scheme (jarsigner)
Format: boolean
Default value: true
Example: <v1SigningEnabled>true</v1SigningEnabled>

Element: v2SigningEnabled
Description: Use the v2 signing scheme (full APK signing)
Format: boolean
Default value: false
Example: <v2SigningEnabled>true</v2SigningEnabled>

Element: sha256CertificateFingerprint (only for signMode == google, signMode == amazon)
Description: SHA256 certificate fingerprint of the target certificate. The value can be found: Amazon - Amazon Developer Consolse, settings of your application: Application -> Binary Files -> Appstore Certificate Hashes -> SHA-256 -> Hexadecimal, Google - Google Play Console, then go to settings of your application: App Signing -> App signing certificate -> SHA-256 certificate fingerprint
Format: string
Default value: no default value
Example: <sha256CertificateFingerprint>1B:5F:8B:D0:5A:A2:37:FC:D3:5F:AF:21:B7:F1:57:BD:E0:17:17:FA:6D:C3:35:FC:D5:AB:7A:2A:A5:70:33:2E</sha256CertificateFingerprint>

Element: mainAPK (Enterprise only)
Description: Attribute for DynamicApkProtection mechanism. To be set to false when protecting dynamically loadable modules, so-called external APKs or dynamic APKs
Format: boolean
Default value: true
Example: <mainAPK>false</mainAPK>

Element: proguardMapFile
Description: Path to ProGuard's map file (class name mappings after name obfuscation)
Format: string
Default value: no default value / DexProtector Gradle Plugin: the value is set automatically
Example: <proguardMapFile>/Users/developer/project/proguard_map.txt</proguardMapFile>

Element: rngSeedFile (since DexProtector 6.5.7, Enterprise only)
Description: The file name to store the initialization vector for a pseudo-random random number generator.
Format: string
Valid values: The absolute file path
Default value: no default value


Element: abiFilter (since DexProtector 7.1.17)
Description: This function is designed to filter only certain ABI configurations for which DexProtector native protection libraries will be added.
Format: string
Valid values: See supported ABIs Default value: no default value
Example: <abiFilter>armeabi-v7a, x86</abiFilter>

Element: stripLogging
Description: This function is designed to remove invocations of methods of android.util.Log
Format: string
Valid values:
all - strip android.util.Log.d(...), android.util.Log.e(...), android.util.Log.i(...), android.util.Log.v(...), android.util.Log.w(...), android.util.Log.wtf(...)
debug - strip android.util.Log.d(...)
error - strip android.util.Log.e(...)
info - strip android.util.Log.i(...)
verbose - strip android.util.Log.v(...)
warning - strip android.util.Log.w(...)
wtf - strip android.util.Log.wtf(...)
Default value: no default value
Example: <stripLogging>debug,verbose,warning,wtf</stripLogging>

Element: stripMethodCalls (since DexProtector 8.1.81)
Description: This function is designed to remove invocations of arbitrary methods (for instance, third-party logging libraries method calls)
Attribute: mode
Valid values: off - disable method invocations stripping
Format: contains nested elements
Nested elements (<filters>List of <filter/> methods</filters>) (Only for mode != off):
    Element: filter (Many)
    Format: string
    Default value: no default value
    Example: <filter>android.util.Log.println</filter>

Example:

<stripMethodCalls>
    <filters>
        <filter>android.util.Log.println</filter>
    </filters>
</stripMethodCalls>



Element: platformApplicationSupport (Enterprise only)
Description: Sets the support for applications to be signed with a platform vendor key
Format: string
Valid values: on - enable support, off - disable support
Default value: off
Example: <platformApplicationSupport>on</platformApplicationSupport>

Element: aar (Enterprise only)
Description: Process the input file as Android Library Archive (AAR)

Attribute: autoInit
Valid values: on - enable the DexProtector's automatic initialization mechanism, off - disable the DexProtector's automatic initialization mechanism. If autoInit="off" you must specify either initMethod(s) or/and initClass(es)
Default value: off

Important:
If autoInit="on" we strongly recommend to set autoInitAuthorities="${applicationId}" within the aar tag to avoid any conflicts. The autoInit mechanism leverages a Content Provider approach to get your protected AAR initialized (DexProtector's internal engine needs to start before your AAR's classes get referenced in the application's code). Thus, there can be a conflict of a few content providers with the same name, which is not allowed in Android. That is why you need to set autoInitAuthorities="${applicationId}".

Attribute: autoInitAuthorities
Description: URI authority of the autogenerated Content Provider
Fortmat: string
Valid values (recommended): ${applicationId}

Example:

<aar autoInit="on" autoInitAuthorities="${applicationId}" nativeHideAccess="on">

Attribute: desugar
Valid values: on - enable the support for libraries that built with the target of Java 8 (sourceCompatibility/targetCompatibility == VERSION_1_8), off - disable the support for libraries that built with Java 8 target
Default value: off

Attribute: kotlinSupport
Valid values: on - enable the support for libraries containing Kotlin code, off - disable the support for libraries containing Kotlin code
Default value: off

Attribute: nativeHideAccess
Valid values: on - enable the Native Invokedynamic Engine for the HideAccess function, off - disable the Native Invokedynamic Engine for the HideAccess function
Default value: off
Format: contains nested elements
Nested elements:
    Element: initMethod (Many)
    Format: string
    Default value: no default value
    Example: <initMethod>com.sample.Library.initMethod</initMethod>

    Element: initClass (Many)
    Format: string
    Default value: no default value
    Example: <initClass>com.sample.MyReceiver</initClass>

Example:

<aar>
    <initMethod>com.sample.Library.initMethod</initMethod>
    <initClass>com.sample.MyReceiver</initClass>
</aar>

Important: A method that is set in initMethod must have a parameter of type android.content.Context

Element: stringEncryption
Description: Encrypt Strings in the input application (APK) or Android Library (AAR)
Attribute: mode
Valid values: all - use filters set in the nested elements, annotations - use annotations
Default value: all
Format: contains nested elements
Nested elements (<filters>List of <filter/> tags</filters>) (Only for mode==all):
    Element: filter (Many)
    Format: string
    Default value: no default value
    Example: <filter>glob:com/sample/Library/**</filter>

Example:

<stringEncryption>
    <filters>
        <filter>glob:com/sample/Library/**</filter>
    </filters>  
</stringEncryption>
<stringEncryption mode="annotations"/>


Element: classEncryption
Description: Encrypt classes in the input application (APK) or Android Library (AAR)
Attribute: mode
Valid values: all - use filters set in the nested elements, annotations - use annotations
Default value: all
Format: contains nested elements
Nested elements (<filters>List of <filter/> tags</filters>) (Only for mode==all):
    Element: filter (Many)
    Format: string
    Default value: no default value
    Example: <filter>glob:com/sample/Library/**</filter>

Example:

<classEncryption>
    <filters>
        <filter>glob:com/sample/Library/**</filter>
    </filters>  
</classEncryption>
<classEncryption mode="annotations"/>


Element: hideAccess
Description: Hides accesses to methods/fields in the input application (APK) or Android Library (AAR)
Attribute: mode
Valid values: all - use filters set in the nested elements, annotations - use annotations
Default value: all
Format: contains nested elements
Nested elements (<filters>List of <filter/> tags</filters>) (Only for mode==all):
    Element: filter (Many)
    Format: string
    Default value: no default value
    Example: <filter>glob:com/sample/Library/**</filter>

Example:

<hideAccess>
    <filters>
        <filter>glob:com/sample/Library/**</filter>
    </filters>  
</hideAccess>
<hideAccess mode="annotations"/>


Element: resourceEncryption
Description: Encrypt resources in the input application (APK) or Android Library (AAR). Due to the Android platform limitations, res folder encryption is not available for AARs.
Attribute: androidManifestMangling (Enterprise only)
Valid values: on - enable android manifest mangling, off - disable android manifest mangling
Default value: off
Attribute: nameObfuscation
Valid values: on - enable resource name obfuscation, off - disable resource name obfuscation
Default value: off
Attribute: webViewSupport
Valid values: on - enable support for webView/Cordova/Phonegap, off - disable support for webView/Cordova/Phonegap
Default value: off
Format: contains nested elements
Nested elements (<assets/>,<res/>):
    Element: assets
    Description: Encryption settings for the assets folder. If the element exists in the configuration file, files from the assets folder are encrypted in accordance with the filter.
    Format: contains nested elements
        Nested elements (<filters>List of <filter/> tags</filters>):
        Element: filter (Many)
        Format: string
        Default value: no default value
        Example: <filter>*.html</filter>

    Element: res
    Description: Encryption settings for the res folder. If the element exists in the configuration file, files from the res folder are encrypted in accordance with the filter.
    Format: contains nested elements
        Nested elements (<filters>List of <filter/> tags</filters>):
        Element: filter (Many)
        Format: string
        Default value: no default value
        Example: <filter>*.png</filter>

    Element: strings (Enterprise only)
    Description: Encryption settings for strings and string-arrays in resources.arsc. If the element exists in the configuration file, entities in resources.arsc are encrypted in accordance with the filter.
    Format: contains nested elements
        Nested elements (<filters>List of <filter/> tags</filters>):
        Element: filter (Many)
        Format: string
        Default value: no default value
        Example: <filter>string_array</filter>

    Element: androidManifestMangling (Enterprise only)
    Description: Mangling settings for AndroidManifest.xml. If the element exists in the configuration file, entities in AndroidManifest.xml are mangled in accordance with the filter.
    Format: contains nested elements
        Nested elements (<filters>List of <filter/> tags</filters>):
        Element: filter (Many)
        Format: string
        Default value: no default value
        Example: <filter>glob:com/sample/Library/**</filter>

Example:

<resourceEncryption nameObfuscation="on" webViewSupport="on" androidManifestMangling="on">
    <assets>
        <filters>
            <filter>*.html</filter>
        </filters>
    </assets>    
    <res>
        <filters>
            <filter>*.png</filter>
        </filters>
    </res>    
    <strings>
        <filters>
            <filter>string</filter>
            <filter>string_array</filter>
            <filter>more_strings*</filter>
            <filter>more_string_arrays*</filter>
        </filters>
    </strings>        
    <androidManifestMangling>
        <filters>
            <filter>glob:!**/**</filter>
            <filter>glob:com/sample/Library/**</filter>
        </filters>
    </androidManifestMangling>    
</resourceEncryption>


Note: If there are no assets/res elements in the configuration file under resourceEncryption section the encryption of assets folder is performed in accordance with the default filter. The root for expressions in assets and res filters is /assets and /res accordingly. For example, the encryption of assets folder is enabled, and there is a filter *.html in the configuration, thus all the HTML files are encrypted in the /assets folder (/assets/*.html). The same for res encryption.

Note: If nameObfuscation is enabled (on) the obfuscation of resources.arsc is performed. In the Enterprise version all the names of files from res folder are obfuscated.

Note: Please note that the androidManifestMangling mechanism is available only when you use the CLI, it is not available from the GUI.


    Element: xamarinAssemblies (since DexProtector 8.1.81, Enterprise only)
    Description: A special feature which allows you to encrypt Xamarin’s assemblies.
    Attribute: dir
    Valid values: If the assemblies are not in the default folder (assets/assemblies), there is an attribute dir of the xamarinAssemblies that allows you to set a path to them. The path should start from the APK’s root, for example: assets/xxx/assemblies

Example:

<resourceEncryption>
    <xamarinAssemblies/>
</resourceEncryption>


Note: Please note that the xamarinAssemblies mechanism is available only when you use the CLI, it is not available from the GUI.

    Element: unityManagedCode (since DexProtector 8.1.31, Enterprise only)
    Description: A special feature which is designed for the Unity managed code (DLLs) protection.

Example:

<resourceEncryption mode="all" nameObfuscation="off" webViewSupport="off">
    <unityManagedCode/>
    <res mode="off"/>
    <assets mode="off"/>
</resourceEncryption>

Note: In order to protect the Unity code, you have to disable the resource encryption for res and assets, and enable the unityManagedCode node (see a config example above):

Note: Please note that the unityManagedCode mechanism is available only when you use the CLI, it is not available from the GUI.


Element: nativeLibraryEncryption (Enterprise only)
Description: Encrypt native libraries in the input application (APK)
Format: contains nested elements
Nested elements (<filters>List of <filter/> tags</filters>) (Only for mode==all):
    Element: filter (Many)
    Format: string
    Default value: no default value
    Example: <filter>libsome.so</filter>

Example:

<nativeLibraryEncryption>
    <filters>
        <filter>libsome.so</filter>
    </filters>  
</nativeLibraryEncryption>


Element: jniObfuscation (Enterprise only)
Description: Obfuscate JNI method names in the native libraries and classes
Attribute: mode
Valid values: all - use filters set in the nested elements, annotations - use annotations
Default value: all
Format: contains nested elements
Nested elements (<filters>List of <filter/> tags</filters>) (Only for mode==all):
    Element: filter (Many)
    Format: string (path the class JNI methods of which must be obfuscated)
    Default value: no default value
    Example: <filter>glob:com/sample/NativeLibrary.class</filter>

Example:

<jniObfuscation>
    <filters>
        <filter>glob:com/sample/NativeLibrary.class</filter>
    </filters>  
</jniObfuscation>
<jniObfuscation mode="annotations"/>

Note: Only classes that have JNI methods should be set in the filter, native libraries that have the JNI methods from those classes will be processed automatically.


Element: integrityControl (Enterprise only)
Description: Controls the configuration of the tamper resistance module
Format: contains nested elements
Nested element:
    Element: checkCertificate
    Format: string
    Valid values: on - enable certificate check, off - disable certificate check
    Default value: on
    Example: <checkCertificate>off</checkCertificate>

Example:

<integrityControl>
    <checkCertificate>off</checkCertificate>
</integrityControl>


Public Key Pinning

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

Element: publicKeyPinning (Enterprise only)
Description: Settings for SSL/HTTP Public Key Pinning. The followings approaches are available: security configuration file in res/xml (in accordance with specification for Android N), or via a network-security-config nested element.
Attribute: src
Valid values: Path to a security configuration file (see details here), thus if the file exists all the settings are taken from the file. If the src attribute is not set and there is a network-security-config tag all the settings are taken from the configuration defined inside the tag and the res/xml/network_security_config.xml will be created, it will contain settings from the network-security-config tag, and also the following information will be added into the AndroidManifest.xml:

<app ...>
    <meta-data android:name="android.security.net.config"
               android:resource="@xml/network_security_config" />
    ...
</app>

Default value: no default value
Format: contains nested elements (actions/reportUri/network-security-config)
Nested elements:
    Element: actions
        Description: List of actions that are to be performed if there were errors or anomalies in Public Key Pinning's validations
        Format: list with the ',' separator. Available values: block - block the connection, report - send a report regarding the connection.
        Default value: block, report
        Example: <actions>block, report</actions>
    Element: reportUri
        Description: Address that will be used to send JSON reports regarding the errors and anomalies detected during the execution of the Public Key Pinning's checks
        Format: string
        Example:

<reportUri>http://example.com/pkp-report</reportUri>

    Element: reportMethod
        Description: ClassName.methodName a method to which JSON reports are passed to when there were errors of validation of Public Key Pinning checks. These methods should have public static modifier and (String jsonStr) signature.

        Format: string
        Example:

<reportMethod>com.sampleapp.MainActivity.pkpReport</reportMethod>

    Element: cacheTTL
        Description: Time to live for a server SSL certificate chain check result for each domain
        Format: int
        Default value: 180
        Example: <cacheTTL>180</cacheTTL>


    Element: network-security-config
        Description: Embedded Security Configuration File
        Format: network-security-config
        Example #1:

        <network-security-config>
            <domain-config>
                <domain includeSubdomains="true">example.com</domain>
                    <pin-set expiration="2018-01-01">
                    <pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin>
                    <!-- backup pin -->
                    <pin digest="SHA-256">fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=</pin>
                    </pin-set>
            </domain-config>
        </network-security-config>

        Example #2 (Security Configuration File in res/xml APK):

        <publicKeyPinning src="res/xml/network_security_config.xml">
            <reportUri>http://example.com/pkp-report</reportUri>
        </publicKeyPinning>

         Example #3 (Embedded Security Configuration File):

<publicKeyPinning>
    <reportUri>http://example.com/pkp-report</reportUri>
    <network-security-config>
        <domain-config>
            <domain includeSubdomains="true">example.com</domain>
                <pin-set expiration="2018-01-01">
                <pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin>
                <!-- backup pin -->
                <pin digest="SHA-256">fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=</pin>
                </pin-set>
        </domain-config>
    </network-security-config>
</publicKeyPinning>


Tamper Notifications and Environment Checks

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

Element: detect (Enterprise only)
Description: Controls the device/environment checks
Format: contains nested elements (root/emulator/debug/integrity/customFirmware/hooks/wirelessSecurity)
Nested elements:
    Element: root/emulator/debug/integrity/customFirmware/hooks/wirelessSecurity
    Format: contains nested elements (positiveCheckCallback/negativeCheckCallback/probeMethod)
        Nested elements:
        Element: positiveCheckCallback
        Description: ClassName.methodName - callback method to be called if the check was successful
        Format: string
        Example: <positiveCheckCallback>com.sample.MainActivity.positiveCheck</positiveCheckCallback>

        Element: negativeCheckCallback
        Description: ClassName.methodName - callback method to be called if the result of the check is negative
        Format: string
        Example: <negativeCheckCallback>com.sample.MainActivity.negativeCheck</negativeCheckCallback>

        Element: probeMethod
        Description: ClassName.methodName - method to be used for embedment of device/environment checks
        Format: string
        Example: <probeMethod>com.sample.MainActivity.doProbe</probeMethod>

Example:

<detect>
  <root>
     <positiveCheckCallback>com.sampleapp.MainActivity.positiveCheckCallback</positiveCheckCallback>
     <negativeCheckCallback>com.sampleapp.MainActivity.negativeCheckCallback</negativeCheckCallback>
     <probeMethod>com.sampleapp.MainActivity.doProbe</probeMethod >
  </root>
</detect>

Important: Methods that are set in positiveCheckCallback/negativeCheckCallback must have public static modificator and (Object o) signature. Method that is set in probeMethod must have android.content.Context as one of its parameters and must be called in your application prior to using the checks' results.

Note: It is possible to set which files will be controlled by the integrity check, to do so you can use filters, for example:

APKs:

<dexprotector>
...
    <detects>
        <integrity>
            <filters>
                <filter>glob:**</filter>
                <filter>glob:!META-INF/**</filter>
                <filter>glob:!AndroidManifest.xml</filter>
            </filters>
        </integrity>
        ...
        ...
    </detects>
...
</dexprotector>

AABs:

<dexprotector>
...
    <detects>
        <integrity>
            <filters>
                <filter>glob:classes*.dex</filter>
                <filter>glob:assets/**</filter>
            </filters>
        </integrity>
        ...
        ...
    </detects>
...
</dexprotector>

AARs:

<dexprotector>
...
    <detects>
        <integrity>
            <filters>
                <filter>glob:assets/**</filter>
            </filters>
        </integrity>
        ...
        ...
    </detects>
...
</dexprotector>

Filter format

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

DexProtector provides a flexible mechanism of setting the filters for its protection functions. You can use glob or regex syntax modes. Wherein it is possible to use exclusions by placing ! before the filter's expression.

Let us see at different filter settings (glob syntax is used in the following examples).

Say we want to configure a Class Encryption's filter. In the classes.dex we have got the following structure of packages:

    android/support/...
    com/google/..
    com/facebook/..
    com/mycompany/..
    com/mycompany/ui/..
    com/mycompany/core/..

1. Protection of certain packages

In order to protect the com/mycompany package (i.e. all the classes that lie under com/mycompany) we should set the following filter:

    glob:com/mycompany/**

2. Protection of a certain class

To protect a single class, for example com/mycompany/core/InternalEngine.class we use the following filter:

    glob:com/mycompany/core/InternalEngine.class

3. Exclusion of certain packages from processing

Here are a few examples of how to exclude a certain package or packages from processing:

    glob:!android/support/**
    glob:!com/google/**
    glob:!com/facebook/**

In this case a result will be the same as in the first case, where we included everything except android/support, com/google and com/facebook. And in the second example we excluded everything except com/mycompany.

Exclusion for a single class is made in the same way and it is needed to place ! before the class name:

    glob:!com/mycompany/core/BumpGenerator.class

4. Mixed configuration

DexProtector allows using inclusions and exclusions at the same time. When doing that keep in mind the following logic:

  • At first we add an exclusion filter for all the packages and classes
  • Set include filters
  • Add exclude filters for certain packages and/or classes

In other words DexProtector reads and applies rules from the top to the bottom.

For example:

    glob:!**/**
    glob:com/mycompany/**
    glob:!com/mycompany/ui/**
    glob:com/mycompany/ui/Payment.class

As a result all the classes from com/mycompany and com/mycompany/core are protected, and the com/mycompany/ui/Payment.class is protected as well. Remaining classes from com/mycompany/ui are leaved untouched.

The same approach is used for all the functions that use filters, i.e. String Encryption, Hide Access, Resource Encryption and Native Library Protection.

Please see dexprotector.xml file in the root folder of the distribution kit for additional examples.

Detailed syntax information

Filter is to be defined by the syntax and the pattern and takes the form: syntax:pattern, where ':' stands for itself.

Two syntaxes are supported: the "glob" and "regex". The value of the syntax component is compared without regard to case. When the syntax is "glob" then the String representation of the path is matched using a limited pattern language that resembles regular expressions but with a simpler syntax. For example:
*.* Matches file names containing a dot.
foo.? Matches file names starting with foo. and a single character extension.
com/*/* Matches package /com/test/a.
com/** Matches all packages and classes inside a com package.

The following rules are used to interpret glob patterns:

  • The * character matches zero or more characters of a name component without crossing directory boundaries.
  • The ** characters matches zero or more characters crossing directory boundaries.
  • The ? character matches exactly one character of a name component.
  • The backslash character (\) is used to escape characters that would otherwise be interpreted as special characters. The expression \\ matches a single backslash and \{ matches a left brace for example.
  • The [ ] characters are a bracket expression that matches a single character of a name component out of a set of characters. For example, [abc] matches "a", "b", or "c". The hyphen (-) may be used to specify a range so [a-z] specifies a range that matches from "a" to "z" (inclusive). These forms can be mixed so [abce-g] matches "a", "b", "c", "e", "f" or "g". If the character after the [ is a ! then it is used for negation so [!a-c] matches any character except "a", "b", or "c". Within a bracket expression the *, ? and \ characters match themselves. The - character matches itself if it is the first character within the brackets or the first character after the ! if negating.
  • The { } characters are a group of subpatterns, where the group matches if any subpattern in the group matches. The , character is used to separate the subpatterns. Groups cannot be nested.
  • Leading period/dot characters in the file name are treated as regular characters in match operations. For example, the * glob pattern matches file name ".login".
  • The ! character in the beginning of the pattern component negates the pattern.

When the syntax is "regex" then the pattern component is a regular expression composed in accordance with java regex rules.

Note: If the syntax is not set (glob: or regex:) old filter format will be used in order to preserve backward compatibility with DexProtector’s versions < 5.0.

Signing Modes

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

IMPORTANT: The new signing modes: google and amazon, work only from the CLI and Gradle/Ant/Maven plugins. They do not work from the GUI.

DexProtector's APK anti-tampering protection and integrity control are always enabled. In order to make these functions highly reliable and secure, DexProtector needs to know what will be your target certificate. It takes your certificate information alongside many other parameters into account for building a cryptographic chain of trust. That is why it is impossible to re-sign a DexProtected application - it will become inoperable. Since version 8.1, DexProtector supports amazon (Amazon App Store Signing) and google (Google Play App Signing) signing modes.

Google Play App Signing

If your application gets published on Google Play and you use Google Play App Signing (with an upload key) it is needed to use google signing mode. You will need your upload key and sha256CertificateFingerprint of corresponding target certificate. Once your application is signed on Google servers, it will become operable. For debug purposes, please use debug (<signMode>debug</signMode>) or release (<signMode>release</signMode>) signing modes.

How to configure it:

a. Set the signing mode:

    <signMode>google</signMode>

b. Add a new setting to your configuration:

    <sha256CertificateFingerprint>PUT_YOUR_VALUE_HERE</sha256CertificateFingerprint>

You can obtain the value by going to Google Play Console, then go to settings of your application: App Signing -> App signing certificate -> SHA-256 certificate fingerprint

For instance:

    <sha256CertificateFingerprint>1B:5F:8B:D0:5A:A2:37:FC:D3:5F:AF:21:B7:F1:57:BD:E0:17:17:FA:6D:C3:35:FC:D5:AB:7A:2A:A5:70:33:2E</sha256CertificateFingerprint>

c. Keystore-related tags should be also set as always (in case you use Gradle it will be taken automatically from the signingConfig), a corresponding upload key must be used.

Example:

    <dexprotector>
    ...
    ...
        <signMode>google</signMode>
        <!-- If google signing mode is set you must use your corresponding upload key below -->
        <keystore>/Users/developer/keystores/production.keystore</keystore>
        <storepass>android</storepass>
        <alias>android</alias>
        <keypass>android</keypass>
        <sha256CertificateFingerprint>1B:5F:8B:D0:5A:A2:37:FC:D3:5F:AF:21:B7:F1:57:BD:E0:17:17:FA:6D:C3:35:FC:D5:AB:7A:2A:A5:70:33:2E</sha256CertificateFingerprint>        
    ...
    ...
    </dexprotector>

d. More likely, you should add a new buildType/productFlavor specifically for Google Play as it will not work for Amazon App Store/other stores/direct distribution.

Amazon App Store Signing

If your application gets published on Amazon App Store, it is needed to use amazon signing mode. You will need sha256CertificateFingerprint of your target certificate. Once your application is signed on Amazon servers, it will become operable. For debug purposes, please use debug (<signMode>debug</signMode>) or release (<signMode>release</signMode>) signing modes.

How to configure it:

a. Set the signing mode:

    <signMode>amazon</signMode>

b. Add a new setting to your configuration:

    <sha256CertificateFingerprint>PUT_YOUR_VALUE_HERE</sha256CertificateFingerprint>

You can obtain the value by going to Amazon Developer Consolse, then go to settings of your application: Application -> Binary Files -> Appstore Certificate Hashes -> SHA-256 -> Hexadecimal

For instance:

    <sha256CertificateFingerprint>1B:5F:8B:D0:5A:A2:37:FC:D3:5F:AF:21:B7:F1:57:BD:E0:17:17:FA:6D:C3:35:FC:D5:AB:7A:2A:A5:70:33:2E</sha256CertificateFingerprint>

c. Keystore-related tags should be also set as always (in case you use Gradle it will be taken automatically from the signingConfig).

Example:

    <dexprotector>
    ...
    ...
        <signMode>amazon</signMode>
        <!-- If amazon signing mode is set you might use any key below -->
        <keystore>/Users/developer/keystores/production.keystore</keystore>
        <storepass>android</storepass>
        <alias>android</alias>
        <keypass>android</keypass>
        <sha256CertificateFingerprint>1B:5F:8B:D0:5A:A2:37:FC:D3:5F:AF:21:B7:F1:57:BD:E0:17:17:FA:6D:C3:35:FC:D5:AB:7A:2A:A5:70:33:2E</sha256CertificateFingerprint>        
    ...
    ...
    </dexprotector>

d. More likely, you should add a new buildType/productFlavor specifically for Amazon as it will not work for Google Play/other stores/direct distribution.

Important: It is needed to disable Amazon DRM (Application -> Binary Files -> Apply Amazon DRM? -> No), as basically this is a tampering with, which will trigger DexProtector's defense mechanisms.

Annotations

NOTE: This documentation page is no longer updated and the information it contains may not be accurate. Please find current DexProtector documentation at our new website licelus.com.

To fine tune your protection process, you can use annotations. Annotations will be used only if you will enable the corresponding parameters in your configuration. You can enable annotations for String Encryption, Class Encryption and Hide Access, the annotations are respectively: @StringEncryption, @ClassEncryption and @HideAccess. If there are the annotations in a project then class files and/or their elements marked with the annotations will be protected.

The @StringEncryption annotation can be used at the following hierarchy levels:

Class field - a specified class String is encrypted:

import com.dexprotector.annotations.*;

public class Test {
 @StringEncryption
  final String SOME_TEXT="12345678";
   ....
}

Class - all Strings of the class are encrypted:

...
import com.dexprotector.annotations.*;

@StringEncryption 
public class Test {
   ....
}

Class method - all Strings of the method are encrypted:

import com.dexprotector.annotations.*;

public class Test {
   ....
  @StringEncryption
  public void someMethod(){
     ...
  }
   ....
}

The @ClassEncryption annotation can be used at the following hierarchy levels:

Class - the class is encrypted:

...
import com.dexprotector.annotations.*;

@ClassEncryption 
public class Test {
   ....
}

The @HideAccess annotation can be used at the following hierarchy levels:

Class - all calls of all class methods are hidden:

...
import com.dexprotector.annotations.*;

@HideAccess 
public class Test {
   ....
}

Class method - all method calls and accesses to fields are protected:

import com.dexprotector.annotations.*;

public class Test {
   ....
  @HideAccess
  public void someMethod(){
     ...
  }
   ....
}

To use the annotations in your projects, add the dexprotector-annotations.jar library from the distribution kit to the project classpath.

Important Note: If you are using ProGuard alongside DexProtector, please make sure you have the following rules in your ProGuard configuration file:

-keep interface com.dexprotector.annotations.ClassEncryption
-keep interface com.dexprotector.annotations.HideAccess
-keep interface com.dexprotector.annotations.StringEncryption

Samples

The samples are available on GitHub.

Uninstallation Information

In order to uninstall DexProtector from your computer, please delete your DEXPROTECTOR_HOME directory (where you unpacked the distribution kit) and your license file, it is located in your home folder and called dexprotector.licel.

Last update: 26.06.2023 - 16:24