Android應用混淆So庫中的方法名
前言
在Android應用中,出於對安全性的考慮,開發者會把一些重要的邏輯放到native層,即so庫中。但是so庫也並非絕對的安全,在強大的IDA反編譯下,so庫中的邏輯也將無所遁形。今天,我們要說的就是混淆so庫中的方法名。
正文
我們先來看下為什麼要這麼做。我們新建一個Android專案,新增NDK支援,預設專案中會有一個方法如下
external fun stringFromJNI(): String companion object { // Used to load the 'native-lib' library on application startup. init { System.loadLibrary("native-lib") } }
然後我們編譯執行,在 app/build/intermediates/cmake/debug/obj/armeabi/libnative-lib.so
目錄下找到我們編譯出來的so庫,在IDA中開啟,我們可以很輕易的找到這個方法對應的地方

image.png
JNI
的時候,採用javah命令生成的標頭檔案,裡面的方法名預設就是
java_com_xxxx
這種形式。所以我們現在要做的就是改變這種對映關係。
當虛擬機器載入這個這個庫的時候,從 java
層進入本地層首先會執行 JNI_Onload
這個函式,java層的方法就是在這個方法中註冊的,使用的方法為 registerNativeMethods
,我們在這一步將註冊我們自定義的方法,這樣方法名就可以由我們自己來定義。接下來看程式碼實現。
- 重寫
JNI_Onload
方法
extern "C" jint JNI_OnLoad(JavaVM* vm,void* reserved){ JNIEnv* env; if (vm->GetEnv((void**)(&env), JNI_VERSION_1_6) != JNI_OK) { return -1; } //這一步,註冊我們的方法 if (!registerNatives(env)) { return -1; } return JNI_VERSION_1_6; }
- 接下來看
registerNatives
方法的實現
static JNINativeMethod gMethods[] = { //第一個引數為Java層的方法名 //第二個引數為方法的簽名,括號內為引數型別,後面為返回型別 //第三個引數即為我們需要重新註冊的方法名 { "stringFromJNI", "()Ljava/lang/String;", (void*)getStr}, }; extern "C" int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods) { jclass clazz; clazz = env->FindClass(className); if (clazz == NULL) { return JNI_FALSE; } if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) { return JNI_FALSE; } return JNI_TRUE; } extern "C" int registerNatives(JNIEnv* env) { if (!registerNativeMethods(env, JNIREG_CLASS, gMethods, sizeof(gMethods) / sizeof(gMethods[0]))) return JNI_FALSE; return JNI_TRUE; }
到這裡我們成功的替換了註冊的方法,重新用IDA開啟so庫,發現我們這次找不到形如 java_com_xxxx
的方法了最後,還有一步,我們還得實現替換後的方法
extern "C" //這裡指定該程式碼所在的段,編譯的時候就會把這個函式編譯到自定義的名叫”.mytext“的section裡面 //由於我們在java層沒有定義這個函式因此要寫到一個自定義的section裡面。 __attribute__((section (".mytext")))JNICALL jstring getStr (JNIEnv *env, jobject obj) { return (env)->NewStringUTF("abc"); }
至此,我們就完成了所有混淆方法的操作。
後記
這只是一步基礎的安全操作,也很容破解。比如通過IDA動態除錯找到RegisterNatives方法,就能直接找到所對應的方法,也能通過直接找額外的段來找到這個方法,但是這些就不在本文詳細說明了,有興趣的同學可以自己去嘗試下。