Sunday, July 3, 2011

Android - securing the app, 1 - obfuscation with proguard

Ok, we've seen reports of how easy it is to pirate android apps, how nobody pays for them, how they are even being repackaged and sold by unscrupulous piraters as their own product on asian web sites.

So, the question is, how to best secure the application? The in-app-billing mentioned a number of measures that could be taken. One of these, obfuscating the code, seems like it could be pretty easy. Others, such as call methods with reflection, are probably worth it only for sensitive areas such as in-app-billing. Another one, encrypting multimedia files, is something I'm interested in but not sure if it's worth it.

Ok, first, there is code-obfuscation. While this won't prevent copying, it will help to prevent decompilation of source code, and repackaging for sale.

Here's the entry on code-obscation:

Obfuscate your code

You should obfuscate your in-app billing code so it is difficult for an attacker to reverse engineer security protocols and other application components. At a minimum, we recommend that you run an obfuscation tool like Proguard on your code.

In addition to running an obfuscation program, we recommend that you use the following techniques to obfuscate your in-app billing code.

Inline methods into other methods.
Construct strings on the fly instead of defining them as constants.
Use Java reflection to call methods.
Using these techniques can help reduce the attack surface of your application and help minimize attacks that can compromise your in-app billing implementation.

Note: If you use Proguard to obfuscate your code, you must add the following line to your Proguard configuration file:

-keep class com.android.vending.billing.**

Let's follow the progaurd link:

ProGuard
In this document
Enabling ProGuard
Configuring ProGuard
Decoding Obfuscated Stack Traces
Debugging considerations for published applications
See also
ProGuard Manual »
ProGuard ReTrace Manual »

The ProGuard tool shrinks, optimizes, and obfuscates your code by removing unused code and renaming classes, fields, and methods with semantically obscure names.

The result is a smaller sized .apk file that is more difficult to reverse engineer.

Because ProGuard makes your application harder to reverse engineer, it is important that you use it when your application utilizes features that are sensitive to security like when you are Licensing Your Applications.

// Ok, I don't have any really "sensitive" areas yet; except for maybe the part that specifies the free amount.

ProGuard is integrated into the Android build system, so you do not have to invoke it manually. ProGuard runs only when you build your application in release mode, so you do not have to deal with obfuscated code when you build your application in debug mode. Having ProGuard run is completely optional, but highly recommended

// Hmmm..I think I usually build it in release mode.

This document describes how to enable and configure ProGuard as well as use the retrace tool to decode obfuscated stack traces.

// Oh, so the stack trace is also a hassle. Hmmm...

Enabling ProGuard

When you create an Android project, a proguard.cfg file is automatically generated in the root directory of the project.


This file defines how ProGuard optimizes and obfuscates your code, so it is very important that you understand how to customize it for your needs.

The default configuration file only covers general cases, so you most likely have to edit it for your own needs.

See the following section about Configuring ProGuard for information on customizing the ProGuard configuration file.

// ok

To enable ProGuard so that it runs as part of an Ant or Eclipse build, set the proguard.config property in the /default.properties file. The path can be an absolute path or a path relative to the project's root.

