Tuesday, July 1, 2014

Securing Android LVL Applications


[This post is by Trevor Johns, whos a Developer Programs Engineer working on Android. — Tim Bray]

The Android Market licensing service is a powerful tool for protecting your applications against unauthorized use. The License Verification Library (LVL) is a key component. A determined attacker who’s willing to disassemble and reassemble code can eventually hack around the service; but application developers can make the hackers’ task immensely more difficult, to the point where it may simply not be worth their time.

Out of the box, the LVL protects against casual piracy; users who try to copy APKs directly from one device to another without purchasing the application. Here are some techniques to make things hard, even for technically skilled attackers who attempt to decompile your application and remove or disable LVL-related code.

  • You can obfuscate your application to make it difficult to reverse-engineer.

  • You can modify the licensing library itself to make it difficult to apply common cracking techniques.

  • You can make your application tamper-resistant.

  • You can offload license validation to a trusted server.

This can and should be done differently by each app developer. A guiding principle in the design of the licensing service is that attackers must be forced to crack each application individually, and unfortunately no client-side code can be made 100% secure. As a result, we depend on developers introducing additional complexity and heterogeneity into the license check code — something which requires human ingenuity and and a detailed knowledge of the application the license library is being integrated into.

Technique: Code Obfuscation

The first line of defense in your application should be code obfuscation. Code obfuscation will not protect against automated attacks, and it doesn’t alter the flow of your program. However, it does make it more difficult for attackers to write the initial attack for an application, by removing symbols that would quickly reveal the original structure of a compiled application. As such, we strongly recommend using code obfuscation in all LVL installations.

To understand what an obfuscator does, consider the build process for your application: Your application is compiled and converted into .dex files and packaged in an APK for distribution on devices. The bytecode contains references to the original code — packages, classes, methods, and fields all retain their original (human readable) names in the compiled code. Attackers use this information to help reverse-engineer your program, and ultimately disable the license check.

Obfuscators replace these names with short, machine generated alternatives. Rather than seeing a call to dontAllow(), an attacker would see a call to a(). This makes it more difficult to intuit the purpose of these functions without access to the original source code.

There are a number of commercial and open-source obfuscators available for Java that will work with Android. We have had good experience with ProGuard, but we encourage you to explore a range of obfuscators to find the solution that works best for you.

We will be publishing a separate article soon that provides detailed advice on working with ProGuard. Until then, please refer to the ProGuard documentation.

Technique: Modifying the license library

The second line of defense against attack from crackers is to modify the license verification library in such a way that it’s difficult for an attacker to modify the disassembled code and get a positive license check as result.

This actually provides protection against two different types of attack: it protects against attackers trying to crack your application, but it also prevents attacks designed to target other applications (or even the stock LVL distribution itself) from being easily ported over to your application. The goal should be to both increase the complexity of your application’s bytecode and make your application’s LVL implementation unique.

When modifying the license library, there are three areas that you will want to focus on:

  • The core licensing library logic.

  • The entry/exit points of the licensing library.

  • How your application invokes the licensing library and handles the license response.

In the case of the core licensing library, you’ll primarily want to focus on two classes which comprise the core of the LVL logic: LicenseChecker and LicenseValidator.

Quite simply, your goal is to modify these two classes as much as possible, in any way possible, while still retaining the original function of the application. Here are some ideas to get you started, but you’re encouraged to be creative:

  • Replace switch statements with if statements.

  • Use XOR or hash functions to derive new values for any constants used and check for those instead.

  • Remove unused code. For instance, if you’re sure you won’t need swappable policies, remove the Policy interface and implement the policy verification inline with the rest of LicenseValidator.

  • Move the entirety of the LVL into your own application’s package.

  • Spawn additional threads to handle different parts of license validation.

  • Replace functions with inline code where possible.

For example, consider the following function from LicenseValidator:

