欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

详解Android的反编译和代码混淆

程序员文章站 2023-11-13 13:55:16
前言 包括以下内容 要反编译apk需要下面3个工具 反编译资源文件 反编译类文件 代码混淆 要反编译apk需要下面3个工具 1、apk...

前言

包括以下内容

  1. 要反编译apk需要下面3个工具
  2. 反编译资源文件
  3. 反编译类文件
  4. 代码混淆

要反编译apk需要下面3个工具

1、apktool(资源文件获取)
作用:资源文件获取,可以提取图片文件和布局文件进行使用查看

2、dex2jar(源文件获取)
作用:将apk反编译成java源码(classes.dex转化成jar文件)

3、jd-gui
作用:查看apk中classes.dex转化成的jar文件,即源码文件

下面进行反编译资源文件和类文件:

反编译资源文件

资源文件:包括图片资源、布局资源、动画、样式等其他资源

详解Android的反编译和代码混淆 

详解Android的反编译和代码混淆 

详解Android的反编译和代码混淆 

这样资源文件都可以看得到了。

反编译类文件

方式一:反编译得到java类

1.下载并解压dex2jar-2.0,得到dex2jar-2.0文件夹,里面包含dex2jar.bat及其文件

2.将apk文件改为xx.zip文件,并解压得到classes.dex文件,并将其复制到dex2jar-2.0文件夹中

3

详解Android的反编译和代码混淆 

生成一个classes-dex2jar.jar文件,使用jd-gui.exe打开生成的classes-dex2jar.jar文件

方式二:直接使用smali2java工具

什么是smali?smali是将android字节码用可阅读的字符串形式表现出来的一种语言,可以称之为android字节码的反汇编语言。

代码混淆

只能混淆java类,不能混淆资源文件。系统定义的组件不能混淆。必须是导出的apk。

如何实现代码混淆

混淆类文件

修改module:app下的build.gradle

  buildtypes {
    release {
      //是否需要混淆,默认false代表不混淆,true代表混淆
      minifyenabled true
      //混淆需要用到的一个工具:proguard,对应的一个文件是:proguard-android.txt(这个文件在android-sdk \tools\proguard目录下)
      //proguard是一个压缩、优化和混淆java字节码文件的免费工具
      proguardfiles getdefaultproguardfile('proguard-android.txt'), 'proguard-rules.pro'
    }

在proguard-rules.pro中添加:

详解Android的反编译和代码混淆 

把下面代码,放入proguard-rules.pro文末:

#指定代码的压缩级别
-optimizationpasses 5

#包明不混合大小写
-dontusemixedcaseclassnames

#不去忽略非公共的库类
-dontskipnonpubliclibraryclasses

#优化 不优化输入的类文件
-dontoptimize

#预校验
-dontpreverify

#混淆时是否记录日志
-verbose

# 混淆时所采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

#保护注解
-keepattributes *annotation*

# 保持哪些类不被混淆
-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

#忽略警告
-ignorewarning

##记录生成的日志数据,gradle build时在本项目根目录输出##

#apk 包内所有 class 的内部结构
-dump class_files.txt
#未混淆的类和成员
-printseeds seeds.txt
#列出从 apk 中删除的代码
-printusage unused.txt
#混淆前后的映射
-printmapping mapping.txt

########记录生成的日志数据,gradle build时 在本项目根目录输出-end######

#####混淆保护自己项目的部分代码以及引用的第三方jar包library#######

#-libraryjars libs/umeng-analytics-v5.2.4.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


#如果不想混淆 keep 掉
-keep class com.lippi.recorder.iirfilterdesigner.** {*; }
#友盟
-keep class com.umeng.**{*;}
#项目特殊处理代码

#忽略警告
-dontwarn com.lippi.recorder.utils**
#保留一个完整的包
-keep class com.lippi.recorder.utils.** {
     *;
}

-keep class com.lippi.recorder.utils.audiorecorder{*;}

#如果引用了v4或者v7包
-dontwarn android.support.**

####混淆保护自己项目的部分代码以及引用的第三方jar包library-end####

-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>;
}

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

#保持自定义控件类不被混淆
-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>;
}

#避免混淆泛型 如果混淆报错建议关掉
#–keepattributes signature

#移除log 测试了下没有用还是建议自己定义一个开关控制是否输出日志
#-assumenosideeffects class android.util.log {
#  public static boolean isloggable(java.lang.string, int);
#  public static int v(...);
#  public static int i(...);
#  public static int w(...);
#  public static int d(...);
#  public static int 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.** { *; }

同步,然后再打包

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。