https://github.com/Pangu-Immortal

先来分析一下问题出现的原因

我们看一眼Android 11 的源码,如下:

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,那么就会返回 null,上层就会抛出方法找不到的异常。这里和 Android P 没什么不同,只是把 ShouldBlockAccessToMember 改了个名而已。
ShouldDenyAccessToMember 会调用到 hiddenapi::ShouldDenyAccessToMember,该函数是这样实现的:

template<typename T>
inline bool ShouldDenyAccessToMember(T* member,const std::function<AccessContext()>& fn_get_access_context,AccessMethod access_method)REQUIRES_SHARED(Locks::mutator_lock_) {const uint32_t runtime_flags = GetRuntimeFlags(member);// 1:如果该成员是公开API,直接通过if ((runtime_flags & kAccPublicApi) != 0) {return false;}// 2:不是公开API(即为隐藏API),获取调用者和被访问成员的 Domain // 主要看这个const AccessContext caller_context = fn_get_access_context();const AccessContext callee_context(member->GetDeclaringClass());// 3:如果调用者是可信的,直接返回if (caller_context.CanAlwaysAccess(callee_context)) {return false;}// ......}

原来的方案失效了能在 FirstExternalCallerVisitor 的 VisitFrame 方法中找到答案

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;
}

我们看一下如何解决

  1. native hook 住 ShouldDenyAccessToMember 方法,直接返回 false
  2. 破坏调用堆栈绕过去,使 VM 无法识别调用方

我们采用的是第二种方案,有什么方法可以让 VM 无法识别我的调用栈呢?这可以通过 JniEnv::AttachCurrentThread(…) 函数创建一个新的 Thread 来完成。

具体我们可以参考这:https://developer.android.com/training/articles/perf-jni

然后配合 std::async(…) 与 std::async::get(…) 就能搞定了。

下面是关键代码:

// java 层直接用 jni 调用这个方法
static jobject Java_getDeclaredMethod(JNIEnv *env,jclass interface,jobject clazz,jstring method_name,jobjectArray params) {// ...... 省掉一些转换代码//  先用 std::async 调用 getDeclaredMethod_internal 方法auto future = std::async(&getDeclaredMethod_internal, global_clazz,global_method_name,global_params);auto result = future.get();return result;
}static jobject getDeclaredMethod_internal(jobject clazz,jstring method_name,jobjectArray params) {// 这里就是一些普通的 jni 操作了JNIEnv *env = attachCurrentThread();jclass clazz_class = env->GetObjectClass(clazz);jmethodID get_declared_method_id = env->GetMethodID(clazz_class, "getDeclaredMethod","(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");jobject res = env->CallObjectMethod(clazz, get_declared_method_id,method_name, params);detachCurrentThread();return env->NewGlobalRef(res);
}JNIEnv *attachCurrentThread() {JNIEnv *env;// AttachCurrentThread 核心在这里int res = _vm->AttachCurrentThread(&env, nullptr);return env;
}

https://github.com/Pangu-Immortal