public void verify(PublicKey publicKey, int responseCode, String signedData, String signature) {
// ... Response validation code omitted for brevity ...
switch (responseCode) {
// In Java bytecode, LICENSED will be converted to the constant 0x0
case LICENSED:
case LICENSED_OLD_KEY:
LicenseResponse limiterResponse = mDeviceLimiter.isDeviceAllowed(userId);
handleResponse(limiterResponse, data);
break;
// NOT_LICENSED will be converted to the constant 0x1
case NOT_LICENSED:
handleResponse(LicenseResponse.NOT_LICENSED, data);
break;
// ... Extra response codes also removed for brevity ...
}

In this example, an attacker might try to swap the code belonging to the LICENSED and NOT_LICENSED cases, so that an unlicensed user will be treated as licensed. The integer values for LICENSED (0x0) and NOT_LICENSED (0x1) will be known to an attacker by studying the LVL source, so even obfuscation makes it very easy to locate where this check is performed in your application’s bytecode.

To make this more difficult, consider the following modification:

public void verify(PublicKey publicKey, int responseCode, String signedData, String signature) {
// ... Response validation code omitted for brevity …

// Compute a derivative version of the response code
// Ideally, this should be placed as far from the responseCode switch as possible,
// to prevent attackers from noticing the call to the CRC32 library, which would be
// a strong hint as to what were done here. If you can add additional transformations
// elsewhere in before this value is used, thats even better.
java.util.zip.CRC32 crc32 = new java.util.zip.CRC32();
crc32.update(responseCode);
int transformedResponseCode = crc32.getValue();

// ... put unrelated application code here ...
// crc32(LICENSED) == 3523407757
if (transformedResponse == 3523407757) {
LicenseResponse limiterResponse = mDeviceLimiter.isDeviceAllowed(userId);
handleResponse(limiterResponse, data);
}
// ... put unrelated application code here ...
// crc32(LICENSED_OLD_KEY) == 1007455905
if (transformedResponseCode == 1007455905) {
LicenseResponse limiterResponse = mDeviceLimiter.isDeviceAllowed(userId);
handleResponse(limiterResponse, data);
}
// ... put unrelated application code here ...
// crc32(NOT_LICENSED) == 2768625435
if (transformedResponseCode == 2768625435):
userIsntLicensed();
}
}

In this example, we’ve added additional code to transform the license response code into a different value. We’ve also removed the switch block, allowing us to inject unrelated application code between the three license response checks. (Remember: The goal is to make your application’s LVL implementation unique. Do not copy the code above verbatim — come up with your own approach.)

For the entry/exit points, be aware that attackers may try to write a counterfeit version of the LVL that implements the same public interface, then try to swap out the relevant classes in your application. To prevent this, consider adding additional arguments to the LicenseChecker constructor, as well as allow() and dontAllow() in the LicenseCheckerCallback. For example, you could pass in a nonce (a unique value) to LicenseChecker that must also be present when calling allow().

Note: Renaming allow() and dontAllow() won’t make a difference, assuming that you’re using an obfuscator. The obfuscator will automatically rename these functions for you.

Be aware that attackers might try and attack the calls in your application to the LVL. For example, if you display a dialogue on license failure with an “Exit” button, consider what would happen if an attacker were to comment out the line of code that displayed that window. If the user never pushes the “Exit” button in the dialog (which is no not being displayed) will your application still terminate? To prevent this, consider invoking a different Activity to handle informing a user that their license is invalid, and immediately terminating the original Activity; add additional finish() statements to other parts of your code that get will get executed in case the original one gets disabled; or set a timer that will cause your application to be terminated after a timeout. It’s also a good idea to defer the license check until your application has been running a few minutes, since attackers will be expecting the license check to occur during your application’s launch.

Finally, be aware that certain methods cannot be obfuscated, even when using a tool such as ProGuard. As a key example, onCreate() cannot be renamed, since it needs to remain callable by the Android system. Avoid putting license check code in these methods, since attackers will be looking for the LVL there.

