Android反射@hide API 方法、变量,支持Android11和Android12

news2025/8/2 22:02:03

Android源码中现在有大量的方法和变量被@hide所修饰,而这些被hide修饰的方法和变量是不允许应用层进行反射获取的,所以富有探索精神的程序员们就开始想尽各种办法绕过系统hide限制来使用@hide修饰的方法和变量。

1、套娃(适配Android10即之前)

Android11之前我们可以使用套娃的形式来欺骗系统,让系统误以为是系统调用的hide方法。而到了Android11之后,套娃就已经失效了喽,要寻找新的方法来和系统对抗。

  1. 我们通过反射 API 拿到 getDeclaredMethod 方法。getDeclaredMethod 是 public 的,不存在问题;这个通过反射拿到的方法我们称之为元反射方法。

  1. 我们通过刚刚反射拿到元反射方法去反射调用 getDeclardMethod。这里我们就实现了以系统身份去反射的目的——反射相关的 API 都是系统类,因此我们的元反射方法也是被系统类加载的方法;所以我们的元反射方法调用的 getDeclardMethod 会被认为是系统调用的,可以反射任意的方法。

例子:

Method metaGetDeclaredMethod =
        Class.class.getDeclaredMethod("getDeclardMethod"); // 公开API,无问题
Method hiddenMethod = metaGetDeclaredMethod.invoke(hiddenClass,
        "hiddenMethod", "hiddenMethod参数列表"); // 系统类通过反射使用隐藏 API,检查直接通过。
hiddenMethod.invoke // 正确找到 Method 直接反射调用

代表:FreeReflection

2、源码分析

而目前的Android11和Android12系统修复了这个漏洞,套娃无法在继续使用。

所以我们只能另辟蹊径。

系统在判断调用者的时候是通过调用栈来判断调用者的方向的,所以只要我们在调用栈上做手脚,让系统误以为不是应用层的调用栈,即可绕过@hide限制。

static jobject Class_getDeclaredMethodInternal(JNIEnv* env, jobject javaThis, jstring name, jobjectArray args) {
  // ……
  Handle<mirror::Method> result = hs.NewHandle(
      mirror::Class::GetDeclaredMethodInternal<kRuntimePointerSize>(
          soa.Self(),
          klass,
          soa.Decode<mirror::String>(name),
          soa.Decode<mirror::ObjectArray<mirror::Class>>(args),
          GetHiddenapiAccessContextFunction(soa.Self())));
  if (result == nullptr || ShouldDenyAccessToMember(result->GetArtMethod(), soa.Self())) {
    return nullptr;
  }
  return soa.AddLocalReference<jobject>(result.Get());
}

如果ShouldDenyAccessToMember返回true,则getDeclaredMethodInternal会返回null,则上层会抛出异常。

bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) {
    ArtMethod *m = GetMethod();
    ......
    ObjPtr<mirror::Class> declaring_class = m->GetDeclaringClass();
    if (declaring_class->IsBootStrapClassLoaded()) {
        ......
        // 如果 PREVENT_META_REFLECTION_BLACKLIST_ACCESS 为 Enabled,跳过来自 java.lang.reflect.* 的访问
        // 系统对“套娃反射”的限制的关键就在此
        ObjPtr<mirror::Class> proxy_class = GetClassRoot<mirror::Proxy>();
        if (declaring_class->IsInSamePackage(proxy_class) && declaring_class != proxy_class) {
            if (Runtime::Current()->isChangeEnabled(kPreventMetaReflectionBlacklistAccess)) {
                return true;
            }
        }
    }

    caller = m;
    return false;
}

套娃为什么会失效,原因就在VisitFrame中

3、重点来了--解决方案(适配Anroid11&Android12)

我们解决方法的方向就是破坏调用堆栈,让系统无法识别api的真正调用者。

具体做法:

  1. 通过在jni层创建线程来执行真正的反射操作,当然,只是这样还不足以欺骗系统。

  1. 通过对线程调用attachthread方法来改变调用堆栈,从而达到欺骗系统的目的。google对attachthread的部分讲解:https://developer.android.com/training/articles/perf-jni?hl=zh-cn

4、源码

话不多说,直接上源码:

1、通过async来创建线程,因为async可以返回future来把异步同步化,线程内执行getDeclaredField_internal

Java_com_macoli_reflect_1helper_NativeReflect_getDeclaredField(JNIEnv *env, jobject t,
                                                               jclass clz, jstring fieldName) {
    auto global_clazz = env->NewGlobalRef(clz);
    jstring global_method_name = static_cast<jstring>(env->NewGlobalRef(fieldName)) ;
    //通过async来创建线程,因为async可以返回future来把异步同步化,线程内执行getDeclaredField_internal
    auto future = std::async(&getDeclaredField_internal, global_clazz, global_method_name);
    auto result = future.get();

    env->DeleteGlobalRef(global_clazz) ;
    env->DeleteGlobalRef(global_method_name) ;

    return result ;
}