If you left the proguard.cfg file in its default location (the project's root directory), you can specify its location like this:

proguard.config=proguard.cfg

You can also move the the file to anywhere you want, and specify the absolute path to it:

proguard.config=/path/to/proguard.cfg

// Ok.

Ok, let's start with the default location. Add that line to default.properties

Ok. Next?

When you build your application in release mode, either by running ant release or by using the Export Wizard in Eclipse, the build system automatically checks to see if the proguard.config property is set.

// Ah, ok. So, I don't have to worry about it in development. But it might make it more difficult to debug a dump I get from
// someone else.

If it is, ProGuard automatically processes the application's bytecode before packaging everything into an .apk file. Building in debug mode does not invoke ProGuard, because it makes debugging more cumbersome.

// Sure.

dump.txt
Describes the internal structure of all the class files in the .apk file
mapping.txt
Lists the mapping between the original and obfuscated class, method, and field names. This file is important when you receive a bug report from a release build, because it translates the obfuscated stack trace back to the original class, method, and member names. See Decoding Obfuscated Stack Traces for more information.
seeds.txt
Lists the classes and members that are not obfuscated
usage.txt
Lists the code that was stripped from the .apk

// Ok, so it produces these files.

These files are located in the following directories:

/bin/proguard if you are using Ant.
/proguard if you are using Eclipse.

Caution: Every time you run a build in release mode, these files are overwritten with the latest files generated by ProGuard. Save a copy of them each time you release your application in order to de-obfuscate bug reports from your release builds. For more information on why saving these files is important, see Debugging considerations for published applications.

// Hmm...it does make it more difficult to keep track.

Configuring ProGuard

For some situations, the default configurations in the proguard.cfg file will suffice. However, many situations are hard for ProGuard to analyze correctly and it might remove code that it thinks is not used, but your application actually needs. Some examples include:

a class that is referenced only in the AndroidManifest.xml file
a method called from JNI
dynamically referenced fields and methods

The default proguard.cfg file tries to cover general cases, but you might encounter exceptions such as ClassNotFoundException, which happens when ProGuard strips away an entire class that your application calls.

You can fix errors when ProGuard strips away your code by adding a -keep line in the proguard.cfg file. For example:

-keep public class

There are many options and considerations when using the -keep option, so it is highly recommended that you read the ProGuard Manual for more information about customizing your configuration file. The Overview of Keep options and Examples section are particularly helpful. The Troubleshooting section of the ProGuard Manual outlines other common problems you might encounter when your code gets stripped away.


// Ok, I don't think I'm using any of those...

Decoding Obfuscated Stack Traces

When your obfuscated code outputs a stack trace, the method names are obfuscated, which makes debugging hard, if not impossible. Fortunately, whenever ProGuard runs, it outputs a /bin/proguard/mapping.txt file, which shows you the original class, method, and field names mapped to their obfuscated names.

The retrace.bat script on Windows or the retrace.sh script on Linux or Mac OS X can convert an obfuscated stack trace to a readable one. It is located in the /tools/proguard/ directory. The syntax for executing the retrace tool is:

retrace.bat|retrace.sh [-verbose] mapping.txt []

For example:

retrace.bat -verbose mapping.txt obfuscated_trace.txt

If you do not specify a value for , the retrace tool reads from standard input.

// Ok, that makes sense.

Debugging considerations for published applications

Save the mapping.txt file for every release that you publish to your users. By retaining a copy of the mapping.txt file for each release build, you ensure that you can debug a problem if a user encounters a bug and submits an obfuscated stack trace. A project's mapping.txt file is overwritten every time you do a release build, so you must be careful about saving the versions that you need.

For example, say you publish an application and continue developing new features of the application for a new version. You then do a release build using ProGuard soon after. The build overwrites the previous mapping.txt file. A user submits a bug report containing a stack trace from the application that is currently published. You no longer have a way of debugging the user's stack trace, because the mapping.txt file associated with the version on the user's device is gone. There are other situations where your mapping.txt file can be overwritten, so ensure that you save a copy for every release that you anticipate you have to debug.

How you save the mapping.txt file is your decision. For example, you can rename them to include a version or build number, or you can version control them along with your source code.

// Ok. This looks like it will be very easy to implement. The question is, do I want the hassle of it? Well, I've already set it up,
// I believe when I updated the properties. But - where is the progaurd configuration?

The doc says it should have been created with the project. I've apparently deleted it. Well, let's create a new android project, and see if it shows up.

Yes! Awesome. Let's copy it into my directory - proguard.cfg.

Here's what it looks like:

-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService

-keepclasseswithmembernames class * {
native ;
}

-keepclasseswithmembernames class * {
public (android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembernames class * {
public (android.content.Context, android.util.AttributeSet, int);
}

-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}

-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}

I don't see anything specific to the project name. Good. Alright, that's a wrap. I'll plan to save these files for each release:



dump.txt
Describes the internal structure of all the class files in the .apk file
mapping.txt
Lists the mapping between the original and obfuscated class, method, and field names. This file is important when you receive a bug report from a release build, because it translates the obfuscated stack trace back to the original class, method, and member names. See Decoding Obfuscated Stack Traces for more information.
seeds.txt
Lists the classes and members that are not obfuscated
usage.txt
Lists the code that was stripped from the .apk

These files are located in the following directories:

/bin/proguard if you are using Ant.
/proguard if you are using Eclipse.

No comments:

Post a Comment