in recent spare time wrote an application of "Shake Ah Shake", AZ, Android, 360 and several other application stores have been approved and online. From the idea to the final product made and released, intermittent spent nearly 2.5 months of spare time, overall is still smooth, although the period also encountered several small technical difficulties, the final solution is still satisfactory. Today, one of the small technical difficulties, now think of this small technical difficulty is also very common, but still share out, hope to have the same doubts of the students have help. Because of the Java language's own characteristics, Causes the Android program to be very easy to decompile, although may use the code to confuse the way, but if uses the third party library, the confusion footstep writing is not good, the code confusion then may appear the program to run the instability problem. Without confusing the program once the anti-compilation, the source of a lot of sensitive information will be exposed. For example, the server interaction with the URL address information, if the use of dynamic link library, then the native method will be exposed, and confusion is not confusing native method. Others see native method, you can load so file, so many core things, others can be used indirectly, although he may not necessarily be able to use, but at least can be called. In view of the above a wide list of programs that may occur after the problem, my solution is to use JNI technology, in the NDK environment to do package signature information verification, because it is the NDK environment, so this is difficult to decompile, it is difficult to bypass the verification. In theory, the signature file KeyStore is unique and only available to the program author. Specifically, in all native methods, to increase the signature information verification judgment, only the signature information verification through, the program can do further operation, or directly return null, so that even if someone else got the so file, touched the native method parameters and usage, but because the signature information is inconsistent, The native method returns all Null,so files instantly into bricks. Similarly, for sensitive information such as URL address, to increase the verification of signature information, only through the verification, the program will return the correct string, otherwise directly return null, so that the sensitive information can be well hidden and protected. Said for a while, the key step is how to obtain package signature information in the NDK environment, the following code is related to implementation.
Jstring loadsignature (jnienv* env, Jobject obj) {//Get the context class Jclass CLS = (*env)->getobjectclass (env, obj); Get the ID of the Getpackagemanager method Jmethodid mid = (*env)->getmethodid (env, CLS, "Getpackagemanager", "() landroid/content/ Pm/packagemanager; "); Get the App Package Manager jobject PM = (*env)->callobjectmethod (env, obj, mid); Get the ID of the Getpackagename method mid = (*env)->getmethodid (env, CLS, "Getpackagename", "() ljava/lang/string;"); Get the current app package name jstring PackageName = (jstring) (*env)->callobjectmethod (env, obj, mid); Get Packagemanager class CLS = (*env)->getobjectclass (env, PM); Get the ID of the Getpackageinfo method mid = (*env)->getmethodid (env, CLS, "Getpackageinfo", "(ljava/lang/string;i) Landroid/cont Ent/pm/packageinfo; "); Get the app package information jobject PackageInfo = (*env)->callobjectmethod (Env, PM, Mid, PackageName, 0x40); Get_signatures = 64; Get PackageInfo Class CLS = (*env)->getobjectclass (env, packageinfo); Gets the ID of the signature array property Jfieldid FID = (*enV)->getfieldid (env, CLS, "signatures", "[Landroid/content/pm/signature;"); Get signature Array Jobjectarray signatures = (Jobjectarray) (*env)->getobjectfield (env, PackageInfo, FID); Get signed Jobject sign = (*env)->getobjectarrayelement (env, signatures, 0); Get Signature Class CLS = (*env)->getobjectclass (env, sign); Get the ID of the Tocharsstring method mid = (*env)->getmethodid (env, CLS, "Tocharsstring", "() ljava/lang/string;"); Returns the current app signature information return (jstring) (*env)->callobjectmethod (env, sign, mid);}
The package signature information obtained by the above code is actually a long string, which can be MD5 encrypted and encrypted into a 32-bit string format for more efficient signature information. In addition, I see in the process of information, I saw some of the data mentioned in the package signed Hashcode value to do the comparison, this way is simpler, but I did not use this way, I always feel that this way may not be accurate, just a person feel that interested students can read more relevant information. It is also important to note that the above code obtains the package signature string information, after using MD5 encryption, the resulting encryption results are inconsistent with the actual MD5 fingerprint of the package signature. This is mainly because the signature information is converted to a string after using tocharsstring () for MD5 encryption, if you use Tobytearray () to convert it to a group, and then encrypt, the encryption results and package signature actual MD5 fingerprint will be consistent.
Verification of signature information and protection of sensitive information for Android applications using JNI technology