国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

學徒淺析Android開發——SO文件的混淆

2019-11-09 18:30:25
字體:
來源:轉載
供稿:網友

 

.so(SharedObject)作用等同于windows環境下的.dll(dynamic link library)文件,我們在引用第三方SDK時,也會遇到需要調用相應的.so文件的情況,.so文件本事更多的是集成公共處理方法,當然有事也會用來保存重要的數據信息。

對于應用的編譯與反編譯過程中,本地混淆一直是有效的方法。對于.so文件,同樣也適用于混淆,.so文件雖然在使用破解工具IDA打開后看到的是匯編數據,但仍然存在著規律可循,不妨礙專業人員的閱讀,所以掌握對.so文件的混淆也是必須的。

.so文件的混淆是從兩方面入手:

1:方法名混淆

2:數據混淆

方法名混淆

我們在創建構建.so文件所需的.c和.h文件時,NDK會幫助我們自動生成native方法名,這個方法名是格式化,該方法名同時也是索引表中的索引名。因其特殊性,在IDA瀏覽時,可以通過索引表快速查看到。比如我們創建一個TestSimple,在里面聲明一個native方法showDsc(),最終得到的方法名是:      java_com_example_xx_TestSimple_showDsc

生成的.so文件在經過IDA反編譯后,可以在函數索引表中清楚的看到:

好在NDK提供了修改的方法,幫助我們隱藏掉這種顯眼的名字。首先說一下兩個基礎方法:1、簡化方法名,該方法如下:

   繼續以TestSimple為例,聲明

#defineJNIFUNCTION_NATIVE(sig)  Java_com_example_xx_TestSimple_##sig

   將函數名前邊的路徑剔除掉,只顯示函數名,避免顯得直接。

  

 JNIEXPORT void JNICALL JNIFUCTION_NATIVE (showMath(JNIEnv *env, jobject obj));

   該方法只能用來簡化方法名,在編輯時有用,但是在破解中,對隱藏沒有作用,修改后,在IDA中依然可以查看到:

 

2、替換section索引名,該方法如下:

__attribute__((section(".XXXX")))

其中XXXX表示自定義的索引名,需要在指定的函數名前 聲明該方法, 例如:

__attribute__((section (".xxxsimple")))  JNICALL jstring show(JNIEnv *env, jclass obj){         return realShow(env,obj);}

實際效果圖如下:

 

該方法通過改變屬性類型,影響破解后相關代碼段解析順序,

 

NDK的方法名混淆就是將1和2 兩種方法通過配合RegisterNatives()注冊的方式混合使用,RegisterNatives()可以實現與類關聯的本地方法,這步操作必須在調用之前完成,也就是庫加載過程中。一般是用JNI_Onload這個函數來完成。通過RegisterNatives()進行關聯,將實際執行函數由聲明的類函數轉變成本地函數,達到隱藏的效果,調用步驟如下:

 

步驟一:

聲明待替換的方法集合JNINativeMethod,是一個方法類型集合,

//指針操作,將java層的showDsc函數指向到Native層的show()函數上static JNINativeMethodgetMethods[] = {        {"showDsc","()Ljava/lang/String;",(void*)show},};

其中JNINativeMethod的結構定義如下:

typedef struct{   char *name;// 待指向函數名   char *signature;// 待指向函數和形參類型   void *fnPtr//函數指針,實際執行函數}

 

聲明待注冊的類名

#define JNIREG_CLASS"com/example/xx/Test"

步驟二:

在實際執行函數前標記自定義屬性名稱

__attribute__((section(".xxxfirst"))) JNICALL jstring show(JNIEnv *env, jclass obj){        return realShow(env,obj);}

步驟三:

在實際執行函數完成操作。

jstringrealShow(JNIEnv *env, jclass obj){     return (*env)-> NewStringUTF(env,“10086”);}

步驟四:

執行RegisterNatives(),注冊與指定類相關聯的方法

static int registerNativeMethods(JNIEnv* env, const char* className,JNINativeMethod* gMethods, int numMethods){    jclass clazz;    clazz = (*env)->FindClass(env, className);    if (clazz == NULL) {        return JNI_FALSE;    }    if ((*env)->RegisterNatives(env, clazz, getMethods, numMethods) < 0) {        return JNI_FALSE;    }    return JNI_TRUE;}

步驟五:對指定的類進行指定方法名注冊,注冊成功則返回0,失敗為1。

static intregisterNatives(JNIEnv* env){if(!registerNativeMethods(env,JNIREG_CLASS,getMethods, sizeof(getMethods) /sizeof(getMethods[0]))){           return JNI_FALSE;}    return JNI_TRUE;}

 

步驟六:

在JNI_OnLoad中執行注冊操作

JNIEXPORT jintJNI_OnLoad(JavaVM* vm, void* reserved){    JNIEnv* env = NULL;jint result = -1;    if ((*vm)->GetEnv(vm,(void**) &env, JNI_VERSION_1_4) != JNI_OK) {//GetEnv()用以獲得一個JNIEnv全局對象        return -1;    }    assert(env != NULL);    if (!registerNatives(env)) {        return -1;    }    result = JNI_VERSION_1_4;    return result;}

構建成功之后,我們可以看到,在方法名索引表中找不到調用的函數名稱。只有找到自定的section區域才能進行下一步解析。

 

數據混淆

通常情況下,在.so庫中放置的是方法集合,但是如果存在文本內容時,就需要考慮數據混淆了,一旦使用聲明常量的方式設置文本數據,這些數據在使用過程中會被基本類型完整保存,這些數據在通過破解后,會直白的出現在破解者面前。這種設置讓匯編程序在進行地址指引時,指向的是一個數據源,而非指針地址時。如果我們對外提供文本數據時,對數據采取數組拼接的方式,指向數組獲得的是一個指針地址,這樣破解者看到的是地址標記而非直白的數據源。下面是兩組對比。

直接以文本形式輸出:

JNIEXPORT jstring JNICALLJava_com_example_xx_Test_showC(JNIEnv *env, jobject obj){      charsha[100];              nstrcpy(sha,H, A, C, E, J, F, NULL);      return(*env)-> NewStringUTF(env, sha);}

使用數組組合的形式:

JNIEXPORT jstring JNICALLJava_com_example_xx_Test_showB(JNIEnv *env, jobject obj){          char str[15];          str[0]= O[1];          str[1]= N[4];          str[2]= P[0];          str[3]= N[2];          str[4]= D[0];          str[5]= Q[0];          str[6]= Q[2];          str[7]= O[1];          str[8]= D[0];          str[9]= P[3];          str[10]= '/0';      return(*env)-> NewStringUTF(env, str);}

 

最后,說一下,其實沒有破解不了的保護,只有破解不了的人心,不管安全軟件機構如何宣傳,碰到有心人士也是無解,我們做開發的,只是在增加破解難度而已。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 虎林市| 易门县| 同心县| 太白县| 桑植县| 中阳县| 虞城县| 太谷县| 苏尼特右旗| 揭阳市| 康乐县| 凯里市| 康保县| 万荣县| 枣庄市| 大姚县| 襄樊市| 政和县| 昭苏县| 五家渠市| 东乡族自治县| 同江市| 洪江市| 广宁县| 体育| 安西县| 宁强县| 阿合奇县| 修水县| 南川市| 靖江市| 嘉鱼县| 石景山区| 湖北省| 彭泽县| 宁陵县| 新兴县| 酉阳| 兴安盟| 临沭县| 西青区|