美文网首页
如何在Android 12版本之后手机上使用hide的系统方法

如何在Android 12版本之后手机上使用hide的系统方法

作者: vb12 | 来源:发表于2023-12-07 14:21 被阅读0次
    参考文章,

    一种绕过Android P对非SDK接口限制的简单方法
    另一种绕过 Android P以上非公开API限制的办法

    背景

    Android P 引入了针对非 SDK 接口(俗称为隐藏API)的使用限制。这是继 Android N上针对 NDK 中私有库的链接限制之后的又一次重大调整。从今以后,不论是native层的NDK还是 Java层的SDK,我们只能使用Google提供的、公开的标准接口

    解决方案

    对于在android14版本上, 我们的思路仍然是前言参考文章中的修改虚拟机类dalvik.system.VMRuntimesetHiddenApiExemptions()方法, 将要进行反射调用的函数进行豁免.
    具体的原理, 上面的weishu大佬文章已经解释的很清楚了. 并且提供了一个项目:https://github.com/tiann/FreeReflection
    具体实现方法有两种, 如下:

    1. 使用自加载dex代码, 调用其中的方法, 对dalvik.system.VMRuntimesetHiddenApiExemptions()方法进行反射调用. 从而对要反射调用的方法进行豁免. 比如我们的最终想要反射调用方法funcA(), 那么就可以把这个方法前面传给上面的setHiddenApiExemptions()方法. 这也是目前FreeReflection项目中使用的方式.
      这个方法依赖的是在代码中手工加载dex的思路, 在加载dex时, 不去设置classLoader, 从而让加载动作上升到boot classLoader中, 而由boot classloader加载的代码默认就由了系统权限. 从而可以在进行反射操作时绿灯大开.
     DexFile dexFile = new DexFile(code);
    // 注意下面最后一个参数null, 此处就是classloader
     Class<?> bootstrapClass = dexFile.loadClass("me.weishu.reflection.BootstrapClass", null);
    

    但是需要注意的是dexFile.loadClass()已经被标注为废弃, 未来很可能被删除.

    1. 在native层面hook修改Runtime结构体
      对于高版本, 比如android 12, 从native层修改Runtime结构体的hidden_api_policy_字段的方法没有在项目中体现. 项目中的unsealNative的方式是失败的. 主要是因为兼容性的问题, 每个android版本的Runtime结构体都不尽相同, 这里我主要针对android 12版本的Runtime结构体进行hook处理.
      代码:http://aospxref.com/android-12.0.0_r3/xref/art/runtime/runtime.h
    // Android 12: http://aospxref.com/android-12.0.0_r3/xref/art/runtime/runtime.h
    struct PartialRuntimeS {
        // Specifies target SDK version to allow workarounds for certain API levels.
        uint64_t monitor_timeout_ns_;
        bool is_profileable_from_shell_ = false;
        bool is_profileable_ = false;
        uint32_t zygote_max_failed_boots_;
        ExperimentalFlags experimental_flags_;
        std::string fingerprint_;
        void *oat_file_manager_;
        bool is_low_memory_mode_;
        bool madvise_random_access_;
        size_t madvise_willneed_total_dex_size_;
        size_t madvise_willneed_odex_filesize_;
        size_t madvise_willneed_art_filesize_;
        bool safe_mode_;
    
        // Whether access checks on hidden API should be performed.
        EnforcementPolicy hidden_api_policy_;
    };
    
    

    这里hook的锚点是monitor_timeout_ns_字段, 这个默认值为500000000, 从而可以确定offset. 但是android13, android14 对于Runtime结构体的定义有些许差异, 需要根据版本分开处理, 但原理是相同的.

    int offsetOfMonitorNs 
       = findOffset(runtime, targetSdkVersionOffset, MAX, (uint64_t) 500000000);
    
    int findOffset(void *start, int regionStart, int regionEnd, T value) {
    
        if (NULL == start || regionEnd <= 0 || regionStart < 0) {
            return -1;
        }
        char *c_start = (char *) start;
    
        for (int i = regionStart; i < regionEnd; i += 4) {
            T *current_value = (T *) (c_start + i);
            if (value == *current_value) {
                LOGV("found offset: %d", i);
                return i;
            }
        }
        return -2;
    }
    

    示例代码已经上传到github:
    https://github.com/shaopx/SimpleReflectionAndroid12

    相关文章

      网友评论

          本文标题:如何在Android 12版本之后手机上使用hide的系统方法

          本文链接:https://www.haomeiwen.com/subject/nivsgdtx.html