Troubleshooting

XTD Protect for Android: Command Line Tools

Collecting troubleshooting information

The artifacts extracted during protection builds, along with debug logs of the tools, are archived in ZIP files under the current working directory. Filenames are:

  • apkdefender: <app-ID>-protect-build-artifacts.zip
  • aardefender: <sdk-name>-build-artifacts.zip
  • aabdefender: <app-ID>-protect-build-artifacts.zip

Application already protected

Problems in protecting an APK may be caused by the APK already being protected with XTD Protect or with another security tool. Interoperability with security tools is not guaranteed or supported by default, but a workaround may be attempted by excluding any potentially problematic packages with the exclude_packages option in the configuration JSON file.

Asset encryption is failing

Asset encryption feature requires that the decryption hooks are injected to all asset manager calls. The hooks can only be injected to translated code. Therefore, if there are any calls to the asset manager in the parts of code that are non-translatable, or are excluded from translation by the user, asset encryption feature must be narrowed down by explicitly blacklisting any problematic assets with the exclude_assets configuration option. For example use of reflection, or asset usage in the native code will cause decryption failures. Generally, the simpler and recommended solution is to work from the opposite direction and whitelist any sensitive assets that need to be encrypted with the include_assets configuration option.

Resource string encryption is failing

In some cases resource encryption may cause problems at runtime due to nested resources that could not be decrypted. Such decryption problems may typically cause display of base64-encoded garbage strings in the user interface, or cause obscure resource inflate errors showing base64-encoded garbage identifiers in the logcat stack traces.

To work around such problems, identify any such problematic resource string identifiers, and use exclude_strings option in the configuration JSON file to exclude them from resource encryption. Alternatively, the resource encryption feature can be turned off by setting the enable_resource_encryption option to false.

Please note also that if the application has used resource string encryption feature, the Android instrumentation test cases should not access string resources by using the R.id.<resource-id> mapping. The resource string decryption funtionality will be available only in the application, and thus only encrypted strings would be visible to the instrumentation test APK when accessing string resources via R.id.<resource-id>.

Android runtime issues

Identifying the problematic packages, classes, or methods is a very effective way of resolving Android runtime issues. If a runtime error occurs when a protected build is run, the Android logcat output usually helps to locate the problem. The failing translated function can often be identified with the ndk-stack tool from the build artifacts:

$ANDROID_NDK/ndk-stack -sym <app-id>-protect-build-artifacts/symlibs/<abi>/ -dump <path-to-logcat-output-file>

With the mapping in the protection_coverage.json file it is then possible to find the original problematic Java method. A good way to start investigating the problem is by excluding a whole package, a class, or a method that according to the logcat output is causing the runtime problem. Repeat this procedure by excluding more packages/classes/methods until the runtime errors disappear.

Alternatively, resolving Android runtime problems can be attempted by incrementally including packages to the protection scope, until the problematic package is identified. Once such a package is identified, the exclusion can be refined to classes, or even methods. This technique can also be employed if the logcat does not present any plausible targets for exclusion. Please refer to the Defining the Protection Scope section for more details.

Comparison by reference

Java string comparison must not be done by reference instead of value. Comparing by reference does not work correctly, when the string is removed from the bytecode and replaced by native lookup call.

WeakHashMap

Using WeakHashMap implementation of Map interface may result in a situation, where after translation process there are no longer any strong references to the Map keys on the bytecode side. When the key is used from the native side, a new string is always allocated with JNI, and there is no reference to the existing key string. In this case the garbage collector may remove the corresponding entry from the WeakHashMap. Therefore, inability to collect a value from WeakHashMap should enforce re-retrieval of the data that was stored to the Map. It should not lead to a different code execution path.

To avoid this situation, use of WeakHashMap is not recommended, regular HashMap should be used instead.

apkdefender fails with certificate fingerprint mismatch error

If a keystore configuration is given in the configuration JSON file to automatically generate a locally signed, protected APK, the signing key certificate must match the one that is given as the signing_certificate option. Otherwise the signing certificate binding verification would fail at runtime.

installer.pkg requires root privileges

When installing apkdefender tools from the installer.pkg package in macOS with the graphical native installer, the installer may require a root password, and then install the binaries with incorrect access rights. This is a known platform bug. As a workaround, the apkdefender tool can be installed via command line. The issue is not present, if command line is used.

