当前位置: 首页 > article >正文

Lsposed Java HOOK原理及检测

当使用 XposedBridge.hookMethod 这个 api对java函数进行hook时:

public static XC_MethodHook.Unhook hookMethod(Member hookMethod, XC_MethodHook callback) {
    if (!(hookMethod instanceof Executable)) {
        throw new IllegalArgumentException("Only methods and constructors can be hooked: " + hookMethod);
    } else if (Modifier.isAbstract(hookMethod.getModifiers())) {
        throw new IllegalArgumentException("Cannot hook abstract methods: " + hookMethod);
    } else if (hookMethod.getDeclaringClass().getClassLoader() == XposedBridge.class.getClassLoader()) {
        throw new IllegalArgumentException("Do not allow hooking inner methods");
    } else if (hookMethod.getDeclaringClass() == Method.class && hookMethod.getName().equals("invoke")) {
        throw new IllegalArgumentException("Cannot hook Method.invoke");
    }
 
 
    if (callback == null) {
        throw new IllegalArgumentException("callback should not be null!");
    }
 
    if (!HookBridge.hookMethod(false, (Executable) hookMethod, LSPosedBridge.NativeHooker.class, callback.priority, callback)) {
        log("Failed to hook " + hookMethod);
        return null;
    }
 
    return callback.new Unhook(hookMethod);
}

会调用  HookBridge.hookMethod 这个内部api,实现在native层:

public class HookBridge {
    public static native boolean hookMethod(boolean useModernApi, Executable hookMethod, Class<?> hooker, int priority, Object callback);
 
 
    public static native boolean unhookMethod(boolean useModernApi, Executable hookMethod, Object callback);
 
    public static native boolean deoptimizeMethod(Executable method);
 
    public static native <T> T allocateObject(Class<T> clazz) throws InstantiationException;
 
    public static native Object invokeOriginalMethod(Executable method, Object thisObject, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;
 
    public static native <T> Object invokeSpecialMethod(Executable method, char[] shorty, Class<T> clazz, Object thisObject, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;
 
    @FastNative
    public static native boolean instanceOf(Object obj, Class<?> clazz);
 
    @FastNative
    public static native boolean setTrusted(Object cookie);
 
    public static native Object[][] callbackSnapshot(Class<?> hooker_callback, Executable method);
}

native层方法定义如下:

LSP_DEF_NATIVE_METHOD(jboolean, HookBridge, hookMethod, jboolean useModernApi, jobject hookMethod,
                      jclass hooker, jint priority, jobject callback) {
    bool newHook = false;
#ifndef NDEBUG
    struct finally {
        std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
        bool &newHook;
        ~finally() {
            auto finish = std::chrono::steady_clock::now();
            if (newHook) {
                LOGV("New hook took {}us",
                     std::chrono::duration_cast<std::chrono::microseconds>(finish - start).count());
            }
        }
    } finally {
        .newHook = newHook
    };
#endif
    auto target = env->FromReflectedMethod(hookMethod);     //ArtMethod 结构体
    HookItem * hook_item = nullptr;
    hooked_methods.lazy_emplace_l(target, [&hook_item](auto &it) {
        hook_item = it.second.get();
    }, [&hook_item, &target, &newHook](const auto &ctor) {
        auto ptr = std::make_unique<HookItem>();
        hook_item = ptr.get();
        ctor(target, std::move(ptr));
        newHook = true;
    });
    if (newHook) {
        auto init = env->GetMethodID(hooker, "<init>", "(Ljava/lang/reflect/Executable;)V");
        auto callback_method = env->ToReflectedMethod(hooker, env->GetMethodID(hooker, "callback",   //LSPosedBridge.NativeHooker
                                                                               "([Ljava/lang/Object;)Ljava/lang/Object;"),
                                                      false);
        auto hooker_object = env->NewObject(hooker, init, hookMethod);  //新建 NativeHooker 对象,传入 目标hookMethod
        hook_item->SetBackup(lsplant::Hook(env, hookMethod, hooker_object, callback_method)); //传入的目标method 和 NativeHooker对象
        env->DeleteLocalRef(hooker_object);
    }
    jobject backup = hook_item->GetBackup();
    if (!backup) return JNI_FALSE;
    JNIMonitor monitor(env, backup);
    if (useModernApi) {
        if (before_method_field == nullptr) {
            auto callback_class = JNI_GetObjectClass(env, callback);
            callback_ctor = JNI_GetMethodID(env, callback_class, "<init>", "(Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;)V");
            before_method_field = JNI_GetFieldID(env, callback_class, &#

http://www.kler.cn/a/314740.html

相关文章:

  • Appium配置2024.11.12
  • 图片画廊 day2 (可复制源码)
  • Spring框架之观察者模式 (Observer Pattern)
  • flink sql + kafka + mysql 如何构建实时数仓
  • 使用pdfjs加载多页pdf并实现打印
  • ArcGIS Pro属性表乱码与字段名3个汉字解决方案大总结
  • 我的AI工具箱Tauri版-VideoIntroductionClipCut视频介绍混剪
  • Nacos与Eureka的区别:深入解析微服务中的服务注册与发现
  • npm切换为淘宝镜像源
  • GPU加速生物信息分析的尝试
  • 数据结构之存储位置
  • AIGC专栏15——CogVideoX-Fun详解 支持图文生视频 拓展CogVideoX到256~1024任意分辨率生成
  • Web_php_include 攻防世界
  • C++20 std::format
  • Windows下如何定时执行自定义任务
  • 2024年中国研究生数学建模竞赛C题——解题思路
  • 开源PHP导航网源码/精美简约网址导航收录网站/QQ技术导航程序
  • MySQL 索引事务
  • PyCharm的使用
  • 英特尔AI加速器Gaudi 3下周发布,挑战NVIDIA统治地位!
  • 连续数组问题
  • 『功能项目』QFrameWork框架重构OnGUI【63】
  • 深度学习02-pytorch-04-张量的运算函数
  • Selenium4.0实现自动搜索功能
  • 链式前向星建图
  • 【MySQL】 索引