apk 加密
为了防止apk被轻易破解,想办法对java层的代码进行加密,防止反编译,代码混淆基本没什么效果,一般情况下我会对dex进行加密,通过动态加载的方法实现java层的代码尽量被隐藏,而动态加载的实现通过jni来完成,最大化的保护代码安全,其实java层这个时候只剩下继承于Application的启动类。
.h文件
#ifndef __ANDROID_JNI_BOOT_HELPER_H__
#define __ANDROID_JNI_BOOT_HELPER_H__ #include <jni.h>
#include <string>
#include "android/asset_manager.h"
#include "android/asset_manager_jni.h" typedef struct JniMethodInfo_
{
JNIEnv * env;
jclass classID;
jmethodID methodID;
} JniMethodInfo; class JniBootHelper
{
public:
static void setJavaVM(JavaVM *javaVM);
static JavaVM* getJavaVM();
static JNIEnv* getEnv(); static bool setassetmanager(jobject activityinstance);
static AAssetManager* getAssetManager() { return _assetmanager; } static bool setFileDir(jobject activityinstance);
static bool setCacheDir(jobject activityinstance); static bool loadDexFile(jobject context,
const char* dexPath,
const char* dexOptDir); static bool loadClass(jobject context); static jobject invokeStaticMethod(JNIEnv *env,
const char* className,
const char* methodName,
jobjectArray pareTyple,
jobjectArray pareVaules); static jobject getFieldOjbect(JNIEnv *env,
const char* className,
const char* fieldName,
jobject obj);
static void setFieldOjbect(JNIEnv *env,
const char* className,
const char* fieldName,
jobject obj,
jobject filedVaule); static std::string jstring2string(jstring str); static std::string FileDir;
static std::string CacheDir; private:
static JNIEnv* cacheEnv(JavaVM* jvm); static bool getMethodInfo(JniMethodInfo &methodinfo,
const char *className,
const char *methodName,
const char *paramCode); static JavaVM* _psJavaVM;
static AAssetManager* _assetmanager;
static jmethodID _loadclassMethod_methodID;
static jobject _classloader;
}; #endif // __ANDROID_JNI_BOOT_HELPER_H__
.cpp文件
#include "JniBootHelper.h"
#include <android/log.h>
#include <string.h>
#include <pthread.h> #include "DexMarcoDef.h" static pthread_key_t g_key; void _detachCurrentThread(void* a) {
LOGD("DetachCurrentThread");
JniBootHelper::getJavaVM()->DetachCurrentThread();
} JavaVM* JniBootHelper::_psJavaVM = nullptr;
std::string JniBootHelper::FileDir = "";
std::string JniBootHelper::CacheDir = "";
AAssetManager* JniBootHelper::_assetmanager = nullptr;
jmethodID JniBootHelper::_loadclassMethod_methodID = nullptr;
jobject JniBootHelper::_classloader = nullptr; bool JniBootHelper::setassetmanager(jobject activityinstance) {
JniMethodInfo _getassetsMethod;
if (!JniBootHelper::getMethodInfo(_getassetsMethod,
"android/content/Context",
"getAssets",
"()Landroid/content/res/AssetManager;")) {
LOGE("getmethod getAssets() failed.");
return false;
} jobject _am = JniBootHelper::getEnv()->CallObjectMethod(activityinstance,
_getassetsMethod.methodID); if (nullptr == _am) {
LOGE("CallObjectMethod getAssets() failed.");
return false;
} JniBootHelper::_assetmanager = AAssetManager_fromJava(JniBootHelper::getEnv(), _am);
return true;
} bool JniBootHelper::setFileDir(jobject activityinstance)
{
JniMethodInfo _getFileDirMethod;
if (!JniBootHelper::getMethodInfo(_getFileDirMethod,
"android/content/Context",
"getFilesDir",
"()Ljava/io/File;")) {
LOGE("getmethod getFilesDir() failed.");
return false;
}
jobject _f = JniBootHelper::getEnv()->CallObjectMethod(activityinstance,
_getFileDirMethod.methodID);
if (nullptr == _f) {
LOGE("CallObjectMethod getFilesDir() failed.");
return false;
}
JniMethodInfo _getFilePathMethod;
if (!JniBootHelper::getMethodInfo(_getFilePathMethod,
"java/io/File",
"getAbsolutePath",
"()Ljava/lang/String;")) {
LOGE("getmethod getAbsolutePath() failed.");
return false;
}
jstring _p = (jstring)JniBootHelper::getEnv()->CallObjectMethod(_f,
_getFilePathMethod.methodID);
if (nullptr == _p) {
LOGE("CallObjectMethod getAbsolutePath() failed.");
return false;
} JniBootHelper::FileDir.assign(JniBootHelper::jstring2string(_p));
LOGD("apk FileDir : %s", JniBootHelper::FileDir.c_str());
JniBootHelper::getEnv()->DeleteLocalRef(_p);
return true;
} bool JniBootHelper::setCacheDir(jobject activityinstance)
{
JniMethodInfo _getFileDirMethod;
if (!JniBootHelper::getMethodInfo(_getFileDirMethod,
"android/content/Context",
"getCacheDir",
"()Ljava/io/File;")) {
LOGE("getmethod getCacheDir() failed.");
return false;
}
jobject _f = JniBootHelper::getEnv()->CallObjectMethod(activityinstance,
_getFileDirMethod.methodID);
if (nullptr == _f) {
LOGE("CallObjectMethod getCacheDir() failed.");
return false;
}
JniMethodInfo _getFilePathMethod;
if (!JniBootHelper::getMethodInfo(_getFilePathMethod,
"java/io/File",
"getAbsolutePath",
"()Ljava/lang/String;")) {
LOGE("getmethod getAbsolutePath() failed.");
return false;
}
jstring _p = (jstring)JniBootHelper::getEnv()->CallObjectMethod(_f,
_getFilePathMethod.methodID);
if (nullptr == _p) {
LOGE("CallObjectMethod getAbsolutePath() failed.");
return false;
} JniBootHelper::CacheDir.assign(JniBootHelper::jstring2string(_p));
LOGD("apk CacheDir : %s", JniBootHelper::CacheDir.c_str());
JniBootHelper::getEnv()->DeleteLocalRef(_p);
return true;
} bool JniBootHelper::loadClass(jobject context)
{
JNIEnv *env = JniBootHelper::getEnv();
if (!env) {
return false;
} jstring _jstrClassName = env->NewStringUTF("com/origingame/InApplicationMethod");
jclass _classid = (jclass) env->CallObjectMethod(JniBootHelper::_classloader,
JniBootHelper::_loadclassMethod_methodID,
_jstrClassName);
if(!_classid)
{
LOGE("can not find class com/origingame/InApplicationMethod");
}
jmethodID _mid = env->GetStaticMethodID(_classid, "onCreate", "(Landroid/content/Context;)V");
if(!_mid)
{
LOGE("failed to find methodID onCreate");
}
env->CallStaticVoidMethod(_classid, _mid, context);
env->DeleteLocalRef(_jstrClassName);
env->DeleteGlobalRef(JniBootHelper::_classloader);
} bool JniBootHelper::loadDexFile(jobject context,
const char* dexPath,
const char* dexOptDir)
{
JNIEnv *env = JniBootHelper::getEnv();
if (!env) {
return false;
} jstring dexPathString, dexOptDirString;
dexPathString = env->NewStringUTF(dexPath);
dexOptDirString = env->NewStringUTF(dexOptDir); jclass native_clazz = env->GetObjectClass(context);
jmethodID methodID_func = env->GetMethodID(native_clazz,
"getPackageName",
"()Ljava/lang/String;");
jstring packagename = (jstring) (env->CallObjectMethod(context, methodID_func));
std::string _packagename = JniBootHelper::jstring2string(packagename);
LOGD("packagename: %s",_packagename.c_str());
char libsDir[];
sprintf(libsDir, "/data/data/%s/lib", _packagename.c_str());
jstring jlibsDir = env->NewStringUTF(libsDir); jclass jActivityThread = env->FindClass("android/app/ActivityThread");
if(!jActivityThread)
{
LOGE("can not find class android/app/ActivityThread");
}
jmethodID jcATmid = env->GetStaticMethodID(jActivityThread, "currentActivityThread", "()Landroid/app/ActivityThread;");
jobject currentActivityThread = env->CallStaticObjectMethod(jActivityThread, jcATmid); jclass class_hashmap = env->FindClass("java/util/Map"); jobject obj_hashmap = JniBootHelper::getFieldOjbect(env,
"android.app.ActivityThread",
"mPackages",
currentActivityThread);
/*
jmethodID map_size = env->GetMethodID(class_hashmap,
"size",
"()I");
jint size = (jint)env->CallObjectMethod(obj_hashmap,
map_size
);
LOGD("map size : %d", (int)size);
*/
if(!obj_hashmap)
{
LOGE("obj_hashmap is null");
} jclass class_WeakReference = env->FindClass("java/lang/ref/WeakReference");
if (!class_WeakReference)
{
LOGE("class_WeakReference Not Found ");
} jmethodID WeakReference_get_method = env->GetMethodID(class_WeakReference,
"get",
"()Ljava/lang/Object;");
if (!WeakReference_get_method)
{
LOGE("WeakReference_get_method Not Found ");
} jmethodID get_func = env->GetMethodID(class_hashmap,
"get",
"(Ljava/lang/Object;)Ljava/lang/Object;");
if (!get_func) {
LOGE("method get Not Found ");
} jobject get_obj = env->CallObjectMethod(obj_hashmap,
get_func,
packagename);
if (!get_obj) {
LOGE("get_obj Not Found ");
} jobject get_get_obj = env->CallObjectMethod(get_obj,
WeakReference_get_method);
if (!get_get_obj) {
LOGE("get_get_obj Not Found ");
} /*
jclass class_DexClassloader = env->FindClass("dalvik/system/DexClassLoader");
if (!class_DexClassloader) {
LOGE("class_DexClassloader Not Found ");
} jmethodID DexClassloader_construct_method = env->GetMethodID(class_DexClassloader,
"<init>",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V");
if (!DexClassloader_construct_method) {
LOGE("DexClassloader_construct_method Not Found ");
} jobject obj_DexClassloader = env->NewObject(class_DexClassloader,
DexClassloader_construct_method,
dexPathString,
dexOptDirString,
jlibsDir,
JniBootHelper::getFieldOjbect(env, "android.app.LoadedApk", "mClassLoader", get_get_obj));
if (!obj_DexClassloader) {
LOGE("obj_DexClassloader Not Found ");
}
*/
jclass class_DexClassloader = env->FindClass("dalvik/system/PathClassLoader");
if (!class_DexClassloader) {
LOGE("class_DexClassloader Not Found ");
} jmethodID DexClassloader_construct_method = env->GetMethodID(class_DexClassloader,
"<init>",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V");
if (!DexClassloader_construct_method) {
LOGE("DexClassloader_construct_method Not Found ");
} jobject obj_DexClassloader = env->NewObject(class_DexClassloader,
DexClassloader_construct_method,
dexPathString,
jlibsDir,
JniBootHelper::getFieldOjbect(env, "android.app.LoadedApk", "mClassLoader", get_get_obj));
if (!obj_DexClassloader) {
LOGE("obj_DexClassloader Not Found ");
} JniBootHelper::_classloader = env->NewGlobalRef(obj_DexClassloader);
JniBootHelper::_loadclassMethod_methodID = env->GetMethodID(class_DexClassloader,
"loadClass",
"(Ljava/lang/String;)Ljava/lang/Class;"); JniBootHelper::setFieldOjbect(env, "android.app.LoadedApk", "mClassLoader", get_get_obj, obj_DexClassloader);
env->DeleteLocalRef(dexPathString);
env->DeleteLocalRef(dexOptDirString);
env->DeleteLocalRef(jlibsDir);
LOGD("finish.");
return true;
} JavaVM* JniBootHelper::getJavaVM() {
pthread_t thisthread = pthread_self();
LOGD("JniBootHelper::getJavaVM(), pthread_self() = %ld", thisthread);
return _psJavaVM;
} void JniBootHelper::setJavaVM(JavaVM *javaVM) {
pthread_t thisthread = pthread_self();
LOGD("JniBootHelper::setJavaVM(%p), pthread_self() = %ld", javaVM, thisthread);
_psJavaVM = javaVM; pthread_key_create(&g_key, _detachCurrentThread);
} JNIEnv* JniBootHelper::cacheEnv(JavaVM* jvm) {
JNIEnv* _env = nullptr;
// get jni environment
jint ret = jvm->GetEnv((void**)&_env, JNI_VERSION_1_4); switch (ret) {
case JNI_OK :
// Success!
pthread_setspecific(g_key, _env);
return _env; case JNI_EDETACHED :
// Thread not attached
if (jvm->AttachCurrentThread(&_env, nullptr) < )
{
LOGE("Failed to get the environment using AttachCurrentThread()"); return nullptr;
} else {
// Success : Attached and obtained JNIEnv!
pthread_setspecific(g_key, _env);
return _env;
} case JNI_EVERSION :
// Cannot recover from this error
LOGE("JNI interface version 1.4 not supported");
default :
LOGE("Failed to get the environment using GetEnv()");
return nullptr;
}
} JNIEnv* JniBootHelper::getEnv() {
JNIEnv *_env = (JNIEnv *)pthread_getspecific(g_key);
if (_env == nullptr)
_env = JniBootHelper::cacheEnv(_psJavaVM);
return _env;
} bool JniBootHelper::getMethodInfo(JniMethodInfo &methodinfo,
const char *className,
const char *methodName,
const char *paramCode)
{
if ((nullptr == className) ||
(nullptr == methodName) ||
(nullptr == paramCode)) {
return false;
} JNIEnv *env = JniBootHelper::getEnv();
if (!env) {
return false;
} jclass classID = env->FindClass(className);
if (! classID) {
LOGE("Failed to find class %s", className);
env->ExceptionClear();
return false;
} jmethodID methodID = env->GetMethodID(classID, methodName, paramCode);
if (! methodID) {
LOGE("Failed to find method id of %s", methodName);
env->ExceptionClear();
return false;
} methodinfo.classID = classID;
methodinfo.env = env;
methodinfo.methodID = methodID; return true;
} std::string JniBootHelper::jstring2string(jstring jstr) {
if (jstr == nullptr) {
return "";
} JNIEnv *env = JniBootHelper::getEnv();
if (!env) {
return nullptr;
} const char* chars = env->GetStringUTFChars(jstr, nullptr);
std::string ret(chars);
env->ReleaseStringUTFChars(jstr, chars); return ret;
} jobject JniBootHelper::invokeStaticMethod(JNIEnv *env,
const char* className,
const char* methodName,
jobjectArray pareTyple,
jobjectArray pareVaules)
{
jstring jclassName, jmethodName;
jclassName = env->NewStringUTF(className);
jmethodName = env->NewStringUTF(methodName); jclass _class = env->FindClass("java/lang/Class");
if(!_class)
{
LOGE("invokeStaticMethod: Failed to find class java/lang/Class");
env->ExceptionClear();
return nullptr;
} jmethodID forname_func = env->GetStaticMethodID(_class,
"forName",
"(Ljava/lang/String;)Ljava/lang/Class;");
if(!forname_func)
{
LOGE("invokeStaticMethod: Failed to find method forName");
env->ExceptionClear();
return nullptr;
} jobject class_obj = env->CallStaticObjectMethod(_class,
forname_func,
jclassName); jclass class_java = env->GetObjectClass(class_obj); jmethodID getmethod_func = env->GetMethodID(class_java,
"getMethod",
"(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");
if(!getmethod_func)
{
LOGE("invokeStaticMethod: Failed to find method getMethod");
env->ExceptionClear();
return nullptr;
} jobject method_obj = env->CallObjectMethod(class_obj,
getmethod_func,
jmethodName,
pareTyple);
if(!method_obj)
{
LOGE("invokeStaticMethod: Failed to CallObjectMethod.%s, %s",className, methodName);
env->ExceptionClear();
return nullptr;
} jclass class_method_obj = env->GetObjectClass(method_obj); jmethodID invoke_func = env->GetMethodID(class_method_obj,
"invoke",
"(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"); if(!invoke_func)
{
LOGE("invokeStaticMethod: Failed to find method invoke");
env->ExceptionClear();
return nullptr;
} jobject invoke_obj = env->CallObjectMethod(method_obj,
invoke_func,
NULL,
pareVaules); env->DeleteLocalRef(jclassName);
env->DeleteLocalRef(jmethodName);
env->DeleteLocalRef(class_java);
env->DeleteLocalRef(method_obj);
LOGD("invokeStaticMethod finish.");
return invoke_obj;
} jobject JniBootHelper::getFieldOjbect(JNIEnv *env,
const char* className,
const char* fieldName,
jobject obj)
{
jstring jclassName, jfieldName;
jclassName = env->NewStringUTF(className);
jfieldName = env->NewStringUTF(fieldName); jclass _class = env->FindClass("java/lang/Class");
jmethodID forname_func = env->GetStaticMethodID(_class,
"forName",
"(Ljava/lang/String;)Ljava/lang/Class;");
if(!forname_func)
{
LOGE("getFieldOjbect: Failed to find method forName");
env->ExceptionClear();
return nullptr;
}
jobject class_obj = env->CallStaticObjectMethod(_class,
forname_func,
jclassName);
jclass class_java = env->GetObjectClass(class_obj); jmethodID getfield_func = env->GetMethodID(class_java,
"getDeclaredField",
"(Ljava/lang/String;)Ljava/lang/reflect/Field;");
if(!getfield_func)
{
LOGE("getFieldOjbect: Failed to find method getDeclaredField");
env->ExceptionClear();
return nullptr;
}
jobject method_obj = env->CallObjectMethod(class_obj,
getfield_func,
jfieldName);
jclass class_method_obj = env->GetObjectClass(method_obj); jmethodID setaccess_func = env->GetMethodID(class_method_obj,
"setAccessible",
"(Z)V");
if(!setaccess_func)
{
LOGE("getFieldOjbect: Failed to find method setAccessible");
env->ExceptionClear();
return nullptr;
}
env->CallVoidMethod(method_obj,
setaccess_func,
true); jmethodID get_func = env->GetMethodID(class_method_obj,
"get",
"(Ljava/lang/Object;)Ljava/lang/Object;");
if(!get_func)
{
LOGE("getFieldOjbect: Failed to find method get");
env->ExceptionClear();
return nullptr;
}
jobject get_obj = env->CallObjectMethod(method_obj,
get_func,
obj); env->DeleteLocalRef(class_java);
env->DeleteLocalRef(method_obj);
env->DeleteLocalRef(jclassName);
env->DeleteLocalRef(jfieldName);
return get_obj;
} void JniBootHelper::setFieldOjbect(JNIEnv *env,
const char* className,
const char* fieldName,
jobject obj,
jobject filedVaule)
{
jstring jclassName, jfieldName;
jclassName = env->NewStringUTF(className);
jfieldName = env->NewStringUTF(fieldName); jclass _class = env->FindClass("java/lang/Class");
if(!_class)
{
LOGE("setFieldOjbect: Failed to find java/lang/Class");
env->ExceptionClear();
return;
}
jmethodID forName_func = env->GetStaticMethodID(_class,
"forName",
"(Ljava/lang/String;)Ljava/lang/Class;");
if(!forName_func)
{
LOGE("setFieldOjbect: Failed to find method forname");
env->ExceptionClear();
return;
}
jobject class_obj = env->CallStaticObjectMethod(_class,
forName_func,
jclassName);
jclass class_java = env->GetObjectClass(class_obj); jmethodID getField_func = env->GetMethodID(class_java,
"getDeclaredField",
"(Ljava/lang/String;)Ljava/lang/reflect/Field;");
if(!getField_func)
{
LOGE("setFieldOjbect: Failed to find method getDeclaredField");
env->ExceptionClear();
return;
}
jobject method_obj = env->CallObjectMethod(class_obj,
getField_func,
jfieldName);
jclass class_method_obj = env->GetObjectClass(method_obj); jmethodID setaccess_func = env->GetMethodID(class_method_obj,
"setAccessible",
"(Z)V");
if(!setaccess_func)
{
LOGE("setFieldOjbect: Failed to find method setAccessible");
env->ExceptionClear();
return;
}
env->CallVoidMethod(method_obj, setaccess_func, true); jmethodID set_func = env->GetMethodID(class_method_obj,
"set",
"(Ljava/lang/Object;Ljava/lang/Object;)V");
if(!set_func)
{
LOGE("setFieldOjbect: Failed to find method set");
env->ExceptionClear();
return;
}
env->CallVoidMethod(method_obj,
set_func,
obj,
filedVaule); env->DeleteLocalRef(class_java);
env->DeleteLocalRef(method_obj);
env->DeleteLocalRef(jclassName);
env->DeleteLocalRef(jfieldName);
}
主入口
#include "JniBootHelper.h"
#include "BootFileUtils.h"
#include "CPakReader.h" #include <android/log.h>
#include <jni.h> #include "DexMarcoDef.h" #define Dex_asstesPath "assets/OriginAPP.jar"
#define Dex_NAME "OriginClasses.jar"
#define Dex_RELEASEFLODER "OriginBoot"
#define Dex_CACHEFLODER "OriginBootCache" extern "C"
{
JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
LOGD("JNI_OnLoad has been called.");
JniBootHelper::setJavaVM(vm); return JNI_VERSION_1_4;
} JNIEXPORT void JNI_OnUnLoad(JavaVM *vm, void *reserved)
{
LOGD("JNI_OnUnLoad has been called.");
} JNIEXPORT void Java_com_origingame_OriginShell_nativeLoadClass(JNIEnv* env, jobject thiz, jobject context)
{
JniBootHelper::loadClass(context);
} JNIEXPORT void Java_com_origingame_OriginShell_nativeBoot(JNIEnv* env, jobject thiz, jobject context)
{
bool _initsuccess = true; if(!JniBootHelper::setassetmanager(context)){
LOGE("setassetmanager failed!");
_initsuccess = false;
} if(!JniBootHelper::setFileDir(context)){
LOGE("setFileDir failed!");
_initsuccess = false;
} if(!JniBootHelper::setCacheDir(context)){
LOGE("setCacheDir failed!");
_initsuccess = false;
} if(_initsuccess)
{
LOGD("init success.");
bool _dirExist = false;
bool _exist = false;
BootFileUtils* fileutils = BootFileUtils::getInstance();
std::string _path = JniBootHelper::FileDir;
_path.append("/");
_path.append(Dex_RELEASEFLODER);
LOGD("check dir: %s", _path.c_str());
if(fileutils->isDirectoryExistInternal(_path))
{
_dirExist = true;
std::string _file = JniBootHelper::FileDir;
_file.append("/");
_file.append(Dex_RELEASEFLODER);
_file.append("/");
_file.append(Dex_NAME);
if(fileutils->isFileExistInternal(_file))
_exist = true;
} std::string _cachedirpath = JniBootHelper::FileDir;
_cachedirpath.append("/");
_cachedirpath.append(Dex_CACHEFLODER); if(!_dirExist)
{
LOGD("create dir.");
std::string _filedirpath = JniBootHelper::FileDir;
_filedirpath.append("/");
_filedirpath.append(Dex_RELEASEFLODER);
fileutils->createDirectory(_filedirpath); fileutils->createDirectory(_cachedirpath);
} std::string _dexPath = JniBootHelper::FileDir;
_dexPath.append("/");
_dexPath.append(Dex_RELEASEFLODER);
_dexPath.append("/");
_dexPath.append(Dex_NAME); if(!_exist)
{
LOGD("needed file is not exist.");
CPakReader* PakReader = CPakReader::Create(Dex_asstesPath, true);
TFileBlock fb;
PakReader->GetBlock(Dex_NAME, fb); LOGD("destfile: %s", _dexPath.c_str());
fileutils->writeData2File(_dexPath.c_str(), fb.oData, fb.index.oSize);
delete PakReader;
BootFileUtils::destroyInstance();
}
else
LOGD("needed file is exist."); JniBootHelper::loadDexFile(context, _dexPath.c_str(), _cachedirpath.c_str());
}
}
}
java层代码
package com.origingame; import android.app.Application;
import android.content.Context;
import android.util.Log; public class OriginApplication extends Application {
@Override
protected void attachBaseContext(Context context){
super.attachBaseContext(context);
OriginShell.nativeBoot(context);
} @Override
public void onCreate() {
super.onCreate();
Log.d("OriginGame", "running......");
OriginShell.nativeLoadClass(getApplicationContext());
}
}
OriginShell实现
package com.origingame; import android.content.Context; public class OriginShell {
static{
System.loadLibrary("originshell");
}
public static native void nativeBoot(Context context);
public static native void nativeLoadClass(Context context);
}
由于没怎么注释,所以讲一下基本的原理。
大致原理就是通过重写Application的attachBaseContext方法在c++层new一个PathClassLoader或者DexClassLoader对象,两者的具体区别网上已经有很多说明不在详解,通过new的新对象来加载包含dex的jar文件,最后通过反射机制替换掉app启动时原有的classloader,也就是重新给mClassLoader这个成员变量赋值我们最新的classloader
包含dex的jar文件我这里也有做加密处理,加载之前我是先做解密的,大家也可以自己实现自己的加密方式。
apk 加密的更多相关文章
- App山寨疯狂 爱加密Apk加密平台防破解
App山寨疯狂 爱加密Apk加密平台防破解,Android系统由于其开源性,眼下已占领全球智能机近80%的市场,远超微软的WP系统和苹果的IOS系统.然而也正是由于开源性,Android盗版App在国 ...
- 需要MARK一下,奇怪的ANDROID SDK自带的APK加密功能的问题
花了两天时间,各种调试APP,发现问题不在于代码. 在于用了SDK里的加密,导致运行其中一个多线程中的ACTIVITY, 就会黑屏,返回按钮也没用. 发现这个问题的思路是因为,我发现连手机直接调试,一 ...
- Android动态方式破解apk终极篇(加固apk破解方式)
一.前言 今天总算迎来了破解系列的最后一篇文章了,之前的两篇文章分别为: 第一篇:如何使用Eclipse动态调试smali源码 第二篇:如何使用IDA动态调试SO文件 现在要说的就是最后一篇了,如何应 ...
- android黑科技系列——静态分析技术来破解Apk
一.前言 从这篇文章开始我们开始我们的破解之路,之前的几篇文章中我们是如何讲解怎么加固我们的Apk,防止被别人破解,那么现在我们要开始破解我们的Apk,针对于之前的加密方式采用相对应的破解技术,And ...
- Android apk签名方法介绍
还望支持个人博客站:http://www.enjoytoday.cn 参考博客:http://www.enjoytoday.cn/posts/203 为什么要签名 在介绍签名方法之前,首先我们来了解下 ...
- Android逆向之旅---静态分析技术来破解Apk
一.前言 从这篇文章开始我们开始我们的破解之路,之前的几篇文章中我们是如何讲解怎么加固我们的Apk,防止被别人破解,那么现在我们要开始破解我们的Apk,针对于之前的加密方式采用相对应的破解技术,And ...
- 高效IO之Dex加密(三)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 apk加固原理之dex加密 原理其实不复杂,加固其实就是加密dex文件,防止de ...
- c 开源代码
阅读优秀代码是提高开发人员修为的一种捷径……1. WebbenchWebbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在 ...
- Android混淆那些事儿
博客: 安卓之家 微博: 追风917 CSDN: 蒋朋的家 简书: 追风917 博客园:追风917 # Android混淆 Android混淆是Android开发者经常使用的一种用于代码防止被反编译的 ...
随机推荐
- atexit注册的函数是在main函数之后执行?
跟atexit函数相识已久,man手册里对atexit的解释是这么一段: The atexit() function registers the given function to be called ...
- C#局域网桌面共享软件制作(二)
链接C#局域网桌面共享软件制作(一) 如果你运行这个软件查看流量监控就会发现1~2M/s左右的上传下载,并且有时会报错“参数无效”,如果你将屏幕截图保存到本地的话每张图片大概4M(bmp).120KB ...
- Check Box Select/Deselect All on Grid
The below function is to be used on a grid with multiple check boxes. Place the code behind a FieldC ...
- winform之回车执行某个按钮 以及Esc执行某个按钮
在winform中,我们在登陆的时候,需要点击回车键,就执行登陆,点击Esc键就执行取消,那么最方便的方法就是利用AcceptButton和CancelButton这两个属性(它属于窗体属性). 如图 ...
- excel上传和下载
需要注意的地方: 1.js构造表单并提交 2.js中文传参encodeURI(encodeURI("中文")),action接收并转换value = URLDecoder.deco ...
- 【积硅计划】html标签
一.基础 在html中,标签通常是由开始标签和结束标签组成,开始标签用<标签名>,结束标签用</标签名> 元素是指包括开始标签和结束标签在内的整体,内容是指出 ...
- SQL Server 基础:Cast和Convert的区别
CAST 和 CONVERT 都可以将某种数据类型的表达式显式转换为另一种数据类型. 语法: CAST ( expression AS data_type ) CONVERT (data_type[( ...
- C#读取和写入配置文件
使用.Net2.0中的ConfigurationManager可以方便的实现对配置app.config的读取和写入. ConfigurationManager默认没有自动载入项目,使用前必须手动添加, ...
- Python自然语言工具包(NLTK)入门
在本期文章中,小生向您介绍了自然语言工具包(Natural Language Toolkit),它是一个将学术语言技术应用于文本数据集的 Python 库.称为“文本处理”的程序设计是其基本功能:更深 ...
- 实战Django:官方实例Part3
前面两个部分我们介绍了投票应用的框架和后台管理部分.接下来舍得要介绍这个应用面向用户的界面. 这里我们要引入一个新的概念,"视图".在Django中,视图是一根连接模型和模板的纽带 ...