ElderDrivers / EdXposed

Elder driver Xposed Framework.
https://edxp.meowcat.org/
GNU General Public License v3.0
5.37k stars 621 forks source link

Hooking base Java class in SystemUI #742

Open Mikanoshi opened 3 years ago

Mikanoshi commented 3 years ago

EdXposed 0.4.6.4 I need to hook java.lang.Math.min(int.class,int.class) method, but only inside SystemUI, so hook is in handleLoadPackage(). Hooking does not return any errors, but hook's code is not being executed. Using hookAllMethods() results in all methods being hooked (returns a Set of 4 for int/long/float/double params). Hook for a method with floats is working, but not for ints.

kotori2 commented 3 years ago

Can confirm this on latest Canary.

12-19 21:55:22.074  2133  2133 D EdXposed: LoadedApk#getClassLoader starts: pkg=com.android.systemui, prc=com.android.systemui
12-19 21:55:22.074  2133  2133 D EdXposed: LoadedApk#getClassLoader ends: /system_ext/priv-app/SystemUIGoogle/SystemUIGoogle.apk -> dalvik.system.PathClassLoader[DexPathList[[zip file "/system_ext/priv-app/SystemUIGoogle/SystemUIGoogle.apk"],nativeLibraryDirectories=[/system_ext/priv-app/SystemUIGoogle/lib/arm64, /system_ext/priv-app/SystemUIGoogle/SystemUIGoogle.apk!/lib/arm64-v8a, /system/lib64, /system_ext/lib64, /system/lib64, /system_ext/lib64]]]: pkg=com.android.systemui, prc=com.android.systemui
12-19 21:55:22.074  2133  2133 I EdXposed-Bridge: Injecting into SystemUI...
12-19 21:55:22.074  2133  2133 D EdXposed: hooking public static double java.lang.Math.min(double,double)
12-19 21:55:22.074  2133  2133 D EdXposed: start to generate class for: public static double java.lang.Math.min(double,double)
kotori2 commented 3 years ago

Sorry wrong click

kotori2 commented 3 years ago

It's so weird that I can only reproduce this with SystemUI. It works fine with any other package. Any idea on Java's magic?

elesbb commented 3 years ago

@kotori2 @Mikanoshi

Have either of you looked inside the smali of SystemUI to see where this is called? My guess is you are hooking one where the return value is different than the one being called. Can you post a snippet of the SystemUI method you are trying to change where this min method on the Math class is called from inside SystemUI?

kotori2 commented 3 years ago

It was not even called. It didn’t find any other 3 functions from reflection in initialization stage. Idk if there could be some lazy loading thing in Java.

elesbb notifications@github.com于2020年12月20日 周日05:45写道:

@kotori2 https://github.com/kotori2 @Mikanoshi https://github.com/Mikanoshi

Have either of you looked inside the smali of SystemUI to see where this is called? My guess is you are hooking one where the return value is different than the one being called. Can you post a snippet of the SystemUI method you are trying to change where this min method on the Math class is called from inside SystemUI?

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/ElderDrivers/EdXposed/issues/742#issuecomment-748529583, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEGYNSITPLRSW3S66Z75MLDSVUNHZANCNFSM4VB5ZPXA .

Mikanoshi commented 3 years ago

You don't even need return value type when you hook a method with a known name.

elesbb commented 3 years ago

@kotori2 It didn't even hook anything? But didn't say it wasn't found? I always thought to hook main classes you had to pass a null class loader because those base classes are loaded at boot - not call time.

@Mikanoshi The return value is determined by the parameters being passed to it. That is why I was wondering if you looked at the Smali part of the SystemUI so you can check what parameters are being passed.

Mikanoshi commented 3 years ago

Parameters are ints, so values passed are ints :) To hook Math class you can just do this:

XposedBridge.hookAllMethods(Math.class, "min", new MethodHook() {
    @Override
    protected void before(MethodHookParam param) throws Throwable {
        XposedBridge.log("Math.min: " + param.args[0] + ", " + param.args[1]);
    }
});

I tried findClass("java.lang.Math", null) and findClass("java.lang.Math", lpparam.classLoader) - same result. Also tried hooking after Application.attach(). EdXposed hooks without errors, but does not invoke the hooks.

