android对app进行代码混淆

接到一个新的任务,对现有项目进行代码混淆。之前对混淆有过一些了解,但是不够详细和完整,知道有些东西混淆起来还是比较棘手的。不过幸好目前的项目不是太复杂(针对混淆这块来说),提前完成~~现总结之。

第一部分

介绍下操作流程(eclipse):

1、打开混淆器:找到项目根目录下的project.properties文件,将“#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt”这行前的“#”删除即可;

2、修改混淆配置文件:找到项目根目录下的proguard-project.txt文件,修改其中代码,这部分是最关键;

3、保存相关文件供以后出错时使用:主要有导出的apk文件、项目根目录下的proguard目录下的文件(主要的是mapping.txt)和项目源码;

4、项目运行过程出错处理:根据错误信息和第3步中保存的mapping定位错误位置。

知道这些之后,我们对其进行展开。打开eclipse然后新建一个项目,默认会创建proguard-project.txt和project.properties。编写我们的代码,然后将proguard-project.txt的“#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt”这行前的“#”删除,最后导出即可实现对代码的混淆,即使我们没有去编写proguard-project.txt中的内容。下面是我的测试代码:

public class MainActivity extends Activity {

	private String mName;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		mName = "ttdevs";

		getString(mName);
		setName(mName);
		showDialog();
		// testError();
	}

	public String getString(String name) {
		return "hello " + name;
	}

	public void setName(String name) {
		System.out.println("I'm " + name);
	}

	private void showDialog() {
		new Handler().postDelayed(new Runnable() {

			@Override
			public void run() {
				ScoreAlertDialog.showDialog(MainActivity.this);
			}
		}, 2000);
	}

	public static class ScoreAlertDialog {

		public static void showDialog(final Activity activity) {
			if (activity.isFinishing()) {
				return;
			}
			try {
				AlertDialog.Builder builder = new AlertDialog.Builder(activity);
				builder.setTitle("alert_title");
				builder.setNegativeButton("cancel", null);
				builder.setPositiveButton("submit", new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						try {
							Toast.makeText(activity, "Welcome", Toast.LENGTH_LONG).show();
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				});
				builder.show();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	private void testError() {
		try {
			int error = 1 / 0;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

打包,反编译,最后我们得到如下的代码:

分析上面的代码我们会发现,自定义的方法名都被替换成无特殊意义的短字母,而activity的onCreate()方法却没变;最后一个testError()方法由于我们没有调用也被剔除掉了。这些就是默认的混淆处理策略。看到这里,感觉混淆还是小case的哈~~

继续往下,我们将注销的testError()打开,打包运行这个时候会报错,错误信息如下:

 java.lang.ArithmeticException: divide by zero
 	at com.ttdevs.proguard.MainActivity.b(Unknown Source)
 	at com.ttdevs.proguard.MainActivity.onCreate(Unknown Source)
 	at android.app.Activity.performCreate(Activity.java:4531)
 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1071)
 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2150)
 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2229)
 	at android.app.ActivityThread.access$600(ActivityThread.java:139)
 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1261)
 	at android.os.Handler.dispatchMessage(Handler.java:99)
 	at android.os.Looper.loop(Looper.java:154)
 	at android.app.ActivityThread.main(ActivityThread.java:4945)
 	at java.lang.reflect.Method.invokeNative(Native Method)
 	at java.lang.reflect.Method.invoke(Method.java:511)
 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
 	at dalvik.system.NativeStart.main(Native Method)

由于这个例子比较简单,很容易看出来是何地方出了问题,不过还是可以用来说明我们想表达的问题:如何还原混淆后的代码的错误信息。为了达到这个目的,我们需要三个文件:android-sdk-windows\tools\proguard\bin\retrace.bat、mapping.txt和上面的错误信息(log.txt)。然后执行下面的命令(window系统):

retrace.bat mapping.txt log.txt

从上图中可以很清楚的看到错误日志中的b()方法为我们实际代码中的setName()方法。

这里需要注意的是每次导出apk都会在项目中目录下的proguard文件夹下生成一个对应的mapping文件,所以对于每个apk我们都需要保存与之对应的mapping文件。至此整个混淆的流程介绍完毕。

参考:

官方文档:http://developer.android.com/tools/help/proguard.html

官方文档的翻译:http://www.cnblogs.com/over140/archive/2011/04/22/2024528.html(本想自己去翻一个,结果发现很久以前农民伯伯已经翻译,在此直接引用并感谢之)

第二部分

第一部分讲了如何操作,参照官方文档,基本都会掌握。剩下的也是最难的就是proguard-project.txt文件的编写。对于这部分,两种处理策略:自己编写和使用别人写好的。先说如何使用别人写好的,我们引用的第三方库无论开源还是闭源如有特殊情况我们都可以在他的User Guide中找到混淆代码的配置,如我们引用了大名鼎鼎的guillep PullToRefresh,我们可以在他的文档中找到如下的代码:

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

有了这部分代码我们就可以直接copy插入我们的项目中即可。这种方式还是copy式的。那下面我们举个小例子看看如何自己写代码控制是否混淆。还是用第一部分的例子,我们在这个项目的proguard-project.txt文件中(之前为空)加入如下几行(proguard-project.txt中“#”代表注释):

# -keep public class com.ttdevs.proguard.** { *; }
# -keepclasseswithmembers public class com.ttdevs.proguard.** { *; }

-keep public class com.ttdevs.proguard.MainActivity {
	java.lang.String getString(java.lang.String);
}

然后我们在导出apk然后反编译,得到如下代码:

和之前的对比,我们发现其中的getString方法没有被混淆。没错,上面proguard-project.txt的意思就是保持MainActivity的getString()方法不要被混淆。大家也可以试试上述混淆代码中被注释的两行分别是什么效果。

讲到这里已经开始涉及ProGuard的核心部分了,剩下的就是研读ProGuard的文档,掌握的他的语法并使用之。本想找一个完整的ProGuard的翻译文档,但是找了N久没有发现一个,而且连零零散散的翻译也非常的少,最近时间很紧,加之能力有限,想翻译一下常用的几个命令也是很困,所以细读的想法只能暂时往后推了。这里先简单介绍下keep命令:

-keep [,modifier,...] class_specification

在你的代码中指定作为切入点而被保留的类或者类的成员(属性和方法)。例如,为了保持一个应用,你可以指定主类和他的main方法。为了处理一个库,你需要详细说明他的public访问的元素。

另外还有keep的简单概述 和
语法中规范。Class Specification中会告诉你如何表示构造方法,属性和方法,"*" 与“**”的区别等等。比如"*"表示匹配任何的类名但是不包括包的分隔符,而"**"则是匹配任何的类名并且包括任意数量的包分隔符,因此上面我们注释掉的代码意思如下:第一行:保持com.ttdevs.proguard下的所有类和子包下的类的所有方法都不混淆,第二行保持com.ttdevs.proguard下的所有类和子包下的类的所有方法和成员变量都不混淆。

// TODO 细节还有很多,比如-libraryjars、-dontwarn、-keepattributes等等,这些待续吧

参考:

ProGuard 5.0:http://proguard.sourceforge.net 
 (ProGuard 4.7

时间: 2024-08-24 07:22:46

android对app进行代码混淆的相关文章

浅谈Android保护技术__代码混淆

浅谈Android保护技术__代码混淆 代码混淆 代码混淆(Obfuscated code)亦称花指令,是将计算机程序的代码,转换成一种功能上等价,但是难于阅读和理解的形式的行为.将代码中的各种元素,如变量,函数,类的名字改写成无意义的名字.比如改写成单个字母,或是简短的无意义字母组合,甚至改写成"__"这样的符号,使得阅读的人无法根据名字猜测其用途.对于支持反射的语言,代码混淆有可能与反射发生冲突.代码混淆并不能真正阻止反向工程,只能增大其难度.因此,对于对安全性要求很高的场合,仅仅

Android Studio环境下代码混淆+签名打包

Android Studio环境下代码混淆+签名打包 作者 Mr_冯先生 关注 2016.08.21 01:10 字数 1040 阅读 734评论 5喜欢 34 注:本文使用的Android Studio版本是 2.1.2. 做公司项目,需要对项目进行代码混淆+签名打包,然后就各种搜集查看资料,算是小有成果吧.周末无事就想着总结一下以后再用可做参考.如有不对的地方烦请各位大神指导-- 一.代码混淆 android studio进行代码混淆需要在两个地方做配置:1.添加自己的混淆规则到对应Modu

Android 编程下的代码混淆

什么是代码混淆 Java 是一种跨平台的.解释型语言,Java 源代码编译成中间”字节码”存储于 class 文件中.由于跨平台的需要,Java 字节码中包括了很多源代码信息,如变量名.方法名,并且通过这些名称来访问变量和方法,这些符号带有许多语义信息,很容易被反编译成 Java 源代码.为了防止这种现象,我们可以使用 Java 混淆器对 Java 字节码进行混淆. 混淆就是对发布出去的程序进行重新组织和处理,使得处理后的代码与处理前代码完成相同的功能,而混淆后的代码很难被反编译,即使反编译成功

关于Android studio 怎么使用代码混淆的问题!

为什么要代码混淆? 可以参考:http://www.cnblogs.com/wangcan/p/3477840.html 1,android studio 1.3之前的版本! 以前总以为Intellij idea 和android studio 在proguard-project.txt里面设置以后,在编译的时候就直接把代码给混淆了,后面自己反编译才发现,什么都混淆,原来还有个操作没做, (需要在Generate Signed APK (签名)的时候勾选上Run ProGuard 才行.)重点!

详谈Android 编程下的代码混淆,点开就看....

源码混淆什么 Java 是一种跨平台的.解释型语言,Java 源代码编译成中间”字节码”存储于 class 文件中.由于跨平台的需要,Java 字节码中包括了很多源代码信息,如变量名.方法名,并且通过这些名称来访问变量和方法,这些符号带有许多语义信息,很容易被反编译成 Java 源代码.为了防止这种现象,我们可以使用 Java 混淆器对 Java 字节码进行混淆. 混淆就是对发布出去的程序进行重新组织和处理,使得处理后的代码与处理前代码完成相同的功能,而混淆后的代码很难被反编译,即使反编译成功也

随想录(一个android原生app的代码赏析)

[ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 今天下午,无意看到android一个原生的app代码,也就一个文件SpeechRecorderActivity.java.开发android app原来不难.插句话,android所有的自带app都是开源的,它们其实才是最好的学习资料.接着大家可以看一下,具体内容如下, /* * Copyright (C) 2007 The Android Open Source Project * * L

Android 重启APP application 代码 code restart android app

System.exit(0); Intent i =new Intent(getBaseContext(), POU2.class); i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(i);

Android Studio 代码混淆

新建一个项目,Android Studio默认关闭代码混淆开关,在build.gradle文件中,如下图所示的minifyEnabled 开关,因此如果需要混淆代码,需将false改为true,然后在文件proguard-rules.pro添加具体混淆规则. 自己的build.gradle文件的buildTypes部分 buildTypes { debug { buildConfigField "boolean", "LOG_DEBUG", "true&q

Android Studio代码混淆插件

之前给公司的App添加代码混淆,在代码的混淆过程也遇到了不少的问题,再加上最近学习了一下Android Studio插件的开发,所以就开发一个代码混淆插件方便项目的代码混淆. 截图 第三方库列表清单 目前插件的后台已集成了如下图的第三方开源库的代码混淆以及基本的代码混淆,还在努力地添加中,也欢迎大家通过new issue提交列表中没有的第三方开源库混淆代码.(你认为微不足道的事情,也许可以帮到别人的大忙~) 使用 下载AndroidProGuard插件并安装重启.download 在菜单栏的Ed