为了防止apk被轻易破解,想办法对java层的代码进行加密,防止反编译,代码混淆基本没什么效果,一般情况下我会对dex进行加密,通过动态加载的方法实现java层的代码尽量被隐藏,而动态加载的实现通过jni来完成,最大化的保护代码安全,其实java层这个时候只剩下继承于Application的启动类。
.h文件
1 #ifndef __ANDROID_JNI_BOOT_HELPER_H__ 2 #define __ANDROID_JNI_BOOT_HELPER_H__ 3 4 #include <jni.h> 5 #include <string> 6 #include "android/asset_manager.h" 7 #include "android/asset_manager_jni.h" 8 9 typedef struct JniMethodInfo_10 {11 JNIEnv * env;12 jclass classID;13 jmethodID methodID;14 } JniMethodInfo;15 16 class JniBootHelper17 {18 public:19 static void setJavaVM(JavaVM *javaVM);20 static JavaVM* getJavaVM();21 static JNIEnv* getEnv();22 23 static bool setassetmanager(jobject activityinstance);24 static AAssetManager* getAssetManager() { return _assetmanager; }25 26 static bool setFileDir(jobject activityinstance);27 static bool setCacheDir(jobject activityinstance);28 29 static bool loadDexFile(jobject context,30 const char* dexPath, 31 const char* dexOptDir);32 33 static bool loadClass(jobject context);34 35 static jobject invokeStaticMethod(JNIEnv *env, 36 const char* className, 37 const char* methodName, 38 jobjectArray pareTyple, 39 jobjectArray pareVaules);40 41 static jobject getFieldOjbect(JNIEnv *env, 42 const char* className, 43 const char* fieldName,44 jobject obj);45 static void setFieldOjbect(JNIEnv *env, 46 const char* className, 47 const char* fieldName, 48 jobject obj, 49 jobject filedVaule);50 51 static std::string jstring2string(jstring str);52 53 static std::string FileDir;54 static std::string CacheDir;55 56 private:57 static JNIEnv* cacheEnv(JavaVM* jvm);58 59 static bool getMethodInfo(JniMethodInfo &methodinfo,60 const char *className,61 const char *methodName,62 const char *paramCode);63 64 static JavaVM* _psJavaVM;65 static AAssetManager* _assetmanager;66 static jmethodID _loadclassMethod_methodID;67 static jobject _classloader;68 };69 70 #endif // __ANDROID_JNI_BOOT_HELPER_H__
.cpp文件
1 #include "JniBootHelper.h" 2 #include <android/log.h> 3 #include <string.h> 4 #include <pthread.h> 5 6 #include "DexMarcoDef.h" 7 8 static pthread_key_t g_key; 9 10 11 void _detachCurrentThread(void* a) { 12 LOGD("DetachCurrentThread"); 13 JniBootHelper::getJavaVM()->DetachCurrentThread(); 14 } 15 16 17 JavaVM* JniBootHelper::_psJavaVM = nullptr; 18 std::string JniBootHelper::FileDir = ""; 19 std::string JniBootHelper::CacheDir = ""; 20 AAssetManager* JniBootHelper::_assetmanager = nullptr; 21 jmethodID JniBootHelper::_loadclassMethod_methodID = nullptr; 22 jobject JniBootHelper::_classloader = nullptr; 23 24 bool JniBootHelper::setassetmanager(jobject activityinstance) { 25 JniMethodInfo _getassetsMethod; 26 if (!JniBootHelper::getMethodInfo(_getassetsMethod, 27 "android/content/Context", 28 "getAssets", 29 "()Landroid/content/res/AssetManager;")) { 30 LOGE("getmethod getAssets() failed."); 31 return false; 32 } 33 34 jobject _am = JniBootHelper::getEnv()->CallObjectMethod(activityinstance, 35 _getassetsMethod.methodID); 36 37 if (nullptr == _am) { 38 LOGE("CallObjectMethod getAssets() failed."); 39 return false; 40 } 41 42 JniBootHelper::_assetmanager = AAssetManager_fromJava(JniBootHelper::getEnv(), _am); 43 return true; 44 } 45 46 bool JniBootHelper::setFileDir(jobject activityinstance) 47 { 48 JniMethodInfo _getFileDirMethod; 49 if (!JniBootHelper::getMethodInfo(_getFileDirMethod, 50 "android/content/Context", 51 "getFilesDir", 52 "()Ljava/io/File;")) { 53 LOGE("getmethod getFilesDir() failed."); 54 return false; 55 } 56 jobject _f = JniBootHelper::getEnv()->CallObjectMethod(activityinstance, 57 _getFileDirMethod.methodID); 58 if (nullptr == _f) { 59 LOGE("CallObjectMethod getFilesDir() failed."); 60 return false; 61 } 62 JniMethodInfo _getFilePathMethod; 63 if (!JniBootHelper::getMethodInfo(_getFilePathMethod, 64 "java/io/File", 65 "getAbsolutePath", 66 "()Ljava/lang/String;")) { 67 LOGE("getmethod getAbsolutePath() failed."); 68 return false; 69 } 70 jstring _p = (jstring)JniBootHelper::getEnv()->CallObjectMethod(_f, 71 _getFilePathMethod.methodID); 72 if (nullptr == _p) { 73 LOGE("CallObjectMethod getAbsolutePath() failed."); 74 return false; 75 } 76 77 JniBootHelper::FileDir.assign(JniBootHelper::jstring2string(_p)); 78 LOGD("apk FileDir : %s", JniBootHelper::FileDir.c_str()); 79 JniBootHelper::getEnv()->DeleteLocalRef(_p); 80 return true; 81 } 82 83 bool JniBootHelper::setCacheDir(jobject activityinstance) 84 { 85 JniMethodInfo _getFileDirMethod; 86 if (!JniBootHelper::getMethodInfo(_getFileDirMethod, 87 "android/content/Context", 88 "getCacheDir", 89 "()Ljava/io/File;")) { 90 LOGE("getmethod getCacheDir() failed."); 91 return false; 92 } 93 jobject _f = JniBootHelper::getEnv()->CallObjectMethod(activityinstance, 94 _getFileDirMethod.methodID); 95 if (nullptr == _f) { 96 LOGE("CallObjectMethod getCacheDir() failed."); 97 return false; 98 } 99 JniMethodInfo _getFilePathMethod;100 if (!JniBootHelper::getMethodInfo(_getFilePathMethod,101 "java/io/File",102 "getAbsolutePath",103 "()Ljava/lang/String;")) {104 LOGE("getmethod getAbsolutePath() failed.");105 return false;106 }107 jstring _p = (jstring)JniBootHelper::getEnv()->CallObjectMethod(_f,108 _getFilePathMethod.methodID);109 if (nullptr == _p) {110 LOGE("CallObjectMethod getAbsolutePath() failed.");111 return false;112 }113 114 JniBootHelper::CacheDir.assign(JniBootHelper::jstring2string(_p));115 LOGD("apk CacheDir : %s", JniBootHelper::CacheDir.c_str());116 JniBootHelper::getEnv()->DeleteLocalRef(_p);117 return true;118 }119 120 bool JniBootHelper::loadClass(jobject context)121 {122 JNIEnv *env = JniBootHelper::getEnv();123 if (!env) {124 return false;125 }126 127 jstring _jstrClassName = env->NewStringUTF("com/origingame/InApplicationMethod");128 jclass _classid = (jclass) env->CallObjectMethod(JniBootHelper::_classloader,129 JniBootHelper::_loadclassMethod_methodID,130 _jstrClassName);131 if(!_classid)132 {133 LOGE("can not find class com/origingame/InApplicationMethod");134 }135 jmethodID _mid = env->GetStaticMethodID(_classid, "onCreate", "(Landroid/content/Context;)V");136 if(!_mid)137 {138 LOGE("failed to find methodID onCreate");139 }140 env->CallStaticVoidMethod(_classid, _mid, context);141 env->DeleteLocalRef(_jstrClassName);142 env->DeleteGlobalRef(JniBootHelper::_classloader);143 }144 145 bool JniBootHelper::loadDexFile(jobject context,146 const char* dexPath, 147 const char* dexOptDir)148 {149 JNIEnv *env = JniBootHelper::getEnv();150 if (!env) {151 return false;152 }153 154 jstring dexPathString, dexOptDirString;155 dexPathString = env->NewStringUTF(dexPath);156 dexOptDirString = env->NewStringUTF(dexOptDir);157 158 jclass native_clazz = env->GetObjectClass(context);159 jmethodID methodID_func = env->GetMethodID(native_clazz, 160 "getPackageName", 161 "()Ljava/lang/String;");162 jstring packagename = (jstring) (env->CallObjectMethod(context, methodID_func));163 std::string _packagename = JniBootHelper::jstring2string(packagename);164 LOGD("packagename: %s",_packagename.c_str());165 char libsDir[256];166 sprintf(libsDir, "/data/data/%s/lib", _packagename.c_str());167 jstring jlibsDir = env->NewStringUTF(libsDir);168 169 170 jclass jActivityThread = env->FindClass("android/app/ActivityThread");171 if(!jActivityThread)172 {173 LOGE("can not find class android/app/ActivityThread");174 }175 jmethodID jcATmid = env->GetStaticMethodID(jActivityThread, "currentActivityThread", "()Landroid/app/ActivityThread;");176 jobject currentActivityThread = env->CallStaticObjectMethod(jActivityThread, jcATmid);177 178 179 jclass class_hashmap = env->FindClass("java/util/Map");180 181 182 jobject obj_hashmap = JniBootHelper::getFieldOjbect(env, 183 "android.app.ActivityThread", 184 "mPackages",185 currentActivityThread);186 /*187 jmethodID map_size = env->GetMethodID(class_hashmap, 188 "size", 189 "()I");190 jint size = (jint)env->CallObjectMethod(obj_hashmap, 191 map_size192 );193 LOGD("map size : %d", (int)size);194 */195 if(!obj_hashmap)196 {197 LOGE("obj_hashmap is null");198 }199 200 jclass class_WeakReference = env->FindClass("java/lang/ref/WeakReference");201 if (!class_WeakReference) 202 {203 LOGE("class_WeakReference Not Found ");204 }205 206 jmethodID WeakReference_get_method = env->GetMethodID(class_WeakReference, 207 "get", 208 "()Ljava/lang/Object;");209 if (!WeakReference_get_method) 210 {211 LOGE("WeakReference_get_method Not Found ");212 }213 214 jmethodID get_func = env->GetMethodID(class_hashmap, 215 "get", 216 "(Ljava/lang/Object;)Ljava/lang/Object;");217 if (!get_func) {218 LOGE("method get Not Found ");219 }220 221 jobject get_obj = env->CallObjectMethod(obj_hashmap, 222 get_func, 223 packagename);224 if (!get_obj) {225 LOGE("get_obj Not Found ");226 }227 228 jobject get_get_obj = env->CallObjectMethod(get_obj, 229 WeakReference_get_method);230 if (!get_get_obj) {231 LOGE("get_get_obj Not Found ");232 }233 234 /*235 jclass class_DexClassloader = env->FindClass("dalvik/system/DexClassLoader");236 if (!class_DexClassloader) {237 LOGE("class_DexClassloader Not Found ");238 }239 240 jmethodID DexClassloader_construct_method = env->GetMethodID(class_DexClassloader, 241 "<init>",242 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V");243 if (!DexClassloader_construct_method) {244 LOGE("DexClassloader_construct_method Not Found ");245 }246 247 jobject obj_DexClassloader = env->NewObject(class_DexClassloader,248 DexClassloader_construct_method, 249 dexPathString, 250 dexOptDirString,251 jlibsDir,252 JniBootHelper::getFieldOjbect(env, "android.app.LoadedApk", "mClassLoader", get_get_obj));253 if (!obj_DexClassloader) {254 LOGE("obj_DexClassloader Not Found ");255 }256 */257 jclass class_DexClassloader = env->FindClass("dalvik/system/PathClassLoader");258 if (!class_DexClassloader) {259 LOGE("class_DexClassloader Not Found ");260 }261 262 jmethodID DexClassloader_construct_method = env->GetMethodID(class_DexClassloader, 263 "<init>",264 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V");265 if (!DexClassloader_construct_method) {266 LOGE("DexClassloader_construct_method Not Found ");267 }268 269 jobject obj_DexClassloader = env->NewObject(class_DexClassloader,270 DexClassloader_construct_method, 271 dexPathString,272 jlibsDir,273 JniBootHelper::getFieldOjbect(env, "android.app.LoadedApk", "mClassLoader", get_get_obj));274 if (!obj_DexClassloader) {275 LOGE("obj_DexClassloader Not Found ");276 }277 278 JniBootHelper::_classloader = env->NewGlobalRef(obj_DexClassloader);279 JniBootHelper::_loadclassMethod_methodID = env->GetMethodID(class_DexClassloader,280 "loadClass",281 "(Ljava/lang/String;)Ljava/lang/Class;");282 283 JniBootHelper::setFieldOjbect(env, "android.app.LoadedApk", "mClassLoader", get_get_obj, obj_DexClassloader);284 env->DeleteLocalRef(dexPathString);285 env->DeleteLocalRef(dexOptDirString);286 env->DeleteLocalRef(jlibsDir);287 LOGD("finish.");288 return true;289 }290 291 JavaVM* JniBootHelper::getJavaVM() {292 pthread_t thisthread = pthread_self();293 LOGD("JniBootHelper::getJavaVM(), pthread_self() = %ld", thisthread);294 return _psJavaVM;295 }296 297 void JniBootHelper::setJavaVM(JavaVM *javaVM) {298 pthread_t thisthread = pthread_self();299 LOGD("JniBootHelper::setJavaVM(%p), pthread_self() = %ld", javaVM, thisthread);300 _psJavaVM = javaVM;301 302 pthread_key_create(&g_key, _detachCurrentThread);303 }304 305 JNIEnv* JniBootHelper::cacheEnv(JavaVM* jvm) {306 JNIEnv* _env = nullptr;307 // get jni environment308 jint ret = jvm->GetEnv((void**)&_env, JNI_VERSION_1_4);309 310 switch (ret) {311 case JNI_OK :312 // Success!313 pthread_setspecific(g_key, _env);314 return _env;315 316 case JNI_EDETACHED :317 // Thread not attached318 if (jvm->AttachCurrentThread(&_env, nullptr) < 0)319 {320 LOGE("Failed to get the environment using AttachCurrentThread()");321 322 return nullptr;323 } else {324 // Success : Attached and obtained JNIEnv!325 pthread_setspecific(g_key, _env);326 return _env;327 }328 329 case JNI_EVERSION :330 // Cannot recover from this error331 LOGE("JNI interface version 1.4 not supported");332 default :333 LOGE("Failed to get the environment using GetEnv()");334 return nullptr;335 }336 }337 338 JNIEnv* JniBootHelper::getEnv() {339 JNIEnv *_env = (JNIEnv *)pthread_getspecific(g_key);340 if (_env == nullptr)341 _env = JniBootHelper::cacheEnv(_psJavaVM);342 return _env;343 }344 345 bool JniBootHelper::getMethodInfo(JniMethodInfo &methodinfo,346 const char *className,347 const char *methodName,348 const char *paramCode) 349 {350 if ((nullptr == className) ||351 (nullptr == methodName) ||352 (nullptr == paramCode)) {353 return false;354 }355 356 JNIEnv *env = JniBootHelper::getEnv();357 if (!env) {358 return false;359 }360 361 jclass classID = env->FindClass(className);362 if (! classID) {363 LOGE("Failed to find class %s", className);364 env->ExceptionClear();365 return false;366 }367 368 jmethodID methodID = env->GetMethodID(classID, methodName, paramCode);369 if (! methodID) {370 LOGE("Failed to find method id of %s", methodName);371 env->ExceptionClear();372 return false;373 }374 375 methodinfo.classID = classID;376 methodinfo.env = env;377 methodinfo.methodID = methodID;378 379 return true;380 }381 382 std::string JniBootHelper::jstring2string(jstring jstr) {383 if (jstr == nullptr) {384 return "";385 }386 387 JNIEnv *env = JniBootHelper::getEnv();388 if (!env) {389 return nullptr;390 }391 392 const char* chars = env->GetStringUTFChars(jstr, nullptr);393 std::string ret(chars);394 env->ReleaseStringUTFChars(jstr, chars);395 396 return ret;397 }398 399 jobject JniBootHelper::invokeStaticMethod(JNIEnv *env, 400 const char* className, 401 const char* methodName, 402 jobjectArray pareTyple, 403 jobjectArray pareVaules)404 {405 jstring jclassName, jmethodName;406 jclassName = env->NewStringUTF(className);407 jmethodName = env->NewStringUTF(methodName);408 409 jclass _class = env->FindClass("java/lang/Class");410 if(!_class)411 {412 LOGE("invokeStaticMethod: Failed to find class java/lang/Class");413 env->ExceptionClear();414 return nullptr;415 }416 417 jmethodID forname_func = env->GetStaticMethodID(_class, 418 "forName",419 "(Ljava/lang/String;)Ljava/lang/Class;");420 if(!forname_func)421 {422 LOGE("invokeStaticMethod: Failed to find method forName");423 env->ExceptionClear();424 return nullptr;425 }426 427 jobject class_obj = env->CallStaticObjectMethod(_class, 428 forname_func,429 jclassName);430 431 jclass class_java = env->GetObjectClass(class_obj);432 433 jmethodID getmethod_func = env->GetMethodID(class_java, 434 "getMethod",435 "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");436 if(!getmethod_func)437 {438 LOGE("invokeStaticMethod: Failed to find method getMethod");439 env->ExceptionClear();440 return nullptr;441 }442 443 jobject method_obj = env->CallObjectMethod(class_obj, 444 getmethod_func,445 jmethodName, 446 pareTyple);447 if(!method_obj)448 {449 LOGE("invokeStaticMethod: Failed to CallObjectMethod.%s, %s",className, methodName);450 env->ExceptionClear();451 return nullptr;452 }453 454 jclass class_method_obj = env->GetObjectClass(method_obj);455 456 jmethodID invoke_func = env->GetMethodID(class_method_obj, 457 "invoke",458 "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");459 460 if(!invoke_func)461 {462 LOGE("invokeStaticMethod: Failed to find method invoke");463 env->ExceptionClear();464 return nullptr;465 }466 467 jobject invoke_obj = env->CallObjectMethod(method_obj, 468 invoke_func, 469 NULL,470 pareVaules);471 472 env->DeleteLocalRef(jclassName);473 env->DeleteLocalRef(jmethodName);474 env->DeleteLocalRef(class_java);475 env->DeleteLocalRef(method_obj);476 LOGD("invokeStaticMethod finish.");477 return invoke_obj;478 }479 480 jobject JniBootHelper::getFieldOjbect(JNIEnv *env, 481 const char* className, 482 const char* fieldName,483 jobject obj)484 {485 jstring jclassName, jfieldName;486 jclassName = env->NewStringUTF(className);487 jfieldName = env->NewStringUTF(fieldName);488 489 jclass _class = env->FindClass("java/lang/Class");490 jmethodID forname_func = env->GetStaticMethodID(_class, 491 "forName",492 "(Ljava/lang/String;)Ljava/lang/Class;");493 if(!forname_func)494 {495 LOGE("getFieldOjbect: Failed to find method forName");496 env->ExceptionClear();497 return nullptr;498 }499 jobject class_obj = env->CallStaticObjectMethod(_class, 500 forname_func,501 jclassName);502 jclass class_java = env->GetObjectClass(class_obj);503 504 jmethodID getfield_func = env->GetMethodID(class_java, 505 "getDeclaredField",506 "(Ljava/lang/String;)Ljava/lang/reflect/Field;");507 if(!getfield_func)508 {509 LOGE("getFieldOjbect: Failed to find method getDeclaredField");510 env->ExceptionClear();511 return nullptr;512 }513 jobject method_obj = env->CallObjectMethod(class_obj, 514 getfield_func,515 jfieldName);516 jclass class_method_obj = env->GetObjectClass(method_obj);517 518 jmethodID setaccess_func = env->GetMethodID(class_method_obj,519 "setAccessible", 520 "(Z)V");521 if(!setaccess_func)522 {523 LOGE("getFieldOjbect: Failed to find method setAccessible");524 env->ExceptionClear();525 return nullptr;526 }527 env->CallVoidMethod(method_obj, 528 setaccess_func, 529 true);530 531 jmethodID get_func = env->GetMethodID(class_method_obj, 532 "get",533 "(Ljava/lang/Object;)Ljava/lang/Object;");534 if(!get_func)535 {536 LOGE("getFieldOjbect: Failed to find method get");537 env->ExceptionClear();538 return nullptr;539 }540 jobject get_obj = env->CallObjectMethod(method_obj, 541 get_func, 542 obj);543 544 env->DeleteLocalRef(class_java);545 env->DeleteLocalRef(method_obj);546 env->DeleteLocalRef(jclassName);547 env->DeleteLocalRef(jfieldName);548 return get_obj;549 }550 551 void JniBootHelper::setFieldOjbect(JNIEnv *env, 552 const char* className, 553 const char* fieldName, 554 jobject obj, 555 jobject filedVaule)556 {557 jstring jclassName, jfieldName;558 jclassName = env->NewStringUTF(className);559 jfieldName = env->NewStringUTF(fieldName);560 561 jclass _class = env->FindClass("java/lang/Class");562 if(!_class)563 {564 LOGE("setFieldOjbect: Failed to find java/lang/Class");565 env->ExceptionClear();566 return;567 }568 jmethodID forName_func = env->GetStaticMethodID(_class, 569 "forName",570 "(Ljava/lang/String;)Ljava/lang/Class;");571 if(!forName_func)572 {573 LOGE("setFieldOjbect: Failed to find method forname");574 env->ExceptionClear();575 return;576 }577 jobject class_obj = env->CallStaticObjectMethod(_class, 578 forName_func,579 jclassName);580 jclass class_java = env->GetObjectClass(class_obj);581 582 jmethodID getField_func = env->GetMethodID(class_java, 583 "getDeclaredField",584 "(Ljava/lang/String;)Ljava/lang/reflect/Field;");585 if(!getField_func)586 {587 LOGE("setFieldOjbect: Failed to find method getDeclaredField");588 env->ExceptionClear();589 return;590 }591 jobject method_obj = env->CallObjectMethod(class_obj, 592 getField_func,593 jfieldName);594 jclass class_method_obj = env->GetObjectClass(method_obj);595 596 jmethodID setaccess_func = env->GetMethodID(class_method_obj,597 "setAccessible", 598 "(Z)V");599 if(!setaccess_func)600 {601 LOGE("setFieldOjbect: Failed to find method setAccessible");602 env->ExceptionClear();603 return;604 }605 env->CallVoidMethod(method_obj, setaccess_func, true);606 607 jmethodID set_func = env->GetMethodID(class_method_obj, 608 "set",609 "(Ljava/lang/Object;Ljava/lang/Object;)V");610 if(!set_func)611 {612 LOGE("setFieldOjbect: Failed to find method set");613 env->ExceptionClear();614 return;615 }616 env->CallVoidMethod(method_obj, 617 set_func, 618 obj, 619 filedVaule);620 621 env->DeleteLocalRef(class_java);622 env->DeleteLocalRef(method_obj);623 env->DeleteLocalRef(jclassName);624 env->DeleteLocalRef(jfieldName);625 }
主入口
1 #include "JniBootHelper.h" 2 #include "BootFileUtils.h" 3 #include "CPakReader.h" 4 5 #include <android/log.h> 6 #include <jni.h> 7 8 #include "DexMarcoDef.h" 9 10 #define Dex_asstesPath "assets/OriginAPP.jar" 11 #define Dex_NAME "OriginClasses.jar" 12 #define Dex_RELEASEFLODER "OriginBoot" 13 #define Dex_CACHEFLODER "OriginBootCache" 14 15 extern "C" 16 { 17 JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) 18 { 19 LOGD("JNI_OnLoad has been called."); 20 JniBootHelper::setJavaVM(vm); 21 22 return JNI_VERSION_1_4; 23 } 24 25 JNIEXPORT void JNI_OnUnLoad(JavaVM *vm, void *reserved) 26 { 27 LOGD("JNI_OnUnLoad has been called."); 28 } 29 30 JNIEXPORT void Java_com_origingame_OriginShell_nativeLoadClass(JNIEnv* env, jobject thiz, jobject context) 31 { 32 JniBootHelper::loadClass(context); 33 } 34 35 JNIEXPORT void Java_com_origingame_OriginShell_nativeBoot(JNIEnv* env, jobject thiz, jobject context) 36 { 37 bool _initsuccess = true; 38 39 if(!JniBootHelper::setassetmanager(context)){ 40 LOGE("setassetmanager failed!"); 41 _initsuccess = false; 42 } 43 44 if(!JniBootHelper::setFileDir(context)){ 45 LOGE("setFileDir failed!"); 46 _initsuccess = false; 47 } 48 49 if(!JniBootHelper::setCacheDir(context)){ 50 LOGE("setCacheDir failed!"); 51 _initsuccess = false; 52 } 53 54 if(_initsuccess) 55 { 56 LOGD("init success."); 57 bool _dirExist = false; 58 bool _exist = false; 59 BootFileUtils* fileutils = BootFileUtils::getInstance(); 60 std::string _path = JniBootHelper::FileDir; 61 _path.append("/"); 62 _path.append(Dex_RELEASEFLODER); 63 LOGD("check dir: %s", _path.c_str()); 64 if(fileutils->isDirectoryExistInternal(_path)) 65 { 66 _dirExist = true; 67 std::string _file = JniBootHelper::FileDir; 68 _file.append("/"); 69 _file.append(Dex_RELEASEFLODER); 70 _file.append("/"); 71 _file.append(Dex_NAME); 72 if(fileutils->isFileExistInternal(_file)) 73 _exist = true; 74 } 75 76 std::string _cachedirpath = JniBootHelper::FileDir; 77 _cachedirpath.append("/"); 78 _cachedirpath.append(Dex_CACHEFLODER); 79 80 if(!_dirExist) 81 { 82 LOGD("create dir."); 83 std::string _filedirpath = JniBootHelper::FileDir; 84 _filedirpath.append("/"); 85 _filedirpath.append(Dex_RELEASEFLODER); 86 fileutils->createDirectory(_filedirpath); 87 88 fileutils->createDirectory(_cachedirpath); 89 } 90 91 92 std::string _dexPath = JniBootHelper::FileDir; 93 _dexPath.append("/"); 94 _dexPath.append(Dex_RELEASEFLODER); 95 _dexPath.append("/"); 96 _dexPath.append(Dex_NAME); 97 98 if(!_exist) 99 {100 LOGD("needed file is not exist.");101 CPakReader* PakReader = CPakReader::Create(Dex_asstesPath, true);102 TFileBlock fb;103 PakReader->GetBlock(Dex_NAME, fb);104 105 LOGD("destfile: %s", _dexPath.c_str());106 fileutils->writeData2File(_dexPath.c_str(), fb.oData, fb.index.oSize);107 delete PakReader;108 BootFileUtils::destroyInstance();109 }110 else111 LOGD("needed file is exist.");112 113 114 JniBootHelper::loadDexFile(context, _dexPath.c_str(), _cachedirpath.c_str());115 }116 }117 }
java层代码
1 package com.origingame; 2 3 import android.app.Application; 4 import android.content.Context; 5 import android.util.Log; 6 7 public class OriginApplication extends Application { 8 @Override 9 protected void attachBaseContext(Context context){10 super.attachBaseContext(context);11 OriginShell.nativeBoot(context);12 }13 14 @Override 15 public void onCreate() {16 super.onCreate();17 Log.d("OriginGame", "running......");18 OriginShell.nativeLoadClass(getApplicationContext());19 }20 }
OriginShell实现
1 package com.origingame; 2 3 import android.content.Context; 4 5 public class OriginShell { 6 static{ 7 System.loadLibrary("originshell"); 8 } 9 public static native void nativeBoot(Context context);10 public static native void nativeLoadClass(Context context);11 }
由于没怎么注释,所以讲一下基本的原理。
大致原理就是通过重写Application的attachBaseContext方法在c++层new一个PathClassLoader或者DexClassLoader对象,两者的具体区别网上已经有很多说明不在详解,通过new的新对象来加载包含dex的jar文件,最后通过反射机制替换掉app启动时原有的classloader,也就是重新给mClassLoader这个成员变量赋值我们最新的classloader
包含dex的jar文件我这里也有做加密处理,加载之前我是先做解密的,大家也可以自己实现自己的加密方式。
原标题:apk 加密
关键词:加密