2、真正执行反射操作

关键:attachCurrentThread()来对调用堆栈进行转变。


JNIEnv *attachCurrentThread() {
    JNIEnv *env;
    int res = _vm->AttachCurrentThread(&env, nullptr);
    __android_log_print(ANDROID_LOG_DEBUG, "native", "Found attached %d", res);
    return env;
}

void detachCurrentThread() {
    _vm->DetachCurrentThread();
}


static jobject getDeclaredField_internal(jobject object, jstring field_name) {

    JNIEnv *env = attachCurrentThread();//这里是重点

    jclass clazz_class = env->GetObjectClass(object);
    jmethodID methodId = env->GetMethodID(clazz_class, "getDeclaredField",
                                          "(Ljava/lang/String;)Ljava/lang/reflect/Field;");
    jobject res = env->CallObjectMethod(object, methodId, field_name);
    jobject global_res = nullptr;
    if (res != nullptr) {
        global_res = env->NewGlobalRef(res);
    }

    detachCurrentThread();
    return global_res;
}

总结:

源码已上传到gitee:https://gitee.com/gggl/reflect_helper

反射Android @hide api 适配

Android11&Android12

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/367659.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python实现贝叶斯优化器(Bayes_opt)优化Catboost分类模型(CatBoostClassifier算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。1.项目背景贝叶斯优化器(BayesianOptimization) 是一种黑盒子优化器&#xff0c;用来寻找最优参数。贝叶斯优化器是基…

PHPExcel 表格设置

4.5.3。通过行和列设置单元格值 通过设置坐标单元格值可以使用工作表的setCellValueByColumnAndRow方法来实现。 //设置单元格B8 $objPHPExcel->getActiveSheet()->setCellValueByColumnAndRow(1, 8, ‘Some value’); 4.5.4。由列和行中检索的小区 检索的小区的值&#…

Blender——竹篮的制作

效果图前言参考视频&#xff1a;Blender 竹篮建模编制效果3D教程建议Blender版本在v3.0.0或以上&#xff0c;本实验的blender为v3.4.1操作步骤打开一个【常规项目】。点击shading下拉列表&#xff0c;将颜色改为【随机】&#xff0c;背景改为【世界坐标】&#xff0c;勾选【Cva…

Linux期末考试应急

Linux期末考试应急 虚拟机添加硬盘、分区、格式化、挂载、卸载 fdisk -l#查看系统现有分区fdisk <指定磁盘>#指定磁盘分区sudo mkfs.ext3 <指定分区>#格式化磁盘###挂载磁盘1.新建一个目录sudo mkdir /mnt/test2.将指定分区挂载到对应目录sudo mount /dev/sdb10 /…

里程计(一) 数学模型及STM32实现

一、首先确保接线和硬件没问题&#xff0c;并确定控制逻辑 测试单片机-驱动板-电机连线是否接通&#xff1a;控制板IN1,IN2一个接3.3V一个接GND,ENA1接3.3V测左电机&#xff1b;控制板IN3,IN4一个接3.3V一个接GND,ENA2接3.3V测右电机。 在电机已经安装完毕的情况下&#xff0c;…

SAP ABAP中的数据类型 Data Types

简单来说分两种&#xff1a; 数据字典里定义的在ABAP程序里定义的 文章目录1. ABAP数据字典里的1.1 数字型的1.2 字符型1.3 字节型1.4 特殊类型2. 预定义的ABAP数据类型2.1 预定义数字型2.2 预定义字符型2.3 预定义字节型1. ABAP数据字典里的 1.1 数字型的 用在数学计算里的…

IP、MAC和端口号——网络通信中确认身份信息的三要素

目录 &#x1f30f; IP地址 &#x1f30f; MAC地址 &#x1f30f; 端口号 IP、MAC和端口号——网络通信中确认身份信息的三要素 在茫茫的互联网海洋中&#xff0c;要找到一台计算机非常不容易&#xff0c;有三个要素必须具备&#xff0c;它们分别是 IP 地址、MAC 地址和端口…

【Galois工具开发之路】关于ClassFileTransformer的注意点

关于ClassFileTransformer 该接口是javaagent的 Instrumentation.addTransformer 方法的入参之一&#xff0c;用于给加载的类添加一个类转换器&#xff0c;确保在类进入main方法之前&#xff0c;对类进行字节码插桩。 接口函数说明 该接口只有一个方法&#xff0c;即 byte[…

[SSD固态硬盘技术 19] 谁是数据的守护神? 盘内RAID1/RAID5图文详解_盘内数据冗余保护

版权声明&#xff1a; 付费作品&#xff0c;禁止转载前言提到冗余保护&#xff0c;最容易想到的就是RAID(Redundant Arrays of Independent Disks) , 独立冗余磁盘阵列。它是一种把多块独立的物理硬盘按不同方式组合形成一个硬盘组&#xff0c;以此提供比单个硬盘更高的存储性能…

华为OD机试题,用 Java 解【TLV 解码】问题

最近更新的博客 华为OD机试 - 猴子爬山 | 机试题算法思路 【2023】华为OD机试 - 分糖果(Java) | 机试题算法思路 【2023】华为OD机试 - 非严格递增连续数字序列 | 机试题算法思路 【2023】华为OD机试 - 消消乐游戏(Java) | 机试题算法思路 【2023】华为OD机试 - 组成最大数…

数据库浅谈之 LLVM

数据库浅谈之 LLVM HELLO&#xff0c;各位博友好&#xff0c;我是阿呆 &#x1f648;&#x1f648;&#x1f648; 这里是数据库浅谈系列&#xff0c;收录在专栏 DATABASE 中 &#x1f61c;&#x1f61c;&#x1f61c; 本系列阿呆将记录一些数据库领域相关的知识 &#x1f3c…

【CJSON】嵌入式芯片上基于USB HOST的CJSON文件库移植与应用

一 CJSON简介项目遇到了一个需求&#xff0c;就是需要通过U盘或者其他外接设备&#xff0c;与板子&#xff08;嵌入式芯片使用的是LPC1857&#xff09;进行交互。交互的形式有两种&#xff1a;一种是预存在外接U盘中的配置信息CFG&#xff0c;接上U盘之后&#xff0c;嵌入式芯片…

【HTTP——了解HTTP协议及状态码】

一&#xff0c; 什么是通信通信&#xff0c;就是信息的传递和交换。通信三要素&#xff1a;通信的主体&#xff0c;通信的内容&#xff0c;通信的方式现实生活中的通信&#xff1a;我打电话叫小明来我家吃饭【其中通信的主体是&#xff0c;我&#xff0c;小明。通信内容是&…

华为OD机试题,用 Java 解【最小施肥机能效】问题

最近更新的博客 华为OD机试 - 猴子爬山 | 机试题算法思路 【2023】华为OD机试 - 分糖果(Java) | 机试题算法思路 【2023】华为OD机试 - 非严格递增连续数字序列 | 机试题算法思路 【2023】华为OD机试 - 消消乐游戏(Java) | 机试题算法思路 【2023】华为OD机试 - 组成最大数…

【AI写作】《如何利用 RPA 实现自动化获客?》

写一篇文章《如何利用 RPA 实现自动化获客?》,不少于3000字,使用markdown格式。分10各章节,细化到3级目录。 文章目录 1. 什么是 RPA (Robotic Process Automation)?RPA 的应用场景2. RPA 自动化获客实战2.1 RPA 应该领域2.2 自动化选品 – 电商选品2.3 自动化获客 – 百…

Biome-BGC在模拟过程中,如何使用Linux、Python等,完成前处理和后处理工作???

在Biome-BGC模型中&#xff0c;对于碳的生物量积累&#xff0c;采用光合酶促反应机理模型计算出每天的初级生产力(GPP)&#xff0c;将生长呼吸和维持呼吸减去后的产物分配给叶、枝条、干和根。生物体的碳每天都按一定比例以凋落方式进入凋落物碳库&#xff1b;对于水份输运过程…

【C语言】数据的存储

☃️内容专栏&#xff1a;【C语言】进阶部分 ☃️本文概括&#xff1a; C语言中的数据类型及其存储方式。 ☃️本文作者&#xff1a;花香碟自来_ ☃️发布时间&#xff1a;2023.2.24 目录 一、数据类型详细介绍 1.1 基本的数据类型 1.2 整型家族 1.3 构造类型 1.4 指针类型…

压力传感器MPX5700D/MPX5700GP/MPX5700AP产品概述、特征

MPX5700系列压阻式换能器是最先进的单片硅压力传感器&#xff0c;可广泛用于各种应用&#xff0c;特别是采用A/D输入微控制器或微处理器的应用。这一获得专利的单元件传感器集合了高级微加工技术、薄膜金属化、双极工艺&#xff0c;能够提供精确的、与所施加压力成正比的高电平…

Java面向对象:继承特性的学习

本文介绍了面向对象的继承特性: 什么是继承 继承的概念 Java中继承的语法 在继承下父类成员的访问 super和this关键字 父类和子类构造方法 在继承下类中出现初始化代码的执行顺序 父类成员的访问权限对子类的可见性 Java的继承关系 final关键字 认识继承和组合关系 继承特性的学…

Pytorch学习笔记(7):优化器、学习率及调整策略、动量

目录 一、优化器 1.1 优化器的介绍 1.2 optimizer的属性 1.3 optimizer的方法 1.4 常用优化器 torch.optim.SGD 二、学习率 2.1 学习率介绍 2.2 为什么要调整学习率 2.3 pytorch的六种学习率调整策略 &#xff08;1&#xff09;StepLR &#xff08;2&#xff09;Mu…