前言
由于Android系统的开放性,开发出来的APP很容易被逆向,修改代码逻、加入广告、病毒等二次打包后发布,对开发者和用户造成一定的损失。因此我们的APP运行过程中需要进行签名校验,以及使用加解密算法对数据进行处理,从而保证访问服务端的请求是我们信任的APK。签名校验如果放在Java语言层面,很容易被逆向,因此需要在C/C++层进行校验,从而增加破解的难度。
校验逻辑
- APP启动时候初始化我们所写的动态库,一般在Application的onCrate()方法中初始化
- 获取APP的签名SHA1值
- 匹配获取到的值是否与C/C++中写入的值相同
- APP在加载so文件是,会自动调用JNI_OnLoad方法,因此在该方法中进行判断,如果签名不匹配,返回-1,让App Crash
实现步骤
第一步:NDK环境搭建
NDK环境的搭建可参考谷歌官方文档,已经翻译为中文;
第二步:编写Java层代码
1,工具类
public class SecurityTool {
static {
System.loadLibrary("hts-security");
}
public static void init(){}
}
2,在Application中初始化
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
SecurityTool.init();
}
}
SecurityTool的init(){}方法只写了一个空方法,根据虚拟机类的初始化机制,当遇到new,getstatic,putstatic、invokestatic这4条字节码指令时,会执行类的初始化。类的初始化过程中,先执行静态代码块,因此会自动执行我们动态库的OnLoad,完成校验。
第二步:C++代码完成校验
定义校验文件:app-validate.cpp
//
// Created by qj on 2020/1/8.
//
const char HEX_CODE[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
const char *APP_SIGNATURE = "6C97D7FC026DB630523D6ECA15941129F62B0083";
char *appSha1 = NULL;
/**
*
* get sha1 by reflect
*
*/
char* getAppSha1(JNIEnv *env, jobject context_object){
if(appSha1 == NULL){
jclass context_class = env->GetObjectClass(context_object);
jmethodID methodId = env->GetMethodID(context_class, "getPackag