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 oolsproguardin etrace.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 *;
}</init></init></methods>

有了这部分代码我们就可以直接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等等,这些待续吧

通过此文希望能帮助到读者进行代码的混淆,谢谢大家对本站的支持!

(0)

相关推荐

  • Android实用图文教程之代码混淆、第三方平台加固加密、渠道分发

    第一步:代码混淆(注意引入的第三方jar) 在新版本的ADT创建项目时,混码的文件不再是proguard.cfg,而是project.properties和proguard-project.txt. 新建一个项目的时候,会自动生成project.properties和proguard-project.txt文件,无需自己新建,如果你的项目无法自动生成,那么你就要检查一下你的ADT版本了 如果需要对项目进行全局混码,只需要进行一步操作: 将project.properties的中 "#progua

  • Android Studio多渠道批量打包及代码混淆

    一.批量打包 1.集成了友盟统计,并在AndroidManifest.xml中添加了如下代码 <meta-data android:name="UMENG_CHANNEL" android:value="${CHANNEL_VALUE}"/> 2.在app的build.gradle的android标签下添加如下代码: productFlavors { myapp {} _360 {} appchina {} hiapk {} } productFlavo

  • Android 实现代码混淆的实例

    Android 实现代码混淆的实例 1.简介 代码混淆(Obfuscated code)亦称花指令,是将计算机程序的代码,转换成一种功能上等价,但是难于阅读和理解的形式的行为. 混淆的目的是为了加大反编译的成本,但是并不能彻底防止反编译. 2.如何开启混淆 通常我们需要找到项目路径下app目录下的build.gradle文件,找到minifyEnabled这个配置,然后设置为true即可,如下: release { minifyEnabled true proguardFiles getDefa

  • Android应用开发之代码混淆

    混淆器(ProGuard) 混淆器通过删除从未用过的代码和使用晦涩名字重命名类.字段和方法,对代码进行压缩,优化和混淆.结果是一个比較小的.apk文件,该文件比較难进行逆向project.因此,当你的应用程序对安全敏感(要求高),比如当你授权应用程序的时候,混淆器是一种重要的保护手段. 混淆器被集成在android 构建系统中,所以你不必手动调用它.同一时候混淆器仅在公布模式下进行构建应用程序的时候才会执行起来,所以在调试模式下构建程序时,你不必处理混淆代码.让混淆器执行起来是可选择的,可是推荐

  • android app进行代码混淆实例详解

    接到一个新的任务,对现有项目进行代码混淆.之前对混淆有过一些了解,但是不够详细和完整,知道有些东西混淆起来还是比较棘手的.不过幸好目前的项目不是太复杂(针对混淆这块来说),提前完成--现总结之. 第一部分 介绍下操作流程(eclipse): 1.打开混淆器:找到项目根目录下的project.properties文件,将"#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt"

  • Android 打包三种方式实例详解

     Android 打包三种方式实例详解 前言: 现在市场上很多app应用存在于各个不同的渠道,大大小小几百个,当我们想要在发布应用之后统计各个渠道的用户下载量,我们就要进行多渠道打包. 01.应用的打包签名什么是打包? 打包就是根据签名和其他标识生成安装包. 签名是什么? 1.在android应用文件(apk)中保存的一个特别字符串 2.用来标识不同的应用开发者:开发者A,开发者B 3.一个应用开发者开发的多款应用使用同一个签名 就好比是一个人写文章,签名就相当于作者的署名. 如果两个应用都是一

  • Android activity堆栈及管理实例详解

    本示例演示如何通过设置Intent对象的标记,来改变当前任务堆栈中既存的Activity的顺序. 1. Intent对象的Activity启动标记说明: FLAG_ACTIVITY_BROUGHT_TO_FRONT 应用程序代码中通常不设置这个标记,而是由系统给单任务启动模式的Activity的设置. FLAG_ACTIVITY_CLEAR_TASK 如果给Intent对象添加了这个标记,那么在Activity被启动之前,会导致跟这个Activity关联的任何既存的任务都被清除.也就是说新的Ac

  • Android 开发订单流程view实例详解

     Android 开发订单流程view实例详解 先看看最终效果图: 怎么样,效果还是很不错的吧?群里有人说切四张图的.recycleview的.各种的都有啊,但是最简单的就是通过自定义view来实现了-接下来让我们来实现下这个(订单流程view). 首先我们定义好我们的自定义属性: attrs.xml <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleabl

  • Android TextView Marquee的应用实例详解

    Android TextView Marquee的应用实例详解 亲测可能.直接上代码. Xml代码 <TextView android:id="@+id/toolbar_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" androi

  • Android 中读取Excel文件实例详解

    Android 中读取Excel文件实例详解 最近有个需求需要在app内置数据,新来的产品扔给了我两个Excel表格就不管了(两个表格格式还不统一...),于是通过度娘等方法找到了Android中读取Excel表格文件的一种方法,记录一下. 闲话一下Excel中工作簿和工作表的区别: 工作簿中包含有工作表.工作簿可以由一张或多张工作表组成,一个工作簿就是一个EXCEL表格文件. 好了,开始读取表格文件吧. 前提 首先,我们假设需要读取的表格文件名字为test.xls, 位于assets根目录下.

  • Android USB转串口通信开发实例详解

     Android USB转串口通信开发实例详解 好久没有写文章了,年前公司新开了一个项目,是和usb转串口通信相关的,需求是用安卓平板通过usb转接后与好几个外设进行通信,一直忙到最近,才慢慢闲下来,趁着这个周末不忙,记录下usb转串口通信开发的基本流程. 我们开发使用的是usb主机模式,即:安卓平板作为主机,usb外设作为从机进行数据通信.整个开发流程可以总结为以下几点: 1.发现设备 UsbManager usbManager = (UsbManager) context.getSystem

  • Android 逐帧动画创建实例详解

    Android 逐帧动画创建实例详解 前言: 我们看早期电影的时候,电影通常是一张一张播放,用我们现在专有名词来说,就是一帧帧来,安卓同样有这样动画效果的编排形式. 那么我们先定义逐帧动画xml文件 <?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" an

  • Android Wifi的forget()操作实例详解

    Android  Wifi的forget()操作实例详解 我们在处理某个Wifi连接时,有时会需要忘掉当前连接的密码信息.执行这项操作,我们需要调用WifiManager::forget()函数: /** * Delete the network in the supplicant config. * * This function is used instead of a sequence of removeNetwork() * and saveConfiguration(). * * @p

  • Android 中 Tweened animation的实例详解

    Android 中 Tweened animation的实例详解 Tweened animation有四种类型,下面主要介绍Scale类型. 运行效果如下: Android SDK提供了2种方法:直接从XML资源中读取Animation,使用Animation子类的构造函数来初始化Animation对象,第二种方法在看了Android SDK中各个类的说明就知道如何使用了,下面简要说明从XML资源中读取Animation.XML资源中的动画文件animation.xml内容为: <?xml ve

随机推荐