ART学习系列:Android 9 的隐藏Api的突破-元反射原理解释

ART学习系列:Android 9 的隐藏Api的突破-元反射原理解释

ART学习系列:Android 9 的隐藏Api的突破-元反射原理解释

思路

1.Android 9 IsCallerTrusted 方法解析

2.hiddenapi::IsCallerTrusted的作用

3.VisitFrame 的调用逻辑

55 
  static bool IsCallerTrusted(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) {
    
    
56    // Walk the stack and find the first frame not from java.lang.Class and not from java.lang.invoke.
57    // This is very expensive. Save this till the last.
58    struct FirstExternalCallerVisitor : public StackVisitor {
    
    
59      explicit FirstExternalCallerVisitor(Thread* thread)
60          : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
61            caller(nullptr) {
    
    
62      }
63  
64      bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) {
    
    
65        ArtMethod *m = GetMethod();
66        if (m == nullptr) {
    
    
67          // Attached native thread. Assume this is *not* boot class path.
68          caller = nullptr;
69          return false;
70        } else if (m->IsRuntimeMethod()) {
    
    
71          // Internal runtime method, continue walking the stack.
72          return true;
73        }
74  
75        ObjPtr<mirror::Class> declaring_class = m->GetDeclaringClass();
76        if (declaring_class->IsBootStrapClassLoaded()) {
    
    
77          if (declaring_class->IsClassClass()) {
    
    
78            return true;
79          }
80          // Check classes in the java.lang.invoke package. At the time of writing, the
81          // classes of interest are MethodHandles and MethodHandles.Lookup, but this
82          // is subject to change so conservatively cover the entire package.
83          // NB Static initializers within java.lang.invoke are permitted and do not
84          // need further stack inspection.
85          ObjPtr<mirror::Class> lookup_class = mirror::MethodHandlesLookup::StaticClass();
86          if ((declaring_class == lookup_class || declaring_class->IsInSamePackage(lookup_class))
87              && !m->IsClassInitializer()) {
    
    
88            return true;
89          }
90        }
91  
92        caller = m;
93        return false;
94      }
95  
96      ArtMethod* caller;
97    };
98  
99    FirstExternalCallerVisitor visitor(self);
100    visitor.WalkStack();
101    return visitor.caller != nullptr &&
102           hiddenapi::IsCallerTrusted(visitor.caller->GetDeclaringClass());
103  }

分解来看

static bool IsCallerTrusted(Thread* self) 
    // 创建 vsitor 对象
    FirstExternalCallerVisitor visitor(self);
    // vsitor 对象通过walk stack 方法遍历堆栈
    visitor.WalkStack();
    // 如果 visitor.caller 不为空 则通过hiddenapi::IsCallerTrusted 再次判断
    return visitor.caller != nullptr &&
           hiddenapi::IsCallerTrusted(visitor.caller->GetDeclaringClass());
}

hiddenapi::IsCallerTrusted

inline bool IsCallerTrusted(ObjPtr<mirror::Class> caller) REQUIRES_SHARED(Locks::mutator_lock_) {
    
    
231    return !caller.IsNull() &&
232        detail::IsCallerTrusted(caller, caller->GetClassLoader(), caller->GetDexCache());
233  }
161  ALWAYS_INLINE
162  inline bool IsCallerTrusted(ObjPtr<mirror::Class> caller,
163                              ObjPtr<mirror::ClassLoader> caller_class_loader,
164                              ObjPtr<mirror::DexCache> caller_dex_cache)
165      REQUIRES_SHARED(Locks::mutator_lock_) {
    
    
166    if (caller_class_loader.IsNull()) {
    
    
167      // Boot class loader.
168      return true;
169    }
170  
171    if (!caller_dex_cache.IsNull()) {
    
    
172      const DexFile* caller_dex_file = caller_dex_cache->GetDexFile();
173      if (caller_dex_file != nullptr && caller_dex_file->IsPlatformDexFile()) {
    
    
174        // Caller is in a platform dex file.
175        return true;
176      }
177    }
178  
179    if (!caller.IsNull() &&
180        caller->ShouldSkipHiddenApiChecks() &&
181        Runtime::Current()->IsJavaDebuggable()) {
    
    
182      // We are in debuggable mode and this caller has been marked trusted.
183      return true;
184    }
185  
186    return false;
187  }

visitor.WalkStack(); 看看你walkstack 如何遍历堆栈的

