安卓安全

文章目录[x]
  1. 1:混淆代码
  2. 2:Native方法加密
  3. 3:Native进行签名校验
  4. 4:反Xposed调试

要防止逆向工程师反编译自己的App获取核心算法或其他功能,App核心代码或者功能加密便非常重要。假如需要在App端将请求服务器的参数进行MD5加密生成签名,然后带上签名发起请求。

混淆代码

最基础的加密便是通过配置proguard-rules.proApp中的代码进行混淆,这种可以使App中的类名、方法名等变成不易识别的代码。但是,这种弊端很大,对专门的逆向工程师而言就跟直接看源代码一样。而且四大组件、JNI Native方法都不能混淆,从一定意义上来将,还是属于源代码裸奔状态。因此,Java层做加密(可以防止别人抓包,但是无法防止别人反编译),在Java层进行MD5加密生成签名将毫无意义。

Native方法加密

通过调用Native方法将参数进行加密而生成签名:

external fun signatureParams(info:String):String

这样,逆向工程师就不容易找到加密相关的代码。但是这样还是有弊端的,还是无法防止别人反编译apk,因为Native方法本身原因无法对方法进行混淆,只要匹配好包名和方法名拿到apk中的so包照样可以调用。

Native进行签名校验

要处理上面的这种情况,可以在app启动时在Native层进行包名和签名校验。验证过,在进行MD5加密才进行加密,否则可以直接退出app或者返回一个错误的字符串。

package com.melrose1994.jni3

import android.content.Context

/**
* @author Melrose
* @since 1.0.0
*/
object SignatureUtils {
init {

System.loadLibrary("native-lib")
}

external fun signatureParams(info:String):String

 

/**
* 只允许自己的app使用so ;
*/
external fun signatureVerify(context:Context)
}

在Native中实现如下,在进行MD5进行加密时is_verify为1时才进行加密操作:

//
// Created by Melrose on 2020-05-21.
//
#include "android/log.h"
#include <string>
#include <jni.h>

static const char* PACKET_NAME="com.melrose1994.jni3";
static const char* SIGN="xxxxxx";
static int is_verify = 0;
static const char* JNI_TAG= "JNI_TAG";

extern "C" JNIEXPORT void JNICALL
Java_com_melrose1994_jni3_SignatureUtils_signatureVerify(
JNIEnv *env,
jclass jclz,jobject context) {
//校验包名
jclass jclass1 = env->GetObjectClass(context);
const char* sig1 = "()Ljava/lang/String;";
jmethodID jmethodId = env->GetMethodID(
jclass1,"getPackageName",sig1);
jstring package = static_cast<jstring>(env->CallObjectMethod(context, jmethodId));
const char * c_package = const_cast<char *>(env->GetStringUTFChars(package, NULL));

if(strcmp(PACKET_NAME,c_package)!=0){
return;
}

__android_log_print(ANDROID_LOG_INFO,JNI_TAG,"包名一致");

//校验签名
const char* sig2 = "()Landroid/content/pm/PackageManager;";
jmethodId = env->GetMethodID(jclass1,"getPackageManager",sig2);
jobject manager = env->CallObjectMethod(context,jmethodId);

jclass1 = env->GetObjectClass(manager);
const char* sig3 = "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;";
jmethodId = env->GetMethodID(jclass1,"getPackageInfo",sig3);
jobject package_info = env->CallObjectMethod(manager,jmethodId,package,0x00000040);

jclass1 = env->GetObjectClass(package_info);
jfieldID jfieldId = env->GetFieldID(jclass1,"signatures","[Landroid/content/pm/Signature;");
jobjectArray arr = static_cast<jobjectArray>(env->GetObjectField(package_info, jfieldId));

jobject info =env->GetObjectArrayElement(arr,0);

jclass1 = env->GetObjectClass(info);
const char* sig4 = "()Ljava/lang/String;";
jmethodId = env->GetMethodID(jclass1,"toCharsString",sig4);
jstring j_sign = static_cast<jstring>(env->CallObjectMethod(info, jmethodId));

const char* c_sign =env->GetStringUTFChars(j_sign,NULL);

__android_log_print(ANDROID_LOG_INFO,JNI_TAG,"签名成功:%s",c_sign);

if (strcmp(c_sign,SIGN) == 0){
//签名成功
is_verify = 1;
}
}

反Xposed调试

Xposed框架中,逆向工程师可以对App进行各种Hook操作来获取App中相关重要的信息。可以在Native方法中通过/proc/{Process.myPid()}/maps读取App自身加载的库中的jarso文件查看是否含有XposedBridge.jar文件。

 

点赞

发表评论

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像

Title - Artist
0:00