首页
论坛
专栏
课程

[原创]APK反破解之一:Android Java混淆(ProGuard)

2011-7-13 22:05 48017

[原创]APK反破解之一:Android Java混淆(ProGuard)

2011-7-13 22:05
48017
转载请注明出处:http://www.blogjava.net/zh-weir/archive/2011/07/12/354190.html

Android Java混淆(ProGuard)ProGuard简介

ProGuard是一个SourceForge上非常知名的开源项目。官网网址是:http://proguard.sourceforge.net/

Java的字节码一般是非常容易反编译的。为了很好的保护Java源代码,我们往往会对编译好的class文件进行混淆处理。ProGuard的主要作用就是混淆。当然它还能对字节码进行缩减体积、优化等,但那些对于我们来说都算是次要的功能。

引用ProGuard官方的一段话来介绍就是:

ProGuard is a free Java class file shrinker, optimizer, obfuscator, and preverifier. It detects and removes unused classes, fields, methods, and attributes. It optimizes bytecode and removes unused instructions. It renames the remaining classes, fields, and methods using short meaningless names. Finally, it preverifies the processed code for Java 6 or for Java Micro Edition.

Android Eclipse开发环境与ProGuard

在Android 2.3以前,混淆Android代码只能手动添加proguard来实现代码混淆,非常不方便。而2.3以后,Google已经将这个工具加入到了SDK的工具集里。具体路径:SDK\tools\proguard。当创建一个新的Android工程时,在工程目录的根路径下,会出现一个proguard的配置文件proguard.cfg。也就是说,我们可以通过简单的配置,在我们的elipse工程中直接使用ProGuard混淆Android工程。

具体混淆的步骤非常简单。首先,我们需要在工程描述文件default.properties中,添加一句话,启用ProGuard。如下所示:

# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
# 
# This file must be checked in Version Control Systems.
# 
# To customize properties used by the Ant build system use,
# "build.properties", and override values to adapt the script to your
# project structure.
# Indicates whether an apk should be generated for each density.
split.density=false
# Project target.
target=android-10
proguard.config=proguard.cfg


这样,Proguard就可以使用了。当我们正常通过Android Tools导出Application Package时,Proguard就会自动启用,优化混淆你的代码。



导出成功后,你可以反编译看看混淆的效果。一些类名、方法名和变量名等,都变成了一些无意义的字母或者数字。证明混淆成功!

proguard.cfg配置

稍微深入想一下混淆后的结果,你就会发现,如果一些提供给外部的类、方法、变量等名字被改变了,那么程序本身的功能就无法正常实现。那么Proguard如何知道哪些东西是可以改名,而哪些是不能改变的呢?

这个是靠proguard.cfg文件来进行配置的。Android工程中默认自动生成的proguard.cfg已经针对Android的一般情况进行了配置,我们打开这个配置文件。内容大概如下:

-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-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
 
-keepclasseswithmembernames class * {
    native <methods>;
}
 
-keepclasseswithmembernames class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}
 
-keepclasseswithmembernames class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}
 
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}
 
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}
 


它主要保留了继承自Activity、Application、Service、BroadcastReceiver、ContentProvider、BackupAgentHelper、Preference和ILicensingService的子类。因为这些子类,都是可能被外部调用的。

另外,它还保留了含有native方法的类、构造函数从xml构造的类(一般为View的子类)、枚举类型中的values和valueOf静态方法、继承Parcelable的跨进程数据类。

在实际的一个工程项目中,可能Google自动生成的配置不能胜任我们的混淆工作。所以,我们往往需要自己编写一些ProGuard配置。这方面的资料在官网的Manual -> Usage里有详细说明。大家可以研究一下。

参考资料

《ProGuard 官方》
《Android 2.3 代码混淆proguard技术介绍》

转载请注明出处:http://www.blogjava.net/zh-weir/archive/2011/07/12/354190.html

[公告]安全服务和外包项目请将项目需求发到看雪企服平台:https://qifu.kanxue.com

上传的附件:
最新回复 (17)
gamehacker 1 2011-7-14 00:08
2
0
沙发?沙发?沙发?沙发?沙发?沙发?沙发?沙发?沙发?沙发?
guiyang 2011-8-14 18:42
3
0
收藏慢慢看吧
楼主的帖子都很赞
xiaocaijk 2011-9-22 12:46
4
0
学习 有空练习一下~
chenlm 2011-12-8 10:44
5
0
楼主。。我之前可以,Sdk升级后不能用了。有没有解决的办法
沙加L 1 2011-12-10 17:52
6
0
我反编绎过一些APK文件,混淆之后,原有的Activity类型的名字都没有改,就像你所说的一样!
------------------------------------------------------------------------------------------------------------
它主要保留了继承自Activity、Application、Service、BroadcastReceiver、ContentProvider、BackupAgentHelper、Preference和ILicensingService的子类。因为这些子类,都是可能被外部调用的。
ZhWeir 6 2011-12-12 10:44
7
0
对啊,是这样的。因为这些类需要被外部调用,因此不能改成别的名字,如果改了就无法供外部使用了。所以如果使用混淆的话,核心功能不应该放在这些无法混淆的类中。
kimgao 2012-1-4 23:12
8
0
呵呵~!代码混淆能避免被别人破解吗?
沙加L 1 2012-1-6 22:18
9
0
不能,只是会增加别人破解的难度。如果要防别人破解的话,最好的方法是使用NDK,用C、C++写的代码,用NDK编成so库,用JNI进行调用!
火翼[CCG] 6 2012-1-16 11:31
10
0
SO库文件包含符号, 调试也比java代码方便, 所以某种意义上说逆向so里面的native code比逆向java还容易
Isaiah 10 2012-1-16 12:30
11
0
[QUOTE='火翼[CCG];1038658']SO库文件包含符号, 调试也比java代码方便, 所以某种意义上说逆向so里面的native code比逆向java还容易[/QUOTE]

我近两年第一个顶贴就献给你了……。

Open Source 成就了 GNU Tool-chain. ELF里面符号表是“一等公民”. 所以默认选项生成的目标文件里面带符号,虽然可以通过选项分离符号,但是很多时候都会忽略了这一点。
不过我相信Open Source模式才是未来软件工程的王道。

发下牢骚:为了破解而破解很无聊。 论坛应该引导各位爱好者,多多归纳总结“技巧”,将其提升到方法论的高度。
siwen 2012-3-13 11:36
12
0
Java代码还是公开了好啊,混淆很伤感情。
实在需要保护的代码就做成 .so共享库吧~~~
zhaokang 3 2012-3-23 13:24
13
0
逆向.so共享库用什么软件,IDA行不,也能看到些东西...
kmsmxpro 2012-3-30 10:58
14
0
学习 有空练习一下~
tashika 2012-4-26 21:42
15
0
[QUOTE='火翼[CCG];1038658']SO库文件包含符号, 调试也比java代码方便, 所以某种意义上说逆向so里面的native code比逆向java还容易[/QUOTE]

同感 尤其是对我这种只会arm不会dalvik的人来说 呵呵
crackdung 2012-4-30 23:45
16
0
使用Trace選項,,你會有意想不到的去混淆
ndaye 2013-7-27 01:24
17
0
好文章 留名备用
shangrila 2013-9-25 20:25
18
0
还是有可能被破解,只是增加了难度,
游客
登录 | 注册 方可回帖
返回