elesbb commented 3 years ago

@Mikanoshi

Actually, the code snippet you provided theoretically would not be found, there is no method "min" that takes zero arguments.

You would need something like this:

XposedBridge.hookAllMethods(Math.class, "min", Integer.TYPE, Integer.TYPE, new MethodHook() {
    @Override
    protected void before(MethodHookParam param) throws Throwable {
        XposedBridge.log("Math.min: " + param.args[0] + ", " + param.args[1]);
    }
});

That would hook the min method that returns an int type back. However, SystemUI might be using the min(float, float) method or min(double, double) method, etc.

You would have to hook all of them:

XC_MethodHook myHook = new XC_MethodHook() {
    @Override
    proteted void beforeHookedMethod(MethodHookParam param) throws Throwable {
        XposedBridge.log("Hooked: " + param.args[0].getClass().getName() " min method");
    }
}

XposedBridge.hookAllMethods(Math.class, "min", Integer.TYPE, Integer.TYPE, myHook);
XposedBridge.hookAllMethods(Math.class, "min", Float.TYPE, Float.TYPE, myHook);
XposedBridge.hookAllMethods(Math.class, "min", Double.TYPE, Double.TYPE, myHook);
XposedBridge.hookAllMethods(Math.class, "min", Long.TYPE, Long.TYPE, myHook);

Then you can hook all the methods of "min" and see what is getting called.

Mikanoshi commented 3 years ago

No, check the syntax of hookAllMethods() method.

yujincheng08 commented 3 years ago

@elesbb plz read the document carefully.

public static Set<XC_MethodHook.Unhook> hookAllMethods (Class<?> hookClass, String methodName, XC_MethodHook callback)

Hooks all methods with a certain name that were declared in the specified class. Inherited methods and constructors are not considered. For constructors, use hookAllConstructors(Class, XC_MethodHook) instead

elesbb commented 3 years ago

@Mikanoshi @yujincheng08 I completely misread Mikanoshi's comment.. I totally know about hookAllMethods()

However, have you tried it the way I presented? Maybe there is a problem with hookAllMethods()?

Secondly, I think the problem here is that the hook is not loaded fast enough when limiting to "com.android.systemui" package context only. I always thought main java methods had to be hooked at start of zygote or they wouldn't be hooked?

For example, I have a hook that hooks ViewConfigureation.getLongPressTimeout(). If I call this hook on a package only basis, it does nothing. If I call this hook at startup, it works perfectly.

yujincheng08 commented 3 years ago

ur presented hookAllMethods code snippet wont compile. how come u know it?

elesbb commented 3 years ago

ur presented hookAllMethods code snippet wont compile. how come u know it?

Correct. I misread Mikanoshi's post, thought it simply said "hookMethod". I copied and pasted his code ignorant of what was actually typed out. :)

Mikanoshi commented 3 years ago

I tried XposedHelpers.findAndHookMethod() with param types, there is no difference. Hooks are correct, EdXposed is the problem. I cannot move it to zygote because then it will be applied to every single process and it actually makes my system crash :) Even if it was working it would be too much code being executed (I'll also have to add calling package check inside the hook then).

elesbb commented 3 years ago

I tried XposedHelpers.findAndHookMethod() with param types, there is no difference. Hooks are correct, EdXposed is the problem. I cannot move it to zygote because then it will be applied to every single process and it actually makes my system crash :) Even if it was working it would be too much code being executed (I'll also have to add calling package check inside the hook then).

Well, I didn't think hooking base level code was possible on a per-package bias. I never could get that to work. I always had to hook it first thing. And by hook it before zygote, I don't mean in the initZygote method, I am talking about simply not filtering out the packages in the handleLoadPackage method. Something like this:

    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
        XposedBridge.hookAllMethods(Math.class, "min", new MethodHook() {
        @Override
        protected void before(MethodHookParam param) throws Throwable {
        XposedBridge.log("Math.min: " + param.args[0] + ", " + param.args[1]);
        }
        });
    }

