android IO流_Android安全防护应用防破解指南

现在最流行的App破解技术大多是基于一定相关技术的基础:如一定阅读Java代码的能力、有一些Android基础、会使用eclipse的一些Android调试的相关工具以及了解一些smali的语法规范和字段的自定范围,再利用现有的各种工具:如APKtool、dex2jar、jd-gui以及签名工具。有了这些前基础和工具,就可以破解很多没有加反编译保护措施的App。 那么如何就安卓App安全进行保护了,以下内容将会为读者作出详解。 安卓App安全包含很多内容,其中包括混淆代码、整体Dex加固、拆分Dex加固、虚拟机加固等方面。事实上,这些内容也是国内近几年Android App安全保护的一种主要趋势。 这里我们讲一下代码混淆和加固。

一、混淆代码

  • 前言

混淆是上线前挺重要的一个环节。android使用 的ProGuard,可以起到压缩,混淆,预检, 优化的作用。 代码混淆技术基本原理是将代码中的各种元素 (变量、函数、类名等)改为无意义的名字, 使得阅读的人无法通过名称猜测其用途,增大 反编译者的理解难度,从而达到防止被逆向破 解的目的。其实还有一个重要的功能,就是能 apk瘦身,混淆后的apk要比不混淆的小很多, 这个大家可以自己验证。
  • 一般以下情况都不需要混淆:

    1.使用了自定义控件那么要保证它们不参与混淆     2.使用了枚举要保证枚举不被混淆     3.对第三方库中的类不进行混淆     4.运用了反射的类也不进行混淆     5.使用了 Gson 之类的工具要使JavaBean类即实体类不被混淆     6.在引用第三方库的时候,一般会标明库的混淆 规则的, 建议在使用的时候 就把混淆规则添加 上去,免得到最后才去找     7.有用到 WebView 的 JS 调用也需要保证写的 接口方法不混淆, 原因和第一条一样     8.Parcelable 的子类和 Creator 静态成员变量 不混淆, 否则会产生  Android.os.BadParcelableException 异常
  • 混淆的前期工作

在工程目录下,找到 proguard-rules.pro 文件,它就是你要进行编写混淆配置的文件,在这个文件中编写混淆规则 当然,在这之前,还需要在你 module 的 build.gradle 文件中引用该混淆文件:

e2d59a751de4c9ed98a9e12e47cf4894.png

上图中的 proguard-android.txt 文件,这是系统默认的混淆文件,

具体在…/sdk/tools/proguard/ 目录下,其中包含了 android 最基本的混淆,一般不需要改动,我们需要配置的是项目中 app 下的proguard-rules.pro 文件

  • 混淆模板

