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上的其他绕过方式