JNI 反射

#include <jni.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <android/log.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <elf.h>
#include <sys/mman.h>
#include <assert.h>


/***************************************************************************************
*
* 宏定义
*
****************************************************************************************/
//输出调试信息到logcat
#define   DEBUG
#define   LOG_TAG    "LOG_ANDROID_SHELL"
#define   LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define   LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

//求一维数组元素个数
# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))

//Application类,壳入口
#define JNIREG_CLASS "com/lzy/androidshell/MainApplication"


/***************************************************************************************
*
* 范例代码
*
****************************************************************************************/
//解密dex
JNIEXPORT
void
JNICALL
sub_1111(JNIEnv* env, jobject thiz, jobject context)
{
    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));
    const char *str = env->GetStringUTFChars(packagename, 0);
    char destination[128];
    const char *blank = "/data/data/", *c = "/.cache/";
    strcpy(destination, blank);
    strcat(destination, str);
    strcat(destination, c);
    LOGI("stringcccccccccccccccc %s", destination);

    env->ReleaseStringUTFChars(packagename, str);
    jint a = mkdir(destination, 777);

    LOGI("Created a file in android! %d", a);
    const char *pre = "chmod 755 ";
    char cmd[128];
    strcpy(cmd, pre);
    strcat(cmd, destination);
    LOGI("cmd %s", cmd);
    jstring jcmd = CharTojstring(env, cmd);

    //exec
    jclass Runtime = env->FindClass("java/lang/Runtime");
    jmethodID Runtime_func = env->GetStaticMethodID(Runtime, "getRuntime",
            "()Ljava/lang/Runtime;");
    jobject class_obj = env->CallStaticObjectMethod(Runtime, Runtime_func);
    jclass class_java = env->GetObjectClass(class_obj);

    jmethodID exec_func = env->GetMethodID(class_java, "exec",
            "(Ljava/lang/String;)Ljava/lang/Process;");
    jobject method_obj = env->CallObjectMethod(class_obj, exec_func, jcmd);
    jclass class_method_obj = env->GetObjectClass(method_obj);

    jmethodID waitfor_func = env->GetMethodID(class_method_obj, "waitFor",
            "()I");
    jint result = env->CallIntMethod(method_obj, waitfor_func);

    LOGI("CallIntMethod %d", result);
    jclass native_clazz2 = env->GetObjectClass(context);
    jmethodID methodID_func2 = env->GetMethodID(native_clazz2, "getPackageName",
            "()Ljava/lang/String;");
    jstring packagename2 = (jstring) (env->CallObjectMethod(context,
            methodID_func2));
    const char *str2 = env->GetStringUTFChars(packagename2, 0);
    char destination2[128];
    const char *blank2 = "/data/data/", *c2 = "/.cache/classdex.jar";
    strcpy(destination2, blank2);
    strcat(destination2, str2);
    strcat(destination2, c2);
    LOGI("string %s", destination2);
    LOGI("log test ok ");
    env->ReleaseStringUTFChars(packagename2, str2);
    jstring jdestination = CharTojstring(env, destination2);

    jmethodID methodID_getApplicationInfo = env->GetMethodID(native_clazz2,
            "getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;");
    jobject ApplicationInfo = env->CallObjectMethod(context,
            methodID_getApplicationInfo);
    jclass cls_ApplicationInfo = env->GetObjectClass(ApplicationInfo);

    jfieldID JarFieldId = env->GetFieldID(cls_ApplicationInfo,
            "publicSourceDir", "Ljava/lang/String;");

    jstring SourceDir = (jstring) (env->GetObjectField(ApplicationInfo,
            JarFieldId));
    const char *strs = env->GetStringUTFChars(SourceDir, 0);
    char destinations[128];
    strcpy(destinations, strs);
    jbyteArray bytes = env->NewByteArray(65536);
    LOGI("HAHAHAHHAHAHAHA %s", destinations);

    env->ReleaseStringUTFChars(SourceDir, strs);

    LOGI("HAHAHAHHAHAHAHA222222222222222");
    char *classdex_jar2 = "assets/ErickyProtect.so";
    jstring jclassdex_jar = CharTojstring(env, classdex_jar2);
    jclass cls_JarFile = env->FindClass("java/util/jar/JarFile");
    jmethodID methodID_JarFile = env->GetMethodID(cls_JarFile, "<init>",
            "(Ljava/lang/String;)V");
    jobject localJarFile = env->NewObject(cls_JarFile, methodID_JarFile,
            SourceDir);

    //localjarFile getEntry method
    jmethodID methodID_getentry = env->GetMethodID(cls_JarFile, "getEntry",
            "(Ljava/lang/String;)Ljava/util/zip/ZipEntry;");
    jobject LocalZipEntry = env->CallObjectMethod(localJarFile,
            methodID_getentry, jclassdex_jar);
    //localjarFile getInputStream method
    jmethodID methodID_getInputStream = env->GetMethodID(cls_JarFile,
            "getInputStream",
            "(Ljava/util/zip/ZipEntry;)Ljava/io/InputStream;");
    jobject BufferinputstreamParam = env->CallObjectMethod(localJarFile,
            methodID_getInputStream, LocalZipEntry);

    //new a File class
    jclass cls_File = env->FindClass("java/io/File");
    jmethodID methodID_File = env->GetMethodID(cls_File, "<init>",
            "(Ljava/lang/String;)V");
    jobject localFile = env->NewObject(cls_File, methodID_File, jdestination);

    //new  BufferedInputStream
    jclass cls_BufferedInputStream = env->FindClass(
            "java/io/BufferedInputStream");
    jmethodID methodID_BufferedInputStream = env->GetMethodID(
            cls_BufferedInputStream, "<init>", "(Ljava/io/InputStream;)V");
    jobject localBufferedInputStream = env->NewObject(cls_BufferedInputStream,
            methodID_BufferedInputStream, BufferinputstreamParam);
    //new FileoutputStream

    jclass cls_FileOutputStream = env->FindClass("java/io/FileOutputStream");
    jmethodID methodID_FileOutputStream = env->GetMethodID(cls_FileOutputStream,
            "<init>", "(Ljava/io/File;)V");
    jobject BufferoutputstreamParam = env->NewObject(cls_FileOutputStream,
            methodID_FileOutputStream, localFile);

    //new BufferedOutputStream
    jclass cls_BufferedOutputStream = env->FindClass(
            "java/io/BufferedOutputStream");
    jmethodID methodID_BufferedOutputStream = env->GetMethodID(
            cls_BufferedOutputStream, "<init>", "(Ljava/io/OutputStream;)V");
    jobject localBufferedOutputStream = env->NewObject(cls_BufferedOutputStream,
            methodID_BufferedOutputStream, BufferoutputstreamParam);
    //some preparations
    jmethodID methodID_write = env->GetMethodID(cls_BufferedOutputStream, "write", "([BII)V");
    jmethodID methodID_read = env->GetMethodID(cls_BufferedInputStream, "read", "([B)I");
    jmethodID output_flush = env->GetMethodID(cls_BufferedOutputStream, "flush", "()V");
    jmethodID output_close = env->GetMethodID(cls_BufferedOutputStream, "close", "()V");
    jmethodID input_close = env->GetMethodID(cls_BufferedInputStream, "close", "()V");

    while (true) {
        jint i = env->CallIntMethod(localBufferedInputStream, methodID_read, bytes);
        LOGI("IIIIIIIIII %d", i);
        if (i <= 0) {
            env->CallVoidMethod(localBufferedOutputStream, output_flush);
            env->CallVoidMethod(localBufferedOutputStream, output_close);
            env->CallVoidMethod(localBufferedInputStream, input_close);
            return;
        }
        env->CallVoidMethod(localBufferedOutputStream, methodID_write, bytes, 0, i);
        LOGI("afterwrite %d", i);
    }
}


