Android Hook Dexposed原理小析

本文深入探讨了Dexposed框架的原理与应用,该框架由阿里巴巴基于Xposed开发,用于实现HotPatch。通过修改Demo中的test函数,展示了如何在调用hook前后改变函数的返回值。文章还详细介绍了NDK部分的hook实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

dexposed是阿里巴巴在xposed框架上面开发的hotpatch一套框架

当然hotpatch的方式有很多,这里先介绍下dexposed原理

Demo中有个test函数, 在调用hook之前正常返回”11111”; 调用hook之后, 却返回”newTestMethod”, 被我们给修改

public class Demo
{
    String TAG = "===[hookdemo]===";

    public static String staticTest(String param1)
    {
        return "staticTest";
    }

    public String test(String param1)
    {
        return "11111";
    }

    public void demo()
    {
        String param1 = "param1";
        Log.d(TAG, "===========before hook test:" + this.test(param1));
        hook(Demo1.class, "test", "(Ljava/lang/String;)Ljava/lang/String;");
        Log.d(TAG, "===========after hook test:" + this.test(param1));

        Log.d(TAG, "===========before hook staticTest:" + this.staticTest(param1));
        hook(Demo1.class, "staticTest", "(Ljava/lang/String;)Ljava/lang/String;");
        Log.d(TAG, "===========after hook staticTest:" + this.staticTest(param1));
    }

    private native void hook(Class<?> clazzToHook, String methodName, String methodSig);
}

ndk 中的部分

#include <jni.h>
#include "log.h"
#include "Dalvik.h"

static void showMethodInfo(const Method* method)
{
    //看看method的各个属性都是啥:
    LOGD("accessFlags:%d",method->accessFlags);
    LOGD("clazz->descriptor:%s",method->clazz->descriptor);
    LOGD("clazz->sourceFile:%s",method->clazz->sourceFile);
    LOGD("methodIndex:%d",method->methodIndex);
    LOGD("name:%s",method->name);
    LOGD("shorty:%s",method->shorty);
}

/**
 * 使用jni GetMethodID 方法获取jmethodID 强制转为 Method 的hook 方法 示例
 */
static void newTestMethod(const u4* args, JValue* pResult,
                          const Method* method, struct Thread* self) {

    // args 是原来函数的参数数组, 原来test函数只有一个String型参数
    // 并且要注意, 如果是不是static函数, 下标0 是函数所在类的实例obj
    // 在dvm中Object,  jni 中的jobject 和 java 中的 Object类 都不是同一个东西
    // String类对应StringObject
    // 取出参数打印出来看看
    StringObject* param1 = NULL;

    if(dvmIsStaticMethod(method))
        param1 = (StringObject*)args[0];
    else
        param1 = (StringObject*)args[1];
    LOGD("param1:%s",dvmCreateCstrFromString(param1));

    //JValue 是个union ,要返回int 就 pResult->i=1; 返回Object对象就 pResult->l = ojb;
    // 但是, 在dvm中的Object,  jni 中的jobject 和 java 中的 Object类 都不是同一个东西
    // 所以, 我们这里使用dvm的函数来创建一个StringObject*
    pResult->l = dvmCreateStringFromCstr("newTestMethod");

    // 一般情况应该使用宏 : RETURN_XXX(result);
    return;
}

extern "C" JNIEXPORT void JNICALL
Java_com_zhaoxiaodan_hookdemo_Demo1_hook(JNIEnv *env, jobject instance, jobject clazzToHook,
                                                jstring methodName_, jstring methodSig_) {

    const char *methodName = env->GetStringUTFChars(methodName_, 0);
    const char *methodSig = env->GetStringUTFChars(methodSig_, 0);

    jmethodID methodIDToHook = env->GetMethodID((jclass) clazzToHook,methodName,methodSig);

    // 找不到有可能是个static
    if(nullptr == methodIDToHook){
        env->ExceptionClear();
        methodIDToHook = env->GetStaticMethodID((jclass) clazzToHook,methodName

转载于:https://www.cnblogs.com/lzl-sml/p/5203197.html