Android
Configuring DexProtector
Introduction to configuring DexProtector
DexProtector works best when it is tailored to your app.
Configuration is by means of a single XML file, which can be edited directly or via the DexProtector Studio interface. A default configuration file (dexprotector.xml) can be found in the root folder of the distribution package, but every app (or SDK) has different requirements. We therefore strongly recommend that you create your own tailored configuration, in order to target the correct code and resources for protection.
You can use the configuration file to control the DexProtector process according to your needs. The configuration file allows you to specify the details of:
- Build and logging settings for the DexProtector process
- Signing methods
- Protection mechanisms and filters for including/excluding code and resources for protection
- Environment checks, for the detection of rooted devices; debuggers; emulators; and hooking tools
- Network security options, including certificate monitoring for both Certificate Transparency and Public Key Pinning mechanisms
- Integration with Licel's Threat Reporting and Attack Telemetry system, Alice
Protection Recommendations
We recommend making use of all of the security features provided, as each element of protection adds more security and more resistance against malware, reverse engineering, tampering, and Man-in-the-Middle attacks.
Note: For some features, a DexProtector Enterprise license is required. For more information, see our feature comparison for DexProtector Standard and DexProtector Enterprise.
Configuration file overview
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<dexprotector>
<!-- BUILD SETTINGS -->
<verbose>false</verbose>
<optimize>false</optimize>
<securityAssessment>
<signingCertificateCompromised mode="error" />
<signingCertificateWeakKey mode="error" />
<dependencyCheck mode="warning" />
</securityAssessment>
<proguardMapFile>no_default</proguardMapFile>
<!-- SIGNING -->
<signMode>debug</signMode>
<keystore>no_default</keystore>
<storepass>no_default</storepass>
<alias>no_default</alias>
<keypass>no_default</keypass>
<certificate>no_default</certificate>
<sha256CertificateFingerprint>no_default</sha256CertificateFingerprint>
<legacySha256CertificateFingerprint>no_default</legacySha256CertificateFingerprint>
<!-- CODE STRIPPING -->
<stripLogging>no_default</stripLogging>
<stripMethodCalls>
<filters>
<filter>no_default</filter>
</filters>
</stripMethodCalls>
<!-- CODE PROTECTION -->
<stringEncryption/>
<annotationEncryption/>
<jniObfuscation/>
<hideAccess/>
<classEncryption/>
<nativeLibraryEncryption/>
<!-- RESOURCE PROTECTION -->
<resourceEncryption>
<assets>
<filters>
<filter>no_default</filter>
</filters>
</assets>
<res>
<filters>
<filter>no_default</filter>
</filters>
</res>
<strings>
<filters>
<filter>no_default</filter>
</filters>
</strings>
<nameObfuscation>
<filters>
<filter>no_default</filter>
</filters>
</nameObfuscation>
<androidManifestMangling/>
<xamarinAssemblies/>
</resourceEncryption>
<!-- RASP - ENVIRONMENT CHECKS -->
<antiDebug>true</antiDebug>
<antiEmulator>true</antiEmulator>
<antiManualInstall>true</antiManualInstall>
<antiMalware>true</antiMalware>
<runtimeChecks/>
<!-- NETWORK SECURITY -->
<publicKeyPinning src="no_default">
<trace>0</trace>
<actions>block, report</actions>
<network-security-config>
<domain-config>
<domain includeSubdomains="false">no_default</domain>
<pin-set expiration="no_default">
<pin digest="no_default"></pin>
</pin-set>
</domain-config>
</network-security-config>
</publicKeyPinning>
<certificateTransparency>
<trace>0</trace>
<domain includeSubdomains="false">no_default</domain>
<!-- <logFile>no_default</logFile> -->
</certificateTransparency>
<!-- UI PROTECTION -->
<uiProtection/>
<!-- THREAT REPORTING AND TELEMETRY (ALICE) -->
<reportMonitoring>
<apiKey>no_default</apiKey>
<!-- <customFieldsUpdate>no_default</customFieldsUpdate> -->
<trace>0</trace>
</reportMonitoring>
<!-- AAR PARAMETERS -->
<aar autoInit="on" autoInitAuthorities="${applicationId}" kotlinSupport="on" />
</dexprotector>
Build Settings | Description and values |
---|---|
Verbose Logging boolean |
Element: Description: Enables/disables verbose logging for the DexProtector process. Valid values: true; false. Default value: false
|
Code Optimization boolean |
Element: Description: Removes redundant metadata from the package that might otherwise affect performance and/or be exploited by bad actors Valid values: true; false. Default value: false
|
Security Assessment signingCertificateCompromised signingCertificateWeakKey dependencyCheck |
Element: Description: With Security Assessment enabled, the DexProtector process will fail if the signing certificate is known to be compromised, or recognized as weaker than recommended. Valid values: true; false. Default value: false Nested elements ( Element (nested): Description: If the signing certificate has been compromised, the DexProtector process will throw an error and the build will fail. Valid values: warning; error; off. Default value: error Element (nested): Description: If the signing key is weak (i.e. an RSA key that is <2048 bits), the DexProtector process will throw an error and the build will fail. Valid values: warning; error; off. Default value: error Element (nested): Description: Checks application dependencies for known vulnerabilities. Valid values: warning; error; off. Default value: warning
|
ProGuard mapping file string |
Element: Description: Specifies the absolute path to ProGuard's mapping file. If you use ProGuard for name obfuscation, it is necessary to provide the path to ProGuard's mapping file so that DexProtector can locate classes for encryption. Default value: no default value. Note: When using the DexProtector Gradle Plugin, the value for the proguardMapFile (if necessary) is set automatically.
|
Signing | Description and Values |
---|---|
Signing Mode string |
Element: Description: Specifies options for app signing. Valid values:
|
Keystore information (for signMode == release; signMode == google; signMode == amazon) Keystore Keystore password Key alias Key password |
Element: Description: Specifies the path to the keystore containing the relevant signing key Default value: no default value. Note: With the DexProtector Gradle Plugin, the path is specified automatically. Element: Description: Specifies the password to the keystore containing the relevant signing key Default value: no default value. Note: With the DexProtector Gradle Plugin, the path is specified automatically. Element: Description: Specifies the alias string for the relevant signing key in your keystore Default value: no default value. Note: With the DexProtector Gradle Plugin, the path is specified automatically. Element: Description: Specifies the password for the signing key Default value: no default value. Note: With the DexProtector Gradle Plugin, the path is specified automatically.
|
Keystore information (for signMode == google) SHA-256 Certificate Fingerprint Legacy SHA-256 Certificate Fingerprint |
Element: Description: Specifies the SHA-256 Certificate Fingerprint corresponding to the Google Play App Signing Key used in Play app signing. Default value: no default value. Note: with the DexProtector Gradle plugin, the value is derived automatically.
Element: Description: If you publish your app to Google Play, you can upgrade the signing key for your published app through the Play Console—your new key is used to sign new installs and app updates, while your older app signing key is used to sign updates for users who installed your app before the key upgrade. If you have upgraded the signing key for your published app and are DexProtecting an update, you must specify both the SHA-256 Certificate Fingerprint corresponding to the new key, and the Legacy SHA-256 Certificate Fingerprint corresponding to the original key. Default value: no default value. |
Code Stripping | Description and Values |
---|---|
Logging Call Stripping |
Element: Description: Prevents unwanted log outputs by blocking the calling of methods with android.util.Log. The scale of verbosity (from least to most) is WTF, ERROR, WARNING, INFO, DEBUG, VERBOSE. Valid values: wtf [strip
|
Method Call Stripping filters |
Element: Description: Blocks the calling of specified methods (for example, the method calls of third-party logging libraries) Element (nested): filters (Only when mode != off): Format: string Default value: no default value
|
Code Protection | Description and Values |
---|---|
String Encryption filters |
Element: Description: Enables DexProtector's String Encryption mechanism. Note: We recommend encrypting as many strings as possible, but especially those containing sensitive data (logins, passwords, API credentials, keys, etc.). There is no need, on the other hand, to encrypt any strings contained in publicly available third party libraries, and DexProtector’s default configuration file contains certain example filters to exclude such libraries from the string encryption process. Element (nested): filters Format: string Default value: no default value
|
Annotation Encryption filters |
Element: Description: Encrypt Kotlin annotations to protect sensitive metadata. Important: Filters for Annotation Encryption work differently than for other mechanisms. Filters must target the classes in which annotations are defined, and not the classes in which annotations are referenced. DexProtector will then locate all instances of the annotations and encrypt them. Element (nested): filters Format: string Default value: no default value
|
JNI Obfuscation filters |
Element: Description: Enables the obfuscation of JNI (Java Native Interface) method names in native libraries and classes, in accordance with the specified filters. Note: When setting filters for JNI Obfuscation, you only need to specify the classes that contain JNI methods. DexProtector will then automatically process native libraries containing the JNI methods from those classes. Element (nested): filters Format: string Default value: no default value
|
Hide Access filters |
Element: Description: The Hide Access mechanism conceals method calls and field accesses in the packages and classes specified in the filters, breaking the link between the call site and the function being called. Element (nested): filters Format: string Default value: no default value
|
Class Encryption filters |
Element: Description: DexProtector encrypts entire classes.dex including Application, Activities, ContentProviders, and Receivers, in accordance with the specified filters. Note: DexProtector will encrypt all classes by default, without affecting the application’s performance. However, it is important to exclude any classes that must remain accessible to third parties, such as those that form part of a public API. Element (nested): filters Format: string Default value: no default value
|
Native Library Encryption filters |
Element: Description: DexProtector encrypts native libraries (.so files) within the target package, in accordance with the chosen filters. Element (nested): filters Format: string Default value: no default value
|
Resource Protection | Description and Values |
---|---|
Resource Encryption assets folder encryption res folder encryption resources.arsc string encryption resource name obfuscation root folder encryption AndroidManifest mangling Xamarin assemblies |
Element: Description: Resource encryption protects against malicious copying, modification, and piracy by encrypting an application's internal resources; resource names; and, for cross-platform apps, HTML, JS, and CSS code. Filters can target the assets and res folders, as well as resources in the root folder, and individual string resources. Nested elements (<assets>, <res>, <strings>, <nameObfuscation>,<root>, <androidManifestMangling>, <xamarinAssemblies>): Element (nested): assets Description: Encrypts files in Format: contains nested elements Element (nested): filters Format: string Default value: no default value Element (nested): res Description: Encrypts files in Format: contains nested elements Element (nested): filters Format: string Default value: no default value Element (nested): strings Description: Encrypts strings and string arrays in Format: contains nested elements Element (nested): filters Format: string Default value: no default value Element (nested): nameObfuscation Description: With Resource Name Obfuscation enabled, DexProtector will obfuscate names of names of files in res/. It is possible to set filters for Resource Name Obfuscation independently of the filters specified for res folder encryption. For more information, see the guide to filters for resource encryption. Format: contains nested elements Element (nested): filters Format: string Default value: no default value Element (nested): root Description: Encrypts files in Format: contains nested elements Element (nested): filters Format: string Default value: no default value Element (nested): androidManifestMangling Description: Mangling settings for AndroidManifest.xml. If the element androidManifestMangling is included in the configuration file, DexProtector will mangle entities in the AndroidManifest.xml file. Element (nested): xamarinAssemblies Description: Encrypts Xamarin assemblies Attribute: dir Description: If the assemblies are not in the default folder (assets/assemblies), you can set a path to them using the attribute dir. The path should start from the APK’s root, for example: assets/xxx/assemblies Format: string Default value: no default value
|
RASP (Runtime Application Self-Protection) - Environment & Runtime Checks | Description and Values |
---|---|
Anti-Debug |
Element: Description: With this setting enabled, the DexProtector Runtime Engine will close the app instantly if it detects that a debugger is attached. |
Anti-Emulator |
Element: Description: With this setting enabled, the DexProtector Runtime Engine will prevent the app from running on an emulator. Note: Client-side API and callback options are available as an alternative to closing the app. Please request more details on configuration and implementation. |
Anti-Manual Install |
Element: Description: With this setting enabled, the DexProtector Runtime Engine will prevent the app from running if it was sideloaded. Note: Client-side API and callback options are available as an alternative to closing the app. Please request more details on configuration and implementation. |
Anti-Malware |
Element: Description: With this setting enabled, the DexProtector Runtime Engine will report malware and Potentially Harmful Apps detected on the device to the organization's Alice Threat Intelligence database. Note: <reportMonitoring> must be enabled. Client-side API and callback options are also available. Please request more details on configuration and implementation. |
Runtime Checks |
Element: Description: With this setting enabled, the DexProtector Runtime Engine will prevent the app from running on custom firmware and rooted devices. |
Network Security | Description and Values |
---|---|
Public Key Pinning |
Element: Description: Settings for SSL/HTTP Public Key Pinning. These can be specified either via a security configuration file in res/xml (in accordance with specification for Android N), or via the network-security-config nested element. If you have a separate security configuration file, you must set the path to it within the attribute ‘src’. Attribute: src Valid values: Path to a security configuration file (see details here). Default value: no default value Note: if the file exists, all public key pinning settings are taken from the file. On the other hand, if the src attribute is not set and there is a
Format: contains nested elements (<actions>, <reportUri>, <reportMethod>, <network-security-config>) Element (nested): actions Description: Specifies the actions to be performed if there are errors or anomalies detected during the Public Key Pinning checks Format: list with the ',' separator Valid values: block - block the connection; report - send a report regarding the connection Default value: block, report
Element (nested): reportUri Description: Specifies the address that will be used to send JSON reports regarding any errors or anomalies detected during the Public Key Pinning checks Format: string Element (nested): reportMethod Description: Specfies a method (in the format ClassName.methodName) to which JSON reports are passed in the event of any errors or anomalies detected during the Public Key Pinning checks. These methods should have public static modifier and (String jsonStr) signature. Format: string Element (nested): cacheTTL Description: Time to live for a server SSL certificate chain check result for each domain Format: int Default value: 180 Element (nested): network-security-config Description: Embedded Security Configuration File Examples of embedded security configuration settings: Example #1:
Example #2 (Security Configuration File in res/xml):
|
Certificate Transparency |
Element: Description: Settings for monitoring public key certificates according to the Certificate Transparency standard. DexProtector uses a list of log servers that is located in the distribution package. This list is based on: https://source.chromium.org/chromium/chromium/src/+/master:components/certificate_transparency/data/log_list.json Alternatively, a list of authorized log servers can be specified manually by entering a path to a file containing that list. Format: contains nested elements (<trace>, <logFile>) Element (nested): trace Format: string Description: For debugging purposes, set trace to 1000. Default value: no default value Element (nested): logFile Format: string Description: Path to file containing your own list of authorized log servers. Default value: no default value
|
UI Protection | Description and Values |
---|---|
UI Protection |
Element: Description: DexProtector’s UI Protection blocks screen capture and prevents activity hijacking. Screen capture blocking hardens your app against screenshots, screen recording, and screen casting. Hijacking prevention protects the app from malware that takes control of the application and replaces legitimate windows with impostors. |
Threat Reporting and Telemetry - Alice Integration | Description and Values |
---|---|
Threat Reporting |
Element: Description: Configures Licel’s Real-Time Attack Telemetry and Threat Intelligence service, Alice. For more information, see our guide to Alice. Format: contains nested elements (<apiKey>, <customFieldsUpdate>, <trace>) Element (nested): apiKey Format: string Default value: no default value Element (nested): customFieldsUpdate Format: string Description: Specifies a method, if one is implemented in the package’s code, for customizing the types of data reported to Alice by the monitoring system (e.g. user’s IP address; device serial number, etc.) . The method specified must have the following format:
java
Default value: no default value, but the field must have the following structure:
xml
Element (nested): trace Format: string Description: The logging level of DexProtector messages on the end device. For debugging purposes, set to 1000. Otherwise, set to 0 or exclude the <trace> node. Default value: no default value
xml
|
AAR Parameters | Description and Values |
---|---|
AAR |
Element: Description: Enables the DexProtection of Android libraries & SDKs (AAR). Since DexProtector's runtime engine must start before the AAR is first accessed, it is necessary to configure the initialization process, and/or to leave DexProtector's auto-initialization mechanism enabled. Attribute: autoInit Valid values: on - enable DexProtector's automatic initialization mechanism; off - disable DexProtector's automatic initialization mechanism. If autoInit="off" you must specify either initMethod(s) and/or initClass(es). Default value: on Attribute: autoInitAuthorities Description: To ensure that DexProtector's runtime engine is initialized when necessary, the autoInit mechanism uses a Content Provider approach, and defines a content provider component in the AndroidManifest.xml. Therefore, if autoInit="on" we strongly recommend to specify autoInitAuthorities="${applicationId}", additionally specifying a unique ID for each AAR where necessary, to avoid the risk of conflict whereby multiple content providers with the same name are specified in android:authorities. Default value: ${applicationId} Attribute: kotlinSupport Valid values: on - enable support for libraries containing Kotlin code; off - disable support for libraries containing Kotlin code Default value: off Attribute: nativeClassEncryption Valid values: on - enable the encryption of native classes within the library; off - disable the encryption of native classes within the library Default value: on Attribute: nativeHideAccess Valid values: on - enable the Hide Access mechanism for native classes within the library; off - disable the Hide Access mechanism for native classes within the library Default value: off
We strongly recommend leaving autoInit="on", but if you prefer to set autoInit="off" you must specify either initMethod(s) and/or initClass(es). For example:
|
Filters: A guide to targeting code and resources
An important part of the configuration process is specifying which packages and classes will be targeted for protection. DexProtector therefore provides a flexible mechanism for setting custom filters for each of its Code Protection, Resource Protection, and Code Stripping mechanisms.
If the protection mechanisms are enabled but no filters are specified, DexProtector automatically protects all strings in all classes (String Encryption), all methods, fields, and field accesses in all classes (Class Encryption, Hide Access), and also encrypts resources (Resource Encryption). This offers maximum protection, and is worth trying during the testing phase, but can occasionally lead to inefficiencies in the application's performance. This is especially true of the Hide Access protection mechanism, when particularly demanding loops are involved. We therefore recommend using the filters to fine-tune your protection where necessary.
You can use ‘glob’ or ‘regex’ syntax modes to apply protections according to specified name patterns.
To set a filter to include a given package or class in the protection process, simply specify the syntax mode and the name pattern in the form: ‘syntax:pattern’, where ':' stands for itself.
To exclude a given package or class from protection, use an exclamation mark (!) before the name pattern, in the form: ‘syntax:!pattern’
The following are guides to filters configured for inclusion, exclusion, and both, using the glob syntax mode.
Inclusion
Protecting every class in a specified package
Say we want to configure a filter in order to specify which classes DexProtector should include in its Class Encryption process. In our classes.dex
we have the following structure of packages:
'
android/support/...
com/google/..
com/facebook/..
com/mycompany/..
com/mycompany/ui/..
com/mycompany/core/..
In this case, we want DexProtector to encrypt all of the classes contained in the com/mycompany
package. We should therefore set the following filter in our configuration file:
'
glob:com/mycompany/**
Protecting a single class
To protect a single class - for example com/mycompany/core/InternalEngine.class - we use the following filter format:
'
glob:com/mycompany/core/InternalEngine.class
Exclusion
Excluding every class in a specified package from protection
Exclusion filters are set by adding the exclamation mark (!) before the class or package name pattern:
'
glob:!android/support/**
glob:!com/google/**
glob:!com/facebook/**
Excluding a single class from protection
Exclusion filters for classes are done in the same way, by adding the exclamation mark (!) before the classpath:
'
glob:!com/mycompany/core/BumpGenerator.class
Mixed filters: Combining inclusion and exclusion
One possible (and recommended) approach for String Encryption and Hide Access is first to set a global exclusion filter, to exclude every class from protection, and then to target specific classes for inclusion. For Class Encryption, no problems should arise from encrypting every class in the package, except for any that must remain accessible to third parties, such as those that form part of a public API.
This would be a simple example configuration for String Encryption, Class Encryption, and Hide Access:
<dexprotector>
***
<stringEncryption mode="filters">
<filters>
<filter>glob:!**/**</filter> <!-- This filter excludes everything. The purpose is to exclude all nonsensitive parts of your APK or AAB from String Encryption, as a first step before including the specific packages you intend to secure. -->
<filter>glob:com/test/**</filter> <!-- This filter includes everything within the specified package. Replace the placeholder package name with the one that you intend to secure with string encryption. -->
</filters>
</stringEncryption>
<classEncryption/> <!-- DexProtector will encrypt all classes by default, without affecting the application's performance. However, it is important to exclude any classes that must remain accessible to third parties, such as those that form part of a public API. -->
<hideAccess mode="filters">
<filters>
<filter>glob:!**/**</filter> <!-- This filter excludes everything. The purpose is to exclude all nonsensitive parts of your APK or AAB from the Hide Access mechanism, as a first step before including the specific packages you intend to secure. -->
<filter>glob:com/test/**</filter> <!-- This filter includes everything within the specified package. Replace the placeholder package name with the one that you intend to secure with the Hide Access mechanism. -->
</filters>
</hideAccess>
***
</dexprotector>
Detailed filter syntax information
Filters are determined by the syntax mode and the pattern and take the form: ‘syntax mode:pattern
’, where ':
' stands for itself. The value of the syntax component is not case-sensitive.
When the syntax mode is ‘glob
’, the pattern string representation is matched to paths using a limited pattern language that resembles regular expressions but with a simpler syntax.
For example:
.
-- Matches file names containing '.
'
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 com package.
- 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 (
\
) is used to prevent characters from being interpreted as special characters. For example, the expression\\
matches a single backslash and\{
matches a left brace. - The
[ ]
characters constitute 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, i.e.[!a-c]
matches any character except "a", "b", or "c". Within a bracket expression the*
,?
and\
characters match themselves, and therefore in this context do not have the pattern-matching effects seen above. The - character matches itself if it is either the first character within the brackets or the first character after the!
when!
is used for 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 pattern-matching operations. For example, the*
glob pattern matches file name ".login". - Placing the
!
character at the beginning of the pattern component negates the pattern.
Additional notes on filters: Resource Encryption and Annotation Encryption
Filters for Resource Encryption
For Resource Encryption, broadly the same principles apply as for the other protection mechanisms, but files can also be targeted by file pattern (i.e. *.png denotes all files of PNG file format; DexProtector will locate and encrypt all files of that type in the folder), name pattern (i.e. File1* denotes all files whose names begin with the string "File1"), by specific file name (e.g. File2.json), or by path (e.g. TestDir/File3.txt). Here is an example configuration specifically for the assets folder:
'
<resourceEncryption>
<assets>
<filters>
<filter>*.png</filter>
<filter>File1*</filter>
<filter>File2.json</filter>
<filter>TestDir/File3.txt</filter>
</filters>
</assets>
</resourceEncryption>
And another, with broader filters, targeting the assets and res folders, and strings and string arrays specified in strings.xml in resources.arsc.
'
<resourceEncryption nameObfuscation="on" webViewSupport="off">
<assets>
<filters>
<filter>glob:cert/**</filter>
</filters>
</assets>
<res>
<filters>
<filter>glob:raw/**</filter>
</filters>
</res>
<strings>
<filters>
<filter>my_api_key</filter>
<filter>glob:mobile_token*</filter>
<filter>glob:payments_**</filter>
<filter>glob:sensitive_strings_arrays_etc*</filter>
</filters>
</strings>
</resourceEncryption>
Resource Name Obfuscation
It is possible to separate filters for resource encryption from filters for resource name obfuscation, if so desired. This can be configured as follows:
'
<resourceEncryption nameObfuscation="on/off">
<res>
<filters>
<filter>res-filter-pattern-01</filter>
<filter>res-filter-pattern-02</filter>
</filters>
</res>
<nameObfuscation>
<filters>
<filter>res-name-01</filter>
<filter>res-name-02</filter>
</filters>
</nameObfuscation>
</resourceEncryption>
And the following are the permutations for the <nameObfuscation> element:
attribute ⇩ \ filter ⇨ | Empty filter | Filters specified | No filters specified |
---|---|---|---|
|
Obfuscate all names |
As per filter |
Obfuscate all names |
|
No name obfuscation |
No name obfuscation |
No name obfuscation |
No attribute specified |
Obfuscate all names |
As per filter |
No name obfuscation |
Filters for Annotation Encryption
Filters for Annotation Encryption work differently than for other mechanisms. Filters must target the classes in which annotations are defined, and not the classes in which annotations are referenced. DexProtector will then locate all instances of the annotations and encrypt them. For example:
'
<annotationEncryption>
<filters>
<filter>glob:kotlin/Metadata.class</filter>
<filter>your/own/secret/Annotations.class</filter>
<filter>other/framework/secret/Annotations.class</filter>
</filters>
</annotationEncryption>
Configuring DexProtector for applications (APK & AAB)
DexProtector's protection mechanisms work equally with APKs and AABs, and every Android element listed in the Configuration File Overview, with the exception of those within the <aar> tag, can be applied to both APKs and AABs. There are, however, some important differences between DexProtecting an APK and DexProtecting an AAB.
Firstly, to DexProtect an AAB, it is required to use Android Studio 3.2 (or higher) and (if Gradle is used), Android Gradle Plugin 3.2.0 (or higher).
Secondly, due to Google Play's requirements for app bundles, it is necessary to use Google Play App Signing for AABs that are intended for release via Google Play. That means that in the DexProtector configuration, the <signMode>
must be set to google
. If you select google
signing mode, you will also need to enter your upload key keystore information and the target certificate SHA-256 fingerprint. You can find the certificate fingerprint by going to the App Signing page of the Google Play Console: App Signing → App signing certificate → SHA-256 certificate fingerprint.
It is important to note that if your app is DexProtected with **Google Play App Signing** mode enabled, your app **must **be uploaded to and downloaded directly from Google Play (including for open, closed, or internal testing) in order to work. If Google Play Signing mode is selected in the DexProtector configuration, and the app is tested locally before being processed through Google Play, the app will be inoperable, and will crash on start-up. If you do not wish to use Google Play App signing, but do wish to publish your app to the Google Play Store, then you should use release signing mode in DexProtector. For this, see the section on Local Signing for APKs and AABs. As of August 2021, any new app published to the Google Play Store must be in app bundle (AAB) format, and must be signed via Play app signing.
Example configuration for applications (APK & AAB)
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<dexprotector>
<!-- BUILD SETTINGS -->
<verbose>true</verbose>
<optimize>false</optimize>
<securityAssessment>
<signingCertificateCompromised mode="error" />
<signingCertificateWeakKey mode="error" />
<dependencyCheck mode="warning" />
</securityAssessment>
<proguardMapFile>/Users/developer/project/proguard/mapping.txt</proguardMapFile>
<!-- SIGNING -->
<signMode>google</signMode>
<keystore>/home/developer/example.keystore</keystore>
<storepass>examplestorepass</storepass>
<alias>examplealias</alias>
<keypass>examplekeypass</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>
<!-- CODE STRIPPING -->
<stripLogging>all</stripLogging>
<stripMethodCalls>
<filters>
<filter>android.util.Log.println</filter>
</filters>
</stripMethodCalls>
<!-- CODE PROTECTION -->
<stringEncryption/>
<classEncryption/>
<hideAccess/>
<annotationEncryption/>
<nativeLibraryEncryption/>
<jniObfuscation/>
<!-- RESOURCE PROTECTION -->
<resourceEncryption nameObfuscation="on" webViewSupport="on" idObfuscationMode="auto">
<assets>
<filters>
<filter>glob:cert/**</filter>
</filters>
</assets>
<res>
<filters>
<filter>glob:raw/**</filter>
</filters>
</res>
<strings>
<filters>
<filter>my_api_key</filter>
<filter>glob:mobile_token*</filter>
<filter>glob:payments_**</filter>
<filter>glob:sensitive_strings_arrays_etc*</filter>
</filters>
</strings>
<androidManifestMangling/>
</resourceEncryption>
<!-- RASP - RUNTIME & ENVIRONMENT CHECKS -->
<runtimeChecks/> <!-- From DexProtector 12.5, it is no longer necessary to implement your own probe and callback methods. The <detect> element is deprecated. -->
<!-- NETWORK SECURITY -->
<publicKeyPinning>
<trace>0</trace>
<actions> block<!--, report--></actions>
<network-security-config>
<domain-config>
<domain includeSubdomains="true">onlinebanking.test.com</domain>
<pin-set expiration="2022-10-19">
<pin digest="SHA-256">h/QE8u3I70bpVEqNV43sttidMcKKt2wSt+j1RKJ9PKk=</pin>
</pin-set>
</domain-config>
</network-security-config>
</publicKeyPinning>
<certificateTransparency>
<trace>0</trace>
<domain includeSubdomains="false">no-sct.badssl.com</domain>
<!-- <logFile>path_to_custom_log_list_file</logFile> -->
</certificateTransparency>
<!-- THREAT REPORTING AND TELEMETRY (ALICE) -->
<reportMonitoring>
<apiKey>137feb09-f390-4f00-b43f-ebccf530adf6lt</apiKey>
<!-- <customFieldsUpdate><com.dexprotector.detector.envchecks.AliceCustomizer.update'CustomFields></customFieldsUpdate> -->
<trace>0</trace>
</reportMonitoring>
</dexprotector>
Configuring DexProtector for libraries and SDKs (AAR)
Most of DexProtector’s protection mechanisms can also be applied to Android libraries (AARs), but there are some differences, and certain features must be configured differently from how they are configured for APKs and AABs.
The most important differences between configuring DexProtecting an application package and DexProtecting an AAR concern:
- Initialization
- Kotlin
- Protection of Public APIs
Initialization
Since DexProtector's runtime engine must start before the AAR is first accessed, it is necessary to configure the initialization process, and/or to leave DexProtector's auto-initialization mechanism enabled.
To ensure that DexProtector's runtime engine is initialized when necessary, the autoInit mechanism uses a Content Provider approach, and defines a content provider component in the AndroidManifest.xml. Therefore, if autoInit="on" we strongly recommend to specify autoInitAuthorities="${applicationId}", additionally specifying a unique ID for each AAR where necessary, to avoid the risk of conflict whereby multiple content providers with the same name are specified in android:authorities.
<aar autoInit="on" autoInitAuthorities="${applicationId}" />
We strongly recommend to leave autoInit="on", but if you prefer to set autoInit="off" you must specify either initMethod(s) and/or initClass(es). For example:
<aar autoInit="off" >
<initMethod>com.sample.Lib.initMethod</initMethod>
<initClass>com.sample.MyReceiver</initClass>
</aar>
Kotlin
If your AAR contains Kotlin classes, this needs to be specified in the configuration file (whereas it does not for APKs). The reason is that AARs are compiled to Java bytecode rather than Dalvik bytecode, so must be processed differently by DexProtector's native engines. Simply specify the kotlinSupport attribute within the <aar>
element, as follows:
<aar kotlinSupport="on" />
Protection of Public APIs
It is vital when protecting AARs to specify filters for Class Encryption in such a way that public API classes are not encrypted.
Example configuration for libraries & SDKs (AAR)
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<dexprotector>
<!-- BUILD SETTINGS -->
<verbose>false</verbose>
<optimize>false</optimize>
<proguardMapFile>/Users/developer/project/proguard/mapping.txt</proguardMapFile>
<!-- AAR PARAMETERS -->
<aar autoInit="on" autoInitAuthorities="${applicationId}" kotlinSupport="on" />
<!-- CODE STRIPPING -->
<stripLogging>all</stripLogging>
<stripMethodCalls>
<filters>
<filter>android.util.Log.println</filter>
</filters>
</stripMethodCalls>
<!-- CODE PROTECTION -->
<stringEncryption>
<filters>
<filter>glob:!**/**</filter>
<filter>glob:com/test/**</filter>
</filters>
</stringEncryption>
<classEncryption/>
<hideAccess>
<filters>
<filter>glob:!**/**</filter>
<filter>glob:com/test/**</filter>
</filters>
</hideAccess>
<nativeLibraryEncryption>
<filters>
<filter>libsome.so</filter>
</filters>
</nativeLibraryEncryption>
<jniObfuscation>
<filters>
<filter>glob:com/sample/NativeLibrary.class</filter>
</filters>
</jniObfuscation>
<!-- RESOURCE PROTECTION -->
<resourceEncryption>
<assets>
<filters>
<filter>glob:cert/**</filter>
</filters>
</assets>
</resourceEncryption>
<!-- RASP - RUNTIME & ENVIRONMENT CHECKS -->
<runtimeChecks/> <!-- From DexProtector 12.5, it is no longer necessary to implement your own probe and callback methods. The <detect> element is deprecated. -->
<!-- NETWORK SECURITY -->
<publicKeyPinning>
<trace>0</trace>
<actions> block<!--, report--></actions>
<network-security-config>
<domain-config>
<domain includeSubdomains="true">onlinebanking.test.com</domain>
<pin-set expiration="2022-10-19">
<pin digest="SHA-256">h/QE8u3I70bpVEqNV43sttidMcKKt2wSt+j1RKJ9PKk=</pin>
</pin-set>
</domain-config>
</network-security-config>
</publicKeyPinning>
<certificateTransparency>
<trace>0</trace>
<domain includeSubdomains="false">no-sct.badssl.com</domain>
<!-- <logFile>path_to_custom_log_list_file</logFile> -->
</certificateTransparency>
<!-- THREAT REPORTING AND TELEMETRY (ALICE) -->
<reportMonitoring>
<apiKey>137feb09-f390-4f00-b43f-ebccf530adf6lt</apiKey>
<!-- <customFieldsUpdate><com.dexprotector.detector.envchecks.AliceCustomizer.update'CustomFields></customFieldsUpdate> -->
<trace>0</trace>
</reportMonitoring>
</dexprotector>
App Signing
Signing your app is a vital part of making it secure against tampering and cloning. For the strongest possible anti-tampering protection and integrity control, DexProtector uses a range of parameters to build a cryptographic chain of trust, and an app’s signing certificate information is an important link in that chain.
As a result, if a bad actor tries to re-sign a DexProtected application, the cryptographic chain of trust will be broken and the app will simply stop working. Every new version of your app must therefore be re-protected using DexProtector, and re-signed before release.
DexProtector checks the strength and integrity of the signing certificate as part of its Security Assessment; we strongly recommend a signing certificate with a key strength of at least 2048 bits, and DexProtector is set by default so that an app with a weaker or compromised signing certificate will not be processed, leading to an error message.
Your choice of signing mode will depend on your stage in the build cycle, and whether you are protecting an APK, an AAB, or an AAR. DexProtector therefore supports various signing modes, including both Google Play App Signing and Amazon Appstore Signing, either of which can be entered as the signMode
in the DexProtector configuration file, or selected via DexProtector Studio. The signMode
value can be set as google
, amazon
, debug
, release
, or none
. See below for guides to each signing mode.
Cloud Signing (Google Play App Signing; Amazon Appstore)
Google Play App Signing
You will need to use the google
signing mode if your app is or will be published on the Google Play Store and you use app signing by Google Play, with Google managing your app signing key and using it to sign your APKs when they are distributed.
If you select google
signing mode, you will also need to enter your upload key and the certificate fingerprint of the target certificate’s SHA-256. You can find the certificate fingerprint by going to the App Signing page of the Google Play Console: App Signing -> App signing certificate -> SHA-256 certificate fingerprint.
It is important to note that with Google Play App Signing, you **must** use `google` signing mode in DexProtector, and once an app has been protected using `google` sign mode, it will *only* become functional when it has been **uploaded to and downloaded directly from Google Play**. This is because the app must be signed on Google servers with the expected App Signing Key, corresponding to the SHA-256 Certificate Fingerprint specified in the DexProtector configuration. If you try to run the app locally or with a testing service *without* first uploading it to and downloading it from Google Play, it will crash. If you wish to test an app that has been DexProtected with `google` signing mode, you must do so via the Play Console.
To configure google
signing mode, follow these instructions:
- In the configuration file (
dexprotector.xml
), entergoogle
as thesignMode
value
<signMode>google</signMode>
- Add the SHA-256 Certificate Fingerprint for the App Signing Key you have previously generated for this app through Google Play:
<sha256CertificateFingerprint>PUT_YOUR_VALUE_HERE</sha256CertificateFingerprint>
- Enter the keystore-related information to the configuration file (if you use the DexProtector Gradle plugin, this information will be taken automatically from the
signingConfig
).- keystore - The path to the keystore containing the Upload Key used to generate the App Signing Key
- storepass - password for the keystore
- alias - key alias
- keypass - password for the key
For example:
'
<dexprotector>
...
...
<signMode>google</signMode>
<keystore>/Users/developer/keystores/upload.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>
And if you use Gradle, please be sure to add a new buildType/productFlavor specifically for Google Play publication, as it will not work for other stores, or for direct distribution.
Amazon Appstore Signing
You will need to use the amazon
signing mode if your app is or will be published on the Amazon Appstore.
When you submit your app, Amazon removes the signature you used to sign your app and re-signs it with an Amazon signature that is unique to you, does not change, and is the same for all apps in your account.
Therefore, if you select amazon
signing mode, you will also need to enter the target certificate’s SHA-256 fingerprint. This hash can be found in the Appstore Certificate Hashes section of the Amazon Developer Console.
It is important to note that with Amazon Appstore Signing, you **must** use `amazon` signing mode in DexProtector, and once an app has been protected using `amazon` sign mode, it will *only* become functional when it has been **uploaded to and downloaded directly from Amazon Appstore**. This is because the app must be signed on Amazon servers with the expected Amazon signature, corresponding to the SHA-256 Certificate Fingerprint specified in the DexProtector configuration. If you try to run the app locally or with a testing service *without* first uploading it to and downloading it from the Amazon Appstore, it will crash.
To configure amazon
signing mode, follow these instructions:
- In the configuration file (
dexprotector.xml
), enteramazon
as thesignMode
value
<signMode>amazon</signMode>
- Add the SHA-256 Certificate Fingerprint for the Amazon signature:
<sha256CertificateFingerprint>PUT_YOUR_VALUE_HERE</sha256CertificateFingerprint>
For example:
'
<dexprotector>
...
...
<signMode>amazon</signMode>
<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>
And if you use Gradle, please be sure to add a new buildType/productFlavor specifically for Amazon publication, as it will not work for other stores, or for direct distribution.
Signing for System Apps and Pre-Installed Apps
For system apps and pre-installed apps, for which app signing is managed by the platform or vendor, the signing mode depends on whether you have access to the platform signing key.
If you have access to the key, then set <signMode>release</signMode>
and complete all of the other signing-related tags as you would for your own private key:
'
<signMode>release</signMode>
<keystore>/Users/developer/keystores/production.keystore</keystore>
<storepass>android</storepass>
<alias>android</alias>
<keypass>android</keypass>
If you do not have access to the key, then set <signMode>none</signMode>
and, after asking for the signing certificate file from the platform vendor, add the path to the certificate using the <certificate> tag as follows:
'
<signMode>none</signMode>
<certificate>/home/developer/vendor.cert</certificate>
Local Signing for APKs
If you wish to sign an APK locally (either because it is intended for direct distribution, or because it is an update for an older app), and are therefore not using Google Play App Signing and not submitting the app to the Amazon Appstore, simply select <signMode>release</signMode>
and also specify the keystore, keystore password, key alias, and key password:
'
<signMode>release</signMode>
<keystore>/Users/developer/keystores/production.keystore</keystore>
<storepass>android</storepass>
<alias>android</alias>
<keypass>android</keypass>
-
1. What is DexProtector?
Introduction to DexProtector > 1. What is DexProtector? -
2. The DexProtector process
Introduction to DexProtector > 2. The DexProtector process -
3. DexProtector Studio
Introduction to DexProtector > 3. DexProtector Studio -
4. Alice - Licel’s Attack Telemetry and Threat Intelligence System
Introduction to DexProtector > 4. Alice - Licel’s Attack Telemetry and Threat Intelligence System -
Overview
DexProtector for Android > Overview -
1. Download
Getting started > 1. Download -
2. Activate
Getting started > 2. Activate -
Activate via CLI (online)
Getting started > Activate via CLI (online) -
Activate via CLI (offline)
Getting started > Activate via CLI (offline) -
Activate via DexProtector Studio (online)
Getting started > Activate via DexProtector Studio (online) -
Activate via DexProtector Studio (offline)
Getting started > Activate via DexProtector Studio (offline) -
3. After activation
Getting started > 3. After activation -
Introduction to configuring DexProtector
Configuring DexProtector > Introduction to configuring DexProtector -
Configuration file overview
Configuring DexProtector > Configuration file overview -
Filters: A guide to targeting code and resources
Configuring DexProtector > Filters: A guide to targeting code and resources -
Inclusion
Configuring DexProtector > Inclusion -
Protecting every class in a specified package
Configuring DexProtector > Protecting every class in a specified package -
Protecting a single class
Configuring DexProtector > Protecting a single class -
Exclusion
Configuring DexProtector > Exclusion -
Excluding every class in a specified package from protection
Configuring DexProtector > Excluding every class in a specified package from protection -
Excluding a single class from protection
Configuring DexProtector > Excluding a single class from protection -
Mixed filters: Combining inclusion and exclusion
Configuring DexProtector > Mixed filters: Combining inclusion and exclusion -
Detailed filter syntax information
Configuring DexProtector > Detailed filter syntax information -
Additional notes on filters: Resource Encryption and Annotation Encryption
Configuring DexProtector > Additional notes on filters: Resource Encryption and Annotation Encryption -
Configuring DexProtector for applications (APK & AAB)
Configuring DexProtector > Configuring DexProtector for applications (APK & AAB) -
Example configuration for applications (APK & AAB)
Configuring DexProtector > Example configuration for applications (APK & AAB) -
Configuring DexProtector for libraries and SDKs (AAR)
Configuring DexProtector > Configuring DexProtector for libraries and SDKs (AAR) -
Initialization
Configuring DexProtector > Initialization -
Kotlin
Configuring DexProtector > Kotlin -
Protection of Public APIs
Configuring DexProtector > Protection of Public APIs -
Example configuration for libraries & SDKs (AAR)
Configuring DexProtector > Example configuration for libraries & SDKs (AAR) -
App Signing
Configuring DexProtector > App Signing -
Cloud Signing (Google Play App Signing; Amazon Appstore)
Configuring DexProtector > Cloud Signing (Google Play App Signing; Amazon Appstore) -
Google Play App Signing
Configuring DexProtector > Google Play App Signing -
Amazon Appstore Signing
Configuring DexProtector > Amazon Appstore Signing -
Signing for System Apps and Pre-Installed Apps
Configuring DexProtector > Signing for System Apps and Pre-Installed Apps -
Local Signing for APKs
Configuring DexProtector > Local Signing for APKs -
DexProtector Gradle Plugin
Implementations and Integrations > DexProtector Gradle Plugin -
DexProtecting Hybrid and Cross-Platform Applications (React Native, Ionic, NativeScript, Cordova, Xamarin, Flutter)
Implementations and Integrations > DexProtecting Hybrid and Cross-Platform Applications (React Native, Ionic, NativeScript, Cordova, Xamarin, Flutter) -
JavaScript and HTML-based Hybrid and Cross-Platform Apps
Implementations and Integrations > JavaScript and HTML-based Hybrid and Cross-Platform Apps -
Xamarin
Implementations and Integrations > Xamarin -
Flutter
Implementations and Integrations > Flutter -
Overview
DexProtector Studio > Overview -
Using DexProtector Studio: DexProtector JAR and License File
DexProtector Studio > Using DexProtector Studio: DexProtector JAR and License File -
Managing DexProtector JAR and License File
DexProtector Studio > Managing DexProtector JAR and License File -
Activating your license via Studio (online)
DexProtector Studio > Activating your license via Studio (online) -
Activating your license via Studio (offline)
DexProtector Studio > Activating your license via Studio (offline) -
Protecting your APK, AAB, or AAR with DexProtector Studio
DexProtector Studio > Protecting your APK, AAB, or AAR with DexProtector Studio -
Protection Recommendations
DexProtector Studio > Protection Recommendations -
Load Package for Protection
DexProtector Studio > Load Package for Protection -
Manage Protection Settings
DexProtector Studio > Manage Protection Settings -
Run Protection and View Protection Results
DexProtector Studio > Run Protection and View Protection Results -
Final Checklist
Completing the DexProtector Process > Final Checklist -
Run DexProtector via the CLI
Completing the DexProtector Process > Run DexProtector via the CLI -
Run DexProtector via DexProtector Studio
Completing the DexProtector Process > Run DexProtector via DexProtector Studio -
Using Alice with DexProtector
Alice - Threat Reporting and Telemetry > Using Alice with DexProtector -
General FAQs - DexProtector for Android
FAQs > General FAQs - DexProtector for Android -
FAQs on Installation, Activation, Configuration, and Distribution
FAQs > FAQs on Installation, Activation, Configuration, and Distribution
Link copied!