DashO 10 is now available, with support for R8. Migration to DashO is now easier than ever!
Over the past year, we have seen an influx of developers looking to replace existing ProGuard and DexGuard implementations with DashO. While the three products are conceptually similar, we have found that there are important differences between the products, and those differences can lead to unexpected migration issues. This article summarizes many of the tips and techniques our support team has been refining, to shorten your learning curve and simplify your migration.
This article:
At first glance, the three products offer a common set of features. All three:
-keep
rules in ProGuard), exclusions, and detailed settings to fine-tune behavior.However, there are important differences within these common feature categories.
Platform support: DexGuard is Android-only, while ProGuard and DashO both work on many types of Java applications (including Android). Developers cannot select DexGuard for non-Android applications.
Feature support: DashO and DexGuard offer a significantly broader collection of protection controls than does ProGuard. Users migrating from ProGuard will have new protection controls to evaluate, activate, and configure.
Development patterns: Many DexGuard features are API-based, and as such, require app code changes or additions. DashO is able to inject the corresponding features post-compile, without additional app development. (Note that DashO can also inject custom code, to support app-specific behavior.)
Configuration complexity: DashO includes a sophisticated GUI that serves as the primary configuration interface. The GUI loads bytecode, shows class trees to help configure inclusions and exclusions, and has built-in rules to prevent “illegal” configurations.
DashO’s GUI also includes a Project Wizard that automates much of the work of configuring a new project.
ProGuard and DexGuard only support text-based configuration. The available GUIs are little more than structured text editors, and do not include a Project Wizard. Developers have to rely on copying examples and manually entering names, which is error prone.
Pre-built Android SDK integration: ProGuard is built into the Android SDK, and some of the initial ProGuard configuration is automatic, for Android. DashO and DexGuard are independent tools that must be integrated into the build process.
ProGuard’s Gradle docs (i.e. those published by GuardSquare) recommend integrating ProGuard into an Android build via a custom Gradle task. This it not a common Gradle integration pattern. (It is more typical of build systems like Ant.)
Android’s ProGuard docs (i.e. those published by Google) say “just turn it on”. This is feasible because ProGuard is distributed as part of Google’s Android Gradle plugin, and ProGuard is configured to work like a typical Gradle plugin.
Either approach can work, but “the Gradle way” is to integrate as a plugin. This article assumes that you have followed the Android instructions accordingly.
DashO can also be integrated either way, but it is optimized to be used as a plugin, and that’s the approach this article describes.
This article is based on DashO v8.5.0 and DashO Gradle Plugin v3.1.0. Please use those versions, or newer. Note that upgrading to DashO Gradle Plugin v3.1 might require upgrading the Android Gradle plugin version to v3.1.
In general, you should use the latest available version of DashO and of DashO Gradle Plugin. We continuously optimize and extend both components to improve protection, integration, and ease of use.
This article focuses on migrating an Android application, but the ideas presented here are applicable to migrating Android libraries or non-Android (e.g. desktop) applications, too.
We’ll start by focusing on ProGuard. Most of the details are the same for DexGuard; we’ll cover DexGuard-specific issues later.
To integrate ProGuard into an Android app, the usual approach is to:
build.gradle
per the documentation.-keep
rules, etc.).DashO’s process is different because it has a New Project Wizard that can identify and auto-configure many parts of DashO, specifically for your app. It will also integrate DashO into your Gradle build for you.
DashO integrates into Android’s Gradle plugin in place of ProGuard. This approach simplifies the build integration by e.g. ensuring that up-to-date checking works correctly. Therefore, the first step of integrating DashO is to remove the ProGuard configuration.
To migrate from ProGuard to DashO, use this process:
minifyEnabled
statements (DashO will put new ones in) and any proguardFiles
(or proguardFile
) statements.repositories
or dependencies
sections; if so, remove them.proguard-rules.pro
) from source control.settings.gradle
).build/intermediates/classes/<flavor>/<type>
). If the Wizard also found additional .jar
files (e.g. from your project’s libs/
directory), please Remove those, to make the initial configuration simpler. (DashO will still find them and use them, if they are needed, even if we remove them now.)dasho.gradle
file (that the Wizard created for you, in your app directory) and add transformName = 'proguard'
to the dashOConfig
closure. (The DashO Wizard will configure DashO to generate a ProGuard-compatible map file, which Crashlytics will automatically pick up and use, but the Crashlytics Gradle plugin will generate an error if minifyEnabled
is true but it can’t find a build task named “proguard”. This change works around that error.)-keep
), it might help to review those rules and migrate them to your DashO config. See the table below for details.You can see an example of how the Wizard will modify your Gradle build in the obfuscated
branch of our DashO-GameOfLife sample on GitHub. Specifically, the Wizard will:
flatDir
repository in the root build.gradle
.classpath
in the root build.gradle
.dasho.gradle
file that contains (and isolates) the DashO-specific Gradle configuration.apply from
line to the application’s build.gradle
, pulling in the configuration from dasho.gradle
.project.dox
) to the application directory and configure it according to the choices made in the Wizard. (Flavor-specific config files will have flavor-specific names.)When integrating into a highly-customized build, the Wizard might error while trying to update build.gradle
. In such cases, the Wizard will still configure as much as it can, but check the list above to see if anything is missing. You can also refer to our troubleshooting section below for further resources.
At this point, DashO is integrated and the app has an higher level of protection than it had with ProGuard. Notably, DashO has Control Flow and String Encryption and they are enabled by default.
From here, there are two primary ways you can further improve the level of protection.
First, convert some or all of your libraries to be inputs so they will be obfuscated as well.
For Android Gradle projects, the Inputs are managed by Gradle (and are passed to DashO via the ${gradleInputs}
property), so input configuration is done on the Gradle side via the includeAsInputs
array in the dashOConfig
closure in dasho.gradle
. (There are also some shorthand ways to specify libraries, for Android.)
By default, the Wizard configures your primary application as the only input. Your in-house libraries, and any third-party libraries, will be configured as support libraries. (i.e. the includeAsInputs
array will be unspecified, or empty.)
This makes it easier to get started, and you should keep this configuration until you have your build working. Then, to improve protection, convert your libraries over to be inputs (i.e. list them in the includeAsInputs
array), so they are obfuscated as well.
Second, start using DashO’s advanced features, most notably, Checks. Checks are code that DashO injects into your app, during the build, that detect certain conditions (e.g. whether the app has been tampered) and can either call custom code that you specify, or automatically perform certain actions (e.g. throw a random exception). Checks can also call custom code that you develop, to respond in application-specific ways.
Checks provide run-time security to better protect your app against tampering, unauthorized inspection, and reverse engineering. These controls extend app security beyond the app itself, to the data that flows through the app as it runs. Checks are a powerful way to prevent, detect, and defend against counterfeiting, malware insertion, data theft, piracy, vulnerability analysis, and more.
As of this writing, DashO includes four Checks for Android:
To integrate Checks, use the Injection section of the user interface, and/or see the documentation for help.
There are a few common situations that might come up during or after the initial Wizard integration, and a few frequently-used techniques that can help sort them out.
First, don’t hesitate to take advantage of the fact that DashO users always have access to our world-class support team. We’d be happy to help you with any issues you have during your migration.
Second, make sure you are using the correct version of DashO, DashO Gradle Plugin, and Android Gradle Plugin.
Third, make sure your Inputs are configured correctly.
Check (in the DashO UI, on the Inputs page) that the only DashO input is ${gradleInput}
. Remove any additional values, and (if desired) configure those inputs via includeAsInputs
, per above.
If DashO is still reporting errors about missing classes or methods, you can try enabling Ignore Missing Classes and/or Ignore Missing Methods on the Input – Options screen.
Fourth, review the Entry Points to be sure they are correct. (Note that additional Entry Points may be shown on the Special Classes screen.) Entry Points are the places where your application is called by the operating system (i.e. Android), or by any code reflection. DashO needs to know about all entry points to ensure it doesn’t remove or rename things that are referenced by name at run-time.
Most entry points will be automatically discovered by the Wizard, but any that are missed will cause run-time issues. If you have any manually-configured -keep
rules in your ProGuard configuration, they might need to be manually converted to entry points in DashO.
Fifth, if you have any ProGuard rules that use the implements
or extends
keywords to match a set of subclasses, you will need to configure each matched class individually in DashO. DashO does not (as of this writing) have a corresponding way to configure a group of related entry points all at once.
Sixth, try enabling verbose mode in the DashO Gradle plugin. You can also run gradle with -DSHOW_DASHO_CMD
to see additional detail about how DashO Gradle Plugin calls DashO.
Finally, our Gradle plugin has detailed Troubleshooting documentation that can help with any Gradle-specific error messages you are seeing. (For general DashO build errors, please refer to the DashO User Guide.)
Most of the guidance from the ProGuard migration process applies to migrating from DexGuard, but there are a few important additional details.
First, DexGuard’s Gradle configuration is typically more complex, so removing it typically requires more work:
build.gradle
):flatDir
repository reference to the DexGuard install directory.classpath
dependency reference to the DexGuard plugin.apply plugin: 'dexguard'
line.Second, some of DexGuard’s advanced features (e.g. custom encryption, or DexGuard’s versions of DashO’s Checks) depend on extra libraries that must be integrated into your project, and on extra code that you write into your application. Removing those libraries and that additional code requires additional work:
Third, as with ProGuard, DexGuard does not include Control Flow obfuscation and does not turn String Encryption on by default. DashO includes both, and they are on by default (for Android).
Finally, as before, configure Checks in DashO. In this case, however, you might be able to reuse any custom response code that you wrote for DexGuard by configuring DashO to call it when Checks are triggered.
The following table will help you map your ProGuard or DexGuard settings to DashO:
ProGuard option | Corresponding DashO feature |
---|---|
-adaptresourcefilecontents | DashO automatically identifies and updates resource file references as needed. |
-dontoptimize | Disable optimization globally or for particular packages, classes, or methods. |
-injars | For Android projects, this is handled automatically but can be customized via includeAsInputs in the Gradle configuration. Non-Android projects configure Inputs in DashO. |
-keep | Entry Points, possibly configured as Android Special Classes for Android apps. The Wizard will usually find and configure these. |
-keepattributes | Configure which attributes should be removed or preserved. The Wizard will usually configure these appropriately. |
-keepclassmembers | This does not directly translate, but can be approximated. Configure a Renaming exclusion and uncheck Selects Class. You can also configure a Removal exclusion but that will preserve the class as well. |
-keepnames | Configure a Renaming exclusion. |
-libraryjars | For Android projects, this is handled automatically but can be customized via includeAsInputs in the Gradle configuration. Non-Android projects configure Inputs (as support libraries) in DashO. |
-overloadaggressively | The Overload Induction option for Renaming is on by default. |
-repackageclasses | Configure package flattening. |
-verbose | Enable verbose output. |
We are always interested in feedback from our users. If you have any feedback about this process (good or bad!), we’d love to hear it. Please reach out to our support team or sales team with your questions and comments.
And welcome to DashO!
DexGuard and GuardSquare are trademarks of GuardSquare NV.