Installing with the graphical native installer may also be succesful, if the package is moved away from the Downloads directory.

enable_wipe_string_fields does not wipe String arrays

For string arrays Java compiler will generate the initialization code into the class static initializer block, which cannot be translated into native. This prevents wiping of the String array.

To wipe the content of a String array, a getter method can be used. Then Java compiler will simply insert a method call into the class static initializer block, and the method populating the String array can later be translated to native code. After translation, content of the array initializer method is empty in the final protected DEX bytecode.

public static final String[] GOOD = getGoodData();
static String[] getGoodData()
{
    return new String[]{"foo", "bar"};
}

Protection seems to progress very slowly

The protection process requires creating a large number of temporary files in the system, and sometimes this process is slowing down because of other software, for example an antivirus solution, is opening and scanning the temporary files. This can be avoided by configuring the working directory to a location that is excluded from the virus scans.

apkdefender -c <path-to-configuration-file-w <path-to-location-excluded-from-scanapp-release.apk

Warning messages

These warning messages may be displayed during protection:

Warning messageExplanation
AABs with dynamic feature modules cannot be used with DEX encryptionThis warning is displayed when dex_encryption_mode is set to enforce and the input AAB file contains dynamic feature modules
The debugger detection feature might not work with some native libraries in the application. To enable the anti-debug feature, please configure it using either the apkdefender configuration or the Verimatrix native code protection tool.The unprotected application includes native libraries that have been secured using the Verimatrix native code protection tool. If these protected native libraries have enabled the anti-debug feature, there may be a conflict with the apkdefender debugger detection functionality.
The application appears to be protected by another security tool. Proceeding may cause problems.The unprotected application may have undergone processing by a third-party code protection tool. This could potentially lead to runtime issues with the protected application.
0 methods in 0 target classes converted to native code.No bytecode methods were translated to native code, which may suggest an issue with the protection scope configuration.
Applications targetSdkVersion "35" higher than the installed Android SDK build tools version "34". Please consider updating Android SDK build tools.The Android SDK build-tools version is older than the target SDK version of the unprotected application. To resolve this, please install the latest Android SDK build-tools component.
DEX encryption feature requires minsdk >= 26 when application uses isolated processes.dex_encryption_mode is set to enforce and the unprotected application uses services with the isolatedProcess attribute set to true. To resolve this, please update the application's minSdk to API level 26.
Feature enable_dex_encryption requires minsdk >= 24dex_encryption_mode is set to enforce and the application's minSdk is lower than the required API level 24. To resolve this, please update the application's minSdk to API level 24.
Loader classes contain OS classes:dex_encryption_mode is set to enforce and the application contains bytecode with conflicting classes from the Android OS. The names of one or more conflicting classes will be displayed.
DexFile usage found:dex_encryption_mode is set to enforce and the application contains bytecode that uses the Android DexFile API. The usage of the DexFile API suggests that the application may not be compatible with the encrypted bytecode.
Not applying overlay protection to <ActivityName>. Existing bytecode method incompatible.Overlay protection cannot be applied to the reported Activity due to the inability to patch the existing dispatchTouchEvent method. The protected application will run, but no overlay detection is performed.
Failed to find <ActivityName> from bytecode for overlay protection.Overlay protection cannot be applied because the Activity class is not found in the bytecode. This may be due to the Activity class being part of an AAB dynamic feature. The protected application will run, but no overlay detection is performed.
No overlay hooks appliedOverlay protection could not be applied. No activities were found, or the include_overlays configuration in protection_scope may be misconfigured. The protected application will run, but no overlay detection is performed.
The product license expires in <number> days (<date>)This message is displayed when the product license expiry date is less than one month away. Please contact Verimatrix customer support to update the license.
No matches for include filters:An include filter in the configuration does not yield any matches. A list of include filter entries that do not yield any matches is displayed. Please verify that the package names are spelled correctly.
Could not parse SDK build tool directory: <directory-name>An invalid Android SDK build-tools directory has been detected. The expected format of the build-tools directories look like "35.0.0".
InterruptedThe user interrupted the protection tool process using Ctrl+C.
Failed to generate reportThe efficacy report JSON file could not be saved to disk.
Xamarin assembly exclusion configured, but no assemblies were filtered based on it.This message is displayed when a Xamarin assembly exclusion in the configuration does not yield any matches.