############################################### 基本指令区域(没什么别的需求不需要动)############################################### 代码混淆压缩比,在0~7之间,默认为5,一般不做修改-optimizationpasses 5# 混合时不使用大小写混合,混合后的类名为小写-dontusemixedcaseclassnames# 指定不去忽略非公共库的类-dontskipnonpubliclibraryclasses# 这句话能够使我们的项目混淆后产生映射文件# 包含有类名->混淆后类名的映射关系-verbose# 指定不去忽略非公共库的类成员-dontskipnonpubliclibraryclassmembers# 不做预校验,preverify是proguard的四个步骤之一,Android不需要preverify,去掉这一步能够加快混淆速度。-dontpreverify# 保留Annotation不混淆-keepattributes *Annotation*,InnerClasses# 避免混淆泛型-keepattributes Signature# 抛出异常时保留代码行号-keepattributes SourceFile,LineNumberTable# 指定混淆是采用的算法,后面的参数是一个过滤器# 这个过滤器是谷歌推荐的算法,一般不做更改-optimizations !code/simplification/cast,!field/*,!class/merging/*############################################### Android开发中一些需要保留的公共部分(没什么别的需求不需要动)############################################### 保留我们使用的四大组件,自定义的Application等等这些类不被混淆# 因为这些子类都有可能被外部调用-keep public class * extends android.app.Activity-keep public class * extends android.app.Appliction-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.view.View-keep public class com.android.vending.licensing.ILicensingService# 保留support下的所有类及其内部类-keep class android.support.** {*;}# 保留继承的-keep public class * extends android.support.v4.**-keep public class * extends android.support.v7.**-keep public class * extends android.support.annotation.**# 保留R下面的资源-keep class **.R$* {*;}# 保留本地native方法不被混淆-keepclasseswithmembernames class * {    native ;}# 保留在Activity中的方法参数是view的方法,# 这样以来我们在layout中写的onClick就不会被影响-keepclassmembers class * extends android.app.Activity{    public void *(android.view.View);}# 保留枚举类不被混淆-keepclassmembers enum * {    public static **[] values();    public static ** valueOf(java.lang.String);}# 保留我们自定义控件(继承自View)不被混淆-keep public class * extends android.view.View{    *** get*();    void set*(***);    public (android.content.Context);    public (android.content.Context, android.util.AttributeSet);    public (android.content.Context, android.util.AttributeSet, int);}# 保留Parcelable序列化类不被混淆-keep class * implements android.os.Parcelable {    public static final android.os.Parcelable$Creator *;}# 保留Serializable序列化的类不被混淆-keepclassmembers class * implements java.io.Serializable {    static final long serialVersionUID;    private static final java.io.ObjectStreamField[] serialPersistentFields;    !static !transient ;    !private ;    !private ;    private void writeObject(java.io.ObjectOutputStream);    private void readObject(java.io.ObjectInputStream);    java.lang.Object writeReplace();    java.lang.Object readResolve();}# 对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆-keepclassmembers class * {    void *(**On*Event);    void *(**On*Listener);}# webView处理,项目中没有使用到webView忽略即可#-keepclassmembers class fqcn.of.javascript.interface.for.webview {#    public *;#}#-keepclassmembers class * extends android.webkit.webViewClient {#    public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);#    public boolean *(android.webkit.WebView, java.lang.String);#}#-keepclassmembers class * extends android.webkit.webViewClient {#    public void *(android.webkit.webView, jav.lang.String);#}# 移除Log类打印各个等级日志的代码,打正式包的时候可以做为禁log使用,这里可以作为禁止log打印的功能使用# 记得proguard-android.txt中一定不要加-dontoptimize才起作用# 另外的一种实现方案是通过BuildConfig.DEBUG的变量来控制#-assumenosideeffects class android.util.Log {#    public static int v(...);#    public static int i(...);#    public static int w(...);#    public static int d(...);#    public static int e(...);#}
上面这些基本不用动,描述的也很清晰了,我们主要解决的是下列中的部分–项目中特殊处理部分。
############################################### 项目中特殊处理部分###############################################-----------处理反射类---------------#-----------处理js交互---------------#-----------处理实体类---------------# 在开发的时候我们可以将所有的实体类放在一个包内,这样我们写一次混淆就行了。-keep class com.ghs.ghspm.bean.** { *; }#-----------处理第三方依赖库---------
说一下第三方库,你需要确认你的项目中libs下引用了哪些地方的jar包, 还有就是gradle中添加了哪些第三方库的依赖。 下面介绍一些常用的第三方混淆配置,仅供参考
# AndroidEventBus-keep class org.simple.** { *; }-keep interface org.simple.** { *; }-keepclassmembers class * {    @org.simple.eventbus.Subscriber ;}# 百度地图(jar包换成自己的版本,记得签名要匹配)-libraryjars libs/baidumapapi_v2_1_3.jar-keep class com.baidu.** {*;}-keep class vi.com.** {*;}-keep class com.sinovoice.** {*;}-keep class pvi.com.** {*;}-dontwarn com.baidu.**-dontwarn vi.com.**-dontwarn pvi.com.**# Bugly-dontwarn com.tencent.bugly.**-keep class com.tencent.bugly.** {*;}# ButterKnife-keep class butterknife.** { *; }-dontwarn butterknife.internal.**-keep class **$$ViewBinder { *; } -keepclasseswithmembernames class * {    @butterknife.* ;} -keepclasseswithmembernames class * {    @butterknife.* ;}# EventBus-keepattributes *Annotation*-keepclassmembers class ** {    @org.greenrobot.eventbus.Subscribe ;}-keep enum org.greenrobot.eventbus.ThreadMode { *; }# Facebook-keep class com.facebook.** {*;}-keep interface com.facebook.** {*;}-keep enum com.facebook.** {*;}# FastJson-dontwarn com.alibaba.fastjson.**-keep class com.alibaba.fastjson.** { *; }-keepattributes Signature-keepattributes *Annotation*# Fresco-keep class com.facebook.fresco.** {*;}-keep interface com.facebook.fresco.** {*;}-keep enum com.facebook.fresco.** {*;}# 高德相关依赖# 集合包:3D地图3.3.2 导航1.8.0 定位2.5.0-dontwarn com.amap.api.**-dontwarn com.autonavi.**-keep class com.amap.api.**{*;}-keep class com.autonavi.**{*;}# 地图服务-dontwarn com.amap.api.services.**-keep class com.map.api.services.** {*;}# 3D地图-dontwarn com.amap.api.mapcore.**-dontwarn com.amap.api.maps.**-dontwarn com.autonavi.amap.mapcore.**-keep class com.amap.api.mapcore.**{*;}-keep class com.amap.api.maps.**{*;}-keep class com.autonavi.amap.mapcore.**{*;}# 定位-dontwarn com.amap.api.location.**-dontwarn com.aps.**-keep class com.amap.api.location.**{*;}-keep class com.aps.**{*;}# 导航-dontwarn com.amap.api.navi.**-dontwarn com.autonavi.**-keep class com.amap.api.navi.** {*;}-keep class com.autonavi.** {*;}# Glide-keep public class * implements com.bumptech.glide.module.GlideModule-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {  **[] $VALUES;  public *;}# Gson-keepattributes Signature-keepattributes *Annotation*-keep class sun.misc.Unsafe { *; }-keep class com.google.gson.stream.** { *; }# 使用Gson时需要配置Gson的解析对象及变量都不混淆。不然Gson会找不到变量。# 将下面替换成自己的实体类-keep class com.example.bean.** { *; }# Jackson-dontwarn org.codehaus.jackson.**-dontwarn com.fasterxml.jackson.databind.**-keep class org.codehaus.jackson.** { *;}-keep class com.fasterxml.jackson.** { *; }# 极光推送-dontoptimize-dontpreverify-dontwarn cn.jpush.**-keep class cn.jpush.** { *; }# OkHttp3-dontwarn com.squareup.okhttp3.**-keep class com.squareup.okhttp3.** { *;}-dontwarn okio.**# Okio-dontwarn com.squareup.**  -dontwarn okio.**  -keep public class org.codehaus.* { *; }  -keep public class java.nio.* { *; }# OrmLite-keepattributes *DatabaseField* -keepattributes *DatabaseTable* -keepattributes *SerializedName*  -keep class com.j256.**-keepclassmembers class com.j256.** { *; }-keep enum com.j256.**-keepclassmembers enum com.j256.** { *; }-keep interface com.j256.**-keepclassmembers interface com.j256.** { *; }# Realm-keep class io.realm.annotations.RealmModule-keep @io.realm.annotations.RealmModule class *-keep class io.realm.internal.Keep-keep @io.realm.internal.Keep class * { *; }-dontwarn javax.**-dontwarn io.realm.**# Retrofit-dontwarn retrofit2.**-keep class retrofit2.** { *; }-keepattributes Signature-keepattributes Exceptions# Retrolambda-dontwarn java.lang.invoke.*# RxJava RxAndroid-dontwarn sun.misc.**-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {    long producerIndex;    long consumerIndex;}-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {    rx.internal.util.atomic.LinkedQueueNode producerNode;}-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {    rx.internal.util.atomic.LinkedQueueNode consumerNode;}# 微信支付-dontwarn com.tencent.mm.**-dontwarn com.tencent.wxop.stat.**-keep class com.tencent.mm.** {*;}-keep class com.tencent.wxop.stat.**{*;}# 信鸽-keep public class * extends android.app.Service-keep public class * extends android.content.BroadcastReceiver-keep class com.tencent.android.tpush.**  {* ;}-keep class com.tencent.mid.**  {* ;}-keepattributes *Annotation*# 新浪微博-keep class com.sina.weibo.sdk.* { *; }  -keep class android.support.v4.* { *; }  -keep class com.tencent.* { *; }  -keep class com.baidu.* { *; }  -keep class lombok.ast.ecj.* { *; }  -dontwarn android.support.v4.**  -dontwarn com.tencent.**s  -dontwarn com.baidu.**  # 讯飞语音-dontwarn com.iflytek.**-keep class com.iflytek.** {*;}# 银联-dontwarn com.unionpay.**-keep class com.unionpay.** { *; }# 友盟统计分析-keepclassmembers class * { public (org.json.JSONObject); }-keepclassmembers enum com.umeng.analytics.** {    public static **[] values();    public static ** valueOf(java.lang.String);}# 友盟自动更新-keepclassmembers class * { public (org.json.JSONObject); }-keep public class cn.irains.parking.cloud.pub.R$*{ public static final int *; }-keep public class * extends com.umeng.**-keep class com.umeng.** { *; }# 支付宝钱包-dontwarn com.alipay.**-dontwarn HttpUtils.HttpFetcher-dontwarn com.ta.utdid2.**-dontwarn com.ut.device.**-keep class com.alipay.android.app.IAlixPay{*;}-keep class com.alipay.android.app.IAlixPay$Stub{*;}-keep class com.alipay.android.app.IRemoteServiceCallback{*;}-keep class com.alipay.android.app.IRemoteServiceCallback$Stub{*;}-keep class com.alipay.sdk.app.PayTask{ public *;}-keep class com.alipay.sdk.app.AuthTask{ public *;}-keep class com.alipay.mobilesecuritysdk.*-keep class com.ut.*
待所有的配置完后,签名打包的时候可能还会有问题,这时候你要看 Android studio 右下角的Gradle Console中的提示。

