[Q] Creating a class which extends an abstract class defined in the target apk - Xposed General

I used dex2jar on the apk I am hooking and made it an external jar in eclipse and all my references to classes in it get resolved in eclipse and it doesn't complain. But the code in my module is failing. Specifically, I'm trying to create a class which extends an abstract class in the original apk. When I try to do new MyClass(); the logcat shows:
Unable to resolve superclass
Is there any way to make it work the way I have it, or is there some other way that I need to instantiate my own instance of an abstract class?

If you just instantiate a class, I think Java tries to resolve it using the calling class's classloader. That classloader only knows the classes in your APK, and otherwise falls back to the boot classloader.
The only chance I see is to put your subclass into a separate JAR, then during handleLoadPackage() create a new PathClassLoader and use lpparam.classLoader as parent. Then I think you should be able to find and instantiate your class via reflection.

rovo89 said:
If you just instantiate a class, I think Java tries to resolve it using the calling class's classloader. That classloader only knows the classes in your APK, and otherwise falls back to the boot classloader.
The only chance I see is to put your subclass into a separate JAR, then during handleLoadPackage() create a new PathClassLoader and use lpparam.classLoader as parent. Then I think you should be able to find and instantiate your class via reflection.
Click to expand...
Click to collapse
Thanks for the tip on using the class loader. I managed to get it working without a jar:
Code:
String dexPath = (String)XposedHelpers.getObjectField(getClass().getClassLoader(), "originalPath");
PathClassLoader combinedClassLoader = new PathClassLoader(dexPath, lpparam.classLoader);
Class<?> c = combinedClassLoader.loadClass("MY.CLASS");
EDIT: So it seems I'm able to do c.newInstance() directly in handleLoadPackage, but if I am inside of a replaceHookedMethod I still get the unable to resolve. It's good enough for what I need, because I can create the class in handleLoadPackage just fine.
EDIt2: Well nevermind, it works in both places. It seems I was trying to cast it, and that is what was causing the error. So when doing this, you have to use generic objects, which I suppose makes sense, since the class loader in that context isn't the combined one.

Thanks for posting the solution! Be careful with getClass(), as it depends on where you use it. You might want to grab your APK's path in initZygote instead.
rbox said:
It seems I was trying to cast it, and that is what was causing the error. So when doing this, you have to use generic objects, which I suppose makes sense, since the class loader in that context isn't the combined one.
Click to expand...
Click to collapse
Yes, you can't cast between objects/classes loaded from different class loaders, even when they are the same class from the same APK. Also, it would probably not work in your situation because the class can't be resolved with your class loader.

Related

[GUIDE] Communication without a context object