Now it is hooked regardless of package loaded. I believe the actual package name is "android". That is the only way I have experience hooking such a method in the barebones of java/android.

I agree, you would have to do some sort of filtering in you before method to only hook what you want. That is why I was wondering if you could post a snippet of smali code you are trying to change from the SystemUI apk.

Mikanoshi commented 3 years ago

Package name "android" is for system_server process where all the service classes are, it's a separate process that doesn't fork into anything, so it won't work for hooking SystemUI. When you don't check loadPackageParam.packageName you are hooking all the apps, don't see how it's different from if (loadPackageParam.packageName.equals("com.android.systemui")).

How can a smali snippet help? It just uses Math.min(int.class,int.class) like any app would. And I don't read smali, I decompile it to java :) com.android.systemui.statusbar.phone.NotificationIconContainer

public void calculateIconTranslations() {
    ...
    int childCount = getChildCount();
    int min = Math.min(childCount, 3);
    ...
}

I need to replace 3, it's inside a huge method and rewriting it would be a compatibility nightmare as my module must support Android 7-11 and multiple MIUI versions. I wanted to hook Math.min() inside SystemUI and then check stack trace for calculateIconTranslations.

elesbb commented 3 years ago

@Mikanoshi

If I try to hook this method, it completely halts booting. Gives an android runtime crash

12-19 22:06:21.785: E/AndroidRuntime(14523): Process: com.elesbb.s10xposed, PID: 14523
12-19 22:06:21.785: E/AndroidRuntime(14523): java.lang.ArrayIndexOutOfBoundsException: src.length=3334 srcPos=0 dst.length=2220 dstPos=0 length=3334
12-19 22:06:21.785: E/AndroidRuntime(14523):    at java.lang.System.arraycopy(Native Method)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at java.util.Arrays.copyOfRange(Arrays.java:3590)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at java.lang.StringBuffer.toString(StringBuffer.java:669)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at java.io.StringWriter.toString(StringWriter.java:210)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at android.util.Log.getStackTraceString(Log.java:486)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at de.robv.android.xposed.XposedBridge.log(XposedBridge.java:173)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at com.swift.sandhook.xposedcompat.hookstub.HookStubManager.hookBridge(HookStubManager.java:391)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at SandHookerNew_35f4vrpdo2vmlbkhbqk0r22p8o.hook(Unknown Source:46)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at android.app.LoadedApk.getResources(LoadedApk.java:1248)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at android.app.ContextImpl.createAppContext(ContextImpl.java:2618)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at android.app.ContextImpl.createAppContext(ContextImpl.java:2610)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7027)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at java.lang.reflect.Method.invoke(Native Method)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at com.swift.sandhook.SandHook.callOriginMethod(SandHook.java:185)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at com.swift.sandhook.xposedcompat.hookstub.HookStubManager.hookBridge(HookStubManager.java:376)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at SandHookerNew_5sm3dthec8858ee0to4kj3c1ge.hook(Unknown Source:51)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at android.app.ActivityThread.access$1600(ActivityThread.java:274)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2102)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at android.os.Handler.dispatchMessage(Handler.java:107)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at android.os.Looper.loop(Looper.java:237)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at android.app.ActivityThread.main(ActivityThread.java:8167)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at java.lang.reflect.Method.invoke(Native Method)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
12-19 22:06:21.785: E/AndroidRuntime(14523):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
12-19 22:06:21.786: E/AndroidRuntime(14523): Error reporting crash
12-19 22:06:21.786: E/AndroidRuntime(14523): java.lang.ArrayIndexOutOfBoundsException: src.length=1762 srcPos=0 dst.length=1674 dstPos=0 length=1762
12-19 22:06:21.786: E/AndroidRuntime(14523):    at java.lang.System.arraycopy(Native Method)
12-19 22:06:21.786: E/AndroidRuntime(14523):    at java.util.Arrays.copyOfRange(Arrays.java:3590)
12-19 22:06:21.786: E/AndroidRuntime(14523):    at java.lang.StringBuffer.toString(StringBuffer.java:669)
12-19 22:06:21.786: E/AndroidRuntime(14523):    at java.io.StringWriter.toString(StringWriter.java:210)
12-19 22:06:21.786: E/AndroidRuntime(14523):    at android.app.ApplicationErrorReport$CrashInfo.<init>(ApplicationErrorReport.java:404)
12-19 22:06:21.786: E/AndroidRuntime(14523):    at android.app.ApplicationErrorReport$ParcelableCrashInfo.<init>(ApplicationErrorReport.java:532)
12-19 22:06:21.786: E/AndroidRuntime(14523):    at com.android.internal.os.RuntimeInit$KillApplicationHandler.uncaughtException(RuntimeInit.java:150)
12-19 22:06:21.786: E/AndroidRuntime(14523):    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1073)
12-19 22:06:21.786: E/AndroidRuntime(14523):    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1068)
12-19 22:06:21.786: E/AndroidRuntime(14523):    at java.lang.Thread.dispatchUncaughtException(Thread.java:2187)