二、加固

针对apk,加固是多维度的安全防护方案,包括反破解、反逆向、防篡改等,

可以防止应用被各类常见破解工具逆向,安全性要远大于单纯的代码混淆。

加固原理: 对App进行加固,可以有效防止移动应用被破解、盗版、二次打包、注入、反编译等,保障程序的安全性、稳定性。对于金融类App,尤其重要。 对App dex进行加固的基本步骤如下:      1. 从App原始apk文件里获取到原始dex文件 
    2. 对原始dex文件进行加密,并将加密后的dex文件和相关的存放到 assert目录里      3. 用脱壳dex文件替换原始apk文件里的dex文件;脱壳dex文件的作用主要 有两个,一个是解密加密后的dex文件;二是基于dexclassloader动态 加载解密后的dex文件 
    4. 因为原始apk文件已经被修改,所以需要删除原始apk的签名信息, 即删除META-INF目录下的.RSA、.SF 和MANIFEST.MF文件 
    5. 生成加固后的apk文件 
    6. 对加固后的apk文件进行签名,apk加固完成。

原理分析: 

1.为什么要对原始dex进行加密,同时用脱壳dex文件替换原始dex文件? 大部分的apk反编译工具(dex2jar、apktools、jui等)都是对dex文件进行 反编译,将dex文件反编译成smail,然后再转化成class文件进行阅读和修改。 用脱壳dex替换原始dex文件之后,用上面的反编译工具反编译apk文件, 只能看到脱壳程序的class文件,看不到apk本身的class文件。对dex文件进行 加密,这样即使第三方拿到了dex文件,以为无法解密,也就无法对其进行解 析和分析。  
2.怎么确保apk功能正常运行?加固后的apk启动之后,脱壳dex文件会对加密后 的dex文件进行解密,然后机遇dexclassload动态加载解密后的dex文件。 从用 户的角度,加固前后App的功能和体验基本是一样的。 3.dex加固主要是防止被静态反编译,进而获取源码并修改

加固工具:

1、腾讯加固(https://cloud.tencent.com/)

2、360加固(https://jiagu.360.cn/#/global/index)

到这里就结束啦. 往期精彩回顾:
  • Android实现短信验证码自动填充功能

  • Android仿echo精美弹幕功能

  • Android实现头像重叠排列功能

  • Android仿QQ个性标签功能

  • Android仿QQ侧滑删除的功能

8d38f100cc465a81ec44a47a6db32552.png

a86dbf50ccfe8824e91731a64a719a50.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值