android APK補強編-3.JNIを使用してdexと呼び出し方法をロードする
4435 ワード
1.まずassetsのtestをdexはアプリケーションのfiles空間にコピーされます.
2.JNIメソッドを使用してdexLoaderClassオブジェクトがjavaに割り当てられたdexLoaderClassメンバー変数を作成
3.testを呼び出す.dex中のTest 1類の方法test.
4.2つの方法の比較といくつかの暗号化の説明.
Javaメソッドでdexをロードすると、より簡単に使用できますが、コードが表示されやすく、多くの操作面が表示されます.
JNI/C++でdexをロードするのはjavaでdexをロードするよりずっと面倒ですが、セキュリティ上はもっと高く、assetsのdexを暗号化したりブロック化したりすることができます.
copyがdata空間に到達したときに復号と元のdexを再作成し,暗号化コードはすべてアセンブリ内容であり,具体的な操作を理解することは困難である.
もちろん具体的にはクラスとdexをロードした後、data空間で生成された2つのdexを直接削除し、コードが他の人に見られないようにすると、apkをより強化することができます.
APKの逆コンパイルと解読を防ぐ.
ソース・リンクの2つの方法:http://download.csdn.net/detail/csdn49532/9425977
string copyDexToData(JNIEnv* env, jobject asset, string dexName,
string dataPath)
{
AAssetManager* asMg = AAssetManager_fromJava(env, asset);
AAsset* as = AAssetManager_open(asMg, dexName.c_str(), AASSET_MODE_UNKNOWN);
if (as == NULL)
{
LOGE("%s not found in assets!",dexName.c_str());
return "";
}
string strDexPath = dataPath + "/files/" + dexName;
int len = AAsset_getLength(as);
int file = open(strDexPath.c_str(), O_WRONLY | O_CREAT, 0755);
if (file < 0)
{
AAsset_close(as);
LOGE("Open %s File Error!",strDexPath.c_str());
return "";
}
char* buf = new char[1024];
while (len > 0)
{
memset(buf, 0, 1024);
int n = AAsset_read(as, buf, 1024);
if (n < 0)
break;
write(file, buf, n);
len -= n;
}
delete[] buf;
AAsset_close(as);
close(file);
return strDexPath;
}
2.JNIメソッドを使用してdexLoaderClassオブジェクトがjavaに割り当てられたdexLoaderClassメンバー変数を作成
void Java_com_example_dexload_NativeLoad_loadDex(JNIEnv* env, jobject obj,
jstring dexName, jstring dataPath, jobject asset)
{
JavaVM* jvm;
env->GetJavaVM(&jvm);
JNIUtil::SetJavaVm(jvm);
JNIUtil util;
string strDexName = util.Jstring2String(dexName);
string strdataPath = util.Jstring2String(dataPath);
string strDexPath = copyDexToData(env, asset, strDexName, strdataPath);
string strDestDexPath = strdataPath + "/cache";
LOGI("%s",strDexPath.c_str());
LOGI("%s",strDestDexPath.c_str());
jstring jDexPath = util.String2Jstring(strDexPath.c_str());
jstring jDestDexPath = util.String2Jstring(strDestDexPath.c_str());
// ClassLoader classloader
jclass classloaderClass = env->FindClass("java/lang/ClassLoader");
jmethodID getsysloaderMethod = env->GetStaticMethodID(classloaderClass,
"getSystemClassLoader", "()Ljava/lang/ClassLoader;");
jobject loader = env->CallStaticObjectMethod(classloaderClass,
getsysloaderMethod);
// DexClassLoader dex
jclass dexLoaderClass = env->FindClass("dalvik/system/DexClassLoader");
jmethodID initDexLoaderMethod = env->GetMethodID(dexLoaderClass, "",
"(Ljava/lang/String;Ljava/lang/String;"
"Ljava/lang/String;Ljava/lang/ClassLoader;)V");
jobject dexLoader = env->NewObject(dexLoaderClass, initDexLoaderMethod,
jDexPath, jDestDexPath , NULL, loader);
// java DexClassLoader
jclass native = env->GetObjectClass(obj);
jfieldID loadID = env->GetFieldID(native, "mDex",
"Ldalvik/system/DexClassLoader;");
env->SetObjectField(obj, loadID, dexLoader);
}
3.testを呼び出す.dex中のTest 1類の方法test.
void Java_com_example_dexload_NativeLoad_test(JNIEnv* env, jobject obj,
jobject ac)
{
// java ClassLoader
jclass native = env->GetObjectClass(obj);
jfieldID loadID = env->GetFieldID(native, "mDex",
"Ldalvik/system/DexClassLoader;");
jobject load = env->GetObjectField(obj, loadID);
// ClassLoader loadClass dex Test1
jclass classloaderClass = env->GetObjectClass(load);
jmethodID loadClassMethod = env->GetMethodID(classloaderClass, "loadClass",
"(Ljava/lang/String;)Ljava/lang/Class;");
JNIUtil util;
jstring Test1ClassName = util.String2Jstring("com.example.dextest.Test1");
jclass javaClientClass = (jclass) env->CallObjectMethod(load,
loadClassMethod, Test1ClassName);
// Test1 test
jmethodID initFuncTest = env->GetMethodID(javaClientClass, "", "()V"); // ID
jobject objTest1 = env->NewObject(javaClientClass, initFuncTest);
jmethodID Test_method = env->GetMethodID(javaClientClass, "test",
"(Landroid/app/Activity;)V");
if (Test_method != NULL)
env->CallVoidMethod(objTest1, Test_method, ac);
}
4.2つの方法の比較といくつかの暗号化の説明.
Javaメソッドでdexをロードすると、より簡単に使用できますが、コードが表示されやすく、多くの操作面が表示されます.
JNI/C++でdexをロードするのはjavaでdexをロードするよりずっと面倒ですが、セキュリティ上はもっと高く、assetsのdexを暗号化したりブロック化したりすることができます.
copyがdata空間に到達したときに復号と元のdexを再作成し,暗号化コードはすべてアセンブリ内容であり,具体的な操作を理解することは困難である.
もちろん具体的にはクラスとdexをロードした後、data空間で生成された2つのdexを直接削除し、コードが他の人に見られないようにすると、apkをより強化することができます.
APKの逆コンパイルと解読を防ぐ.
ソース・リンクの2つの方法:http://download.csdn.net/detail/csdn49532/9425977