天天看点

Android APK反编译以及代码混淆

一,反编译

在学习Android开发的过程你,你往往会去借鉴别人的应用是怎么开发的,那些漂亮的动画和精致的布局可能会让你爱不释手,作为一个开发者,你可能会很想知道这些效果界面是怎么去实现的,这时,你便可以对改应用的APK进行反编译查看。下面是我参考了一些文章后简单的教程详解。

(注:反编译不是让各位开发者去对一个应用破解搞重装什么的,主要目的是为了促进开发者学习,借鉴好的代码,提升自我开发水平。)

测试环境:

        win 7 

使用工具:

     CSDN上下载地址:

       apktool (资源文件获取)  下载  

       dex2jar(源码文件获取) 下载

       jd-gui  (源码查看) 下载

工具介绍:

apktool  

     作用:资源文件获取,可以提取出图片文件和布局文件进行使用查看

dex2jar

     作用:将apk反编译成Java源码(classes.dex转化成jar文件)

jd-gui

     作用:查看APK中classes.dex转化成出的jar文件,即源码文件

反编译流程:

一、apk反编译得到程序的源代码、图片、XML配置、语言资源等文件

下载上述工具中的apktool,解压得到3个文件:aapt.exe,apktool.bat,apktool.jar ,将需要反编译的APK文件放到该目录下,

打开命令行界面(运行-CMD) ,定位到apktool文件夹,输入以下命令:apktool.bat d -f  test.apk  test    

Android APK反编译以及代码混淆

(命令中test.apk指的是要反编译的APK文件全名,test为反编译后资源文件存放的目录名称,即为:apktool.bat   d  -f    [apk文件 ]   [输出文件夹])

Android APK反编译以及代码混淆

说明获取成功,之后发现在文件夹下多了个test文件,点击便可以查看该应用的所有资源文件了。

如果你想将反编译完的文件重新打包成apk,那你可以:输入apktool.bat   b    test(你编译出来文件夹)便可,效果如下:

Android APK反编译以及代码混淆

之后在之前的test文件下便可以发现多了2个文件夹:

build

dist(里面存放着打包出来的APK文件)

二、Apk反编译得到Java源代码

下载上述工具中的dex2jar和jd-gui ,解压

将要反编译的APK后缀名改为.rar或则 .zip,并解压,得到其中的额classes.dex文件(它就是java文件编译再通过dx工具打包而成的),将获取到的classes.dex放到之前解压出来的工具dex2jar-0.0.9.15 文件夹内,

在命令行下定位到dex2jar.bat所在目录,输入dex2jar.bat   classes.dex,效果如下:

Android APK反编译以及代码混淆

在改目录下会生成一个classes_dex2jar.jar的文件,然后打开工具jd-gui文件夹里的jd-gui.exe,之后用该工具打开之前生成的classes_dex2jar.jar文件,便可以看到源码了,效果如下:

Android APK反编译以及代码混淆

被混淆过的效果图(类文件名称以及里面的方法名称都会以a,b,c....之类的样式命名):

Android APK反编译以及代码混淆

二,代码混淆

先看下代码没有混淆过被反编译的代码:(代码都可以看的见)

Android APK反编译以及代码混淆

关于代码混淆,大致如下:

Android APK反编译以及代码混淆

在app下的build.gradle文件中添加如下代码(minifyEnabled表示是否混淆,默认是false,这里要记得设置成true):  

其中proguard-andorid.txt文件是本地sdk/tool/proguard 文件夹下的默认文件;接下来prguard-rules.pro文件就是用来编写混淆带代码的(下图是我从我们项目复制出来的):

#指定代码的压缩级别
 -optimizationpasses 5
 #包明不混合大小写
 -dontusemixedcaseclassnames
 #不去忽略非公共的库类
 -dontskipnonpubliclibraryclasses
  #优化  不优化输入的类文件
 -dontoptimize
  #不做预校验
 -dontpreverify
  #混淆时是否记录日志
 -verbose
  # 混淆时所采用的算法
 -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
  #忽略警告
 -ignorewarning
 #保护注解
 -keepattributes *Annotation*

