Androidapk安全措施详细说明(签名、混淆、加固、H5安全⽅案)
⽂章简介:当⼀个Android app 开发完成后,我们总是希望对app进⾏⼀些安全措施,防⽌⾃⼰开发的apk被别⼈⼆次打包和签名上传到应⽤市场,同时防⽌apk被别⼈拿到之后进⾏反编译进⾏⼆次开发。那么我们应该都做哪些防护措施呢?下⾯来⼀⼀说明。
1、apk签名
打正式包之前,需要对apk进⾏签名,如果您是⽤Android Studio开发⼯具,那么打包、签名就⾮常简单了。具体怎么签名,⽹上⽂章很多,这⾥不做详细描述。那么我们重点说说为什么要对apk进⾏签名呢?
(1)apk签名是应⽤程序作者对apk进⾏⼀个⾃定义的签名,和权威机构的数字证书不同,它是开发者可⾃由定义的、作为此apk的唯⼀标识符,标识了apk的来源,任何第三⽅进⾏此apk⼆次打包时,如果签名不⼀致则⽆法进⾏⼆次打包,并不能成功安装到⼿机上。
(2)当新版程序和旧版程序的数字证书相同时,Android系统才会认为这两个程序是同⼀个程序的不同版本。如果新版程序和旧版程序的数字证书不相同,则Android系统认为他们是不同的程序,并产⽣冲突,会要求新程序更改包名。
(3)Android系统允许拥有同⼀个数字签名的程序运⾏在⼀个进程中,Android程序会将他们视为同⼀个
程序。所以开发者可以将⾃⼰的程序分模块开发,⽽⽤户只需要在需要的时候下载适当的模块。有利于程序的模块化设计和开发。
(4)可以通过权限(permission)的⽅式在多个程序间共享数据和代码。Android提供了基于数字证书的权限赋予机制,应⽤程序可以和其他的程序共享概功能或者数据给那那些与⾃⼰拥有相同数字证书的程序。如果某个权限(permission)的protectionLevel是signature,则这个权限就只能授予那些跟该权限所在的包拥有同⼀个数字证书的程序。
2、代码混淆
代码混淆的⽬的就是为了防⽌代码的⼆次反编译。Android apk通过反编译⼯具可将classes.dex 字节码转换为java源代码。为了防⽌看到最初的代码,通过⼀定的⽅式将代码进⾏混淆,混淆之后再反编译后代码就变的不可读了。此外还优化、压缩了⼀些⽆⽤代码、删掉⽇志输出等。⽬前随着混合开发框架的兴起,许多原⽣代码混淆都变得没有意义,但是,开发者或多或少的也会写⼀些核⼼的原⽣代码作为业务⽀撑,当然混淆还是必不可少的,下⾯就列出常⽤的混淆⽅式。
2.1 混淆⼯具
官⽹介绍了proguar在Android项⽬中使⽤配置,下⾯来进⾏详细说明
在adle中 按照如下⽅式进⾏配置 属性
/**
* android 混淆
*/
buildTypes {
release {
// 不显⽰Log
buildConfigField "boolean", "LOG_DEBUG", "false"
//混淆
minifyEnabled true
// 移除⽆⽤的resource⽂件
shrinkResources true
useProguard true
proguardFiles getDefaultProguardFile(''), 'proguard-rules.pro'
//lease
}
}
当我们开启混淆后 (minifyEnabled 为 true 时)默认使⽤的混淆⽂件是。这个⽂件所在的位置为 /sdk/tools/下。⼀般来说使⽤默认的混淆⽂件即可进⾏混淆,但是混淆之后打包出来的apk并不不能运⾏,因为,有些需要保留的类没有进⾏保留,这就需要你来⾃定义设置了,这时就需要掌握proguard规则。如果需要⾃定义设置规则,则需要在app⽬录下创建⽂件proguard-
rules.pro,在这个⽂件中进⾏规则设置,下⾯来贴⼀下我混淆使⽤的模版(适⽤于混合开发框架corodva及原⽣框架)
这⾥不做过多解释,因为在模版的注释中已经详细说明。
#添加依赖
#-libraryjars libs/AMap3DMap_7.9.1_AMapSearch_7.9.0_AMapLocation_5.3.1_20210414.jar
# 不使⽤⼤⼩写混合类名,混淆后的类名为⼩写
-dontusemixedcaseclassnames
# 混淆第三⽅库
-dontskipnonpubliclibraryclasses
# 混淆时记录⽇志,有助于排查错误
-verbose
# 代码混淆使⽤的算法.
-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
# 跳过预检验
-
dontpreverify
# 代码混淆压缩⽐,值在0-7之间,默认为5.
-optimizationpasses 5
# 优化时允许访问并修改有修饰符的类和类的成员
-allowaccessmodification
# 保护代码中的Annotation不被混淆
-keepattributes *Annotation*
# 避免混淆泛型, 这在JSON实体映射时⾮常重要
# -keepattributes Signature
# 抛出异常时保留代码⾏号
-keepattributes SourceFile,LineNumberTable
>>>>>>##不需要混淆的>>>>###
# 这些类不混淆(混淆时默认保留,可不进⾏配置)
-keep public class * extends android.app.Activity
#-keep public class * extends android.app.Application
#-keep public class * extends android.app.Service
#-keep public class * t.BroadcastReceiver
#-keep public class * t.ContentProvider
#-keep public class * extends android.app.backup.BackupAgent
#-keep public class * extends android.preference.Preference
#-keep public class * extends android.support.v4.app.Fragment
#-keep public class * extends android.support.v4.app.DialogFragment
##-keep public class * extends com.actionbarsherlock.app.SherlockListFragment
##-keep public class * extends com.actionbarsherlock.app.SherlockFragment
##-keep public class * extends com.actionbarsherlock.app.SherlockFragmentActivity
#-keep public class * extends android.app.Fragment
#-keep public class com.android.vending.licensing.ILicensingService
# 不混淆,最后这两个类我们基本也⽤不上,是接⼊Google原⽣的⼀些服务时使⽤的。
-keep public le.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService
# Native⽅法不混淆 ni⽅法不可混淆,因为这个⽅法需要和native⽅法保持⼀致;
-keepclasseswithmembernames class * {
native <methods>;
}
# 枚举类型不混淆因为enum类的特殊性,以下两个⽅法会被反射调⽤
-keepclassmembers enum * {
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# 保留Parcelable序列化类不被混淆
# Parcelable的⼦类和Creator静态成员变量不混淆,否则会产⽣Android.os.BadParcelableException异常;
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-keepclassmembers class **.R$* {
public static <fields>;
}
# We want to keep methods in Activity that could be used in the XML attribute onClick
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
# keep setters in Views so that animations can still work.
# see proguard.sourceforge/manual/examples.html#beans
-keepclassmembers public class * extends android.view.View {
void set*(***);android获取真正的签名
*** get*();
}
# The support library contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version.  We know about them, and they are safe.
# 打包时忽略警告
-dontwarn android.support.**
# Understand the @Keep support annotation.
-keep class android.support.annotation.Keep
-keep @android.support.annotation.Keep class * {*;}
-
keepclasseswithmembers class * {
@android.support.annotation.Keep <methods>;
}
-keepclasseswithmembers class * {
@android.support.annotation.Keep <fields>;
}
-keepclasseswithmembers class * {
@android.support.annotation.Keep <init>(...);
}
# 保留第三⽅库android.support.v4不被混淆
#-keep class android.support.v4.app.** { *; }
#-keep interface android.support.v4.app.** { *; }
#使⽤反射的类
-keep class android.app.AivityThread  {*;}
-keep t.pm.IPackageManager {*;}
-keep class com.customer.plugins.appupdate.PackageManagerHook  {*;}
>>>>####⾼德地图混淆处理,不混淆⾼德地图中已经混淆的类>>>>>> -dontwarn com.amap.api.**
# -dontwarn com.a.a.**
-dontwarn com.autonavi.**
-keep class com.amap.api.** {*;}
-keep class com.autonavi.** {*;}
#-keep class com.a.a.** {*;}
>>>>####不混淆corodva相关,Cordova plugin 初始化时⽆法进⾏初始化>>>>>####
-keep class dova.** { *; }
#-keep class cordova.** {*;}
#-keep class com.customer.plugins.** {*;}
-keep class * extends dova.CordovaPlugin
开启了混淆打包过程中可能会出现⼀些报错⽇志以及由于混淆之后出现的打包错误⽇志,可在如下图位置(Toggle view)查看
混淆出现的错误可参考
3、H5压缩包设置密码或从服务端拉取
如果您的应⽤时混合开发模式,那么就涉及到了H5代码的安全管理了。我们打包的apk,通过解压缩后就会在assets⽂件夹下看到我们开发的H5相关⽂件,如js、html、资源⽂件等。这些⽂件的核⼼业务代码会直接暴露出来。这⾥我提供两种安全思路:
(1)可将H5⽂件的www包进⾏压缩,放到Android框架中,并对压缩包设置密码,此时,如果设置了密码那么就会多做⼀些额外的⼯作;应⽤启动时和 apk版本升级时 都会涉及带密码的压缩包的解压。
(2)将H5相关⽂件存放到服务端,每次应⽤加载时都服务端拉取,并缓存到本地沙箱中,这样打包出来的apk就不会出现H5源码⽂件了。这样做的缺点在于每次在进⾏版本升级时需要在前端进⾏版本⽐较。
(3)当然⼀些加固收费的⼯具可以对H5进⾏加固,加固的⽬标:H5加固服务,通过将JavaScript代码进⾏混淆加密、压缩等⼿段达到对HTML5应⽤的反调试、反窃取、反篡改等保护⾏为,保护H5应⽤的安全。⼀般来说都需要收费
4、应⽤加固
应⽤加固的⽬的,下⾯摘取360基础加固服务(不收费)的图:
具体加固⽅式可到官⽹获取,步骤⾮常详细。应⽤加固的⽅式也有很多种,可根据需要⾃⾏选择。
5、总结
上述⼏步并不是并⾏的,⼀个apk的安全措施上述⼏步是必须要做的。下⾯来截⼏张混淆后和加固后的
反编译之后的java源码的对⽐图:附上
(1)混淆后加固前的 字节码反编译为java源码的截图如下所⽰

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。

发表评论