代码混淆

ProGuard是ADT自带的apk混淆器,它的用途有:
1、压缩apk包的大小,能删除无用的代码,并简化部分类名和方法名。
2、加大破解源码的难度,因为部分类名和方法名被重命名,使得程序逻辑变得难以理解。

代码混淆的规则在proguard-project.txt中编写,然后在project.properties补充规则文件的路径,如下所示:

proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

下面是proguard-project.txt的一个例子:

#指定代码的压缩级别
-optimizationpasses 5
#是否使用大小写混合
-dontusemixedcaseclassnames
#优化/不优化输入的类文件
-dontoptimize
#是否混淆第三方jar包
-dontskipnonpubliclibraryclasses
#混淆时是否做预校验
-dontpreverify
#混淆时是否记录日志
-verbose
#混淆时所采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#保护注解
-keepattributes *Annotation*#保持JNI用到的native方法不被混淆
-keepclasseswithmembers class * {native <methods>;
}#保持自定义控件的构造函数不被混淆,因为自定义控件很可能直接写在布局文件中
-keepclasseswithmembers class * {public <init>(android.content.Context, android.util.AttributeSet);
}#保持自定义控件的构造函数不被混淆
-keepclasseswithmembers class * {public <init>(android.content.Context, android.util.AttributeSet, int);
}#保持布局中onClick属性指定的方法不被混淆
-keepclassmembers class * extends android.app.Activity {public void *(android.view.View);
}#保持枚举enum类不被混淆
-keepclassmembers enum * {public static **[] values();public static ** valueOf(java.lang.String);
}#保持序列化的Parcelable不被混淆
-keep class * implements android.os.Parcelable {public static final android.os.Parcelable$Creator *;
}#指定哪些第三方jar包需要混淆
#-libraryjars libs/bcprov-jdk16-1.46.jar#保持哪些系统组件类不被混淆
-keep public class * extends android.app.Fragment
-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 * extends android.support.v4.**
-keep public class com.android.vending.licensing.ILicensingService#保持哪些第三方jar包不被混淆
-keep class org.bouncycastle.**
-dontwarn org.bouncycastle.**

下面是进行代码混淆时的注意事项:
1、jni的方法要屏蔽混淆,因为so库要求包名、类名、函数名要完全一致
2、可能会在布局文件中直接引用的类名或方法名,要屏蔽混淆。包括自定义控件、布局中onClick属性指定的方法等等。
3、保持第三方jar包不被混淆,有时需要把“keep class”提到“dontwarn”前面。
4、jar包的文件名中不要有特殊字符,比如说“(”、“)”等字符在混淆时就会报错,文件名最好只包含字母、横线、小数点。
5、使用WebView时,会被js调用的类和方法,要屏蔽混淆。具体做法除了要在proguard-project.txt加上如下说明外,还要在java代码中调用一下js使用的方法,才能保证内部类与方法都不会被混淆。有关WebView中调用js的说明参见《 Android开发笔记(六十四)网页加载与JS调用》

-keep class com.example.exmweb.WebActivity$MobileSignal{public <fields>;public <methods>;
}

防二次打包

前面的《 Android开发笔记(七十)反编译初步》提到,apk破解得到smali文件后,可以进行修改并重新打包,从而制造一个山寨的APP。因此为了防止自己辛辛苦苦做的APP被别人山寨,就得在代码中加上防二次打包的处理。具体说来,首先开发者在打包前记下签名证书的MD码,然后在代码中获取app安装后的签名,对比两个签名的MD值是否一致,如果不一致就退出app,这样就能防止被二次打包了。

下面是获取apk签名的代码例子

 public static String getSignMD5(Context context) {String signMD5 = "";String packageName = context.getPackageName();PackageManager pkgMgr = context.getPackageManager();PackageInfo info = null;try {info = pkgMgr.getPackageInfo(packageName,PackageManager.GET_SIGNATURES);} catch (PackageManager.NameNotFoundException e) {return signMD5;}if (info == null) {return signMD5;} else {Signature[] signs = info.signatures;if ((signs == null) || (signs.length == 0)) {return signMD5;} else {Signature sign = signs[0];signMD5 = MD5Util.encrypBytes(sign.toByteArray());return signMD5;}}}

以上代码用到了MD5加密,加密算法参见《 Android开发笔记(七十二)数据加密算法》。

下面是打包apk时的md5签名值的截图

下面是app运行时获取到的md5签名截图

花指令

代码混淆通过对类名和方法名重命名,只是加大了破解的难度,但并不能完全阻止代码被破解。有个办法就是通过让反编译程序出错,使得代码破解失败,花指令便是这样一种思想。花指令(junk code)意思是程序中加入一些与业务无关的指令,希望在反汇编的时候出错,让破解者无法正确地进行反汇编工作,从而迷失方向。常见的花指令常常是随意跳转,一旦目标位置是另一条指令的中间,反汇编的时候便会出现混乱。下面是花指令的一段示例代码(在jd-gui 0.3.6和1.4.0版本上都测试过,加了花指令的函数就无法正常破解):

     //花指令开始BufferedReader br = null;try {br = new BufferedReader(new FileReader("/proc/net/arp"));String line;while ((line = br.readLine()) != null) {String[] splitted = line.split(" +");if (splitted.length >= 0) {break;}}} catch (Exception e) {e.printStackTrace();} finally {try {br.close();} catch (IOException e) {e.printStackTrace();}}//花指令结束

