本例仅在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, "<init>","(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");
-
}