I have no idea why? I don't change anything. All I do is write a log? I am trying to change it in my own app. Like when I make that call

Mikanoshi commented 3 years ago

Yep, that's what happens. Either in initZygote or in handleLoadPackage without filters. Some packages don't like it, apps like Camera and Google Play Services start to crash for me. It's ExceptionInInitializerError, if I wrap hook in another hook of Application.attach() then it's this ArrayIndexOutOfBoundsException. Just don't do it :)

elesbb commented 3 years ago

Yep, that's what happens. Either in initZygote or in handleLoadPackage without filters. Some packages don't like it, apps like Camera and Google Play Services start to crash for me. It's ExceptionInInitializerError, if I wrap hook in another hook of Application.attach() then it's this ArrayIndexOutOfBoundsException. Just don't do it :)

Even if I filtered to just my application it crashes and prevents my application from loading. Even if the hooked method has nothing in it it crashes xD

This is surely bizarre.

I thought you were having troubles with it not hooking. Like, no errors or anything, it just didn't hook.

However,

in your app, can't you just replace getChildCount() with your own value? I'm missing a lot of context so i'm just wingin it here xD

I wonder if that is a viewgroup you are hooking.

Also, how you decompile to java?

Mikanoshi commented 3 years ago

Filtering to com.android.systemui has no errors or crashes. getChildCount() is used further in the code to iterate through children. I cannot do anything post factum, this method changes children positions based on tons of conditions. Decompile with jadx.

kotori2 commented 3 years ago

It didn't even hook anything? But didn't say it wasn't found?

It hooked 1 out of 4 method with same name.

If I try to hook this method, it completely halts booting. Gives an android runtime crash

Sound like crashing when figuring out stack trace.

kotori2 commented 3 years ago

Well I smh can't reproduce it anymore. From the log it obviously hooked all 4 functions.

