Skip to content

Commit 407269e

Browse files
committed
Avoid hardcoding ART struct layout
1 parent 9aaf446 commit 407269e

File tree

1 file changed

+32
-7
lines changed

1 file changed

+32
-7
lines changed

library/src/main/java/org/lsposed/hiddenapibypass/HiddenApiBypass.java

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import org.lsposed.hiddenapibypass.library.BuildConfig;
2828

29+
import java.io.File;
2930
import java.lang.invoke.MethodHandle;
3031
import java.lang.invoke.MethodHandles;
3132
import java.lang.reflect.Constructor;
@@ -41,9 +42,24 @@
4142
import java.util.Set;
4243
import java.util.stream.Collectors;
4344

45+
import dalvik.system.PathClassLoader;
4446
import dalvik.system.VMRuntime;
4547
import sun.misc.Unsafe;
4648

49+
class ChildFirstClassLoader extends PathClassLoader {
50+
public ChildFirstClassLoader(String dexPath, ClassLoader parent) {
51+
super(dexPath, parent);
52+
}
53+
54+
@Override
55+
public Class<?> loadClass(String name) throws ClassNotFoundException {
56+
if ("java.lang.Object".equals(name)) {
57+
return Object.class;
58+
}
59+
return findClass(name);
60+
}
61+
}
62+
4763
@RequiresApi(Build.VERSION_CODES.P)
4864
public final class HiddenApiBypass {
4965
private static final String TAG = "HiddenApiBypass";
@@ -65,12 +81,21 @@ public final class HiddenApiBypass {
6581
//noinspection JavaReflectionMemberAccess DiscouragedPrivateApi
6682
unsafe = (Unsafe) Unsafe.class.getDeclaredMethod("getUnsafe").invoke(null);
6783
assert unsafe != null;
68-
methodOffset = unsafe.objectFieldOffset(Helper.Executable.class.getDeclaredField("artMethod"));
69-
classOffset = unsafe.objectFieldOffset(Helper.Executable.class.getDeclaredField("declaringClass"));
70-
artOffset = unsafe.objectFieldOffset(Helper.MethodHandle.class.getDeclaredField("artFieldOrMethod"));
71-
methodsOffset = unsafe.objectFieldOffset(Helper.Class.class.getDeclaredField("methods"));
72-
iFieldOffset = unsafe.objectFieldOffset(Helper.Class.class.getDeclaredField("iFields"));
73-
sFieldOffset = unsafe.objectFieldOffset(Helper.Class.class.getDeclaredField("sFields"));
84+
ClassLoader bootClassloader = null;
85+
try {
86+
if (new File("/apex/com.android.art/javalib/core-oj.jar").exists()) {
87+
bootClassloader = new ChildFirstClassLoader("/apex/com.android.art/javalib/core-oj.jar", null);
88+
} else if (new File("/apex/com.android.runtime/javalib/core-oj.jar").exists()) {
89+
bootClassloader = new ChildFirstClassLoader("/apex/com.android.runtime/javalib/core-oj.jar", null);
90+
}
91+
} catch (Throwable ignored) {
92+
}
93+
methodOffset = unsafe.objectFieldOffset((bootClassloader != null ? bootClassloader.loadClass(Executable.class.getName()) : Helper.Executable.class).getDeclaredField("artMethod"));
94+
classOffset = unsafe.objectFieldOffset((bootClassloader != null ? bootClassloader.loadClass(Executable.class.getName()) : Helper.Executable.class).getDeclaredField("declaringClass"));
95+
artOffset = unsafe.objectFieldOffset((bootClassloader != null ? bootClassloader.loadClass(MethodHandle.class.getName()) : Helper.MethodHandle.class).getDeclaredField("artFieldOrMethod"));
96+
methodsOffset = unsafe.objectFieldOffset((bootClassloader != null ? bootClassloader.loadClass(Class.class.getName()) : Helper.Class.class).getDeclaredField("methods"));
97+
iFieldOffset = unsafe.objectFieldOffset((bootClassloader != null ? bootClassloader.loadClass(Class.class.getName()) : Helper.Class.class).getDeclaredField("iFields"));
98+
sFieldOffset = unsafe.objectFieldOffset((bootClassloader != null ? bootClassloader.loadClass(Class.class.getName()) : Helper.Class.class).getDeclaredField("sFields"));
7499
Method mA = Helper.NeverCall.class.getDeclaredMethod("a");
75100
Method mB = Helper.NeverCall.class.getDeclaredMethod("b");
76101
mA.setAccessible(true);
@@ -233,7 +258,7 @@ public static List<Executable> getDeclaredMethods(@NonNull Class<?> clazz) {
233258
* @param parameterTypes argument types of the expected method with name {@code methodName}
234259
* @return the found method
235260
* @throws NoSuchMethodException when no method matches the given parameters
236-
* @see Class#getDeclaredMethod(String, Class[])
261+
* @see Class#getDeclaredMethod(String, Class[])
237262
*/
238263
@NonNull
239264
public static Method getDeclaredMethod(@NonNull Class<?> clazz, @NonNull String methodName, @NonNull Class<?>... parameterTypes) throws NoSuchMethodException {

0 commit comments

Comments
 (0)