為什麼需要混淆
Android App 只要把 .apk 檔換成 .zip 我們就可以將它解壓縮,看到裡面的 resource 以及 dex 檔,
很容易利用相關工具例如 dex2jar、jd-gui ,便可以把裡面的程式碼看的一覽無遺,當然如果是開源的話,就沒關係,但如果我們是商業用 apk ,安全疑慮無疑是個大漏洞,利用混淆讓程式碼可讀性降低,延緩破解速度,不僅有此好處,透過 Proguard 我們可以藉此優化 apk 的大小,它會幫我們移除不必要的程式碼,簡化程式碼的寫法。
很容易利用相關工具例如 dex2jar、jd-gui ,便可以把裡面的程式碼看的一覽無遺,當然如果是開源的話,就沒關係,但如果我們是商業用 apk ,安全疑慮無疑是個大漏洞,利用混淆讓程式碼可讀性降低,延緩破解速度,不僅有此好處,透過 Proguard 我們可以藉此優化 apk 的大小,它會幫我們移除不必要的程式碼,簡化程式碼的寫法。
Proguard 的優點
https://www.youtube.com/watch?v=5frxLkO4oTM
這裡有個不錯的影片告訴我們其實 proguard 不只混淆,它影響了 apk 大小,也減少了 method 數。( java 有限制 method 數量 限制在 65535 ,只要超過了就會編譯失敗,當然現在有 multidex 解決了問題,不過 apk 大小仍然是影響著使用者的下載意願)
這裡有個不錯的影片告訴我們其實 proguard 不只混淆,它影響了 apk 大小,也減少了 method 數。( java 有限制 method 數量 限制在 65535 ,只要超過了就會編譯失敗,當然現在有 multidex 解決了問題,不過 apk 大小仍然是影響著使用者的下載意願)
https://lab.getbase.com/proguard-for-android/
這篇文章更是一步一步帶領我們實際驗證透過 proguard 優化了 apk。使用 dependencies 掛越多第三方 lib 會越有感覺, apk 的大小不斷的在增長。
這篇文章更是一步一步帶領我們實際驗證透過 proguard 優化了 apk。使用 dependencies 掛越多第三方 lib 會越有感覺, apk 的大小不斷的在增長。
相關指令:
打包 apk 後可以看見包完的 總時間
./gradlew assembleDebug
打包 apk 後可以看見包完的 總時間
dexcount ./app/build/outputs/apk/app-debug.apk
分析 apk 使用的 method 數量
Proguard 混淆優化程式碼
透過 proguard 混淆程式碼後, class name 、 method name 、變數,都會變成 a、b、c…這種難以閱讀的樣子,並且移除 log、註解 ,簡化一些複雜的程式邏輯。這些都可以透過反編譯後看見。
|
|
在 gradle 打開混淆的設定方式就是
minifyEnabled true
, sdk 有一個預設寫好的 proguard 檔案就是proguard-android.txt
,而後面的 proguard-rules.pro
就是我們自己的 proguard rule 的檔案。
打開
proguard-rules.pro
後,要寫 App 有哪些地方需要保留不被 proguard 混淆優化,通常第三方 SDK 在文件都會提供 rule ,那些都要寫進去 proguard file,我們自己 App 的 code 要保留的 code rule 注意事項。- Activity 、 View 、 Broadcast….四大組件,這些需要被保留,因為 AndroidManifest.xml 註冊著它們的 name ,如果混淆了,會找不到。
- JNI 程式碼需保留
- 運行的程式碼需保留(例如有反射,尋找 name 的相關 method 都需要保留 (App 最常遇到要保留的是 gson mapping 的物件)、序列化物件…)官方提供了一個基本的 proguard rule 寫法
https://android.googlesource.com/platform/sdk/+/master/files/proguard-android.txt有一個更完整的寫法,算是比較廣泛 App 會使用到的 rule
https://gist.github.com/albinmathew/c4436f8371c9c41461ab
常用第三方保留的 rule
https://github.com/krschultz/android-proguard-snippets
https://github.com/krschultz/android-proguard-snippets
不過實際上建議依據自己的 App 去調配你要保留的規則,通常會在 release apk 做混淆,混淆後還是需要安裝 apk 測試一下那些功能壞掉了,然後保留那個部分,並且搭配反編譯去看 code 解析問題點。
-keep class com.squareup.okhttp.** { *; }
遇到問題的萬用保留法,這個會讓 package 下 所有包含子 package 還有 class 、 method 、 變數都保留不受 proguard 混淆優化。
-dontwarn com.squareup.okhttp.**
打包 apk 打開 proguard 時,會有一些 warn 警告導致打包 apk fail ,此 rule 也會比較常用到。
混淆後的 Exception 追蹤
最麻煩的莫過於這個了,proguard 打開後,連 crash 的行數都找不到了,如果使用者有問題工程師 debug 也麻煩,Crashlytics SDK 官方其實有提供相關的保留規則。
https://docs.fabric.io/android/crashlytics/dex-and-proguard.html
https://docs.fabric.io/android/crashlytics/dex-and-proguard.html
-keepattributes *Annotation*
保留注解
-keepattributes SourceFile,LineNumberTable
保留 crash 有意義的錯誤回報、行數
-keep public class * extends java.lang.Exception
保留 Exception
-printmapping mapping.txt
產出混淆前後的差異文件檔
為什麼要產生
mapping.txt
是因為即使寫了保留以上的規則,但 crash 時還是顯示混淆後的行數、package name,其實行數不對,看到的 package name 也都是 com.a.b.c ,所以需要倚賴一個 sdk 附的工具 retrace
和 mapping.txt
再次把錯誤訊息解出來。retrace.bat -verbose mapping.txt obfuscated_trace.txt
還有一個圖形化界面的工具
路徑大概是長這樣,要看你把 Android sdk 放哪個檔案。
proguardgui.sh
幫助我們,路徑大概是長這樣,要看你把 Android sdk 放哪個檔案。
xxx/Android/sdk/tools/proguard/bin/proguardgui.sh
反編譯 APK
這邊教學不用 dex2jar 工具,多次使用後發現其實有時無法真實還原出 apk ,還會產出 error 檔,google 一輪後發現還真不好處理,猜測是因為專案有使用了 kotlin ,因此 error 檔出現了 data class hashcode 的錯誤 (這真的網路上沒找到甚麼好的解法,討論極少),故發現了一個更好用的工具幫助我們反編譯,名為 enjarify,重點是它是 google 官方的工具!
enjarify github 連結:https://github.com/google/enjarify
使用它只需要安裝 python3 以及 把它 clone 下來執行即可。
官方有特別說明 dex2jar 其實是較為老舊的一個工具,不建議使用的原因皆寫在 github 上。
使用它只需要安裝 python3 以及 把它 clone 下來執行即可。
官方有特別說明 dex2jar 其實是較為老舊的一個工具,不建議使用的原因皆寫在 github 上。
- Mac 操作流程
- 打開 terminal
git clone https://github.com/google/enjarify.git
把 enjarify 用 git clone 下來 到你要的資料夾路徑
(可以在clone 前cd ~
就切到 home路徑)
(無安裝 git 請到 https://git-scm.com/book/zh-tw/v2/%E9%96%8B%E5%A7%8B-Git-%E5%AE%89%E8%A3%9D%E6%95%99%E5%AD%B8)sudo ./enjarify.sh myapp.apk
此步驟就是執行 enjarify ,可以把 apk 反編譯 並產生成 jar 檔,注意 apk 跟 enjarify 需要同路徑- 下載 jd-gui 工具打開 jar 檔 http://jd.benow.ca/
程式碼就赤裸裸地出現了!
- 還有一個值得注意的工具叫做
apktool
,它幫我們解包 apk 並可以讓 apk 再打包,但它解出來 java code 是用 smali 語法呈現,它的好處是可以解出資源檔像是 xml 那些,如果單純用 dex2jar 跟 enjarify 就看不到 xml 相關的檔案了。 不過本文著重於混淆後用反編譯工具檢查 java code ,此工具不再討論範圍內。(https://ibotpeaches.github.io/Apktool/install/)
總結
其實有了 Proguard 無法保證 Apk 絕對安全,它能保證做一定程度的優化是無庸置疑的,更深入的混淆可以用付費的 Dexguard ,它可以連字串都幫你做加密,不過費用是年費,且不便宜,或是有其他 Apk 加殼的方式,不過付費方案的討論較少,請斟酌自己的需求選用。
相關介紹:https://www.guardsquare.com/zh-hans/blog/dexguard-vs-proguard
相關介紹:https://www.guardsquare.com/zh-hans/blog/dexguard-vs-proguard
沒有留言:
張貼留言