Technique: Make your application tamper-resistant

In order for an attacker to remove the LVL from your code, they have to modify your code. Unless done precisely, this can be detected by your code. There are a few approaches you can use here.

The most obvious mechanism is to use a lightweight hash function, such as CRC32, and build a hash of your application’s code. You can then compare this checksum with a known good value. You can find the path of your application’s files by calling context.GetApplicationInfo() — just be sure not to compute a checksum of the file that contains your checksum! (Consider storing this information on a third-party server.)

[In a late edit, we removed a suggestion that you use a check that relies on GetInstallerPackageName when our of our senior engineers pointed out that this is undocumented, unsupported, and only happens to work by accident. –Tim]

Also, you can check to see if your application is debuggable. If your application tries to keep itself from performing normally if the debug flag is set, it may be harder for an attacker to compromise:

boolean isDebuggable =  ( 0 != ( getApplcationInfo().flags &= ApplicationInfo.FLAG_DEBUGGABLE ) );

Technique: Offload license validation to a trusted server

If your application has an online component, a very powerful technique to prevent piracy is to send a copy of the license server response, contained inside the ResponseData class, along with its signature, to your online server. Your server can then verify that the user is licensed, and if not refuse to serve any online content.

Since the license response is cryptographically signed, your server can check to make sure that the license response hasn’t been tampered with by using the public RSA key stored in the Android Market publisher console.

When performing the server-side validation, you will want to check all of the following:

  • That the response signature is valid.

  • That the license service returned a LICENSED response.

  • That the package name and version code match the correct application.

  • That the license response has not expired (check the VT license response extra).

  • You should also log the userId field to ensure that a cracked application isn’t replaying a license response from another licensed user. (This would be visible by an abnormally high number of license checks coming from a single userId.)

To see how to properly verify a license response, look at LicenseValidator.verify().

As long as the license check is entirely handled within server-code (and your server itself is secure), it’s worth nothing that even an expert cracker cannot circumvent this mechanism. This is because your server is a trusted computing environment.

Remember that any code running on a computer under the user’s control (including their Android device) is untrusted. If you choose to inform the user that the server-side license validation has failed, this must only be done in an advisory capacity. You must still make sure that your server refuses to serve any content to an unlicensed user.

Conclusion

In summary, remember that your goal as an application developer is to make your application’s LVL implementation unique, difficult to trace when decompiled, and resistant to any changes that might be introduced. Realize that this might involve modifying your code in ways that seem counter-intuitive from a traditional software engineering viewpoint, such as removing functions and hiding license check routines inside unrelated code.

For added protection, consider moving the license check to a trusted server, where attackers will be unable to modify the license check code. While it’s impossible to write 100% secure validation code on client devices, this is attainable on a machine under your control.

And above all else, be creative. You have the advantage in that you have access to a fully annotated copy of your source code — attackers will be working with uncommented bytecode. Use this to your advantage.

Remember that, assuming you’ve followed the guidelines here, attackers will need to crack each new version of your application. Add new features and release often, and consider modifying your LVL implementation with each release to create additional work for attackers.

And above all else, listen to your users and keep them happy. The best defense against piracy isn’t technical, it’s emotional.

Read More..

Introducing Android Training

[This post is by Reto Meier, Android Developer Relations Tech Lead. — Tim Bray]

Today I’m thrilled to announce the beta launch of Android Training — a collection of classes that we hope will help you to build better Android apps.

From designing effective navigation, to managing audio playback, to optimizing battery life, these classes are designed to demonstrate best practices for solving common Android development problems.

Each class explains the steps required to solve a problem, or implement a feature, with plenty of code snippets and sample code for you to use within your own apps.

We’re starting small and this is just the beginning for Android Training. Over the coming months we will be increasing the number of classes available, as well as introducing over-arching courses and sample apps to further help your development experience.

