People have a tendency to install and enable things that they do not fully understand. In this article I will try to explain just what Root and Xposed Bridge is and how dangerous it can be. Don't get me wrong, I love both of these things, but it is important to be careful and not grant just any application these types of rights.
Let's picture a small village. In the middle of this village is a large bank. It is surrounded with a lot of smaller buildings. The bank represents the core Android system while the buildings are all of the Applications. All the people within each building can communicate with one another since they are all within the same building. If a building needs to communicate with another building, it has to send someone across town to the other building. It is then up to the people in that building to decide whether or not they want to let that person inside. While inside, the person can make a request or a delivery. Maybe he wants to borrow some sugar. He then delivers the response (in this case the sugar) back to his building. The same applies for the bank which is surrounded by guards. To make a request for a specific item in the bank, a building will need a permission slip for that item in order to bypass the guard watching it.
One building however has an Xposed Module implemented. In this case it is a specific type of person, I spy if you will. The building can send this person over to the bank and make him act as a guard. The bank and it's other guards will not not sense that anything is wrong. This spy can now move around in any section of the bank without any permission slip. He can steel items, place new items or make changes to the existing once without anyone asking questions. He can also disguise himself as a member of other buildings and walk around those without an invite. This spy is essentially a god amongst men.
In Android it allows applications to provide features not normally available, like changing theme and colors in any part of the system, create security modules that can restrict other applications from gathering specific information and much more. But it also allows application to do things that you might not want it to, like gathering information and uploading it to a server. Since the module can do whatever it wants, there is no way to restrict it.
Root is similar. It is the main built-in Administrator in the Linux kernel (Which Android is built on top of). In this case it acts as the emperor of the village. It is the main authority in the system and no one would dare to tell it no. It can move, do and behave just as it feels like without no one trying to stop it. The most important thing to note here is that Xposed Modules is able to acts as root, even if the device is not rooted. It is also important to note that gaining root via Xposed Bridge will not trigger your normal Root Popup window on rooted devices. So you will not even know that this has happened.
There is no doubt that devices with Xposed Bridge and Root enabled are much more fun. This article is not meant to scare anyone from rooting their devices or install Xposed Bridge on them. It is meant to inform people about the danger of doing so to make them more aware next time they enable an Xposed module or grant root to an application asking for it. Make sure that the application in question can be trusted, which most importantly mean that you should not allow this for Closed Source applications. If the source codes are close, there is no telling what has been implemented into the application.
So the next time you think about enabling an application in Xposed Bridge or grant root to an application, do some research first. Make sure that you can find a link to the source codes, make sure that the developer is contactable, do some searches to make sure that others have not warned about this application.
In any case, do not just blindly enable whatever the application asks for.
Showing posts with label XposedBridge. Show all posts
Showing posts with label XposedBridge. Show all posts
Wednesday, May 27, 2015
Friday, November 8, 2013
Custom System Service using XposedBridge
For those of you who don't know XposedBridge, you should really have a look at it. By enabling you to hook any Class and Method within Android, system classes as well as normal application classes, this is just as powerful a tool as a root shell session. This however operates within the Java VM instead of hacking your way in from a shell.
After working with XposedBridge for awhile, I started stumbling across a few limitations. The Xposed Framework might be able to hook any method in any class, but it can of cause only add a hook before and after execution of the original method. This means that you cannot change anything within a method, but instead either replace it, change the arguments being parsed to it or change the result from it. In most cases this will be enough, however since Android parses a lot of things between multiple processes in JVM and Native code (which you cannot hook), there are circumstances where this will not be enough. For an example, if you decide to add a hook to PhoneWindowManager's interceptKeyBeforeQueueing or interceptKeyBeforeDispatching methods to change the incoming key code or some policy flags, that hook will not be enough. The two original methods will be executed with these new values, but after they have executed, the Native Event Handler will parse the original values to the application dispatchers, and your hook changes will not affect that part. This means that you would also have to add a hook to the KeyEvent's dispatch method. But, since that one will run in different processes than your first hook(s), you cannot share data between them, not even if you add all hooks to one single class instance or use a static class.
In some cases, you can use Broadcasts to send data from one process to another. But the problem with Broadcasts is that you cannot be sure about when the receiver will be invoked or when it is done processing your data. Also, sending a Broadcast or adding a Receiver requires access to a Context, and when working with Xposed you will not always have one of those. The best option in these cases is adding a custom System Service that you can use to share data between processes. The positive thing about System Services, unlike normal Application Services, is that they are available always, from the beginning of System Boot and until the System is shut down. Also they are much easier to connect to. Normally you would not be able to create such a service, but since we are working with XposedBridge, you can actually add whatever you'd like since you can operate as being part of Android.
The first thing that we will need, is an AIDL interface file. You cannot have a System Service without this. In your project, create a new package named android.os and in that package create a new file named ICustomService.aidl that looks like the below example.
android.os.ICustomService.aidl:
We will also need a class in our regular project package that will be used to hook the service into Android. Create a class named CustomServiceHook.java somewhere in your project package.
CustomServiceHook.java:
Since you should already be familiar with XposedBridge, you should already know how to add this hook to be invoked by Xposed during boot.
The CustomService class that we call in our hook above is our System Service Class. The inject() method is a static method from where we will inject the Service into Android so that it can be used by our module. Create a new package named com.android.server and create a new class in that package named CustomService.java.
com.android.server.CustomService.java:
This is our basic classes. Now it's time to extend CustomService.java to actually make it work. All of Android's original services are created and registered from com.android.server.SystemServer.java. However, all of the creation and registration is done from within a Thread. The problem here is that this Thread keeps the System Context as a normal variable, so we have no way to access it outside the Run() method. And since we cannot hook our way into the method but only add a hook before or after, this method and class is of no use to us.
However, the first thing that this method does, is invoke the main() method of com.android.server.am.ActivityManagerService in order to get the System Context. So if we add a hook after that method, the hook will be invoked in the beginning of the SystemServer thread, and we will also have access to the System Context which will be in the result from the main() method that we added our hook to. Let's change our CustomService.java file and add this hook to it.
com.android.server.CustomService.java:
The service will now be created and registered with Android during boot, but we are not quite done yet. At the time this service is created, no other services are available. So if you want to do some initializing, the constructor is not the place to do it. What we need is yet another hook that will be invoked once the system is ready. The ActivityManagerService class also has a good place for this. It has a systemReady() method that is invoked once all of the services has been created and is up and running. Let's add this to our CustomService class.
com.android.server.CustomService.java:
Now you are done. Your new service will now be loaded into Android's ServiceManager during boot via our first hook to the ActivityServiceManager.main() method and it will be initialized once all services is ready via our second hook to ActivityServiceManager.systemReady().
After the initialization, you can access the binder using ServiceManager.getService( name ) just like with any other System Service provided by Android.
All that is left is to implement whatever options you would like this service to provide and start using it in your module.
Example of usage:
After working with XposedBridge for awhile, I started stumbling across a few limitations. The Xposed Framework might be able to hook any method in any class, but it can of cause only add a hook before and after execution of the original method. This means that you cannot change anything within a method, but instead either replace it, change the arguments being parsed to it or change the result from it. In most cases this will be enough, however since Android parses a lot of things between multiple processes in JVM and Native code (which you cannot hook), there are circumstances where this will not be enough. For an example, if you decide to add a hook to PhoneWindowManager's interceptKeyBeforeQueueing or interceptKeyBeforeDispatching methods to change the incoming key code or some policy flags, that hook will not be enough. The two original methods will be executed with these new values, but after they have executed, the Native Event Handler will parse the original values to the application dispatchers, and your hook changes will not affect that part. This means that you would also have to add a hook to the KeyEvent's dispatch method. But, since that one will run in different processes than your first hook(s), you cannot share data between them, not even if you add all hooks to one single class instance or use a static class.
In some cases, you can use Broadcasts to send data from one process to another. But the problem with Broadcasts is that you cannot be sure about when the receiver will be invoked or when it is done processing your data. Also, sending a Broadcast or adding a Receiver requires access to a Context, and when working with Xposed you will not always have one of those. The best option in these cases is adding a custom System Service that you can use to share data between processes. The positive thing about System Services, unlike normal Application Services, is that they are available always, from the beginning of System Boot and until the System is shut down. Also they are much easier to connect to. Normally you would not be able to create such a service, but since we are working with XposedBridge, you can actually add whatever you'd like since you can operate as being part of Android.
The first thing that we will need, is an AIDL interface file. You cannot have a System Service without this. In your project, create a new package named android.os and in that package create a new file named ICustomService.aidl that looks like the below example.
android.os.ICustomService.aidl:
package android.os; /** {@hide} */ interface IXAService { }
We will also need a class in our regular project package that will be used to hook the service into Android. Create a class named CustomServiceHook.java somewhere in your project package.
CustomServiceHook.java:
public final class CustomServiceHook implements IXposedHookZygoteInit { @Override public void initZygote(IXposedHookZygoteInit.StartupParam startupParam) throws Throwable { CustomService.inject(); } }
Since you should already be familiar with XposedBridge, you should already know how to add this hook to be invoked by Xposed during boot.
The CustomService class that we call in our hook above is our System Service Class. The inject() method is a static method from where we will inject the Service into Android so that it can be used by our module. Create a new package named com.android.server and create a new class in that package named CustomService.java.
com.android.server.CustomService.java:
public class CustomService extends ICustomService.Stub { public static void inject() { } }
This is our basic classes. Now it's time to extend CustomService.java to actually make it work. All of Android's original services are created and registered from com.android.server.SystemServer.java. However, all of the creation and registration is done from within a Thread. The problem here is that this Thread keeps the System Context as a normal variable, so we have no way to access it outside the Run() method. And since we cannot hook our way into the method but only add a hook before or after, this method and class is of no use to us.
However, the first thing that this method does, is invoke the main() method of com.android.server.am.ActivityManagerService in order to get the System Context. So if we add a hook after that method, the hook will be invoked in the beginning of the SystemServer thread, and we will also have access to the System Context which will be in the result from the main() method that we added our hook to. Let's change our CustomService.java file and add this hook to it.
com.android.server.CustomService.java:
public class CustomService extends ICustomService.Stub { private Context mContext; private static CustomService oInstance; public static void inject() { final Class ActivityManagerServiceClazz = XposedHelpers.findClass("com.android.server.am.ActivityManagerService", null); XposedBridge.hookAllMethods( ActivityManagerServiceClazz, "main", new XC_MethodHook() { @Override protected final void afterHookedMethod(final MethodHookParam param) { Context context = (Context) param.getResult(); oInstance = new CustomService(context); XposedHelpers.callMethod( XposedTools.findClass("android.os.ServiceManager"), "addService", new Class[]{String.class, IBinder.class}, "custom.service", oInstance ); } } ); } public XAService(Context context) { mContext = context; } }
The service will now be created and registered with Android during boot, but we are not quite done yet. At the time this service is created, no other services are available. So if you want to do some initializing, the constructor is not the place to do it. What we need is yet another hook that will be invoked once the system is ready. The ActivityManagerService class also has a good place for this. It has a systemReady() method that is invoked once all of the services has been created and is up and running. Let's add this to our CustomService class.
com.android.server.CustomService.java:
public class CustomService extends ICustomService.Stub { private Context mContext; private static CustomService oInstance; public static void inject() { final Class ActivityManagerServiceClazz = XposedHelpers.findClass("com.android.server.am.ActivityManagerService", null); XposedBridge.hookAllMethods( ActivityManagerServiceClazz, "main", new XC_MethodHook() { @Override protected final void afterHookedMethod(final MethodHookParam param) { Context context = (Context) param.getResult(); oInstance = new CustomService(context); XposedHelpers.callMethod( XposedTools.findClass("android.os.ServiceManager"), "addService", new Class[]{String.class, IBinder.class}, "custom.service", oInstance ); } } ); XposedBridge.hookAllMethods( ActivityManagerServiceClazz, "systemReady", new XC_MethodHook() { @Override protected final void afterHookedMethod(final MethodHookParam param) { oInstance.systemReady(); } } ); } public XAService(Context context) { mContext = context; } private void systemReady() { // Make your initialization here } }
Now you are done. Your new service will now be loaded into Android's ServiceManager during boot via our first hook to the ActivityServiceManager.main() method and it will be initialized once all services is ready via our second hook to ActivityServiceManager.systemReady().
After the initialization, you can access the binder using ServiceManager.getService( name ) just like with any other System Service provided by Android.
All that is left is to implement whatever options you would like this service to provide and start using it in your module.
Example of usage:
public class SomeClass { ICustomService mService; public void someMethod() { if (mService == null) { mService = ICustomService.Stub.asInterface( ServiceManager.getService("custom.service") ); } mService.someServiceMethod(); } }
Subscribe to:
Posts (Atom)