Android 代码混淆机制

由于Android项目是基于java语言的,而java属于高层抽象语言,易于反编译,其编译后的程序包包含了大量的源代码变量、函数名、数据结构等信息,根据其编译打包后的APK文件,可以非常容易的得到 近乎源代码质量 的反编译代码。如果不加混淆,相当于直接将源代码拱手送人,内容严密的app权限审核可以说是形同虚设。如果大家想避免自己的成果被别人夺取,然后重新修改策划而额外增加的工作量,那就尽量得自己的Android项目加上混淆吧。

原理

android平台的混淆原理是把代码中原来有具体含义的包名,类名,变量名,方法名等名称全部替换成按顺序排列的无意义的英文字母a、b、c….这样代码结构没有变化,还可以运行得到一样的结果,并且就算代码被反编译出来,别人想弄懂代码的架构和具体意思也比较难。

具体方法

比较常用的方法有以下两种:

一、通过eclipse混淆代码

启用代码混淆

找到Android项目目录下的project.properties文件,如果需要对项目进行全局混码,只需要进行一步操作:将project.properties文件中的“# proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt”中的“#”去掉就可以了。

但是如果有一些代码不能被混淆,比如引入了第三方jar文件或加入了so文件,需要调用里面的方法,那么调用JNI访问so文件的方法就不能被混码。在导出的时候,可能不会报错。但是在手机上运行的时候,需要调用so文件的时候,就会报某某方法无法找到。这个时候就需要用到proguard-project.txt。

编写混淆脚本

找到Android项目目录下的“proguard-project.txt”文件,在proguard-project.txt文件中,你需要做的就是指定混淆规则,还有指明要过滤那些文件或代码块。具体内容来看一个例子:

-ignorewarnings-optimizationpasses 7 #指定代码的压缩级别 0 - 7-dontusemixedcaseclassnames #是否使用大小写混合-dontskipnonpubliclibraryclasses #是否混淆第三方jar-dontpreverify #混淆时是否做预校验(可去掉加快混淆速度)-verbose #混淆时是否记录日志(混淆后生产映射文件 map 类名 -> 转化后类名的映射-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* #淆采用的算法

-keep public class * extends android.app.Activity #所有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 #指定具体类不要去混淆

-keepclasseswithmembernames class * { native ; #保持 native 的方法不去混淆

}

-keepclasseswithmembers class * { public (android.content.Context, android.util.AttributeSet); #保持自定义控件类不被混淆,指定格式的构造方法不去混淆

}

-keepclasseswithmembers class * { public (android.content.Context, android.util.AttributeSet, int);

}

-keepclassmembers class * extends android.app.Activity { public void *(android.view.View); #保持指定规则的方法不被混淆(Android layout 布局文件中为控件配置的onClick方法不能混淆)

}

-keep public class * extends android.view.View { #保持自定义控件指定规则的方法不被混淆 public (android.content.Context);

public (android.content.Context, android.util.AttributeSet);

public (android.content.Context, android.util.AttributeSet, int);

public void set*(...);

}

-keepclassmembers enum * { #保持枚举 enum 不被混淆 public static **[] values();

public static ** valueOf(java.lang.String);

}

-keep class * implements android.os.Parcelable { #保持 Parcelable 不被混淆(aidl文件不能去混淆) public static final android.os.Parcelable$Creator *;

}

-keepnames class * implements java.io.Serializable #需要序列化和反序列化的类不能被混淆(注:Java反射用到的类也不能被混淆)

-keepclassmembers class * implements java.io.Serializable { #保护实现接口Serializable的类中,指定规则的类成员不被混淆 static final long serialVersionUID;

private static final java.io.ObjectStreamField[] serialPersistentFields;

!static !transient ;

private void writeObject(java.io.ObjectOutputStream);

private void readObject(java.io.ObjectInputStream);

java.lang.Object writeReplace();

java.lang.Object readResolve();

}

-keepattributes Signature #过滤泛型(不写可能会出现类型转换错误,一般情况把这个加上就是了)

-keepattributes *Annotation* #假如项目中有用到注解,应加入这行配置

-keep class **.R$* { *; } #保持R文件不被混淆,否则,你的反射是获取不到资源id的

-keepclassmembernames class com.cgv.cn.movie.common.bean.** { *; } #转换JSON的JavaBean,类成员名称保护,使其不被混淆

-assumenosideeffects #g过滤代码中的日志class android.util.Log

{

public static ***

e(...);

public static ***

w(...);

public static ***

wtf(...);

public static ***

d(...);

public static ***

v(...);

}

# 下面都是项目中引入的第三方 jar包 ==== 引入jar包的绝对路径

#-libraryjars libs/android-support-v4.jar

#-dontwarn android.support.v4.**

#-keep class android.support.v4.**{ *; }

