近來閒的無聊,看了看Android 應用安全防禦和逆向分析,裏面有個使用apk簽名防止反編譯的篇章。java
實踐了一下。git
有兩種方式,github
1. 可在java層斷定安全
獲取簽名的java代碼app
public static String getSignature(){ Context context = mContext; try{ PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES); Signature[]signatures = packageInfo.signatures; StringBuilder stringBuilder = new StringBuilder(); for(Signature signature : signatures){ stringBuilder.append(signature.toCharsString()); } return stringBuilder.toString(); } catch (PackageManager.NameNotFoundException e){ e.printStackTrace(); } return ""; }
而後簡單斷定一下:函數
private boolean isOwnApp(){ if (APP_SIGN.equalsIgnoreCase(getSignature())){ return true; } return false; }
這種方式比較簡單,但也很容易被破解。ui
2. 在jni層判斷,編譯一個sospa
調用上面定義的獲取簽名函數和app_sig對比code
const char *app_sig = "xxx"; JNIEXPORT jboolean JNICALL Java_com_example_signatureprotect_SignatureJni_isEqual (JNIEnv *env, jclass jcla, jstring sig) { char *className = "com/example/signatureprotect/MainActivity"; jclass clazz = (env)->FindClass(className); if (clazz == NULL) { LOGI("do not find class '%s'", className); return false; } LOGI("find class '%s'", className); jmethodID method = (env)->GetStaticMethodID( clazz, "getSignature", "()Ljava/lang/String;"); if (method == NULL) { LOGI("do not find method"); return false; } LOGI("find method"); jstring obj = (jstring)(env)->CallStaticObjectMethod( clazz, method); if (obj == NULL){ LOGI("invoke error: %p", obj); return false; } LOGI("invoke method"); const char *str = (env)->GetStringUTFChars(obj, 0); LOGI("str %s", str); int cmpval = strcmp(str, app_sig); LOGI("strcmp pass"); if (cmpval == 0) { LOGI("equal return true"); return true; } (env)->ReleaseStringUTFChars(obj,str); LOGI("equal return false"); return false; }
能夠在java層調用,可是這樣調用跟上面的第一種方法區別不大,可在java層破解。blog
private boolean isOwnApp2(){ if (SignatureJni.isEqual("")){ return true; } return false; }
能夠在加載so的時候判斷,重寫JNI_OnLoad函數便可
jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; jint result = -1; LOGI("JNI_OnLoad"); if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { LOGI("ERROR: GetEnv failed\n"); goto bail; } if(env == NULL) return result; /* success -- return valid version number */ result = JNI_VERSION_1_4; if (!Java_com_example_signatureprotect_SignatureJni_isEqual(env, NULL, NULL)) { char *className = "com/example/signatureprotect/MainActivity"; jclass clazz = (env)->FindClass(className); if (clazz == NULL) { LOGI("do not find class '%s'", className); return false; } jmethodID method = (env)->GetStaticMethodID( clazz, "killMyself", "()V"); if (method == NULL) { LOGI("do not find method"); return result; } LOGI("find method"); (env)->CallStaticVoidMethod( clazz, method); }
這樣相對會好一些
源碼地址:https://github.com/george-cw/AppAddShellDemo
這個源碼有三個模塊,APP模塊是簽名保護的demo,可是裏面的定義的簽名字符串不是APP的簽名(是加殼app的簽名,詳細描述見下一篇文章),若是須要單獨使用請替換~
簽名的字符串