12-20 14:27:47.008  1275  1335 I ActivityManager: Start proc 2465:com.android.systemui/u0a211 for added application com.android.systemui
...
12-20 14:27:47.567  2465  2465 D EdXposed: hooking public static double java.lang.Math.min(double,double)
12-20 14:27:47.567  2465  2465 D EdXposed: start to generate class for: public static double java.lang.Math.min(double,double)
12-20 14:27:47.581  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7c8e6f4408
12-20 14:27:47.581  2465  2465 I EdXposed: setNonCompilable: change access flags from 0x10080009 to 0x12080009
12-20 14:27:47.581  2465  2465 D EdXposed: target=public static double java.lang.Math.min(double,double), hook=public static double EdHooker_java.lang.Math.hook(double,double), backup=public static double EdHooker_java.lang.Math.backup(double,double)
12-20 14:27:47.581  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7088bb98
12-20 14:27:47.581  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7c8e6f4430
12-20 14:27:47.581  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7c8e6f43e0
12-20 14:27:47.581  2465  2465 I EdXposed: target method is at 0x7088bb98, hook method is at 0x7c8e6f4430, backup method is at 0x7c8e6f43e0
12-20 14:27:47.581  2465  2465 I EdXposed: setNonCompilable: change access flags from 0x93080009 to 0x93080009
12-20 14:27:47.581  2465  2465 I EdXposed: setNonCompilable: change access flags from 0x10080009 to 0x12080009
12-20 14:27:47.581  2465  2465 I EdXposed: replace entry point from 0x7ca9cbcfa0 to 0x7f3acf1008
12-20 14:27:47.581  2465  2465 I EdXposed: replace entry point from 0x70b770b0 to 0x7f3acaa008
12-20 14:27:47.581  2465  2465 I EdXposed: hook and backup done
12-20 14:27:47.581  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7088bb98
12-20 14:27:47.581  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7c8e6f43e0
12-20 14:27:47.581  2465  2465 D EdXposed: hooking public static float java.lang.Math.min(float,float)
12-20 14:27:47.581  2465  2465 D EdXposed: start to generate class for: public static float java.lang.Math.min(float,float)
12-20 14:27:47.594  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7c8e63a408
12-20 14:27:47.594  2465  2465 I EdXposed: setNonCompilable: change access flags from 0x10080009 to 0x12080009
12-20 14:27:47.594  2465  2465 D EdXposed: target=public static float java.lang.Math.min(float,float), hook=public static float EdHooker_java.lang.Math.hook(float,float), backup=public static float EdHooker_java.lang.Math.backup(float,float)
12-20 14:27:47.594  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7088bbc0
12-20 14:27:47.594  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7c8e63a430
12-20 14:27:47.594  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7c8e63a3e0
12-20 14:27:47.594  2465  2465 I EdXposed: target method is at 0x7088bbc0, hook method is at 0x7c8e63a430, backup method is at 0x7c8e63a3e0
12-20 14:27:47.594  2465  2465 I EdXposed: setNonCompilable: change access flags from 0x93880009 to 0x93880009
12-20 14:27:47.594  2465  2465 I EdXposed: setNonCompilable: change access flags from 0x10080009 to 0x12080009
12-20 14:27:47.594  2465  2465 I EdXposed: replace entry point from 0x7ca9cbcfa0 to 0x7f3aafc008
12-20 14:27:47.594  2465  2465 I EdXposed: replace entry point from 0x70b770d0 to 0x7f3aa7d008
12-20 14:27:47.594  2465  2465 I EdXposed: hook and backup done
12-20 14:27:47.594  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7088bbc0
12-20 14:27:47.594  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7c8e63a3e0
12-20 14:27:47.595  2465  2465 D EdXposed: hooking public static int java.lang.Math.min(int,int)
12-20 14:27:47.595  2465  2465 D EdXposed: start to generate class for: public static int java.lang.Math.min(int,int)
12-20 14:27:47.606  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7c8e53d408
12-20 14:27:47.606  2465  2465 I EdXposed: setNonCompilable: change access flags from 0x10080009 to 0x12080009
12-20 14:27:47.606  2465  2465 D EdXposed: target=public static int java.lang.Math.min(int,int), hook=public static int EdHooker_java.lang.Math.hook(int,int), backup=public static int EdHooker_java.lang.Math.backup(int,int)
12-20 14:27:47.606  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7088bbe8
12-20 14:27:47.606  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7c8e53d430
12-20 14:27:47.606  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7c8e53d3e0
12-20 14:27:47.606  2465  2465 I EdXposed: target method is at 0x7088bbe8, hook method is at 0x7c8e53d430, backup method is at 0x7c8e53d3e0
12-20 14:27:47.606  2465  2465 I EdXposed: setNonCompilable: change access flags from 0x94880009 to 0x96880009
12-20 14:27:47.606  2465  2465 I EdXposed: setNonCompilable: change access flags from 0x10080009 to 0x12080009
12-20 14:27:47.607  2465  2465 I EdXposed: replace entry point from 0x7ca9cbcfa0 to 0x7f3a8c0008
12-20 14:27:47.607  2465  2465 I EdXposed: replace entry point from 0x70b770f0 to 0x7f3a8bf008
12-20 14:27:47.607  2465  2465 I EdXposed: hook and backup done
12-20 14:27:47.607  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7088bbe8
12-20 14:27:47.607  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7c8e53d3e0
12-20 14:27:47.607  2465  2465 D EdXposed: hooking public static long java.lang.Math.min(long,long)
12-20 14:27:47.607  2465  2465 D EdXposed: start to generate class for: public static long java.lang.Math.min(long,long)
12-20 14:27:47.617  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7c8e516408
12-20 14:27:47.617  2465  2465 I EdXposed: setNonCompilable: change access flags from 0x10080009 to 0x12080009
12-20 14:27:47.617  2465  2465 D EdXposed: target=public static long java.lang.Math.min(long,long), hook=public static long EdHooker_java.lang.Math.hook(long,long), backup=public static long EdHooker_java.lang.Math.backup(long,long)
12-20 14:27:47.617  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7088bc10
12-20 14:27:47.617  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7c8e516430
12-20 14:27:47.617  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7c8e5163e0
12-20 14:27:47.617  2465  2465 I EdXposed: target method is at 0x7088bc10, hook method is at 0x7c8e516430, backup method is at 0x7c8e5163e0
12-20 14:27:47.617  2465  2465 I EdXposed: setNonCompilable: change access flags from 0x94080009 to 0x96080009
12-20 14:27:47.617  2465  2465 I EdXposed: setNonCompilable: change access flags from 0x10080009 to 0x12080009
12-20 14:27:47.617  2465  2465 I EdXposed: replace entry point from 0x7ca9cbcfa0 to 0x7f3a5a7008
12-20 14:27:47.617  2465  2465 I EdXposed: replace entry point from 0x70b77120 to 0x7f3a5a6008
12-20 14:27:47.617  2465  2465 I EdXposed: hook and backup done
12-20 14:27:47.617  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7088bc10
12-20 14:27:47.617  2465  2465 I EdXposed: HookMain: getArtMethod: 0x7c8e5163e0

