混淆
因為開啟混淆會使編譯時間變長,所以debug模式下不開啟。我們需要做的是:
1.將release下minifyEnabled
的值改為true
,打開混淆;
2.buildConfigField
?不顯示log日志
?
為什么要混淆:
?
- 優化java的字節碼
- 減小apk文件的大小,在混淆過程中會刪除未使用過的類和成員
- 代碼安全,使類、函數、變量名隨機變成無意義的代號形如:a,b,c...之類。防止app被反編譯之后能夠很容易的看懂代碼
?
?
APP需要保留的公共部分(通用)
- 四大組件以及子類;
- 自定義Application;
-
- native方法
- R下面的資源
- 序列化(Parcelable,Serializable)
- support下面的繼承子類
- Activity中參數是view的方法
- 枚舉
- 自定義View
- 帶有回調函數(On*Listener,OnEvent)
- WebView
?
1. 判斷程序是否運行在模擬器上
boolean isRunningInEmualtor() {boolean qemuKernel = false;Process process = null;DataOutputStream os = null;try{ process = Runtime.getRuntime().exec("getprop ro.kernel.qemu"); os = new DataOutputStream(process.getOutputStream());BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream(),"GBK"));os.writeBytes("exit\n"); os.flush();process.waitFor();// getprop ro.kernel.qemu == 1 在模擬器// getprop ro.product.model == "sdk" 在模擬器// getprop ro.build.tags == "test-keys" 在模擬器qemuKernel = (Integer.valueOf(in.readLine()) == 1);Log.d("com.droider.checkqemu", "檢測到模擬器:" + qemuKernel); } catch (Exception e){ qemuKernel = false;Log.d("com.droider.checkqemu", "run failed" + e.getMessage()); } finally {try{ if (os != null) { os.close(); } process.destroy(); } catch (Exception e) {} Log.d("com.droider.checkqemu", "run finally"); }return qemuKernel;}
2. 檢測keystore簽名,再與之前得做比較
public int getSignature(String packageName) { PackageManager pm = this.getPackageManager();PackageInfo pi = null;int sig = 0;try {pi = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);Signature[] s = pi.signatures;sig = s[0].hashCode(); } catch (Exception e1) {sig = 0;e1.printStackTrace();}return sig;}
?
3. 檢測包名,版本名和版本號,然后做判斷:
private String getAppInfo() {try {String pkName = this.getPackageName();String versionName = this.getPackageManager().getPackageInfo(pkName, 0).versionName;int versionCode = this.getPackageManager().getPackageInfo(pkName, 0).versionCode;return pkName + " " + versionName + " " + versionCode;} catch (Exception e) {}return null;}
?4.完整性校驗
Android工程代碼經編譯打包生成apk包后,開發者需要對其簽名才能在安卓市場上發布供用戶下載和安裝。對apk包簽名后,會在原apk包結構基礎上加入META-INF文件目錄。
META-INF文件目錄下含有三個文件:MANIFEST.MF文件、ANDROIDD.SF文件、ANDROIDD.RSA文件,META_INF目錄文件結構如下圖所示:
其中,MANIFEST.MF文件描述了在簽名時,簽名工具對apk包中各個文件摘要計算后的哈希值,并對哈希值做了Base64編碼。MANIFEST.MF文件中描述的classes.dex文件的SHA-1哈希值如下圖所示:
一旦攻擊者對APK中反編譯并篡改代碼,經二次打包簽名后的classes.dex文件的SHA-1必定改變,因此,我們可以將該文件中的classes.dex文件的SHA-1哈希值保存起來作為校驗對比值,應用程序啟動時讀取apk安裝包中的MANIFEST.MF文件,解析出classes.dex的SHA-1哈希值,然后與原SHA-1哈希值進行比較,判斷此APK包代碼文件是否被篡改。
通過檢查簽名文件classes.dex文件的哈希值來判斷代碼文件是否被篡改的java實現代碼如下所示:
通過檢查簽名文件classes.dex文件的哈希值來判斷代碼文件是否被篡改
@param orginalSHA 原始Apk包的SHA-1值
public static void apkVerifyWithSHA(Context context, String baseSHA) { String apkPath = context.getPackageCodePath(); // 獲取Apk包存儲路徑 try { MessageDigest dexDigest = MessageDigest.getInstance("SHA-1"); byte[] bytes = new byte[1024]; int byteCount; FileInputStream fis = new FileInputStream(new File(apkPath)); // 讀取apk文件 while ((byteCount = fis.read(bytes)) != -1) { dexDigest.update(bytes, 0, byteCount); } BigInteger bigInteger = new BigInteger(1, dexDigest.digest()); // 計算apk文件的哈希值 String sha = bigInteger.toString(16); fis.close(); if (!sha.equals(baseSHA)) { // 將得到的哈希值與原始的哈希值進行比較校驗 Process.killProcess(Process.myPid()); // 驗證失敗則退出程序 } } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
5.Android逆向-.so文件動態調試步驟
?
so庫加密的方法
1.是在有源碼的基礎上進行對特定的section進行加密
2.基于二進制級別的特定函數的加密
?
參考博客:
https://blog.csdn.net/nicolelili1/article/details/79243744
?
https://blog.csdn.net/feibabeibei_beibei?t=1
?
---------------------
作者:深南大盜
來源:CSDN
原文:https://blog.csdn.net/WHB20081815/article/details/88960114
版權聲明:本文為作者原創文章,轉載請附上博文鏈接!
內容解析By:CSDN,CNBLOG博客文章一鍵轉載插件