Helping developers build great apps is what the Android Developer Relations team is all about, so we’re excited to see how you use these classes to make your apps even better.

We’d love to know what you think of these classes, and what classes you’d like to see next.

Read More..

Monday, June 30, 2014

New Resources for Developers

Were back in action after a Thanksgiving break filled with turkey, stuffing, and pumpkin pie. Now its the holiday season (at least, here in the U.S.) and were filled with good will toward developers. Today I wanted to talk about a couple things we just finished polishing up.

First, the Android 1.0 SDK, release 2 is now available. Like the previous 1.0_r1 release, this new 1.0_r2 build creates applications that are compatible with Android 1.0 devices, such as the T-Mobile G1. This new release fixes a few bugs. In 1.0_r1, it was possible for developers to write technically-illegal code by using the Java Reflection APIs to access private or protected fields and methods. 1.0_r2 fixes that problem by enforcing private/protected visibility of items accessed via Reflection. Meanwhile, the class android.R.styleable was included in 1.0_r1 primarily for documentation purposes as a way for developers to look up the style attributes available to them to use. However, actually referring to that class via source code would result in applications that might break when run on future versions of the Android platform, so 1.0_r2 corrects the oversight and removes access to the class from the android.jar file. (The class remains in the documentation for reference purposes, though.)

Both of these problems are obscure "future-proofing" issues, and Id be quite surprised if they actually caused problems for anyone, but now theyre fixed. 1.0_r2 also includes a few other smaller changes; check out the release notes for all the details.

Second, many of you have asked if developer devices will be available. Weve worked with our partners to create a program for developers to purchase devices that enable them to test and debug applications more easily.

I think these new tools will be quite helpful to developers, and Im looking forward to seeing what people do with Android, next.

Read More..

Live folders

Live folders have been introduced in Android 1.5 and let you display any source of data on the Home screen without forcing the user to launch an application. A live folder is simply a real-time view of a ContentProvider. As such, a live folder can be used to display all your contacts, your bookmarks, your email, your playlists, an RSS feed, etc. The possibilities are endless! Android 1.5 ships with a few stock live folders to display your contacts. For instance, the screenshot below shows the content of the live folders that displays all my contacts with a phone number:

If a contacts sync happens in the background while Im browsing this live folder, I will see the change happen in real-time. Live folders are not only useful but its also very easy to modify your application to make it provider a live folder. In this article, I will show you how to add a live folder to the Shelves application. You can download its source code and modify it by following my instructions to better understand how live folders work.

To give the user the option to create a new live folder, you first need to create a new activity with an intent filter who action is android.intent.action.CREATE_LIVE_FOLDER. To do so, simply open AndroidManifest.xml and add something similar to this:

<activity
android:name=".activity.BookShelfLiveFolder"
android:label="BookShelf">
<intent-filter>
<action android:name="android.intent.action.CREATE_LIVE_FOLDER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

The label and icon of this activity are what the user will see on the Home screen when choosing a live folder to create:

Since you just need an intent filter, it is possible, and sometimes advised, to reuse an existing activity. In the case of Shelves, we will create a new activity, org.curiouscreature.android.shelves.activity.BookShelfLiveFolder. The role of this activity is to send an Intent result to Home containing the description of the live folder: its name, icon, display mode and content URI. The content URI is very important as it describes what ContentProvider will be used to populate the live folder. The code of the activity is very simple as you can see here:

public class BookShelfLiveFolder extends Activity {
public static final Uri CONTENT_URI = Uri.parse("content://shelves/live_folders/books");

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

final Intent intent = getIntent();
final String action = intent.getAction();

if (LiveFolders.ACTION_CREATE_LIVE_FOLDER.equals(action)) {
setResult(RESULT_OK, createLiveFolder(this, CONTENT_URI,
"Books", R.drawable.ic_live_folder));
} else {
setResult(RESULT_CANCELED);
}

finish();
}