#-keep interface android.support.v4.**{*;}

#-keep public class * extends android.support.v4.**{*;}

#-keep public class * extends android.app.Fragment

-libraryjars libs/armeabi-v7a/libijkffmpeg.so

-dontwarn com.google.protobuf.nano.**-keep class com.google.protobuf.nano.**{*;}

-dontwarn com.google.gson.**-keep class com.google.gson.**{*;}

# 第三方统计SDK友盟相关过滤

-keepclassmembers class * { #友盟SDK中的部分代码使用,反射来调用构造函数 public (org.json.JSONObject);

}

-keep public class [com.wormhole.sdk].R$*{ #过滤R文件,友盟SDK需要引用导入工程的资源文件public static final int *;

}

具体哪行代码是什么作用大部分上面都有注释,比较常用的有以下几点:

1.从脚本中可以看到,混淆中保留了继承自Activity、Service、Application、BroadcastReceiver、ContentProvider等基本组件。

2.保留了所有的Native变量名及类名,所有类中部分以设定了固定参数格式的构造函数,枚举等等。(详细信息请参考\examples中的例子及注释)

3.需要序列化和反序列化的类不能被混淆。(注:Java反射用到的类也不能被混淆)

4.保持R文件不被混淆,否则,你的反射是获取不到资源id的。

5.过滤引入的第三方jar包,so文件和外部lib等

//过滤第三方jar包,com.google.gson替换成要想要过滤的包名

-dontwarn com.google.gson.**

-keep class com.google.gson.**{*;}

//过滤so文件,libs/armeabi-v7a/libijkffmpeg.so换成想过滤的搜文件路径

-libraryjars libs/armeabi-v7a/libijkffmpeg.so

打包测试

编写完混淆脚本后就可以直接用eclipse签名打包出APK文件了,但是有时候可能有混淆脚本有错误或遗漏,导致打包失败的情况,这时候就得检查混淆文件哪里出了错。还有一种情况是可以正常打包出APK文件,但是不一定能运行,能运行也会在某一步上出错,这种情况一般是因为把代码中不可混淆的字段或文件给混淆了比如引入的jar包和so文件等,导致程序功能变化。

二、通过ProGuard工具混淆代码

如果你想把你的Android项目打包成jar文件然后再混淆,那这种方法比较适合

下载运行ProGuard工具

1.首先到http://proguard.sourceforge.net/下载proguard,目前我下载并使用的是proguard5.1

2.解压proguard5.1,执行 bin目录下的proguardgui.bat文件打开ProGuard工具

从Android项目到处jar包

笔者是通过eclipse来到处Android项目jar包的,用Android Studio来做也差不多,这就不过多介绍了。

eclipse中右键点击项目Export–>Java–>JAR file–>Next,然后出现如下界面

只需要选择java文件即可,其他配置文件什么的都不用选择

配置ProGuard工具

1.打开ProGuard工具,点击左边“input/output”菜单,然后点击右边的“Add input”按钮,添加需要混淆的jar包,我这里是test.jar,然后点击“add output”,选择输出的路径和包名。

2.添加支持库,这个地方很重要,很多同学刚开始使用这个工具的时候就是这里老是出问题。点击右边的“add”。

这里需要注意一下,最好把你的eclipse里java project里的libraries所有Library的jar包,包含web项目lib下面的包,jdk中jre下面的包和servlet.jar包等copy到一个目录,然后在这里加入这些jar包。系统默认会带上rt.jar,这里我们可以先remove掉,然后到jre下面copy所有的包。

3.切换左侧的“shrinking”,obfuscation”和“optimization”等标签来设置你所需要的混淆规则。

4.点击information,设置如图所示,注意选择jdk版本(Target选项)。

5.点击“process”,再点击“save configuration”,在弹出的对话框中,输入要保存的配置文件名称,最后点击“保存”。

至此就完成了jar文件的混淆,并保存了混淆文件。

当然,如果你已经写好的混淆文件,那么直接通过导入混淆文件进行混淆就行了。具体操作如下:

1.打开progrard目录,执行 bin目录下的proguardgui.bat。

2.点击第一个选项“Proguard”,再点击“Load configuration”,选择你的混淆文件进行加载。

3.然后点击Process,然后点击View configuration查看是否是已经修改过后的配置文件。

检测测试混淆后的jar文件

如果混淆过程中出错,可以在View configuration查看错误日志,然后直接通过文本编辑器打开混淆配置文件,然后进行相应修改。

Ending

好了,至此已经把我所了解的Android混淆机制及使用方法介绍完毕,如果有错误的地方或者有不明了之处请大家留言指出。

