Letts assume there is a method
public static native boolean doSomething(params...);
which gets called by regular Java code.
Can Xposed hook it?
EDIT: I'm wrong, see rovo's answer.
Yes, native methods can be hooked. However, in case this is for an app's code, it has to be done after System.loadLibrary(), otherwise the latter overwrites the hook. Ideally, the framework should take care of this itself, but it's not straight-forward and the has been vey little need for this.
rovo89 said:
Yes, native methods can be hooked. However, in case this is for an app's code, it has to be done after System.loadLibrary(), otherwise the latter overwrites the hook. Ideally, the framework should take care of this itself, but it's not straight-forward and the has been vey little need for this.
Click to expand...
Click to collapse
I've always assumed this wasn't the case. Just to clarify, Xposed is able to hook native functions, but not (native) C/C++ code/libraries? I've read more than once it can't so I'm a bit confused. Thanks for the correction.
GermainZ said:
Just to clarify, Xposed is able to hook native functions, but not (native) C/C++ code/libraries?
Click to expand...
Click to collapse
Correct. Only JNI functions can be hooked, i.e. those which are declared in and called by Java code.
How to do it "after System.loadLibrary()"?
How you go about hooking such methods? I am trying to hook some API methods, mainly the ones declared in the "Connectivity" class one such example is "isTetheringSupported" however I am struggling to do so as when I hook the method directly, the hook is never executed as I believe it is being called via the java.lang.reflect.Method invoke method, and when I try and hook that method I get the following error "java.lang.NoSuchMethodError: java.lang.reflect.Method#invoke()#exact"
hwhh_1 said:
How you go about hooking such methods? I am trying to hook some API methods, mainly the ones declared in the "Connectivity" class one such example is "isTetheringSupported" however I am struggling to do so as when I hook the method directly, the hook is never executed as I believe it is being called via the java.lang.reflect.Method invoke method, and when I try and hook that method I get the following error "java.lang.NoSuchMethodError: java.lang.reflect.Method#invoke()#exact"
Click to expand...
Click to collapse
Are you talking about EdXposed? If so it should be noted that hook not working for a particular method can also be a result of art compiler optimizations. E.g. if the method is simple and not called from many places, compiler will include body of such method directly into methods that call that method. It's called inlining. So while you can see method at source code level, during runtime it's empty and never called as original body became part of another method. To overcome this you have to find a different strategy, e.g. hook such methods that are less likely to become inlined.
C3C076 said:
Are you talking about EdXposed? If so it should be noted that hook not working for a particular method can also be a result of art compiler optimizations. E.g. if the method is simple and not called from many places, compiler will include body of such method directly into methods that call that method. It's called inlining. So while you can see method at source code level, during runtime it's empty and never called as original body became part of another method. To overcome this you have to find a different strategy, e.g. hook such methods that are less likely to become inlined.
Click to expand...
Click to collapse
In order to see if it inlined, there is a setting in EDXPOSED to deoptimize boot image.
Related
This thread is intended for module developers. Make sure you follow it (i.e. subscribe) to be informed about any API changes and additions.
I will announce changes before the release if they might make existing modules incompatible.
If you're interested in more details, you can follow the GitHub repositories:
https://github.com/rovo89/XposedBridge/commits/master
https://github.com/rovo89/Xposed/commits/master
https://github.com/rovo89/XposedInstaller/commits/master
Here you can also download the API jar file that you need to reference from your project. Make sure you read the development tutorial to understand how it works. Especially make sure that the classes are not included in your APK, but only referenced.
Note that I will only post the latest API version here to drive the adoption of updates.
This is on pretty short notice, but I have removed the method AndroidAppHelper.getActivityThread_mPackages(): https://github.com/rovo89/XposedBridge/commit/892ba9195da5516dd79f175ac95be2b313c8f8ca
It had been used internally some time ago. I scanned the modules which have been uploaded to the repository and didn't find any which uses this method.
Apart from that, I'm planning to make Xposed for command line tools (e.g. am and pm), implemented via IXposedHookCmdInit/initCmdApp(), optional and disabled by default. It is currently used only by App Settings (but unnecessary and therefore removed in the next version) and NFC LockScreenOff Enabler (I will contact the authors).
As the low usage shows, this feature is hardly needed, so there is no need to load Xposed every time such an app is started. It also avoids the additional log entries, which could be confusing for some users. Actually it is so rarely used that I might not even offer a setting in the UI for it, just a command file for experts. I will not remove it completely as it's useful for low-level framework development (I can quickly test whether my native code changes work without having to reboot).
Xposed 2.6 will bring support for replacing dimensions defined in code (instead of merely forwarding to your own resources): https://github.com/rovo89/XposedBridge/commit/48227c5b0a7ae3e3f81d76ad3bbaf017dc95614c
The new API will be published once that version is out. Until then, it would still be possible to make adjustments of the API. If you think anything should be changed, please let me know as soon as possible.
Ok devs, 2.6 beta1 is out, and so is the new API (version 52).
Here are the relevant XposedBridge changes to version 42 (internal changes/optimizations are not listed):
The resources API can be disabled via a debug setting in the UI. If your module implements IXposedHookInitPackageResources, it will not be loaded because it likely depends on this API. You can also check (but don't change) the status via XposedBridge.disableResources if you use the API in other ways.
Hooking abstract methods (including methods declared in interfaces) will throw an IllegalArgumentException now. The callback was never executed for them anyway. This change avoids debugging effort on your side because you will notice it immediately.
It's now possible to create a DimensionReplacement object and use it to replace "dimen" resources with values calculated at runtime. Previously it was only possible to forward such resources to your module. Example in the commit message: https://github.com/rovo89/XposedBridge/commit/48227c5b0a7ae3e3f81d76ad3bbaf017dc95614c
Removed AndroidAppHelper.createResourcesKey() methods and AndroidAppHelper.getActivityThread_mPackages() - weren't used by any module in the repository.
Fix delayed configuration update for forwarded resources. That's only of interest if your replacement resource contains variants for different qualifiers that might change at runtime (e.g. drawable-land/drawable-port). https://github.com/rovo89/XposedBridge/commit/1c81954e295cdda191cf8a1cf33d21d7c5ea334d
New findConstructorExact() / findAndHookConstructor() methods, similar to the one for methods: https://github.com/rovo89/XposedBridge/commit/a233fa0bc9499eadbe2efc0b49fc3f4a46264614
IXposedHookCmdInit is deprecated now, initCmdApps() won't be called anymore unless an undocumented file has been created. Only two modules used it, both got rid of it without any loss of functionality. This also averts situations like this where logging for tools like am/pm masks errors for Zygote.
Due to some internal changes, the constructor of XResources isn't called anymore (a good thing!), which breaks some features in App Settings (a not so good thing). That's because it relied on updateConfiguration() being called twice, so it could retrieve the package name in the second call and do its changes. A fix for that is on the way, using a new method (getPackageNameDuringConstruction()) added in the last minute, which returns the package name for a very specific situation. You will probably not need it.
Apart from that, there is now an official way to open a certain section in the installer:
Code:
Intent intent = new Intent("de.robv.android.xposed.installer.OPEN_SECTION");
intent.setPackage("de.robv.android.xposed.installer");
intent.putExtra("section", "modules");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Possible values for "section" are currently: install, modules, download, logs, settings, about.
You can for example use this to send the user to the module section if you find out that your module isn't active yet. The best way to find out is something like that:
Code:
// in your Activity, call it to find out the activation status
private static boolean isModuleActive() {
return false;
}
// in handleLoadPackage()
if (lpparam.packageName.equals("your.package.name")) {
// don't use YourActivity.class here
findAndHookMethod("your.package.name.YourActivity", lpparam.classLoader,
"isModuleActive", XC_MethodReplacement.returnConstant(true));
}
Do NOT try to read - or even change - the internal files of the Xposed Installer to get this information or force your module to be activated. Not only can this break anytime, it will also be bad user experience and a security threat if your module is active without explicit selection in the app. You will probably see your app removed from the repository if you break the rules.
If you have any questions or remarks, please let me know. And if you haven't subscribed to this thread yet, make sure to do so now in order to stay up-to-date with new developments.
IllegalAccessException if you use reflection yourself
One additional change in the new version was the removal of a hack that nuked some access checks in Dalvik by making them return "true" every time. After some of the other internal changes, some of the processing that required this hack was no longer necessary. With some more refactoring, I was finally able get rid of this hack. That's good because it caused crashes on some badly built ROMs (incorrect smali hacks), but also in some rare cases in normal apps: https://github.com/rovo89/XposedInstaller/issues/89
However, some modules relied on the deactivation of these access checks. Now they get IllegalAccessExceptions when trying to access e.g. private fields or methods.
Does this mean that Xposed used to cause security issues on the whole system? After all, it meant that any app could access things that they couldn't access otherwise, right? So it destroyed Java's security system!
The answer is: No, that wasn't a security issue! The Java access check system is actually optional. When you get a field/method/class via reflection, you just need to call setAccessible(true) on it to disable the access check. Example in XPrivacy: https://github.com/M66B/XPrivacy/co...430849f#diff-a350382a0ec1158ad9769d07bd754a63
Note that this is only needed if you use reflection yourself, e.g. with getDeclaredMethod() / getDeclaredField(). The methods in XposedHelpers call setAccessible() on the result before returning it to you.
2.6 final comes with XposedBridge v54.
The only changes relevant for developers are the addition of XSharedPreferences.hasFileChanged() and XSharedPreferences.getFile(), and a fix for replaced animation/xml resources. If you're using the latter and want to avoid that someone with the buggy version 2.6 beta1 runs into issues with your module, consider bumping the minimum required Xposed version to 54.
In Lollipop, there were a few architectural changes in Android. I hinted one of them in the Q&A:
The most significant one is that the code for system services has been moved to a separate file. For most of the affected modules, this can be solved by a little refactoring (moving code to a different place).
Click to expand...
Click to collapse
In detail, this means: If you want to hook a system service like PackageManagerService, you can no longer do that in initZygote(). Instead, move your code to handleLoadPackage() and check for dummy package "android". Make sure you use lpparam.classLoaders when looking for classes and hooking methods. This way has worked in older Android versions as well, so you don't lose backwards-compatiblity.
I'll just repeat here what I wrote in the official announcement thread, as it'll be helpful for all module developers:
rovo89 said:
After a long time with mainly bug fixes, version 81 focuses on improvements for developers:
There is a proper API now. Previously, I basically published the sources of XposedBridge.jar, which included many internal classes/methods that modules shouldn't use. Hiding them makes it easier to find the correct methods to use and also makes it easier for me to change implementation details.
The API is published on Bintray/JCenter, so it's easy to use, especially with Gradle/Android Studio. Full explanations here: https://github.com/rovo89/XposedBridge/wiki/Using-the-Xposed-Framework-API
100% of the API are documented with Javadoc now: http://api.xposed.info/
Apart from that, downloads have moved to http://dl-xda.xposed.info/framework/ and are GPG-signed now. You can verify them against this key (fingerprint: 0DC8 2B3E B1C4 6D48 33B4 C434 E82F 0871 7235 F333). That's actually the master key, the files are signed with subkey 852109AA.
There are no real changes for end-users in this release, nevertheless I would recommend that at least developers test their modules with it.
Click to expand...
Click to collapse
I'd like to hook the query() method in ContentProvider in order to get to know which applications are accessing the personal information(e.g: contacts, sms) stored in the device. By reading the tutorial, we know that we can hook methods in app packages. However, what can we do when the methods we want to hook are in those system components? Any suggestion is appreciated.
x11911778 said:
I'd like to hook the query() method in ContentProvider in order to get to know which applications are accessing the personal information(e.g: contacts, sms) stored in the device. By reading the tutorial, we know that we can hook methods in app packages. However, what can we do when the methods we want to hook are in those system components? Any suggestion is appreciated.
Click to expand...
Click to collapse
Well first off, you can't hook ContentProvider.query() because it's an abstract method (at least one of the two variants). So you would have to hook the subclasses that provide an implementation for this method.
You would also need to clarify what you mean with "system components". I think some of these providers are implemented in system apps, so you would hook them like any other app. Others might be part of the system process (system_server), which also hosts all the system services like package manager etc. Simply use the special package name "android" for these, otherwise handle it like a normal app. And then there might be cases where you want to hook a Android framework method on the whole system. You would do that in initZygote().
In all cases, you would first have do identify a good place to hook into, then find out when to place the hook (as described above) and then use findAndHookMethod().
rovo89 said:
Well first off, you can't hook ContentProvider.query() because it's an abstract method (at least one of the two variants). So you would have to hook the subclasses that provide an implementation for this method.
You would also need to clarify what you mean with "system components". I think some of these providers are implemented in system apps, so you would hook them like any other app. Others might be part of the system process (system_server), which also hosts all the system services like package manager etc. Simply use the special package name "android" for these, otherwise handle it like a normal app. And then there might be cases where you want to hook a Android framework method on the whole system. You would do that in initZygote().
In all cases, you would first have do identify a good place to hook into, then find out when to place the hook (as described above) and then use findAndHookMethod().
Click to expand...
Click to collapse
Thanks a lot, that really helps~
Problem
would you mind give me a example (like a code) about how to hook the query() method? I really confused about that. Thanks a lot!!!!
I've been playing with Xposed for a little bit as it's been fun to explore.
As a test, I wanted to write an app that would hook into SMS methods, and change the content of the text.
I managed to do this quite easily with the SMS app I use, as the package name was obviously easy to find, and there weren't a great deal of classes to check.
What I noticed when doing this was that the method I was hooking was little more than a wrapper for a call to an Android library function, namely
Code:
android.telephony.SmsManager.sendSingleSMS()
And I got interested in just hooking that method directly.
The problem is that while I could readily find the source code for SmsManager and its method sendSingleSMS, by downloading Android source code, I couldn't locate the actual package containing them.
I thought this would be as simple as
Code:
if (!lpparam.packageName.equals("android.telephony.SmsManager"))
Or
Code:
if (!lpparam.packageName.equals("android.telephony"))
But these did not work, and even
Code:
if (!lpparam.packageName.contains("tele"))
Fails to find any results.
So in essence, how best can I go about hooking android.telephony.SmsManager.sendSingleSMS()?
The package is android. I'd suggest using initZygote instead of handleLoadPackage for hooking that, though,
GermainZ said:
The package is android. I'd suggest using initZygote instead of handleLoadPackage for hooking that, though,
Click to expand...
Click to collapse
Ah, right I see, that seems obvious now. Thanks
same question about android.os.UserHandle
I'd like to hook UserHandle.getUid(int uid);
to trick system to think my apps uid is system...
but I can't seen to understand what is the package for UserHandle
10X
Here's what I think XPosed does:
1. Before zygote_init, hook all apis and insert xposed_before_xxx and xposed_after_xxx method (where xxx is the name of the api).
2. Load modules. Load hook class, realize it and keep it in memory of zygote. For each injecting method, add it to the private list of xposed_before/after_xxx.
3. When an new app loads (forks from zygote), it also forked the hook class and the hooked method.
4. When an app calls xxx, it actually runs xposed_before_xxx first, and the latter calls every inject method in its private list. Then the original api is called. Then xposed_after_xxx is called, and deals with itself's list.
So for each app, hook class is individual after forking from zygote. So, static members are not shared. Cause each hook class has only one instance in an app, static members act the same as non-static members. Am I right?
And by the way, how does a xposed module to communicate between processes? I've seen a post realizing its own rpc by getting context and creating a service. Any simpler ways for just single direction transferring? Currently I'm using XSharedPreference and SharedPreference, but then then the hook method can't write back anything (such as logging). Any ideas to solve this?
Thanks for reading my long & poor English...
the problem is, i use OP5T, and none of any 8.0/8.1 stock custom rom does support 18:9 scaling feature like in OOS, this feature named as "Full Screen Apps" under app category.
after a few googling, i came up with these method:
1.) add/inject/force this into manifest file of every installed app. or maybe doing some workaround with the packagemanager
<meta-data android:name="android.max_aspect" android:value="2.1" />
Click to expand...
Click to collapse
2.) playing inside AOSP source code, parsePackage method.
frameworks/base/core/java/android/content/pm/PackageParser.java.
Click to expand...
Click to collapse
i know nothing of creating xposed module, but before starting my journey, is it possible to do the first method with xposed?
after seeing module like Xinstaller, App Settings, and XAspect. i thought it may be possible with xposed to approach this.
really appreciate every kind of help, thanks before
I can see at least two solutions there.
The first one, probably the most simple.
1)
Hook parseMetaData method to add
android.max_aspect to returned bundle in after hook (if doesn't already exist)
2)
Hook setMaxAspectRatio
Get mAppMetaData of passed Package (owner.mAppMetaData) in before hook and add android.max_aspect to it (if doesn't already exist)
Edit: Apart from <meta-data> app dev can also specify aspect ratio within <Activity> element in the manifest.
This has higher priority over <meta-data> so the best solution would be to hook setMaxAspectRatio of Activity class and modify maxAspectRatio parameter to desired value in before hook.