private static Intent createLiveFolder(Context context, Uri uri, String name, int icon) {
final Intent intent = new Intent();

intent.setData(uri);
intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME, name);
intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON,
Intent.ShortcutIconResource.fromContext(context, icon));
intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_DISPLAY_MODE, LiveFolders.DISPLAY_MODE_LIST);

return intent;
}
}

This activity, when invoked with theACTION_CREATE_LIVE_FOLDER intent, returns an intent with a URI, content://shelves/live_folders/books, and three extras to describe the live folder. There are other extras and constants you can use and you should refer to the documentation of android.provider.LiveFolders for more details. When Home receives this intent, a new live folder is created on the users desktop, with the name and icon you provided. Then, when the user clicks on the live folder to open it, Home queries the content provider referenced by the provided URI.

Live folders content providers must obey specific naming rules. The Cursor returned by the query() method must have at least two columns named LiveFolders._ID and LiveFolders.NAME. The first one is the unique identifier of each item in the live folder and the second one is the name of the item. There are other column names you can use to specify an icon, a description, the intent to associate with the item (fired when the user clicks that item), etc. Again, refer to the documentation of android.provider.LiveFolders for more details.

In our example, all we need to do is modify the existing provider in Shelves called org.curiouscreature.android.shelves.provider.BooksProvider. First, we need to modify the URI_MATCHER to recognize our content://shelves/live_folders/books content URI:

private static final int LIVE_FOLDER_BOOKS = 4;
// ...
URI_MATCHER.addURI(AUTHORITY, "live_folders/books", LIVE_FOLDER_BOOKS);

Then we need to create a new projection map for the cursor. A projection map can be used to "rename" columns. In our case, we will replace BooksStore.Book._ID, BooksStore.Book.TITLE and BooksStore.Book.AUTHORS with LiveFolders._ID, LiveFolders.TITLE and LiveFolders.DESCRIPTION:

private static final HashMap LIVE_FOLDER_PROJECTION_MAP;
static {
LIVE_FOLDER_PROJECTION_MAP = new HashMap();
LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders._ID, BooksStore.Book._ID +
" AS " + LiveFolders._ID);
LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders.NAME, BooksStore.Book.TITLE +
" AS " + LiveFolders.NAME);
LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders.DESCRIPTION, BooksStore.Book.AUTHORS +
" AS " + LiveFolders.DESCRIPTION);
}

Because we are providing a title and a description for each row, Home will automatically display each item of the live folder with two lines of text. Finally, we implement the query() method by supplying our projection map to the SQL query builder:

public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {

SQLiteQueryBuilder qb = new SQLiteQueryBuilder();

switch (URI_MATCHER.match(uri)) {
// ...
case LIVE_FOLDER_BOOKS:
qb.setTables("books");
qb.setProjectionMap(LIVE_FOLDER_PROJECTION_MAP);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}

SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, BooksStore.Book.DEFAULT_SORT_ORDER);
c.setNotificationUri(getContext().getContentResolver(), uri);

return c;
}

You can now compile and deploy the application, go to the Home screen and try to add a live folder. I added a books live folder to my Home screen and when I open it, I can see the list of all of my books, with their titles and authors, and all it took was a few lines of code:

The live folders API is extremely simple and relies only on intents and content URI. If you want to see more examples of live folders implementation, you can read the source code of the Contacts application and of the Contacts provider.

You can also download the result of our exercise, the modified version of Shelves with live folders support.


Learn about Android 1.5 and more at Google I/O. Members of the Android team will be there to give a series of in-depth technical sessions and to field your toughest questions.

Read More..

Android at Mobile World Congress

Im happy to announce that well be hosting a very special Android Developer Lab at Mobile World Congress (MWC) in Barcelona on Wednesday, February 17th as part of the inaugural App Planet event.

There will be technical presentations throughout the day and a developer lounge where you can talk to Android team members and meet others in the growing Android developer community.