android 混淆后的机制,Android 代码混淆机制相关推荐

  1. Android之如何看混淆后的错误日志代码

    第一步: 找到混淆的mapping.txt文件 build -> outputs -> mapping -> release -> mapping.txt 或者:1项目目录的p ...

  2. android 打包 混淆配置_玩转代码混淆工具:ProGuard

    维基百科对ProGuard的介绍是:ProGuard是一个压缩(shrink),优化(optimize)与混淆(Obfuscate)Java代码的开源命令行工具.也就是说混淆只是ProGuard的其中 ...

  3. android更新后名称不变,Android 10这个新名字虽然无聊 但改名却是正确之举

    本文由腾讯数码独家发布 自从2009年谷歌发布Android 1.5 Cupcake系统以来,安卓的每个新版本系统在数字后面都会加一个糕点或甜品的名称来起到点缀以及个性化的作用.比如对我个人来说,冰淇 ...

  4. android 动画后的位置,Android:Comp之后会重置动画位置

    Android:Comp之后会重置动画位置 我正在使用xml定义的动画将视图滑出屏幕. 问题是,动画完成后,它将立即重置为其原始位置. 我需要知道如何解决这个问题. 这是xml: 这是我用来调用它的J ...

  5. android layout后还原位置,Android图片框架photoview如何记住所有状态并还原,包括缩放度,缩放后的移动的距离等等...

    Android图片框架photoview如何记住状态并还原,包括缩放度,缩放后的移动的距离等等,尝试了好多方法都没有作用. private void generateImages() { for (i ...

  6. 读懂Android中的代码混淆

    本文为本人的一些实践总结,介绍一些混淆的知识和注意事项.希望可以帮助大家更好的学习和使用代码混淆. 什么是混淆 关于混淆维基百科上该词条的解释为 代码混淆(Obfuscated code)亦称花指令, ...

  7. 读懂 Android 中的代码混淆

    在Android开发工作中,我们都或多或少接触过代码混淆.比如我们想要集成某个SDK,往往需要做一些排除混淆的操作. 本文为本人的一些实践总结,介绍一些混淆的知识和注意事项.希望可以帮助大家更好的学习 ...

  8. Android 中的代码混淆

    在Android开发工作中,我们都或多或少接触过代码混淆.比如我们想要集成某个SDK,往往需要做一些排除混淆的操作. 本文为本人的一些实践总结,介绍一些混淆的知识和注意事项.希望可以帮助大家更好的学习 ...

  9. android混淆成不可见字符,读懂 Android 中的代码混淆

    在Android开发工作中,我们都或多或少接触过代码混淆.比如我们想要集成某个SDK,往往需要做一些排除混淆的操作. 本文为本人的一些实践总结,介绍一些混淆的知识和注意事项.希望可以帮助大家更好的学习 ...

最新文章

  1. 不擅长物理科学计算机吗,物理难学否?答案因人而异,高二同学3 + 3选科莫要太随意...
  2. 表决器c语言课程设计,项目二:玩转RGB点阵屏——表情表决器
  3. SqlServer 算法 :Nested Loops Join(嵌套连接)
  4. ImportError: cannot import name 'is_string_like'
  5. 随想录(程序调试与dll注入)
  6. Windows 无法删除文件夹的只读
  7. 附录A 编译安装Hadoop
  8. 编解码器的学习笔记(十):Ogg系列
  9. USACO Section 1.3 Prime Cryptarithm 解题报告
  10. React入门第一天(绑定事件,动态渲染,修改样式、传参)
  11. 梦织未来Windows驱动编程 第03课 驱动的编程规范
  12. 惠普179fnw打印机使用说明_惠普179fnw驱动下载
  13. c语言中万年历公历农历转换,公历农历转换,教你切换阳历和阴历生日
  14. 20年前的网文:我彷徨在唯物主义和唯心主义之间
  15. 计算机二级C语言选择题——01
  16. Android隐藏虚拟按键
  17. Linux进程管理四大工具ps \dstat\ top\ htop
  18. Java - 计算两个经纬度之间的直线距离
  19. 人力资源年终数据分析报告怎么写?这份攻略拿走不谢
  20. JScript.NET或者JScript是什么?

热门文章

  1. 3DMAX中CryEngine导出插件的配置方法
  2. 自来水中锰超标怎么办
  3. 呦呦,这些代码有点臭,重构大法带你秀(SPI接口化),skr~
  4. 链表结点的物理顺序与逻辑顺序
  5. Git merge时使用--no-ff参数
  6. 站长百科访谈第59期:张清分享网站优化技巧
  7. PgRouting求解大数据量最短路径
  8. DirectX11.2前哨战 R7/R9显卡性能首测
  9. 爱奇艺体育与巴塞罗那足球俱乐部达成合作;中国机械工业百强、汽车工业整车二十强公布 | 美通企业日报...
  10. myBase Desktop 6.x 用户手册