#####################记录生成的日志数据,gradle build时在本项目根目录输出################
  #apk 包内所有 class 的内部结构
  -dump class_files.txt
  #未混淆的类和成员
  -printseeds seeds.txt
  #列出从 apk 中删除的代码
  -printusage unused.txt
  #混淆前后的映射
  -printmapping mapping.txt

    #我是以libaray的形式引用了一些框架,如果不想混淆 keep 掉
    -keep class com.android.support.** { *; }
    -keep class com.github.bumptech.glide.** { *; }
#    -keep class com.jakewharton:butterknife.** { *; }
    -keep class com.readystatesoftware.systembartint.** { *; }
#    -keep class com.yqritc:recyclerview-flexibledivider.** { *; }
#    -keep class com.jakewharton:butterknife.** { *; }
#    -keep class com.squareup.okhttp3:okhttp.** { *; }
    -keep class com.bartoszlipinski.** { *; }
#    -keep org.simple:androideventbus.** { *; }
#    -keep com.google.code.gson:gson.** { *; }


    #保持哪些类不被混淆 google默认 不混淆 Activity 、Service ... 类的子类
    #混淆了可能编译不通过
#    -keep public class * extends android.app.Fragment
#    -keep public class * extends android.app.Activity
    -keep public class * extends android.app.Application
    -keep public class * extends android.app.Service
    -keep public class * extends android.content.BroadcastReceiver
    -keep public class * extends android.content.ContentProvider
    -keep public class * extends android.app.backup.BackupAgentHelper
    -keep public class * extends android.preference.Preference
    -keep public class com.android.vending.licensing.ILicensingService
    #如果有引用v4包可以添加下面这行
    -keep public class * extends android.support.v4.app.Fragment
    #如果引用了v4或者v7包
     -dontwarn android.support.**
     -keep public class * extends android.view.View {
         public <init>(android.content.Context);
         public <init>(android.content.Context, android.util.AttributeSet);
         public <init>(android.content.Context, android.util.AttributeSet, int);
         public void set*(...);
     }

     #保持 native 方法不被混淆
    -keepclasseswithmembernames class * {
       native <methods>;
    }
    # Keep names - Native method names. Keep all native class/method names.
     -keepclasseswithmembers,allowshrinking class * {
         native <methods>;
     }

    #保持自定义控件类不被混淆
   -keepclasseswithmembers class * {
         public <init>(android.content.Context, android.util.AttributeSet);
     }

    #保持自定义控件类不被混淆
    -keepclasseswithmembers class * {
        public <init>(android.content.Context, android.util.AttributeSet, int);
    }

     #保持自定义控件类不被混淆
    -keepclassmembers class * extends android.app.Activity {
        public void *(android.view.View);
     }

     #保持 Parcelable 不被混淆
   -keep class * implements android.os.Parcelable {
       public static final android.os.Parcelable$Creator *;
     }

     #保持 Serializable 不被混淆
     -keepnames class * implements java.io.Serializable

     #保持 Serializable 不被混淆并且enum 类也不被混淆
   -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();
     }

     #保持枚举 enum 类不被混淆 如果混淆报错,建议直接使用上面的 -keepclassmembers class * implements java.io.Serializable即可
#   -keepclassmembers enum * {
#         public static **[] values();
#         public static ** valueOf(java.lang.String);
#     }

    -keepclassmembers class * {
        public void *ButtonClicked(android.view.View);
    }
     #不混淆资源类
   -keepclassmembers class **.R$* {
         public static <fields>;
     }

      #不混淆H5交互
   -keepattributes *JavascriptInterface*
     #ClassName是类名,H5_Object是与javascript相交互的object,建议以内部类形式书写
   -keepclassmembers   class **.ClassName$H5_Object{
                     *;
      }

   #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 + js
    -keepattributes *JavascriptInterface*
    # keep 使用 webview 的类
    -keepclassmembers class  com.veidy.activity.WebViewActivity {
       public *;
    }
    # keep 使用 webview 的类的所有的内部类
    -keepclassmembers  class  com.veidy.activity.WebViewActivity$*{
        *;
    }
   #keep model
   -keep class com.uyac.elegantlife.entity.**{*;}
   #keep 适配器
   -keep class com.uyac.elegantlife.adapter.**{*;}
      

混淆过的额代码截图:

Android APK反编译以及代码混淆
Android APK反编译以及代码混淆

这里要注意的是很多网上资料都注明主要子类不被混淆(那混淆还有什么意义),图为吧Fragment,Activity 子类都混淆,才有上图效果,不然代码还可以看的