Whether you’re already developing Android apps, youre an experienced mobile developer, or you’re considering making your first foray into writing mobile applications, the Android Developer Lab will provide access to the resources you need to create innovative and compelling apps for the Android platform.

Space is limited in the technical sessions, so if youre attending MWC and want to come by the Android Developer Lab, make sure to sign up now.

Also, were offering a limited number of complimentary passes that provide access to the Android Developer Lab, the rest of App Planet, and the general exhibition areas for MWC. Sign up to be considered to receive a pass.

Hope to see you in Barcelona!

Read More..

Sunday, June 29, 2014

ADC 2 Round 2 Voting Open

The results from ADC 2 Round 1 are now tabulated and verified. With the top 200 applications identified, its time to begin the final round judging. Be sure to download the ADC 2 judging application, or update your existing application, and help us select the final winners!

For the final round, both users and a Google-selected panel of industry judges will provide votes to determine the final winners. Prizes will be distributed to the top 3 entrants in each of the 10 categories, and the top 3 overall entrants will receive additional prizes. Please see our reference page for full challenge information.

Your vote is critical! We will keep voting open until we have received sufficient votes for all of the applications. We encourage you to download the ADC 2 judging application and evaluate entrants for yourself.

Download Android Developer Challenge 2:

Read More..

Dalvik JIT

[This post is by Dan Bornstein, virtual-machine wrangler. — Tim Bray]

As the tech lead for the Dalvik team within the Android project, I spend my time working on the virtual machine (VM) and core class libraries that sit beneath the Android application framework. This layer is mostly invisible to end users, but done right, it helps make Android devices run smoothly and improves developer productivity.

The 2.2 release is particularly pleasing to me, as it is the first release since before 1.0 in which we have been able to deliver significantly new VM technology. And unlike much of what my team and I do, it is something that can be experienced directly by end users.

“Dalvik” isn’t exactly a household word (at least in my country), and most people wouldn’t know a virtual machine if it hit them in the face, but when you tell them you were able to make their existing device work better — run faster, use less battery — they will actually take notice!

What Makes This Possible?

We added a Just In Time (JIT) compiler to the Dalvik VM. The JIT is a software component which takes application code, analyzes it, and actively translates it into a form that runs faster, doing so while the application continues to run. If you want to learn more about the design of the Dalvik JIT, please watch the excellent talk from Google I/O 2010 given by my colleagues Bill Buzbee and Ben Cheng, which should be posted to YouTube very soon.

To be clear, the differences aren’t always dramatic, nor do they apply uniformly to all applications. Code that is written to run the CPU all-out can now do more in the same amount of time (running faster), and code that is written to be rate-limited can get its work done using less time and less of the CPU (using less battery). On the performance front in particular, we have seen realistic improvements of 2x to 5x for CPU-bound code, compared to the previous version of the Dalvik VM. This is equivalent to about 4x to 10x faster than a more traditional interpreter implementation.

The team is proud of our new JIT in general, but we are especially proud of two aspects of it:

Many previous JIT implementations react slowly, delivering performance improvements only after a long warm up period. In the extreme, it can be minutes or even hours before the code is fully up to speed. On the other hand, the Dalvik JIT reacts quickly, so that mere moments after you hit the “Start” button on your favorite game, you are already benefiting from the work of the JIT.

We are also very pleased with how little memory the JIT uses. The code for the JIT itself is well under 100k, and each process that the JIT runs in will typically only use another 100k or so of RAM. On the current generation of Android phones, device users won’t even notice this additional memory usage; on my own phone, I can still have literally dozens of applications warmed up in memory and ready to go.

The Dalvik team isn’t resting on its laurels, either. We are hoping to see the Dalvik JIT deployed on many devices in the coming months. Looking forward, the team has an endless list of ideas for making the VM and library code better, which we are diligently working on.

Read More..