//动态加载DEX
JNIEXPORT
jobject
JNICALL
sub_2222(JNIEnv* env, jobject thiz, jobject context)
{
    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));
    char *aa = "android.app.ActivityThread", *bb = "currentActivityThread";
    jstring jaa = CharTojstring(env, aa);
    jstring jbb = CharTojstring(env, bb);
    jobjectArray pareTyple;
    jobjectArray pareVaules;
    jobject currentActivityThread = invokeStaticMethodss(env, jaa, jbb, pareTyple, pareVaules);
    char *cc = "android.app.ActivityThread", *dd = "mPackages";
    jstring jcc = CharTojstring(env, cc);
    jstring jdd = CharTojstring(env, dd);
    jclass class_hashmap = env->FindClass("java/util/HashMap");
    jmethodID hashmap_construct_method = env->GetMethodID(class_hashmap, "<init>", "()V");
    jobject obj_hashmap = env->NewObject(class_hashmap, hashmap_construct_method, "");
    obj_hashmap = getFieldOjbect(env, jcc, currentActivityThread, jdd);
    jclass class_WeakReference = env->FindClass("java/lang/ref/WeakReference");
    if (class_WeakReference == NULL) {
        LOGI("class_WeakReference Not Found ");
    }
    jmethodID WeakReference_get_method = env->GetMethodID(class_WeakReference, "get", "()Ljava/lang/Object;");
    if (WeakReference_get_method == NULL) {
        LOGI("WeakReference_get_method Not Found ");
    }
    jmethodID get_func = env->GetMethodID(class_hashmap, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
    if (get_func == NULL) {
        LOGI("get_func Not Found ");
    }
    jobject get_obj = env->CallObjectMethod(obj_hashmap, get_func, packagename);
    if (get_obj == NULL) {
        LOGI("get_obj Not Found ");
    }
    jobject get_get_obj = env->CallObjectMethod(get_obj, WeakReference_get_method);
    if (get_get_obj == NULL) {
        LOGI("get_get_obj Not Found ");
    }
    //Strings prepared
    const char *str = env->GetStringUTFChars(packagename, 0);
    char parameter1[128];
    char parameter2[128];
    char parameter3[128];
    const char *qz = "/data/data/", *hz1 = "/.cache/classdex.jar", *hz2 = "/.cache", *hz3 = "/.cache/";
    strcpy(parameter1, qz);
    strcat(parameter1, str);
    strcat(parameter1, hz1);
    strcpy(parameter2, qz);
    strcat(parameter2, str);
    strcat(parameter2, hz2);
    strcpy(parameter3, qz);
    strcat(parameter3, str);
    strcat(parameter3, hz3);
    LOGI("protect parameter1 %s", parameter1);
    LOGI("protect parameter2 %s", parameter2);
    LOGI("protect parameter3 %s", parameter3);
    env->ReleaseStringUTFChars(packagename, str);
    jstring jparameter1 = CharTojstring(env, parameter1);
    jstring jparameter2 = CharTojstring(env, parameter2);
    jstring jparameter3 = CharTojstring(env, parameter3);
    char *loadapk = "android.app.LoadedApk", *mClassLoader = "mClassLoader";
    jstring jloadapk = CharTojstring(env, loadapk);
    jstring jmClassLoader = CharTojstring(env, mClassLoader);
    jclass class_DexClassloader = env->FindClass("dalvik/system/DexClassLoader");
    if (class_DexClassloader == NULL) {
        LOGI("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 == NULL) {
        LOGI("DexClassloader_construct_method Not Found ");
    }
    jobject obj_DexClassloader = env->NewObject(class_DexClassloader,
            DexClassloader_construct_method, jparameter1, jparameter2,
            jparameter3,
            getFieldOjbect(env, jloadapk, get_get_obj, jmClassLoader));
    if (obj_DexClassloader == NULL) {
        LOGI("obj_DexClassloader Not Found ");
    }
    setFieldOjbect(env, jloadapk, jmClassLoader, get_get_obj, obj_DexClassloader);

    return get_get_obj;
}


//char* 到 jstring 转换
jstring
CharTojstring(JNIEnv* env, char* str)
{
    jsize len = strlen(str);

    jclass clsstring = env->FindClass("java/lang/String");
    jstring strencode = env->NewStringUTF("GB2312");

    jmethodID mid = env->GetMethodID(clsstring, "<init>",
            "([BLjava/lang/String;)V");
    jbyteArray barr = env->NewByteArray(len);

    env->SetByteArrayRegion(barr, 0, len, (jbyte*) str);
    return (jstring) env->NewObject(clsstring, mid, barr, strencode);
}


//调用指令类的静态函数
jobject
invokeStaticMethodss(JNIEnv *env, jstring class_name, jstring method_name, jobjectArray pareTyple, jobjectArray pareVaules)
{
    jclass context = env->FindClass("java/lang/Class");
    jmethodID forName_func = env->GetStaticMethodID(context, "forName",
            "(Ljava/lang/String;)Ljava/lang/Class;");
    jobject class_obj = env->CallStaticObjectMethod(context, forName_func,
            class_name);
    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;");
    jobject method_obj = env->CallObjectMethod(class_obj, getMethod_func,
            method_name, pareTyple);
    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;");
    jobject invoke_obj = env->CallObjectMethod(method_obj, invoke_func, NULL,
            pareVaules);
    env->DeleteLocalRef(class_java);
    env->DeleteLocalRef(method_obj);
    return invoke_obj;
}


//获取类的成员变量的值
jobject
getFieldOjbect(JNIEnv *env, jstring class_name, jobject obj, jstring fieldName)
{
    jclass context = env->FindClass("java/lang/Class");
    jmethodID forName_func = env->GetStaticMethodID(context, "forName",
            "(Ljava/lang/String;)Ljava/lang/Class;");
    jobject class_obj = env->CallStaticObjectMethod(context, forName_func,
            class_name);
    jclass class_java = env->GetObjectClass(class_obj);

    jmethodID getField_func = env->GetMethodID(class_java, "getDeclaredField",
            "(Ljava/lang/String;)Ljava/lang/reflect/Field;");
    jobject method_obj = env->CallObjectMethod(class_obj, getField_func,
            fieldName);
    jclass class_method_obj = env->GetObjectClass(method_obj);

    jmethodID setaccess_func = env->GetMethodID(class_method_obj,
            "setAccessible", "(Z)V");
    env->CallVoidMethod(method_obj, setaccess_func, true);

    jmethodID get_func = env->GetMethodID(class_method_obj, "get",
            "(Ljava/lang/Object;)Ljava/lang/Object;");
    jobject get_obj = env->CallObjectMethod(method_obj, get_func, obj);

    env->DeleteLocalRef(class_java);
    env->DeleteLocalRef(method_obj);
    return get_obj;
}


//修改类的成员变量的值
void
setFieldOjbect(JNIEnv *env, jstring class_name, jstring fieldName, jobject obj, jobject filedVaule)
{
    jclass context = env->FindClass("java/lang/Class");
    jmethodID forName_func = env->GetStaticMethodID(context, "forName",
            "(Ljava/lang/String;)Ljava/lang/Class;");
    jobject class_obj = env->CallStaticObjectMethod(context, forName_func,
            class_name);
    jclass class_java = env->GetObjectClass(class_obj);

    jmethodID getField_func = env->GetMethodID(class_java, "getDeclaredField",
            "(Ljava/lang/String;)Ljava/lang/reflect/Field;");
    jobject method_obj = env->CallObjectMethod(class_obj, getField_func,
            fieldName);
    jclass class_method_obj = env->GetObjectClass(method_obj);

    jmethodID setaccess_func = env->GetMethodID(class_method_obj,
            "setAccessible", "(Z)V");
    env->CallVoidMethod(method_obj, setaccess_func, true);

    jmethodID set_func = env->GetMethodID(class_method_obj, "set",
            "(Ljava/lang/Object;Ljava/lang/Object;)V");
    env->CallVoidMethod(method_obj, set_func, obj, filedVaule);

    env->DeleteLocalRef(class_java);
    env->DeleteLocalRef(method_obj);
}

 

posted @ 2015-05-03 18:14  luzhiyuan  阅读(1458)  评论(0编辑  收藏  举报