My code

public class HookMain implements IXposedHookLoadPackage {
    public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
        if (lpparam.packageName.equals("com.android.systemui")) {
            XposedBridge.log("Injecting into SystemUI...");

            Class<?> at = Class.forName("java.lang.Math", false, lpparam.classLoader);
            for (Member method : at.getDeclaredMethods()) XposedBridge.log(method.getName());

            XposedBridge.hookAllMethods(at, "min", new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) {
                    XposedBridge.log("java.lang.Math.min: beforeHookedMethod");
                    if (param.args[0].getClass() == Integer.class){
                        XposedBridge.log("Type is int");
                    } else if (param.args[0].getClass() == Float.class) {
                        XposedBridge.log("Type is float");
                    } else {
                        XposedBridge.log("Type is unknown");
                    }
                }
            });
        }
    }
}
Mikanoshi commented 3 years ago

Still only float forks for me. How to enable these debug logs?

kotori2 commented 3 years ago

@Mikanoshi

Still only float forks for me.

Try canary build? We are pushing them to Alpha very soon.

How to enable these debug logs?

They mostly broken on v0.4.x and they were fixed in v0.5.x

Mikanoshi commented 3 years ago

Currently only interested in 0.4, module is not working with 0.5 anyway.

MlgmXyysd commented 3 years ago

0.4.x is no longer maintained

elesbb commented 3 years ago

@kotori2

How does this work: Class<?> at = Class.forName("java.lang.Math", false, lpparam.classLoader);

It uses the class loader that belongs to com.android.systemui, and the java.lang.Math class belongs to package java.lang

How is it still able to find that class from a different package class loader?

kotori2 commented 3 years ago

It uses the class loader that belongs to com.android.systemui, and the java.lang.Math class belongs to package java.lang

class loader that belongs to com.android.systemui loaded package java.lang. Of course you shouldn't hook the module's class loader, or it just meaningless

Mikanoshi commented 3 years ago

The resulting Class<?> has the same classloader as Math.class.getClassLoader(). @kotori2 Was it the trick with disabled class initialization that did it? or it just magically started working on 0.5?

kotori2 commented 3 years ago

@Mikanoshi TBH I have no idea, I just grabbed those code on internet and it works

Mikanoshi commented 3 years ago
Class<?> at = Class.forName("java.lang.Math", false, lpparam.classLoader);
for (Member method : at.getDeclaredMethods()) XposedBridge.log(method.getName());

~This code only lists 2 "min" methods for me, getMethods() instead of getDeclaredMethods() too.~ Looks like a logging problem, it still finds 4.