// /art/runtime/stack.cc
766  void StackVisitor::WalkStack(bool include_transitions) {
    
    
767 
771    bool exit_stubs_installed = Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled();
772    uint32_t instrumentation_stack_depth = 0;
773    size_t inlined_frames_count = 0;
774  
775    for (const ManagedStack* current_fragment = thread_->GetManagedStack();
776         current_fragment != nullptr; current_fragment = current_fragment->GetLink()) {
    
    
777      cur_shadow_frame_ = current_fragment->GetTopShadowFrame();
778      cur_quick_frame_ = current_fragment->GetTopQuickFrame();
779      cur_quick_frame_pc_ = 0;
780      cur_oat_quick_method_header_ = nullptr;
781  
782      if (cur_quick_frame_ != nullptr) {
    
      // Handle quick stack frames.
783        // Can't be both a shadow and a quick fragment.
784        DCHECK(current_fragment->GetTopShadowFrame() == nullptr);
785        ArtMethod* method = *cur_quick_frame_;
786        DCHECK(method != nullptr);
787        bool header_retrieved = false;
788        if (method->IsNative()) {
    
    
789          //省略 native
822        }
823        while (method != nullptr) {
    
    
824         
829           //省略

830          if ((walk_kind_ == StackWalkKind::kIncludeInlinedFrames)
831              && (cur_oat_quick_method_header_ != nullptr)
832              && cur_oat_quick_method_header_->IsOptimized()) {
    
    
833            CodeInfo code_info = cur_oat_quick_method_header_->GetOptimizedCodeInfo();
834            CodeInfoEncoding encoding = code_info.ExtractEncoding();
835            uint32_t native_pc_offset =
836                cur_oat_quick_method_header_->NativeQuickPcOffset(cur_quick_frame_pc_);
837            StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding);
838            if (stack_map.IsValid() && stack_map.HasInlineInfo(encoding.stack_map.encoding)) {
    
    
839              InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
840              DCHECK_EQ(current_inlining_depth_, 0u);
841              for (current_inlining_depth_ = inline_info.GetDepth(encoding.inline_info.encoding);
842                   current_inlining_depth_ != 0;
843                   --current_inlining_depth_) {
    
    
844                bool should_continue = VisitFrame();
845                if (UNLIKELY(!should_continue)) {
    
    
846                  return;
847                }
848                cur_depth_++;
849                inlined_frames_count++;
850              }
851            }
852          }
853          
             //这块发现 我们在之前看到的在java_lang_class.cc isCallerTrust方法里调用的内容
854          bool should_continue = VisitFrame();
855          if (UNLIKELY(!should_continue)) {
    
    
856            return;
857          }
858  
859         // 省略 大概猜是在遍历吧

926          method = *cur_quick_frame_;
927        }
928      } else if (cur_shadow_frame_ != nullptr) {
    
    
929        do {
    
    
930          SanityCheckFrame();
931          bool should_continue = VisitFrame();
932          if (UNLIKELY(!should_continue)) {
    
    
933            return;
934          }
935          cur_depth_++;
936          cur_shadow_frame_ = cur_shadow_frame_->GetLink();
937        } while (cur_shadow_frame_ != nullptr);
938      }
939      if (include_transitions) {
    
    
940        bool should_continue = VisitFrame();
941        if (!should_continue) {
    
    
942          return;
943        }
944      }
945      if (kCount == CountTransitions::kYes) {
    
    
946        cur_depth_++;
947      }
948    }
949    if (num_frames_ != 0) {
    
    
950      CHECK_EQ(cur_depth_, num_frames_);
951    }
952  }

经过上面的WalkStack,如果VisitFrame 返回false,也就是找到了当前的方法的调用者。

由此可以看出, visitor通过遍历找到了调用的caller。对caller 进行check。

99    FirstExternalCallerVisitor visitor(self);
100    visitor.WalkStack();
101    return visitor.caller != nullptr &&
102           hiddenapi::IsCallerTrusted(visitor.caller->GetDeclaringClass());

那我们看现在的调用关系

在这里插入图片描述

由此可见,通过反射Method本身的方法 getDeclareMethod 使调用关系发生了变化。获得ART检查方法的调用着的信任。

遗留的内容

1.Android 9,10,11 的该方法差距

2.Android 11 不OK的原因猜测

3.Android 11上的其他绕过方式

猜你喜欢

转载自blog.csdn.net/ziyunLLL/article/details/124871450