Android App安全防范措施的小结

关闭日志的打印

关闭打印的日志,防止日志中的调试信息被看到。如果在网络框架中使用了日志,那就更加需要关闭了。

代码混淆

代码混淆是最基本的做法,至少能让App在被反编译之后不那么顺畅地阅读源码。

当然,即使是混淆之后的代码,只要花费一定的时间,仍然是可以厘清代码之间的逻辑。

混淆字典的使用

如果对代码中的类名、变量名变成a、b、c还不爽,那可以自定义一些字符来替代它们。此时需要用到混淆字典。

推荐一个github上的库:https://github.com/ysrc/AndroidObfuseDictionary

在proguard-rules.pro中添加混淆字典的配置

#混淆字典
-obfuscationdictionary dic.txt
-classobfuscationdictionary dic.txt
-packageobfuscationdictionary dic.txt 

native层校验

除了混淆之外,App还需要防止被别人进行二次打包。

由于release签名的唯一性,可以考虑在native层进行签名的校验。如果签名不正确,直接让App crash。

我们重写JNI_OnLoad()函数,在此处进行校验。

jint JNI_OnLoad(JavaVM *vm, void *reserved) {JNIEnv *env = NULL;if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {return JNI_ERR;}if (verifySign(env) == JNI_OK) {return JNI_VERSION_1_4;}LOGE("签名不一致!");return JNI_ERR;
} 

verifySign()函数会执行真正的校验,将存放在native层的签名字符串和当前App的签名进行比对。

static int verifySign(JNIEnv *env) {// Application objectjobject application = getApplication(env);if (application == NULL) {return JNI_ERR;}// Context(ContextWrapper) classjclass context_clz = env->GetObjectClass(application);// getPackageManager()jmethodID getPackageManager = env->GetMethodID(context_clz, "getPackageManager", "()Landroid/content/pm/PackageManager;");// android.content.pm.PackageManager objectjobject package_manager = env->CallObjectMethod(application, getPackageManager);// PackageManager classjclass package_manager_clz = env->GetObjectClass(package_manager);// getPackageInfo()jmethodID getPackageInfo = env->GetMethodID(package_manager_clz, "getPackageInfo","(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");// context.getPackageName()jmethodID getPackageName = env->GetMethodID(context_clz, "getPackageName","()Ljava/lang/String;");// call getPackageName() and cast from jobject to jstringjstring package_name = (jstring) (env->CallObjectMethod(application, getPackageName));// PackageInfo objectjobject package_info = env->CallObjectMethod(package_manager, getPackageInfo, package_name, 64);// class PackageInfojclass package_info_clz = env->GetObjectClass(package_info);// field signaturesjfieldID signatures_field = env->GetFieldID(package_info_clz, "signatures","[Landroid/content/pm/Signature;");jobject signatures = env->GetObjectField(package_info, signatures_field);jobjectArray signatures_array = (jobjectArray) signatures;jobject signature0 = env->GetObjectArrayElement(signatures_array, 0);jclass signature_clz = env->GetObjectClass(signature0);jmethodID toCharsString = env->GetMethodID(signature_clz, "toCharsString", "()Ljava/lang/String;");// call toCharsString()jstring signature_str = (jstring) (env->CallObjectMethod(signature0, toCharsString));// releaseenv->DeleteLocalRef(application);env->DeleteLocalRef(context_clz);env->DeleteLocalRef(package_manager);env->DeleteLocalRef(package_manager_clz);env->DeleteLocalRef(package_name);env->DeleteLocalRef(package_info);env->DeleteLocalRef(package_info_clz);env->DeleteLocalRef(signatures);env->DeleteLocalRef(signature0);env->DeleteLocalRef(signature_clz);const char *sign = env->GetStringUTFChars(signature_str, NULL);if (sign == NULL) {LOGE("分配内存失败");return JNI_ERR;}int result = strcmp(sign, RELEASE_SIGN);// 使用之后要释放这段内存env->ReleaseStringUTFChars(signature_str, sign);env->DeleteLocalRef(signature_str);if (result == 0) { // 签名一致return JNI_OK;}return JNI_ERR;
} 

JNI_OnLoad()函数是只有使用了JNI,才会被调用。为了确保App一启动就能够进行验证签名。

我还写了一个方法:

jstring Java_io_merculet_core_utils_EncryptUtils_nativeCheck(JNIEnv *env, jclass type) {return env->NewStringUTF("Security str from native.");
} 

在App的MainActivity的onCreate()中使用。

 EncryptUtils.nativeCheck() 

EncryptUtils是一个工具类,用于调用native层的方法。

/**
 * @version V1.0 <描述当前版本功能>
 * @FileName: io.merculet.core.utils.EncryptUtils.java
 * @author: Tony Shen
 * @date: 2018-05-21 20:53
 */
public class EncryptUtils {// Used to load the 'native-lib' library on application startup.static {System.loadLibrary("codec");}public static native String nativeCheck();...
} 

关键的密码不要明文传输

例如登录、支付相关的密码,最好不要明文传输,需要进行加密。如果在Java层来做加密容易被反编译,那么可以考虑使用C++来实现。

总结

这些措施也只是冰山一角,因为安全一直是永恒的话题。我们还可以考虑使用加壳、反动态调试等等。

参考资料:

1.http://qbeenslee.com/article/about-wandoujia-proguard-config/
2.https://github.com/Qrilee/AndroidObfuseDictionary
3.https://www.jianshu.com/p/2576d064baf1


Java与Android技术栈:每周更新推送原创技术文章,欢迎扫描下方的公众号二维码并关注,期待与您的共同成长和进步。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值