当然,除了上面说的代码混淆、防止二次打包、花指令等等技巧,还有其他的一些技术手段,下面是其他几种代码加密方式:
1、把部分代码写入jni接口,因为so库难以反编译。例如在做签名校验时,原签名的值就可以保存在jni接口中。jni的介绍参见《 Android开发笔记(六十九)JNI实战》
2、把核心业务放到后端服务器上运行,app与服务器之前通过http接口通信。
3、使用第三方加密平台给app做加壳处理。

点击下载本文用到的代码反破解的工程代码

点此查看Android开发笔记的完整目录

Android开发笔记(七十三)代码混淆与反破解相关推荐

  1. Android开发笔记(十三)视图绘制的几个方法

    三个可进行绘制的方法 在自定义视图中,有三个函数可以重写用于界面绘制,在视图创建过程中,三个函数的执行顺序依次是:onLayout.onDraw.dispatchDraw. 1.onLayout(bo ...

  2. Android开发笔记(序)写在前面的目录

    知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教训,与网友互相切磋,从而去芜存菁进一步提升自己的水平.因此博主就想,入门的东西咱就不写了,人不能老停留在入 ...

  3. Android开发笔记(一百一十四)发布工具

    多渠道打包工具 Eclipse/ADT环境 因为app开发者常常需要统计app在不同渠道的使用量,所以app安装包就得按照不同的渠道号分别打包.至于为什么要进行使用量的统计,可参见< Andro ...

  4. Android开发笔记(八十)运行状态检查

    大家都知道刻舟求剑的寓言故事,说的是事物是发展变化着的,如果拘泥于原来的情况,那随着情况的改变,就不会得到预期的结果.同样,影响app运行的因素,并不只是外部环境(如硬件.系统.权限等等),还包括ap ...

  5. Android开发笔记(序)

    本开发笔记,借鉴与其他开发者整理的文章范例与心得体会.在这里作为开发过程中的一个总结与笔记式记录. 如有侵犯作者权益,请及时联系告知删除.俗话说:集百家成一言,去粕成金. ************** ...

  6. Android开发笔记(序)写在前面的目录大全

    转自  湖前琴亭 的博客https://blog.csdn.net/aqi00/article/details/50012511 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面 ...

  7. Andriod开发之二十:Android开发笔记(序)写在前面的目录

    https://blog.csdn.net/aqi00/article/details/50038385 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教 ...

  8. Android开发笔记(九十五)自定义Drawable

    Drawable Bitmap是Android对图像的定义描述,而Drawable则是对图像的展现描述,在View视图中显示图像都是通过Drawable来实现的.其中有关Bitmap的介绍参见< ...

  9. Android开发笔记(九十九)圆形转盘

    圆形转盘的实现思想 圆形转盘的运用场景常见的有:抽奖转盘.圆形菜单列表.热点客户端环状列表等等.对于圆形转盘的编码实现,主要难点除了手势的触摸控制之外,就在于旋转角度的计算了.下面是旋转角度计算的解决 ...

最新文章

  1. PHP 格式化文件大小
  2. iptables配置
  3. 2.6 Go 读取CSV
  4. kubevela随笔
  5. 机器学习中的数学知识(part4)--拟牛顿法
  6. java读取http请求中的body
  7. php time()为空_PHP time()用法及代码示例
  8. 对int array进行排序
  9. Mongodb系列:初识Mongodb
  10. 伍德里奇计量经济学导论pdf_伍德里奇 计量经济学导论 第三章第三节-1 MLR1-MLR4...
  11. 微信提现php 该怎么加密,关于php 调用接口 微信云支付 HmacSha256 加密 request_content...
  12. 浏览器主页被hao123劫持之解决方案
  13. FAI自动部署debian
  14. 萝卜小铺和店主们的故事(五)
  15. Google Coral USB加速器介绍
  16. 用 Python 一键批量自动生成合同
  17. 住宅代理和数据中心代理哪个更好?
  18. Mac电脑没有声音,苹果电脑没有声音怎么办
  19. 防复制防破解小区门禁梯控升级非联网CPU卡脱机写卡门禁梯控一卡通系统92HID623CPU V5.00操作说明之用户卡加密发卡设置说明
  20. [PHP]浅谈php混淆与反混淆

热门文章

  1. Leetcode每日一题:328.odd-even-linked-list(奇偶链表)
  2. 花书+吴恩达深度学习(十七)序列模型之长短期记忆 LSTM 和门控循环单元 GRU
  3. Loj #2324. 「清华集训 2017」小 Y 和二叉树
  4. MySQL 日期时间相关函数
  5. LeetCode刷题(17)
  6. 1、Fiddler的基本介绍
  7. python找房源_python抓取链家房源信息(二)
  8. python2.7更新python3.6_python2.7升级到python3.6注意事项
  9. 若依前端如何生成序号?
  10. win10开机,内存占用过高