Android 调用C++代码
作用:提高apk包的安全性,降低被逆向破解的风险
目前我尝试了以下几种做法,:
1. c++校验java包文件MD5值
2. c++封装加解密算法
3. 动态注册java加密接口
仅供参考,如要移植到项目请慎重,以下为实现部分代码:
完整工程:https://download.youkuaiyun.com/download/oek8y/10544110
#include "aes.h"
#include <jni.h>
#include <string>
//错误key
BYTE key[] = { 0x6E, 0x65, 0xAE, 0x0B,
0xE7, 0x28, 0x51, 0xEB,
0xA6, 0x12, 0x10, 0x21,
0x13, 0x35, 0x18, 0x2E
};
bool gCheckValid = false;
# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
/*加密接口
* IN jstring
* OUT jbyteArray
*/
jbyteArray Native_Encryt(JNIEnv *env, jobject obj, jstring str)
{
//编码转换
const char *src = env->GetStringUTFChars(str, 0);
jsize srcSize= env->GetStringUTFLength(str);
//加密
jbyte* dst = 0;
CAES aes(key);
jsize dstSize = aes.Encrypt(src, srcSize, (void* &)dst, 0);
env->ReleaseStringUTFChars(str, src);
//返回byte[]
jbyteArray jarEncrty =env->NewByteArray(dstSize);
env->SetByteArrayRegion(jarEncrty, 0,dstSize,dst);
return jarEncrty;
}
static void InitEncrtyEnv()
{
//初始化正确key
BYTE keyCorrect[] = { 0x6E, 0x66, 0xAE, 0x0B,
0xE7, 0x59, 0x41, 0xEB,
0xA6, 0x53, 0x10, 0x21,
0x13, 0x86, 0x08, 0x2E
};
memcpy(key, keyCorrect, 16);
}
static JNINativeMethod method[] = { {"Encryt", "(Ljava/lang/String;)[B", (void*)Native_Encryt}, };
static const char *classPathName = "com/example/administrator/application2/CPlusInterface";
extern "C"
JNIEXPORT jstring
JNICALL
Java_com_example_administrator_application2_MainActivity_stringFromJNI(
JNIEnv *env,
jobject _this )
{
std::string hello = "Hello from C++";
//获取包路径
jclass cls2 = env->GetObjectClass(_this);
jmethodID jmeth = env->GetMethodID(cls2, "getPackageCodePath", "()Ljava/lang/String;");
jstring strPath = (jstring)env->CallObjectMethod(_this, jmeth);
//获取包内classes.dex文件crc32
jclass clsZipFile = env->FindClass("java/util/zip/ZipFile");
jmethodID jmethZipFile = env->GetMethodID(clsZipFile, "<init>", "(Ljava/lang/String;)V");
jobject objZipFile = env->NewObject(clsZipFile,jmethZipFile, strPath);
jmethodID jmethdZipEntry = env->GetMethodID(clsZipFile, "getEntry", "(Ljava/lang/String;)Ljava/util/zip/ZipEntry;");
//需要校验的文件列表
std::string fileList[] = {
"classes.dex"
};
//原始文件classes.dex 的crc32值,编译后修改
long filesCrc32[] = {
0x32343ef
};
bool bCheckSuc = true;
for (int i=0; i<NELEM(fileList); i++)
{
jstring strClassDexName = env->NewStringUTF(fileList[i].c_str());
jobject objZipEntry = env->CallObjectMethod(objZipFile, jmethdZipEntry, strClassDexName);
jclass clsZipEntry = env->GetObjectClass(objZipEntry);
jmethodID jmethdGetCrc = env->GetMethodID(clsZipEntry, "getCrc", "()J");
jlong lcrc= env->CallLongMethod(objZipEntry, jmethdGetCrc);
//与原始文件crc32校验
if (lcrc != filesCrc32[i])
{
bCheckSuc = false;
}
}
//if (bCheckSuc)
{
//注册加密函数
jclass cls = env->FindClass("com/example/administrator/application2/CPlusInterface");
env->RegisterNatives(cls, method, 1);
//初始化加密环境,确保加密与解密匹配
InitEncrtyEnv();
}
return env->NewStringUTF(hello.c_str());
}