其他
一个通用的纯 Java 安卓隐藏 API 限制绕过方案
背景
https://developer.android.google.cn/distribute/best-practices/develop/restrictions-non-sdk-interfaces
旧方法
这是 Canyie 在其博客上^1:
https://blog.canyie.top/2020/06/10/hiddenapi-restriction-policy-on-android-r/
(1) 首先在有隐藏 API 限制的情况下修改自己的 classloader 非常困难。(但是仍可行)
柳暗
花明
这个魔法类顾名思义,是非常不安全的:它可以纯 Java 读写内存!也就是说,有了这个东西,我们就可以读写类中的任意数据成员了!
public final class Class<T> {
private transient ClassLoader classLoader;
private transient Class<?> componentType;
private transient Object dexCache;
private transient ClassExt extData;
private transient Object[] ifTable;
private transient Class<? super T> superClass;
private transient Object vtable;
private transient long iFields;
private transient long methods;
private transient long sFields;
private transient int accessFlags;
private transient int classFlags;
//还有其他成员,这里就写了
}
1. 提取 ArtMethod
class Class {
// Pointer to an ArtMethod length-prefixed array. All the methods where this class is the place
// where they are logically defined. This includes all private, static, final and virtual methods
// as well as inherited default methods and miranda methods.
//
// The slice methods_ [0, virtual_methods_offset_) are the direct (static, private, init) methods
// declared by this class.
//
// The slice methods_ [virtual_methods_offset_, copied_methods_offset_) are the virtual methods
// declared by this class.
//
// The slice methods_ [copied_methods_offset_, |methods_|) are the methods that are copied from
// interfaces such as miranda or default methods. These are copied for resolution purposes as this
// class is where they are (logically) declared as far as the virtual dispatch is concerned.
//
// Note that this field is used by the native debugger as the unique identifier for the type.
uint64_t methods_;
};
inline LengthPrefixedArray<ArtMethod>* Class::GetMethodsPtr() {
return reinterpret_cast<LengthPrefixedArray<ArtMethod>*>(
static_cast<uintptr_t>(GetField64(OFFSET_OF_OBJECT_MEMBER(Class, methods_))));
}
template<typename T>
class LengthPrefixedArray {
static size_t OffsetOfElement(size_t index,
size_t element_size = sizeof(T),
size_t alignment = alignof(T)) {
DCHECK_ALIGNED_PARAM(element_size, alignment);
return RoundUp(offsetof(LengthPrefixedArray<T>, data_), alignment) + index * element_size;
}
T& AtUnchecked(size_t index, size_t element_size, size_t alignment) {
return *reinterpret_cast<T*>(
reinterpret_cast<uintptr_t>(this) + OffsetOfElement(index, element_size, alignment));
}
uint32_t size_;
uint8_t data_[0];
};
2. 计算 ArtMethod 大小
3. Method 与 ArtMethod 互转
public abstract class Executable {
/**
* @hide - exposed for use by {@code java.lang.invoke.*}.
*/
public final long getArtMethod() {
return artMethod;
}
}
public abstract class MethodHandle {
//其他成员...
/** @hide */ protected final long artFieldOrMethod;
}
稳定性分析
源码
看雪ID:yujincheng08
https://bbs.pediy.com/user-home-923805.htm
*本文由看雪论坛 yujincheng08 原创,转载请注明来自看雪社区。
《安卓高级研修班》2021年6月班火热招生中!
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!