您的位置:首页 > 移动开发 > Android开发

Android混淆那些事儿

2015-10-16 19:36 253 查看
博客: 安卓之家

微博: 追风917

CSDN: 蒋朋的家

简书: 追风917

博客园:追风917

Android混淆

Android混淆是Android开发者经常使用的一种用于代码防止被反编译的常见手法,一般在Release模式生效,主要有三个作用:

1 压缩、优化、删除代码;

2 一定程度上提高反编译后被读懂的难度;

3 通过删除代码功能实现的特殊作用。

比如在可以运用混淆技术在发布版本不打印 Log.d等调试信息,防止敏感信息泄露,而在dubug模式下可以打印所有调试信息方便调试。

Android混淆技术

1 Java类名、方法名混淆

Dalvik字节码包含了大量的调试信息,如类名、方法名、字段名、参数名、变量名等,使用反编译工具可以还原这些信息。从Android2.3开始,Google在SDK中加入了一款叫ProGuard的Android混淆工具,ProGuard会删除这些调试信息,并用无意义的字符序列来替换类名、方法名等,使得使用反编译出来的代码难以阅读,提升逆向难度。使用ProGuard 对Android混淆过后,反编译出来的类名和方法名无法阅读,但是反编译出来的功能代码仍然是非常容易阅读的,和源代码差不多,破解者仍通过阅读功能代码来自行标记类名、方法名等,然后逆向破解。

2 Java代码混淆

通过对功能代码流程进行乱序混淆,实际运行时乱序Android混淆后的代码流程却和原始代码流程是一样的,但反编译出来的代码流程静态阅读时与原始流程有很大差异,使破解者很难通过静态分析理解代码功能,从而保护Android混淆代码不被逆向分析。比如,原始的代码流程是1->2->3->4->5->6->7,经过乱序Android混淆后静态反汇编查看到的代码流程可能变成2->7->5->1->6->4->3,实际运行时代码流程仍然是1->2->3->4->5->6->7。

3 Dalvik字节码加密

将dex文件中的部分或全部Dalvik字节码加密,Android混淆,每次需要执行时由专门的Native代码负责动态解密和回填,静态反编译出来的代码已经无法阅读甚至无法反编译,动态调试也难以逆向分析。

4 Android apk加密

Android混淆可以保证源代码的一定安全,但是并不全面。Android apk加密技术包括:DEX加壳保护,DEX指令动态加载保护和高级源码混淆保护。其中DEX加壳保护通过将DEX文件隐藏,并生成一个类似于虚像的壳文件,阻止黑客利用反编译工具获取App源码。

Android Studio下的混淆

在as下混淆安卓项目,只要在build.gradle脚本里设置 一下即可,比如我们可以这样设置:

buildTypes {
debug {
minifyEnabled false
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}


在debug模式下,不混淆,release正式发布版本里混淆,此时用到了两个文件,一个是sdk/tools/proguard/proguard-android.txt文件, 一个是项目下的proguard-rules.pro文件。

一般情况,我们只需要修改proguard-rules.pro文件,把不需要混淆的部分在该文件中声明,因为有些类已经混淆过,。比如使用百度地图安卓sdk需要在proguard-rules.pro中加入下面代码:

-keep class com.baidu.** {*;}
-keep class vi.com.** {*;}
-dontwarn com.baidu.**


注意

使用gson,fastjsoon时,bean类不需要混淆
,否则会出错,为此还特意请教了大神,哈哈。

因为他们利用发射来解析json,混淆后找不到对应的变量导致空指针。

在android Manifest文件中的activity,service,provider, receiver,等都不能进行混淆。一些在xml中配置的view也不能进行混淆,当然,这些在sdk里默认配置文件proguard-android.txt中都有,就不用我们配置咯。

混淆后代码的调试

1 混淆之后,会给我们输出一些文件,android studio 在目录app/build/outputs/mapping下有以下文件:

dump.txt 描述apk文件中所有类文件间的内部结构。

mapping.txt 列出了原始的类,方法,和字段名与混淆后代码之间的映射,常用。

seeds.txt 列出了未被混淆的类和成员

usage.txt 列出了从apk中删除的代码

当我们发布的release版本的程序出现bug时,可以通过以上文件(特别是mapping.txt)找到错误原始的位置,进行bug修改。同时,可能一开始的proguard配置有错误,也可以通过错误日志,根据这些文件,找到哪些文件不应该混淆,从而修改proguard的配置。

注意:重新release编译后,这些文件会被覆盖,所以每发布一次程序,最好都保存一份配置文件。

2 通过mapping.txt,通过映射关系找到对应的类,方法,字段来修复bug。

这里需要利用sdk给我们提供的retrace脚本,可以将一个被混淆过的堆栈跟踪信息还原成一个可读的信息,window下时retrace.bat,linux和mac是retrace.sh,该脚本的位置在*/sdk/tools/proguard/bin/下。语法为:

]" data-snippet-id="ext.5566de12923e7ebc4b9eae5e4e2a4c85" data-snippet-saved="false" data-csrftoken="OtqdR9RL-xHWDK1NhNHUYjhS1tu4eS2U8-ts" data-codota-status="done">[code]retrace.bat|retrace.sh [-verbose] mapping.txt [<stacktrace_file>]


例如:

./retrace.sh -verbose mapping.txt a.txt


其中的a.txt文件可以新建,然后把logcat的错误信息复制后粘贴到a.txt即可。

如果你没有指定,retrace工具会从标准输入(一般是键盘)读取。

这里有个小技巧:不用mapping也可以显示行号,避免Unknown Source

很简单,在混淆里加这么一句就可以:

-keepattributes SourceFile,LineNumberTable


这样,apk包会增大一些,我5.8M的包增加254K大小,还是可以接受的。

3 可以参考无源码调试:传送门——Smalidea无源码调试 android 应用

enjoy!

悦分享,越快乐^_^

欢迎交流,转载请注明出处,谢谢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 混淆