日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android 11 限制反射,如何破解?

發布時間:2024/4/15 Android 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 11 限制反射,如何破解? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


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

我們看一下如何解決

  • native hook 住 ShouldDenyAccessToMember 方法,直接返回 false
  • 破壞調用堆棧繞過去,使 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 限制反射,如何破解?的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。