Wednesday, January 22, 2014

Android NDK Lib Obfuscation

With default settings javac puts the source's line numbers in the .class files.  It is surprisingly the compiled bytecode can be decompiled into quite a readable source by a decompiler. In software development, obfuscation is the deliberate act of creating obfuscated code to prevent tampering, deter reverse engineering, or as a puzzle or recreational challenge for someone reading the source code. Various forms of obfuscation includes to split variables, promote scalars to objects, change variable lifetimes, change encoding, reorder instance variables, scramble identifiers, split/fold/merge arrays, and modify inheritance relations, although these methods promote sloppy code and increase overhead with maintenance. ProGuard is a tool recommend by Android to shrinks, optimizes, and obfuscates the application Java 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. It is why ProGuard should be used as a main obfuscator for Android applications.

Some people suggested to consider using Android NDK for the most critical code to add a significant layer of protection. It allows to hide password information/schemes in C++ files that can be disassembled but cannot be decompiled which run on top of the DVM. It can also be used with digital signature checking to ensure that no one has extracted hidden information in another Android application.

Sometime Android NDK is intended to be implemented as parts of an Android app using native-code languages such as C and C++. So the Proguard obfuscation does not affect the native code (NDK, JNI) of the application in any way. What’s more, the JNI access points to the native library are clearly visible with explicit names. An attacker can simply extract the .so library from the APK and directly reuse it in a different application.

An Android NDK lib should be stripped symbols as more as possible. These symbol strings are in the dynamic symbol table, which is used when the library is loaded at runtime.

   readelf -p .dynstr mylib.so

or objdump will show these entries.

Some stripping options are

arm-eabi-strip -fvisibility=hidden --strip-unneeded --exclude-libs,ALL

Mihai Mobile suggested to use a solution which is for the native code to obtain directly the information it needs, such as the package name, without using a Context instance passed in by the attacker. For this the native side can use

    static android.app.ActivityThread.currentPackageName();

This way it becomes significantly harder for the attacker to present a fake package name.

Freedom_Ben suggested to further protect the native library .so to "take a SHA-2 of the .so after you compile it, and rehash each time at runtime, matching it against the known value. This check will be enforced on the client side, so a skilled RE could just modify the binary to ignore the check. It does make it a bit harder though. If you put checks all throughout your code and use different checking techniques then it extends the amount of work the RE has to do. Do know however that Microsoft has poured millions of dollars into anti-RE techniques and there are still pirated copies of Office and Windows out there. You'll never stop them all. My personal philosophy (now that I've studied RE myself) is that it is ultimately too much of a pain to try and stop them. Just make a good app, make it cheap, and people will buy. The miscreants that steal your stuff wouldn't have bought it anyway.

If your app calls home you could also submit the hash to the server for verification. Of course and RE can still bypass this but it is one more thing to do."

No comments:

Followers

Blog Archive

About Me

My photo
HD Multimedia Technology player