yujincheng08 commented 3 years ago

Good, problem solved.

Mikanoshi commented 3 years ago

@yujincheng08 LOL, what? Nothing is solved. When XposedBridge.log() is called with the same text twice it prints only 1 line in the log, that's another issue, not a solution. Hook is still not working.

kotori2 commented 3 years ago

When XposedBridge.log() is called with the same text twice it prints only 1 line in the log, that's another issue

Android will hide them and you will see a chatty thing in log

Mikanoshi commented 3 years ago

Yeah, so they don't go into Xposed log, that's why I was seeing only 2 out of 4 methods.

Mikanoshi commented 3 years ago

Please reopen this, it's not working on 0.5.1.3 (4653)

kotori2 commented 3 years ago

Please reopen this, it's not working on 0.5.1.3 (4653)

Try debug build and attach logs pls. Most probably because they got inline optimized.

Mikanoshi commented 3 years ago

I can see 3 Math.min() in log except the one (float,float) that is actually working. log.txt

tiann commented 3 years ago

http://aospxref.com/android-10.0.0_r47/xref/art/runtime/interpreter/interpreter_intrinsics.cc#470 http://aospxref.com/android-10.0.0_r47/xref/art/runtime/interpreter/interpreter_intrinsics.cc#472

XspeedPL commented 3 years ago

Hooking native methods from Java code is never a fun practice. By unoptimizing it you might cause more issues than you'd expect.

I'd suggest either hooking one level higher, or if it's a huge method bytecode injection might be a better bet.

kotori2 commented 3 years ago

By unoptimizing it you might cause more issues than you'd expect.

deoptimize is actually meant to kill inline-compiled methods. That always happens in EdXposed Manager so lots of ppl got yellow warning.

kotori2 commented 3 years ago

http://aospxref.com/android-10.0.0_r47/xref/art/runtime/interpreter/interpreter_intrinsics.cc#470 http://aospxref.com/android-10.0.0_r47/xref/art/runtime/interpreter/interpreter_intrinsics.cc#472

@tiann Thanks but I kinda not understand how this work here. From the references it seems this branch will only be used when the callee function is being interpretered and the target methods are implemented (aka INTRINSIC_CASE) So the missing functions should be MathMinLongLong and MathMinIntInt because they are not being interpretered. Also MathMinFloatFloat is actually implemented here. Also I tried to search keywords in Epic but no luck. Is there any tech blog/article that I could read about this issue?

tiann commented 3 years ago

@kotori2 Both interpreter and compiler implement the intrinsics, the compiler is more powerful but interpreter only support some limited method. In theory, if the min(float, float) run in AOT mode, it can not be hooked too. You can try to disable the intrinsics.

There is little article/slides about ART intrinsics optimization, you can only read the FUCKING source code :(

If interested, this book is the only one telling some optimization details about ART: https://item.jd.com/12510921.html

kotori2 commented 3 years ago

@tiann I still think the unimplemented compile time intrinsics should not be blamed. From the conversation above, the point is even with reflection, we can't find the target methods. So runtime intrinsics are missing. I check the code and the runtime intrinsics are initialized as soon as art::Runtime starts. Also they might successfully hook 1 or 3 methods which doesn't exactly match with the amount of compile time intrinsics. So my guess is, ART inline compiled all Math.min(float, float) and tells ART not to initialize those methods for speed. But I didn't found any supporting code anyway.

@Mikanoshi Could you please try deoptimize SystemUI and see if they start working? Because I can't really reproduce this bug now.

Mikanoshi commented 3 years ago

It executes min(float,float) 3 times and then crashes, so no idea if (int,int) is working. How to fix it with adb shell now? :D

XspeedPL commented 3 years ago

Fix with adb shell? You mean disable the module? :P

Mikanoshi commented 3 years ago

I mean deoptimization

kotori2 commented 3 years ago

I mean deoptimization

cmd package compile --reset com.your.package

Mikanoshi commented 3 years ago

cmd package compile --reset com.your.package

No, my module makes SystemUI crash when it's deoptimized. This fixes it: cmd package compile -m speed com.android.systemui