Okay guys.
I have seen a lot of posts where people need to trigger an action inside their own app from the xposed class they hooked. Sometimes (quite often) there is no context object to obtain where we could usually send a broadcast or start a service or even maybe an activity from our own apps we wrote.
This guide will allow me to show you how this is possible without the use of a context object. I have used this myself in multiple modules and it works quite wonderfully. I am going to provide as much code as possible without being too specific, that is where you will need your own intuition to figure out some simple things.
Now for the guide
First, obviously, we need to create a new xposed module. That's another thread found here. For the duration of this guide, I am going to assume you have read that. If you have not, stop reading this, and click that link and go read that please Its fun!
Alright, our module has been created, all manifest declarations established all jars imported. Sweet.
Now we are looking at an empty class file that implements the IXPosedHookLoadPackage.
Next, we need to create a class that extends Service. You can either create a nested class inside the Xposed class, or, my personal choice, create an entirely new class inside your package. ***(Don't forget to add this service to your manifest!!!)
Next, we need to create a boot receiver that will start our newly created service when our device gets booted so its already up and running. (Google that if you don't know how to do that.) here is a great read on how to do this.
Now, go back to your service class (either nested or its own file) and create the "onCreate" method. (If not done already)
Inside the onCreate method of your service, we will need to create a file inside the apps files directory. You can do this in the constructor as well if you please. I have the code below showing how to create your new file.
Code:
@Override
public void onCreate() {
super.onCreate();
File myCommands = new File(this.getFilesDir(), "commands");
}
Yes its that
Now that we have our file object created, we need to actually create the file as follows:
Code:
if(!myCommands.exists()) { //Make sure the file doesn't already exist first.
try {
myCommands.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
However, there are some things we need to do to allow the xposed hooked method permissions to read them, which are simple and as follows.
Code:
myCommands.setReadable(true, false);
myCommands.setWritable(true, false);
We need to use the method "setReadable" and "setWriteable" to set the files permission. The first boolean argument sets the file writeable or readable, the second boolean argument restricts it to the owner only, which since we used false, means that everyone can read and write to this file.
So, now lets take a look at our entire onCreate method thus far:
Code:
@Override
public void onCreate() {
super.onCreate();
File myCommands = new File(this.getFilesDir(), "commands");
if(!myCommands.exists()) {
try {
myCommands.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
myCommands.setReadable(true, false);
myCommands.setWritable(true, false);
}
Pretty simple. Now, we need to actually do something with this file. This is where the magic begins to happen
After our file is created, we need to create what is called a FileObserver. The following code explains how to do that.
Code:
FileObserver myActionsObserver = new FileObserver(myCommands.getAbsolutePath()) {
@Override
public void onEvent(int event, String path) {
// This is where things are done. Every time you open, write to, close etc a file. This method is executed.
}
};
Now our file observer is created. However, it is doing nothing. As of now, it does not even listen for file changes. I want to further define what to do on a file change first before I start receiving the changes.
The "onEvent(int event, String path)" method is what we will be defining.
The "event" argument determines what type of event was acted upon the file. For a full explanation, click here. The "CONSTANTS" table shows the different types of events acted upon a file. For this guide, I will be using the constant "CLOSE_WRITE".
So inside the onEvent method we should have this:
Code:
@Override
public void onEvent(int event, String path) {
// This is where things are done. Every time you open, write to, close etc a file. This method is executed.
if(event == FileObserver.CLOSE_WRITE) {
//This is where we are notified that something has happened.
//This is where we can communicate from the xposed hooked method to our own app where we can do whatever we need to do :)
}
}
Now we are notified of the "CLOSE_WRITE" action onto our file. The next step would be to read the text file for our actual command. For instance, we need to start up an activity. So, for the instance of this guide, I will use the command "startActivity".
Once our "onEvent" method is executed and we see that its action was CLOSE_WRITE, we are going to read the file for the action. This is simple, I really don't feel like I should/have to go into this, but I will to make the guide full.
Here we are going to read the file, I am using a BufferedReader for this.
Code:
try {
BufferedReader br = new BufferedReader(new FileReader(myCommands));
String action = br.readLine();
br.close();
} catch(Exception e) {
e.printStackTrace();
}
Now we got a string object of the contents of the file to determine the necessary actions to take. Don't forget to change the myCommands file to final
Now that we have all that setup, we can finally start receiving actions for the file. We simply do this by calling the "startWatching" method of FileObserver as follows.
Code:
myActionsObserver.startWatching();
Now, whenever that file is written to, we will get notified of it in our service
So now that our service is setup, we need to setup our xposed hooked method to write to the file.
I am going to make something up that prolly doesn't exist in android source, but its just an example method that I am going to hook
The only thing to note when creating the file is that we need to hard code the file's path.
Code:
@Override
protected void afterHookedMethod(MethodHookParam param) {
boolean status = (Boolean)XposedHelpers.getObjectField(param.thisObject, "status");
if(status) {
File myCommand = new File(Environment.getDataDirectory() + <your package name here>, "commands");
FileWriter fw = new FileWriter(myCommands);
fw.write("startActivity");
fw.close();
}
Now we have written to our file and our service will receive the action.
That about sums it up You can also do the reverse, you can create a FileObserver inside your xposed hooked method, and use your own activity or service to write to it and then have the xposed hooked method do some actions regarding the command being written to the file.
Please hit thanks and donate if I helped you out! Don't hesitate to ask questions either!
Thanks!
need help
Hi I`m using your code and it`s work I seccessed to comunicate between the module and the FileObserver.
But my problem is that I want to activate some class or send a intent to activate some function from the FileObserver and I don`t find a way to do it.
Do you have any solution for me??
Thanks
doronmazor said:
Hi I`m using your code and it`s work I seccessed to comunicate between the module and the FileObserver.
But my problem is that I want to activate some class or send a intent to activate some function from the FileObserver and I don`t find a way to do it.
Do you have any solution for me??
Thanks
Click to expand...
Click to collapse
This method is beyond hackey. TBH, I'd be embarrassed to use it in my code.
If you want to communicate from Xposed to your main app, add a broadcast reciever and talk to it via intent and putextra. Provided you're not passing sensitive data, this works wonderfully.
digitalhigh said:
This method is beyond hackey. TBH, I'd be embarrassed to use it in my code.
If you want to communicate from Xposed to your main app, add a broadcast reciever and talk to it via intent and putextra. Provided you're not passing sensitive data, this works wonderfully.
Click to expand...
Click to collapse
lol
Why would you be embarrassed? This works perfectly when we have no context object in the class/method being hooked. If coded properly, it functions the exact same way as a broadcast receiver. Where is your solution to communicating without a context object? Not exactly sure why you think this method doesn't work...
elesbb said:
lol
Why would you be embarrassed? This works perfectly when we have no context object in the class/method being hooked. If coded properly, it functions the exact same way as a broadcast receiver. Where is your solution to communicating without a context object? Not exactly sure why you think this method doesn't work...
Click to expand...
Click to collapse
Look, not trying to be mean...it's just a very hacky solution. There are other ways to resolve the context of the class/method being hooked, and better ways to communicate between xposed and the apk code besides writing a file to the /data partition and then watching it. Sure, it works, but IMHO, it's...well...hacky.
digitalhigh said:
Look, not trying to be mean...it's just a very hacky solution. There are other ways to resolve the context of the class/method being hooked, and better ways to communicate between xposed and the apk code besides writing a file to the /data partition and then watching it. Sure, it works, but IMHO, it's...well...hacky.
Click to expand...
Click to collapse
I am not taking you as being mean. Not one bit. Just trying to expand my knowledge and better my code. You said there are other ways to resolve the context of the class/method being hooked, what are they? You said there are better ways to communicate between xposed and the apk code other than writing and listening to a file, well what are they? lol. I am asking so I can use them.
I have done ample research when I wrote this guide, and there were no other ways to communicate when you couldn't get a context object. I do know you can call other methods and such using xposed to get objects, but that in itself is also hacky. I really would like to know what other ways there are so I can use them instead of the current method. A lot of "helper" class files have issues where there is no context because its not needed. Say you have a class file labeled "MathHelper" and you want to hook the method "getFirstZero" and in that method the user wrote something simple like this:
Code:
private int firstZero(String address) {
int returnValue = address.indexOf("0");
return returnValue;
}
THIS IS JUST A POOR EXAMPLE.
You have no context object. And the class is huge. You want your app to, i don't know, show a notification and perform some task when the address is equal to some explicit value. There is no way of telling your app what the address is.
So what would you personally do to resolve this aside from simply creating a method inside the xposed class with the proper actions. I'm honestly curious.

[Q] Passing a flag between hooks

Hi,
In my Xposed module, I have two classes with different hooks on different classes.
When hook A (from class X) finishes I want to save a flag that hook B (from class Y) will be able to read and act accordingly.
I tried class with static methods and a singleton class, in both cases, hook B can't see the changes hook A has done.
What is the best way to get this done?
Thanks!

[Q] Overriding non-overrode method of a class

I am hooking a class that extends FrameLayout. The FrameLayout has an override method of "onInterceptTouchEvent" that I would like to hook, however, the custom class that I am hooking never overrides this method. So doing the usual, XposedHelpers.findAndHookMethod() causes "method not found exception". I feel like I have done this before, but can't recall exactly what I did to make it work.
Any help is appreciated!
@GermainZ
You have any idea how to do this?
Tip from MohammadAG: you can override the superclass' method (FrameLayout.onInterceptTouchEvent) and check for the class name of the current instance (to see if it matches the class you want to hook or not).
GermainZ said:
Tip from MohammadAG: you can override the superclass' method (FrameLayout.onInterceptTouchEvent) and check for the class name of the current instance (to see if it matches the class you want to hook or not).
Click to expand...
Click to collapse
Thanks man. I wasn't sure if that would work since the custom class doesn't call super.onInterceptTouchEvent() but I will try it. Thanks again boss!

Hook on method in class that is dynamically loaded.

Hi,
I'm trying to hook on a method that belongs to a class that is dynamically loaded from a .dex file (via DexClassLoader). How can I hook on this. I seen comments before where people say to hook using the DexClassLoader instead of standard class loader we have available to us through Xposed. (http://stackoverflow.com/a/28635776/3899529) How can I do this? I'm finding it hard to find examples online? How do I grab an instance and use this instance for hooking? Does anyone have a small snippet example please?
Thanks.
Did you already find out how/where the class is loaded from the dex file? Can you post that snippet please? I assume the DexClassLoader will be stored somewhere. So you could then hook the method that creates the class loader and after it has been executed, you try to fetch the class loader instance from the place where it was stored and use it to hook the method you actually want to target. Details really depend on the implementation of the app...
Hi, thanks for your reply. I figured it out. Thanks.
I didn't realize we could have nested hooks. (i.e declare hooks within hooks).
As it turns out, it was actually DexFile in this particular case I needed to hook on, not DexClassLoader. But I hooked on "after" DexFile.loadDexFile, and in there placed nested hooks. As DexFile.loadDexFile() uses same class loader as the one the app originally was booted with, the class was now loaded at that stage and could be found. So I could hook using the class loader xposed provided me, after a set point in time to hook this dynamically loaded class .
I guess it would be similar approach if DexClassLoader was used. I would hook on the Constructor(?) of DexClassLoader, capture the class loader instance, and use that instance for then hooking in the dynamically loaded classes.

First try of an xposed module

I've been trying to hook a method for hours and I'm kind of desperate.
The scenario:
I have a browser app which allows to create shortcuts on your homescreen. The only problem is: They are not renamable. So I thought I write a little xposed module to make this possible.
Steps taken:
Create module base and make it loadable into xposed - check.
Make sure method hook is only called from inside the application - check.
Create a simple dialog with edit stuff - check.
Finding and hooking the correct method in correct class - fail.
The method I am trying to hook is "sendBroadcast(Intent)". The original method is abstract and not hookable.
My first try was to hook the method in "android.content.Context" -> abstract.
I read somewhere that you can hook a subclass so I tried "android.content.ContextWrapper". Turns out this just inherits the method from android.content.Context and is still abstract.
Same goes to "android.app.Activity". So I searched for the Implementation of the sendBroadcast function. I found it in "android.app.ContextImpl" but this also turned out to be just the abstract method call from "android.content.Context".
It can't be that hard to find the right class to hook, right?
I didn't want to use the "hookAllMethods" because it seemed a little overkill for such a small change.
This is my last hook try:
Code:
findAndHookMethod(XposedHelpers.findClass("android.app.ContextImpl", lpparam.classLoader), "sendBroadcast", Intent.class, new XC_MethodHook(){
//... stuff here which I think is correct
}
the browser calls sendBroadcast with only one argument, right?
do you get a NoSuchMethodException, or just can't find the broadcast you want in this method?
Sorry for the late answer.
The error I get is: "IllegalArgumentException: abstract methods cannot be hooked"
odd because it's not an abstract. are there more findAndHookMethod calls before this one? are you sure they work?
because the sendBroadcast hook might not have been called at all if an exception was thrown beforehand
you can test it by XposedBridge.log() right before it

Categories

Resources