Android Hook Java


Android Hook Java

       
        由于项目需要,实现了一个脱离XPosed框架的Android Hook Java方法。其原理是注入某系统进程,使该进程加载某动态链接库,执行该库里的某函数,通过该函数执行某jar包里的java函数,然后执行hook该进程中的java函数操作。其中Hook Java部分提取了XPosed框架中的hook原理。

        1、进程注入
    target_pid = find_pid_of("system_server");
    if(inject_remote_process(target_pid, "/system/lib/libtest.so", "java_hook_test", "I'm parameter!", strlen("I'm parameter!")) == 0)
        LOGV("inject success");

        2、在C层执行Java方法
    JavaVM* jvm = AndroidRuntime::getJavaVM();
    JNIEnv* env;
    jvm->AttachCurrentThread(&env, NULL);

    jstring apk_path = env->NewStringUTF(INJECT_JAR_PATH);
    jstring dex_out_path = env->NewStringUTF("/data/dalvik-cache");
    jclass dexloader_claxx = env->FindClass("dalvik/system/DexClassLoader");

    snprintf(sig_buffer, 512, "(%s%s%s%s)V", JSTRING, JSTRING, JSTRING, JCLASS_LOADER);
    jmethodID dexloader_init_method = env->GetMethodID(dexloader_claxx, "<init>", sig_buffer);

    snprintf(sig_buffer, 512, "(%s)%s", JSTRING, JCLASS);
    jmethodID loadClass_method = env->GetMethodID(dexloader_claxx, "loadClass", sig_buffer);
    jclass class_loader_claxx = env->FindClass("java/lang/ClassLoader");
    snprintf(sig_buffer, 512, "()%s", JCLASS_LOADER);
    jmethodID getSystemClassLoader_method = env->GetStaticMethodID(class_loader_claxx, "getSystemClassLoader", sig_buffer);
    jobject class_loader = env->CallStaticObjectMethod(class_loader_claxx, getSystemClassLoader_method);
    check_value(class_loader);

    jobject dex_loader_obj = env->NewObject(dexloader_claxx, dexloader_init_method, apk_path, dex_out_path, NULL, class_loader);
    jstring class_name = env->NewStringUTF(CLASS_JAVA);
    jclass class_jia = static_cast<jclass>(env->CallObjectMethod(dex_loader_obj, loadClass_method, class_name));
    check_value(class_jia);

    jmethodID invoke_method = env->GetStaticMethodID(class_jia, "hook", "(I)V");
    check_value(invoke_method);
    env->CallStaticObjectMethod(class_jia, invoke_method, 0);
    LOGI("end hook java");
    jvm->DetachCurrentThread();

        3、添加你想执行hook操作的java函数,interceptKeyBeforeQueueing方法主要做一下对特殊按键的处理。
    Bridge.hookAllMethods(Helpers.findClass("com.android.internal.policy.impl.PhoneWindowManager"), "interceptKeyBeforeQueueing");

        4、类似于XPosed框架,添加你想替换的java函数cb_interceptKeyBeforeQueueing,可根据需求添加执行真正函数前与执行完后的操作。
    static XC_MethodHook cb_interceptKeyBeforeQueueing = new XC_MethodHook() {

        @Override
        protected void beforeHookedMethod(MethodHookParam param)
                throws Throwable {
            Log.v("test", "[KeyPress]" + param.args[0] + " | " + param.args[1] + " | " + param.args[2]);
        }
    };
        handleHookedMethod是真正替换的函数。
    private static Object handleHookedMethod(Member method, int originalMethodId, Object additionalInfoObj,
            Object thisObject, Object[] args) throws Throwable  {
        //Log.v("test", "enter handleHookedMethod");
		
        AdditionalHookInfo additionalInfo = (AdditionalHookInfo) additionalInfoObj;

        MethodHookParam param = new MethodHookParam();
        param.method = method;
        param.thisObject = thisObject;
        param.args = args;

        // call "before method" callbacks
        try {
            if (method.getName().equals("interceptKeyBeforeQueueing"))
                Hook.cb_interceptKeyBeforeQueueing.beforeHookedMethod(param);	
        } catch (Throwable t) {
            Log.v("test", t.getMessage());
            // reset result (ignoring what the unexpectedly exiting callback did)
            param.setResult(null);
            param.returnEarly = false;
        }

        // call original method if not requested otherwise
        if (!param.returnEarly) {
            try {
                param.setResult(invokeOriginalMethodNative(method, originalMethodId,
                    additionalInfo.parameterTypes, additionalInfo.returnType, param.thisObject, param.args));
            } catch (InvocationTargetException e) {
                param.setThrowable(e.getCause());
            }
        }
        // call "after method" callbacks
        Object lastResult =  param.getResult();
        Throwable lastThrowable = param.getThrowable();
        try {
            //<span style="white-space:pre">	</span>if (method.getName().equals("init"))
            //<span style="white-space:pre">		</span>Hook.cb_init.afterHookedMethod(param);
        } catch (Throwable t) {
            Log.v("test", t.getMessage());
            // reset to last result (ignoring what the unexpectedly exiting callback did)
            if (lastThrowable == null)
                param.setResult(lastResult);
            else
                param.setThrowable(lastThrowable);
        }

        // return
        if (param.hasThrowable())
            throw param.getThrowable();
        else
            return param.getResult();}

         整个工程已上传至github: https://github.com/phoebe1990/javaHook 
 
        运行结果如下:
        hook类PhoneWindowManager中interceptKeyBeforeQueueing函数成功,使每次手机按键时都打印一条log信息。

Android Hook Java_第1张图片


你可能感兴趣的:(java,android,hook,xposed)