Any application code (APK) that is published becomes exposed to decompilation. Obfuscating the Java code (e.g. with Proguard) makes the Java decompilation harder.
But 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.
Then, how to protect the native library against such undesired reuse? One tentative solution is presented here: Protecting IP in Android Applications.
But that solution has the drawback of obtaining critical information, such as the application package name, from a Java Context instance that is passed in from the Java side down to the native library. An attacker who has control of the Java side could manufacture a fake instance before passing it in.
A better solution 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
This way it becomes significantly harder for the attacker to present a fake package name.
Next, the most basic protection is for the native library to refuse to function if the package name doesn’t match. Of course all this should be done in a rather obfuscated way — otherwise the check can be easily discovered and removed by the attacker through binary patching of the library.
One more question: if the native library relies only on a simple check of application package name, what prevents the attacker from reusing the package name of the original application for his own app? The simple reason is the “unique package name” policy that is enforced by the Android Market. Thus the attacker, if he chooses to re-use the package name, would not be able to publish the fake app on the Market, which often is enough.