android 防止反編譯的若干方法
第一種方式:混淆策略
混淆策略是每個應用必須增加的一種防護策略,同時他不僅是為了防護,也是為了減小應用安裝包的大小,所以他是每個應用發版之前必須要新增的一項功能,現在混淆策略一般有兩種:
對程式碼的混淆
我們在反編譯apk之後,看到的程式碼類名,方法名,已經程式碼格式看起來不像正常的Android專案程式碼,那麼這時候就會增加閱讀難度,增加破解難度,像這樣的程式碼混淆:
我們一般現在的破解檢視Java層程式碼就是兩種方式:
一種是直接先解壓classes.dex檔案出來,使用dex2jar工具轉化成jar檔案,然後再用jd-gui工具進行檢視類結構
一種是使用apktool工具直接反編譯apk,得到smali原始碼,閱讀smali原始碼
不過這種程式碼混淆有時候在一定程度上能夠增加混淆策略,但是有時候也不是很安全,因為我們知道我們在破解的過程中一般是找程式的入口,那麼這些入口一般都是Application或者是MainActivity之類的,但是這些Android中的元件類是不能進行混淆的,所以我們還是有入口可尋,能夠找到入口程式碼,然後進行跟蹤。
2、對工程資源的混淆
我們上面說到了對程式碼的混淆能夠增加一定的程式碼閱讀難度,有時候我們為了防止資源的保護也是可以做混淆的,這個資源混淆原理這裡就不多解釋了,微信團隊已經將這個功能開源,不瞭解的同學可以轉戰github檢視:
https://github.com/shwenzhang/AndResGuard
主要是對資源的混淆
第二種方式:應用的簽名
我們知道Android中的每個應用都是有一個唯一的簽名。但是這個簽名在之前是可以被偽造,並實現為此打包的。為了防止應用被二次打包,或者是需要破解我們的apk的操作,在入口處新增簽名驗證,如果發現應用的簽名不正確就立即退出程式,我們可以在應用啟動的時候獲取應用的簽名值,然後和正規的簽名值作比對,如果不符合就直接退成程式即可。
public static String getSign(){
Context context= StockApplication.getInstance();
try {
PackageInfo packageInfo=context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
Signature[] signatures=packageInfo.signatures;
StringBuilder builder=new StringBuilder();
for (Signature signature:signatures){
builder.append(signature.toCharsString());
}
return builder.toString();
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return "";
}
我們可以在application啟動的時候,如果不是我們app的簽名,那麼app直接退出
private void checkSign() {
if (!Utils.isMyApp()){
//直接退出
}
}
public static boolean isMyApp(){
String signStr=getSign();
return SIGN.equals(signStr);
}
第三種方式:修改Naitve函式名
這個方法其實不太常用,因為他的安全措施不是很強大的,但是也是可以起到一定的障眼法策略,在說這個知識點的時候,我們先來了解一下so載入的流程:
在Android中,當程式在java層執行System.loadLibrary("jnitest");這行程式碼後,程式會去載入libjnitest.so檔案,與此同時,產生一個"Load"事件,這個事件觸發後,程式預設會在載入的.so檔案的函式列表中查詢JNI_OnLoad函式並執行,與"Load"事件相對,當載入的.so檔案被解除安裝時,“Unload”事件被觸發,此時,程式預設會去在載入的.so檔案的函式列表中查詢JNI_OnUnload函式並執行,然後解除安裝.so檔案。需要注意的是,JNI_OnLoad與JNI_OnUnload這兩個函式在.so元件中並不是強制要求的,使用者也可以不去實現,java程式碼一樣可以呼叫到C元件中的函式,之所以在C元件中去實現這兩個函式(特別是JNI_OnLoad函式),往往是做一個初始化工作或“善後”工作。可以這樣認為,將JNI_ONLoad看成是.so元件的初始化函式,當其第一次被裝載時被執行(window下的dll檔案也可類似的機制,在_DLL_Main()函式中,通過一個swith
case語句來識別當前是載入還是解除安裝)。將JNI_OnUnload函式看成是解構函式,當其被解除安裝時被呼叫。由此看來,就不難明白為什麼很多jni C元件中會實現JNI_OnLoad這個函式了。 一般情況下,在C元件中的JNI_OnLoad函式用來實現給VM註冊介面,以方便VM可以快速的找到Java程式碼需要呼叫的C函式。(此外,JNI_OnLoad函式還有另外一個功能,那就是告訴VM此C元件使用那一個JNI版本,如果未實現JNI_OnLoad函式,則預設是JNI 1.1版本)。
應用層的Java類別通過VM而呼叫到native函式。一般是通過VM去尋找*.so裡的native函式。如果需要連續呼叫很多次,每次都需要尋找一遍,會多花許多時間。此時,C元件開發者可以將本地函式向VM進行註冊,以便能加快後續呼叫native函式的效率.可以這麼想象一下,假設VM內部一個native函式連結串列,初始時是空的,在未顯式註冊之前此native函式連結串列是空的,每次java呼叫native函式之前會首先在此連結串列中查詢需要查詢需要呼叫的native函式,如果找到就直接使用,如果未找到,得再通過載入的.so檔案中的函式列表中去查詢,且每次java呼叫native函式都是進行這樣的流程,因此,效率就自然會下降,為了克服這樣現象,我們可以通過在.so檔案載入初始化時,即JNI_OnLoad函式中,先行將native函式註冊到VM的native函式連結串列中去,這樣一來,後續每次java呼叫native函式時都會在VM中的native函式連結串列中找到對應的函式,從而加快速度
第四種方式:反除錯異常檢測
這種方式其實是為了應對現在很多破解者使用IDA進行動態方式除錯so檔案,從而獲取重要的資訊,如果還不知道如何使用IDA進行動態除錯so檔案的同學可以檢視這篇文章:Android中使用IDA進行動態除錯so檔案 ,看完這篇文章之後,我們可以知道IDA進行so動態除錯是基於程式的注入技術,然後使用Linux中的ptrace機制,進行除錯目標程式的,那麼ptrace機制有一個特點,就是如果一個程式被除錯了,在他程式的status檔案中有一個欄位TracerPid會記錄除錯者的程式id值,比如:
檢視檔案:/proc/[myPid]/status
在第六行,有一個TracerPid欄位,就是記錄了除錯者的程式id
那麼我們就可以這麼做來達到反除錯的功效了,就是我們可以輪訓的遍歷自己程式的status檔案,然後讀取TracerPid欄位值,如果發現他大於0,那麼就代表著自己的應用在被人除錯,所以就立馬退出程式。原理知道了,程式碼實現也很簡單,這裡用pthread建立一個執行緒,然後進行輪訓操作:
使用pthread_create建立一個執行緒,執行緒啟動之後執行thread_function函式
看看thread_funcation函式:
開始輪訓,讀取TracerPid欄位的值,發現大於0,就立馬退出程式,我們執行結果看看:
相關文章
- android 反編譯Android編譯
- Android 反編譯指南Android編譯
- .NET應用如何防止被反編譯編譯
- Cython加密python程式碼防止反編譯加密Python編譯
- Android Apk反編譯系列教程(一)如何反編譯APKAndroidAPK編譯
- 程式碼混淆防止APP被反編譯指南APP編譯
- c#寫的軟體如何防止被反編譯C#編譯
- android編譯方法Android編譯
- Android的反編譯(佈局植入篇)Android編譯
- android 反編譯APK取原始碼。Android編譯APK原始碼
- Android反編譯工具Apktool淺析Android編譯APK
- android反編譯相關命令總結Android編譯
- Android APK反編譯技巧全講解AndroidAPK編譯
- AndroidKiller反編譯失敗的處理方法Android編譯
- java加密保護jar包及class檔案,防止反編譯Java加密JAR編譯
- 利用classfinal-maven-plugin對jar進行加密,防止反編譯MavenPluginJAR加密編譯
- Java編譯與反編譯Java編譯
- Android 反編譯初探 應用是如何被注入廣告的Android編譯
- Android反編譯和微信機器人初探Android編譯機器人
- Android Apk反編譯系列教程(二)APK重打包AndroidAPK編譯
- Android去掉/混淆Log,反編譯都看不到Android編譯
- Android加快編譯速度的另一種方法Android編譯
- Android Apk 檔案反編譯和重新打包的過程分析AndroidAPK編譯
- Android反編譯 檔名或擴充名太長Android編譯
- android dtbo.img和dtb.img dtc反編譯Android編譯
- Java 反彙編、反編譯、volitale解讀Java編譯
- Android Apk反編譯系列教程(三)Android Studio除錯smali程式碼AndroidAPK編譯除錯
- java反編譯工具Java編譯
- Eclipse配置反編譯Eclipse編譯
- Java程式碼的編譯與反編譯那些事兒Java編譯
- libusb android ndk編譯--編譯mipsAndroid編譯
- Android開發:APK的反編譯(獲取程式碼和資原始檔)AndroidAPK編譯
- 反編譯系列教程(上)編譯
- 反編譯系列教程(中)編譯
- 小程式反編譯教程編譯
- c#程式反編譯C#編譯
- Assimp Android 編譯Android編譯
- 反編譯之安裝Apktool編譯APK
- Android 增量編譯小解Android編譯