編輯:關於android開發
本例僅在Android2.3虛擬機跑通過,如果要適配其他機型,請自行研究,這裡只是拋磚引玉。
0x00
在Android中的Apk的加固(加殼)原理解析和實現,一文中脫殼代碼都寫在了java層很容易被識別出來,很多需求需要把脫殼的程序轉移到native層,其實轉移的思路也很簡單,就是在native層通過JNI調用Java層代碼。
0x01
public class ProxyApplication extends Application { @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); DexLoader.load("com.jltxgcy.dynamicdex"); } @Override public void onCreate() { DexLoader.run(); } }還記得原來這兩個方法有著一大堆代碼,這裡僅僅有一行代碼就搞定。
我們再看來DexLoader類。
public class DexLoader { static { System.loadLibrary("dexloader"); } public static native void load(String path); public static native void run(); }
原來核心脫殼代碼放在了native層。
0x02
JNI的實現如下,大家可以看到本質上就是把java層的代碼通過JNI轉移到native層了。
static void loadApk(JNIEnv * env, jclass clazz, jstring package) { jclass activityThreadClazz; jmethodID currentActivityThreadMethodID; jobject activityThreadObject; const char *packageName; const char *className; const char *methodName; int codeoff; jfieldID mPackagesFieldID; jobject mPackagesJObject; jclass mPackagesClazz; jmethodID getMethodID; jobject weakReferenceJObject; jclass weakReferenceJClazz; jmethodID getweakMethodID; jobject loadedApkJObject; jclass loadedApkJClazz; jfieldID mClassLoaderFieldID; jobject mClassLoaderJObject; jstring dexPath; jstring dexOptPath; jclass dexClassLoaderClazz; jmethodID initDexLoaderMethod; jobject dexClassLoaderJObject; activityThreadClazz = env->FindClass("android/app/ActivityThread"); currentActivityThreadMethodID = env->GetStaticMethodID(activityThreadClazz, "currentActivityThread", "()Landroid/app/ActivityThread;"); activityThreadObject = env->CallStaticObjectMethod(activityThreadClazz, currentActivityThreadMethodID); packageName = env->GetStringUTFChars(package, JNI_FALSE); mPackagesFieldID = env->GetFieldID(activityThreadClazz, "mPackages", "Ljava/util/HashMap;"); mPackagesJObject = env->GetObjectField(activityThreadObject, mPackagesFieldID); mPackagesClazz = env->GetObjectClass(mPackagesJObject); getMethodID = env->GetMethodID(mPackagesClazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); weakReferenceJObject = env->CallObjectMethod(mPackagesJObject, getMethodID, package); weakReferenceJClazz = env->GetObjectClass(weakReferenceJObject); getweakMethodID = env->GetMethodID(weakReferenceJClazz, "get", "()Ljava/lang/Object;"); loadedApkJObject = env->CallObjectMethod(weakReferenceJObject, getweakMethodID); loadedApkJClazz = env->GetObjectClass(loadedApkJObject); mClassLoaderFieldID = env->GetFieldID(loadedApkJClazz, "mClassLoader", "Ljava/lang/ClassLoader;"); mClassLoaderJObject = env->GetObjectField(loadedApkJObject, mClassLoaderFieldID); dexPath = env->NewStringUTF("/sdcard/payload_odex/ForceApkObj.apk"); dexOptPath = env->NewStringUTF("/sdcard/payload_odex/"); dexClassLoaderClazz = env->FindClass("dalvik/system/DexClassLoader"); initDexLoaderMethod = env->GetMethodID(dexClassLoaderClazz, "","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V"); dexClassLoaderJObject = env->NewObject(dexClassLoaderClazz,initDexLoaderMethod, dexPath, dexOptPath, NULL, mClassLoaderJObject); env->SetObjectField(loadedApkJObject, mClassLoaderFieldID, dexClassLoaderJObject); ALOGD("packageName:%s", packageName); } static void run(JNIEnv * env, jclass clazz) { jclass activityThreadClazz; jmethodID currentActivityThreadMethodID; jobject activityThreadObject; jfieldID mBoundApplicationFieldID; jobject mBoundApplicationJObject; jclass mBoundApplicationClazz; jfieldID mInfoFieldID; jobject mInfoJObject; jclass mInfoClazz; jfieldID mApplicationFieldID; jobject mApplicationJObject; jfieldID mInitialApplicationFieldID; jobject mInitialApplicationJObject; jfieldID mAllApplicationsFieldID; jobject mAllApplicationsJObject; jclass mAllApplicationsClazz; jmethodID removeMethodID; jfieldID mApplicationInfoFieldID; jobject mApplicationInfoJObject; jclass mApplicationInfoClazz; jfieldID mBindApplicationInfoFieldID; jobject mBindApplicationInfoJObject; jclass mBindApplicationInfoClazz; jfieldID classNameFieldID; jfieldID mBindClassNameFieldID; jstring applicationName; jmethodID makeApplicationMethodID; jobject ApplicationJObject; jclass ApplicationClazz; jmethodID onCreateMethodID; activityThreadClazz = env->FindClass("android/app/ActivityThread"); currentActivityThreadMethodID = env->GetStaticMethodID(activityThreadClazz, "currentActivityThread", "()Landroid/app/ActivityThread;"); activityThreadObject = env->CallStaticObjectMethod(activityThreadClazz, currentActivityThreadMethodID); mBoundApplicationFieldID = env->GetFieldID(activityThreadClazz, "mBoundApplication", "Landroid/app/ActivityThread$AppBindData;"); mBoundApplicationJObject = env->GetObjectField(activityThreadObject, mBoundApplicationFieldID); mBoundApplicationClazz = env->GetObjectClass(mBoundApplicationJObject); mInfoFieldID = env->GetFieldID(mBoundApplicationClazz, "info", "Landroid/app/LoadedApk;"); mInfoJObject = env->GetObjectField(mBoundApplicationJObject, mInfoFieldID); mInfoClazz = env->GetObjectClass(mInfoJObject); mApplicationFieldID = env->GetFieldID(mInfoClazz, "mApplication", "Landroid/app/Application;"); mApplicationJObject = env->GetObjectField(mInfoJObject, mApplicationFieldID); env->SetObjectField(mInfoJObject, mApplicationFieldID, NULL); mInitialApplicationFieldID = env->GetFieldID(activityThreadClazz, "mInitialApplication", "Landroid/app/Application;"); mInitialApplicationJObject = env->GetObjectField(activityThreadObject, mInitialApplicationFieldID); mAllApplicationsFieldID = env->GetFieldID(activityThreadClazz, "mAllApplications", "Ljava/util/ArrayList;"); mAllApplicationsJObject = env->GetObjectField(activityThreadObject, mAllApplicationsFieldID); mAllApplicationsClazz = env->GetObjectClass(mAllApplicationsJObject); removeMethodID = env->GetMethodID(mAllApplicationsClazz, "remove", "(Ljava/lang/Object;)Z"); jboolean isTrue = env->CallBooleanMethod(mAllApplicationsJObject, removeMethodID, mInitialApplicationJObject); mApplicationInfoFieldID = env->GetFieldID(mInfoClazz, "mApplicationInfo", "Landroid/content/pm/ApplicationInfo;"); mApplicationInfoJObject = env->GetObjectField(mInfoJObject, mApplicationInfoFieldID); mApplicationInfoClazz = env->GetObjectClass(mApplicationInfoJObject); mBindApplicationInfoFieldID = env->GetFieldID(mBoundApplicationClazz, "appInfo", "Landroid/content/pm/ApplicationInfo;"); mBindApplicationInfoJObject = env->GetObjectField(mBoundApplicationJObject, mBindApplicationInfoFieldID); mBindApplicationInfoClazz = env->GetObjectClass(mBindApplicationInfoJObject); classNameFieldID = env->GetFieldID(mApplicationInfoClazz, "className", "Ljava/lang/String;"); mBindClassNameFieldID = env->GetFieldID(mBindApplicationInfoClazz, "className", "Ljava/lang/String;"); applicationName = env->NewStringUTF("com.example.forceapkobj.MyApplication"); env->SetObjectField(mApplicationInfoJObject, classNameFieldID, applicationName); env->SetObjectField(mBindApplicationInfoJObject, mBindClassNameFieldID, applicationName); makeApplicationMethodID = env->GetMethodID(mInfoClazz, "makeApplication","(ZLandroid/app/Instrumentation;)Landroid/app/Application;"); ApplicationJObject = env->CallObjectMethod(mInfoJObject, makeApplicationMethodID, JNI_FALSE, NULL); env->SetObjectField(activityThreadObject, mInitialApplicationFieldID, ApplicationJObject); ApplicationClazz = env->GetObjectClass(ApplicationJObject); onCreateMethodID = env->GetMethodID(ApplicationClazz, "onCreate","()V"); env->CallVoidMethod(ApplicationJObject, onCreateMethodID); } JNIEXPORT void JNICALL Java_com_jltxgcy_dynamicdex_DexLoader_load (JNIEnv * env, jclass clazz, jstring packageName) { loadApk(env, clazz, packageName); ALOGD("Java_com_jltxgcy_dynamicdex_DexLoader_load"); } JNIEXPORT void JNICALL Java_com_jltxgcy_dynamicdex_DexLoader_run (JNIEnv * env, jclass clazz) { run(env, clazz); ALOGD("Java_com_jltxgcy_dynamicdex_DexLoader_run"); }
安卓虛擬機adb shell sqlite3數據庫,安卓sqlite3 adb shell 連接: //http://www.c
Xamarin Android 應用程序內圖標上數字提示,xamarinandroid最近在用 Xamarin 做一個 Android 應用,打開應用時,如果有新消息,需
Android Hack1 使用weight屬性實現視圖的居中顯示,androidhack1本文地址:http://www.cnblogs.com/wuyudong/p/
Android導入外部數據庫 當我們軟件中要使用大量數據,我們會選擇將這些數據存儲到一個數據庫中,然後通過數據庫的查詢修改操作來管理這些數據。大多數情況下我們都只在程序中