1. 程式人生 > >Android studio 使用心得(五)---程式碼混淆和破解apk

Android studio 使用心得(五)---程式碼混淆和破解apk

   

這篇文章等是跟大家分享一在Android studio 進行程式碼混淆配置。之前大家在eclipse上也弄過程式碼混淆配置,其實一樣,大家可以把之前在eclipse上的配置檔案直接拿過來用。不管是.cfg檔案還是proguard-rules.pro檔案都一樣。

先給大家貼一個混淆模板吧。註釋很清楚。是我目前一個專案用的proguard.cfg配置檔案

#指定程式碼的壓縮級別
-optimizationpasses5
 
#包明不混合大小寫
-dontusemixedcaseclassnames
 
#不去忽略非公共的庫類
-dontskipnonpubliclibraryclasses
 
 #優化  不優化輸入的類檔案
-dontoptimize
 
 #預校驗
-dontpreverify
 
 #混淆時是否記錄日誌
-verbose
 
 # 混淆時所採用的演算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
 
#保護註解
-keepattributes *Annotation*
 
# 保持哪些類不被混淆
-keeppublicclass* extendsandroid.app.Fragment
-keeppublicclass* extendsandroid.app.Activity
-keeppublicclass* extendsandroid.app.Application
-keeppublicclass* extendsandroid.app.Service
-keeppublicclass* extendsandroid.content.BroadcastReceiver
-keeppublicclass* extendsandroid.content.ContentProvider
-keeppublicclass* extendsandroid.app.backup.BackupAgentHelper
-keeppublicclass* extendsandroid.preference.Preference
-keeppublicclasscom.android.vending.licensing.ILicensingService
#如果有引用v4包可以新增下面這行
-keeppublicclass* extendsandroid.support.v4.app.Fragment
  
 
#忽略警告
-ignorewarning
 
#####################記錄生成的日誌資料,gradle build時在本專案根目錄輸出################
 
#apk 包內所有 class的內部結構
-dumpclass_files.txt
#未混淆的類和成員
-printseeds seeds.txt
#列出從 apk 中刪除的程式碼
-printusage unused.txt
#混淆前後的對映
-printmapping mapping.txt
 
#####################記錄生成的日誌資料,gradle build時 在本專案根目錄輸出-end################
 
 
################<span></span>混淆保護自己專案的部分程式碼以及引用的第三方jar包library#########################
#-libraryjars libs/umeng-analytics-v5.2.4.jar
#-libraryjars libs/alipaysd<span></span>k.jar
#<span></span>-libraryjars libs/alipaysecsdk.jar
#-libraryjars libs/alipayutdid.jar
#-libraryjars libs/wup-1.0.0-SNAPSHOT.jar
#-libraryjars libs/weibosdkcore.jar
 
 
#三星應用市場需要新增:sdk-v1.0.0.jar,look-v1.0.1.jar
#-libraryjars libs/sdk-v1.0.0.jar
#-libraryjars libs/look-v1.0.1.jar
 
#我是以libaray的形式引用了一個圖片載入框架,如果不想混淆 keep 掉
-keepclasscom.nostra13.universalimageloader.** { *; }
 
#友盟
-keepclasscom.umeng.**{*;}
 
#支付寶
-keepclasscom.alipay.android.app.IAliPay{*;}
-keepclasscom.alipay.android.app.IAlixPay{*;}
-keepclasscom.alipay.android.app.IRemoteServiceCallback{*;}
-keepclasscom.alipay.android.app.lib.ResourceMap{*;}
 
 
#信鴿推送
-keepclasscom.tencent.android.tpush.**  {* ;}
-keepclasscom.tencent.mid.**  {* ;}
 
 
#自己專案特殊處理程式碼
 
#忽略警告
-dontwarn com.veidy.mobile.common.**
#保留一個完整的包
-keepclasscom.veidy.mobile.common.** {
    *;
 }
 
-keepclass com.veidy.activity.login.WebLoginActivity{*;}
-keepclass com.veidy.activity.UserInfoFragment{*;}
-keepclass com.veidy.activity.HomeFragmentActivity{*;}
-keepclass com.veidy.activity.CityActivity{*;}
-keepclass com.veidy.activity.ClinikActivity{*;}
 
#如果引用了v4或者v7包
-dontwarn android.support.**
 
############<span></span>混淆保護自己專案的部分程式碼以及引用的第三方jar包library-end##################
 
-keeppublicclass* extendsandroid.view.View {
    public<init>(android.content.Context);
    public<init>(android.content.Context, android.util.AttributeSet);
    public<init>(android.content.Context, android.util.AttributeSet, int);
    publicvoidset*(...);
}
 
#保持 native 方法不被混淆
-keepclasseswithmembernamesclass* {
    native <methods>;
}
 
#保持自定義控制元件類不被混淆
-keepclasseswithmembersclass* {
    public<init>(android.content.Context, android.util.AttributeSet);
}
 
#保持自定義控制元件類不被混淆
-keepclasseswithmembersclass* {
    public<init>(android.content.Context, android.util.AttributeSet, int);
}
#保持自定義控制元件類不被混淆
-keepclassmembersclass*extendsandroid.app.Activity {
   publicvoid*(android.view.View);
}
 
