Android加壳native实现

春衣少年当酒歌,起舞四顾以笑和。这篇文章主要讲述Android加壳native实现相关的知识,希望能为你提供帮助。
    本例仅在android2.3模拟器跑通过,假设要适配其它机型。请自行研究,这里不过抛砖引玉。

    0x00
    在Android中的Apk的加固(加壳)原理解析和实现,一文中脱壳代码都写在了java层非常easy被识别出来。非常多需求须要把脱壳的程序转移到native层,事实上转移的思路也非常简单,就是在native层通过JNI调用Java层代码。
    执行前,首先把ForceApkObj.apk放在/sdcard/payload_odex/文件夹下。
    代码已上传至github,地址为https://github.com/jltxgcy/AndroidNativeShell。



【Android加壳native实现】    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" ); }



    推荐阅读