Android 11 限制反射,如何破解?相关推荐

  1. 大叔也说Xamarin~Android篇~环境部署与破解

    原文:大叔也说Xamarin~Android篇~环境部署与破解 现在移动开发很HOT,以至于很多人都转向了它,大叔也不例外,这次有机制接触一下xamarin这个东西,其实之前也用于xamarin,只是 ...

  2. Android利用Java反射获取用户手机的rom定制系统及版本,EMUI,MIUI,ColorOS,FunthouchOS等

    Android利用Java反射获取用户手机的rom定制系统版本及版本号,EMUI,MIUI,ColorOS,FunthouchOS等 前言 正文 结语 前言 现在手机厂商都推出了自己的基于Androi ...

  3. Android 11 开发者常见问题 | FAQ・第一期

    注: 由于部分问题答案较长,可上下滑动以查看完整内容 存储 01 Q: Android 11 的分区存储是强制的吗?如果 targetSdkVersion 低于 Android 10,运行在 Andr ...

  4. Android 11(platfrom 30)APP启动流程(含Activity)核心点记录

    前言:边分析,边记录 不断更新. 注意:阅读此文请同时打开android-30的源码,一步一步按文章同步跟进阅读源码,因为源码量太大,这里只能贴出部分核心代码. 场景一.从桌面点击APP图标进行启动 ...

  5. 谷歌官方版android,谷歌Android 11正式官方版

    谷歌Android 11正式官方版终于和广大用户朋友们见面了,今天,谷歌正式发布了最新版本的移动操作系统Android 11,此次更新为大家新增了很多的功能,分别分为三个主题,人. 控件和隐私.And ...

  6. 未找到beta版怎么解决_刚刚,谷歌正式发布Android 11 Beta版,带来多项重磅更新...

    作者 | 安卓开发者博客 译者 | 核子可乐 策划 | 小智 转发链接:https://mp.weixin.qq.com/s/gp2XZGe69KDMAtsOeu56YA 前言 今日,谷歌安卓开发者博 ...

  7. android11测试版下载,Find X2系列 Android 11 Beta1 测试版发布,你要尝试一下吗?

    原标题:Find X2系列 Android 11 Beta1 测试版发布,你要尝试一下吗? 今年的特殊情况导致安卓11发布日期的一波三折,然而最后谷歌还是在6月11日发布了安卓Beta1版本.有趣的是 ...

  8. 安卓用户又少了一项自由,Android 11不再支持更改默认相机程序

    萧萧 发自 凹非寺 量子位 报道 | 公众号 QbitAI 在微博.微信上想要拍照上传时,想直接用FaceU或美图秀秀作为默认拍照程序,给自拍加个滤镜? 在即将推出的Android 11里,这些第三方 ...

  9. Android11模拟定位开发,Android 11 中的位置信息更新

    为了进一步保护用户隐私,Android 11 增加了单次位置信息访问权限,并更改了用户授予在后台访问位置信息权限的方式.这些更新会影响到 Android 11 及更高版本上运行的所有应用. 单次访问权 ...

最新文章

  1. 阿里、腾讯、美团、小米……各公司月饼大PK,看完简直想哭泣!
  2. 读《可复制的领导力》
  3. 使用多线程拷贝文件夹
  4. python之多并发socket
  5. python什么是调用_Python中包(package)的调用方式
  6. [数字dp] hdu 3271 SNIBB
  7. 从零基础入门Tensorflow2.0 ----一、1.2 实战分类模型(数据归一化)
  8. chmod与chown
  9. 传统方法做分割 解析种子cues
  10. 结构梁配筋最牛插件_结构分析|结构抗震概念——强柱弱梁
  11. 解决udhcpc命令无法自动获取并设置网卡IP和系统DNS
  12. 概率论-多维随机变量及其分布思维导图
  13. 西安交大计算机考研分数线2020院线,2020西安交通大学考研复试分数线已公布
  14. cocos 微信小游戏 加载云端资源
  15. 专精特新企业认定条件
  16. 哪款蓝牙耳机音质好?内行推荐四款高音质蓝牙耳机
  17. 百度BD09加密经纬度转国测局GCJ02经纬度
  18. 推荐几款适合孩子玩的编程游戏
  19. 关于M1版Macbook Pro 安装JDK 方法
  20. 计算机专业毕业论文4000字免费,计算机专业毕业生毕业论文攻略

热门文章

  1. Linux下kafka的部署
  2. Lucene排序以及自定义排序
  3. 译: 3. RabbitMQ Spring AMQP 之 Publish/Subscribe 发布和订阅
  4. JTextField类(单行文本框)/JPasswordFiel(密码框)/JTextArea(多行文本框)常用方法
  5. ASP.NET MVC编程——控制器
  6. 6. H.264/AVC编码器原理
  7. 做红颜知己就要恪守界限
  8. iPhone放大模式详解
  9. vue-electron 写一个markdown文章编辑器(一)
  10. 国际域名和境外域名能否提交备案