#保持 Parcelable 不被混淆
-keepclass*implementsandroid.os.Parcelable {
  publicstaticfinal android.os.Parcelable$Creator *;
}
 
#保持 Serializable 不被混淆
-keepnamesclass*implementsjava.io.Serializable
 
#保持 Serializable 不被混淆並且enum 類也不被混淆
-keepclassmembersclass*implementsjava.io.Serializable {
    staticfinallongserialVersionUID;
    privatestaticfinal java.io.ObjectStreamField[] serialPersistentFields;
    !static!transient <fields>;
    !private<fields><span></span>;
    !private<methods>;
    privatevoidwriteObject(java.io.ObjectOutputStream);
    privatevoidreadObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}
 
#保持列舉 enum 類不被混淆 如果混淆報錯,建議直接使用上面的 -keepclassmembers class*implementsjava.io.Serializable即可
#-keepclassmembers enum * {
# publicstatic**[] values();
# publicstatic** valueOf(java.lang.String);
#}
 
-keepclassmembersclass* {
    publicvoid*ButtonClicked(android.view.View);
}
 
#不混淆資源類
-keepclassmembersclass**.R$* {
    publicstatic<fields>;
}
 
#避免混淆泛型 如果混淆報錯建議關掉
#–keepattributes Signature
 
#移除log 測試了下沒有用還是建議自己定義一個開關控制是否輸出日誌
#-assumenosideeffectsclassandroid.util.Log {
#   publicstaticboolean isLoggable(java.lang.String, int);

#   publicstaticint v(...);
#   publicstaticint i(...);
#   publicstaticint w(...);
#   publicstaticint d(...);
#   publicstaticint e(...);
#}

另外加上一段,如果用用到Gson解析包的,直接新增下面這幾行就能成功混淆,不然會報錯。

#gson
#-libraryjars libs/gson-2.2.2.jar
-keepattributes Signature
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { *; }

如果你使用了webview
# webview + js
-keepattributes *JavascriptInterface*
# keep 使用 webview 的類
-keepclassmembersclass  com.veidy.activity.WebViewActivity {
   public*;
}
# keep 使用 webview 的類的所有的內部類
-keepclassmembers class  com.veidy.activity.WebViewActivity$*{
    *;
}

?

大家可以先看看這篇文章

瞭解一下打包過程。

然後大家看看打包的配置檔案build.gradle裡面的一段配置程式碼

  //混淆,新版本是ninifyEnabled不再是runproguard   minifyEnabled true   //載入預設混淆配置檔案及自定義混淆 配置 proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard.cfg' 我們設定minifyEnabled true,就會在打包的時候進行程式碼混淆處理. 其中proguard-android.txt不用管,在sdk目錄裡面,我們主要是配置了proguard.cfg檔案。可能大家直接在android studio建立專案不會有這個檔案,而是 proguard-rules.pro檔案,其實一樣的,我這裡是因為專案是從eclipse遷移過來的,之前在eclipse上混淆是 proguard.cfg檔案.

一切就緒後,就是打包了。這裡我就不再多說了,大家可以去看

我這裡用第二種,gradle 命令打包.我建議大家在gradle clean後,不要直接gradle build,而是用gradleassembleRelease .用gradle build第一是因為慢,第二,我自己專案打包時這樣遇到一個錯誤,現在也沒解決

Lint found errors in the project; aborting build.
  
  Fix the issues identified by lint, or add the following to your build script to proceed with errors:
  ...
  android {
      lintOptions {
          abortOnError false
      }
  }
  ...

可以我明明已經設定

//執行lint檢查,有任何的錯誤或者警告提示,都會終止構建,我們可以將其關掉。
    lintOptions {
        abortOnError false
    }
搞不清楚。希望大家誰知道的也告訴下我。

當我們執行命令 gradle build或者gradleassembleRelease後,會自動進行混淆操作。。。直到成功。

各位 注意下,如果你的混淆配置有問題,可能會報錯。Execution failed for task ':proguardUmengRelease'.大家可以根據報錯去排除問題,

比如說我遇到的一個問題,

出現這個問題是因為配置檔案裡面我有一行 keepattributes Signature #避免混淆泛型 , 如果混淆報錯建議關掉,因為下面這個就會避免混淆泛型
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient <fields>;
    !private <fields>;
    !private <methods>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}
大家可以看到這個錯誤提示,有一個line 168 ,這個是行號,但是各位注意了這個行號定位不是特別精準,只能一個大概的定位。 混淆真正的成功與否,需要我們自己來親自驗證,那就是我們來破解自己的apk.我上傳了 一個我使用的破解工具 連結: http://pan.baidu.com/s/1o60tLj0 密碼: 3bqp  1,解壓apk.用好壓就能直接解壓,獲取到classes.dex檔案 2.用dex2jar這個工具來生成classes_dex2jar檔案.  a,把剛剛解壓出來的classes.dex檔案放到dex2jar根目錄,然後用dos命令定位到該目錄,執行命令dex2jar.bat classes.dex直到done. 2.細心的朋友就會發現多了一個jar檔案。 .  c.然後用jd-gui開啟這個jar檔案,就能看到專案的結構了。。 如果有a.b.c這些,就說明混淆成功啦