Hello,
I'm fairly new to using Xposed. I've used it a couple of times to solve some Android CTF challenges, where its ability to hook into an app is a real benefit.
But now I'm trying to understand it a little bit better. As a simple toy project, I'm considering using Xposed to implement a sort of periodic update for Xposed modules. It's not exactly the most useful mod, but it helps me get a better understanding of the framework.
Based on the development tutorial, I thought I could just implement a naive cron.d over the updateClock() method and fire off an AsyncTask to handle
communication to an external server (a package repo if you will). So far, my code goes like this:
Code:
package com.example.red;
import android.app.AndroidAppHelper;
import android.app.Application;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Calendar;
class UpdateModulesTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... voids) {
XposedBridge.log("Updating modules");
try {
Application app = AndroidAppHelper.currentApplication();
Context ctx = app.getApplicationContext();
int res = ctx.checkCallingOrSelfPermission(android.Manifest.permission.INTERNET);
if (res == PackageManager.PERMISSION_DENIED)
XposedBridge.log("No internet");
else
XposedBridge.log("Internet granted");
URL url = new URL("<MY URL>");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
DataOutputStream out = new DataOutputStream(conn.getOutputStream());
out.writeBytes("key=value");
out.flush();
out.close();
int rcode = conn.getResponseCode();
XposedBridge.log("Return code " + String.valueOf(rcode));
if (rcode == 200) {
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = "";
StringBuilder response = new StringBuilder();
while ((line = in.readLine()) != null) {
response.append(line);
}
in.close();
XposedBridge.log(response.toString());
}
} catch (Exception e) {
XposedBridge.log(e.getMessage());
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
XposedBridge.log(sw.toString());
}
return null;
}
}
public class Main implements IXposedHookLoadPackage {
public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
XposedBridge.log(lpparam.packageName);
if (lpparam.packageName.equals("com.android.systemui")) {
findAndHookMethod("com.android.systemui.statusbar.policy.Clock", lpparam.classLoader, "updateClock", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Calendar now = Calendar.getInstance();
int hour = now.get(Calendar.HOUR_OF_DAY);
XposedBridge.log("Hour is: " + String.valueOf(hour));
if (hour == 11) {
int minute = now.get(Calendar.MINUTE);
XposedBridge.log("Minute is: " + String.valueOf(minute));
if (minute % 2 == 0) { // update modules
new UpdateModulesTask().execute();
}
}
}
});
}
}
}
What Xposed logs, instead, goes like this:
Code:
I/Xposed ( 3574): Hour is: 11
I/Xposed ( 3574): Minute is: 50
I/Xposed ( 3574): Updating modules
I/Xposed ( 3574): Internet granted
I/Xposed ( 3574): Permission denied (missing INTERNET permission?)
I/Xposed ( 3574): java.lang.SecurityException: Permission denied (missing INTERNET permission?)
I/Xposed ( 3574): at java.net.InetAddress.lookupHostByName(InetAddress.java:451)
I/Xposed ( 3574): at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
I/Xposed ( 3574): at java.net.InetAddress.getAllByName(InetAddress.java:215)
I/Xposed ( 3574): at com.android.okhttp.HostResolver$1.getAllByName(HostResolver.java:29)
I/Xposed ( 3574): at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:232)
I/Xposed ( 3574): at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:124)
I/Xposed ( 3574): at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:272)
I/Xposed ( 3574): at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:211)
I/Xposed ( 3574): at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:373)
I/Xposed ( 3574): at com.android.okhttp.internal.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:106)
I/Xposed ( 3574): at com.android.okhttp.internal.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:208)
I/Xposed ( 3574): at com.example.red.UpdateModulesTask.doInBackground(Main.java:41)
I/Xposed ( 3574): at com.example.red.UpdateModulesTask.doInBackground(Main.java:26)
I/Xposed ( 3574): at android.os.AsyncTask$2.call(AsyncTask.java:288)
I/Xposed ( 3574): at java.util.concurrent.FutureTask.run(FutureTask.java:237)
I/Xposed ( 3574): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
I/Xposed ( 3574): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
I/Xposed ( 3574): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
I/Xposed ( 3574): at java.lang.Thread.run(Thread.java:818)
I/Xposed ( 3574): Caused by: android.system.GaiException: android_getaddrinfo failed: EAI_NODATA (No address associated with hostname)
I/Xposed ( 3574): at libcore.io.Posix.android_getaddrinfo(Native Method)
I/Xposed ( 3574): at libcore.io.ForwardingOs.android_getaddrinfo(ForwardingOs.java:55)
I/Xposed ( 3574): at java.net.InetAddress.lookupHostByName(InetAddress.java:438)
I/Xposed ( 3574): ... 18 more
I/Xposed ( 3574): Caused by: android.system.ErrnoException: android_getaddrinfo failed: EACCES (Permission denied)
I/Xposed ( 3574): ... 21 more
So, from what I understand, com.android.systemui should have the "android.permission.INTERNET" permission, which is also what the "Internet granted" message in the logcat output indicates. I also checked for SELinux violations and it doesn't seem to be the case.
What I'd like to understand is why my hook, called from the context of com.android.systemui (which hold the Internet permission), checks to see if it has the Internet permission (and it does) and then receives a permission denied error when actually attempting make the connection, despite the fact that there is no intervention from SELinux. Am I missing something obvious with regards to the way Xposed works?
Don't know on which Android version you test this but by simply looking at SystemUI manifest of Android 6.0.1
you can clearly see there is no INTERNET permission.
Your "if" statement is confusing you. You should rather use:
Code:
if (res == PackageManager.PERMISSION_GRANTED)
XposedBridge.log("Internet granted");
else
XposedBridge.log("No internet");
Thanks for the reply, C3C076!
Sorry for not mentioning the Android version. I'm running Android 5.0.0 build LRX21T on a Nexus 4, if that is of any use.
I've looked through the manifest for 5.0.0 and indeed, there seems to be no reference to the Internet permission. So I've looked around for some means to grant that permission, and came up with:
Code:
if (lpparam.packageName.equals("android")) {
final Class<?> pmServiceClass = XposedHelpers.findClass("com.android.server.pm.PackageManagerService", lpparam.classLoader);
findAndHookMethod(pmServiceClass, "grantPermissionsLPw", "android.content.pm.PackageParser.Package", boolean.class, String.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
final String pkgname = (String) XposedHelpers.getObjectField(param.args[0], "packageName");
XposedBridge.log("Called for package: " + pkgname);
if (pkgname.equals("com.android.systemui")) {
Object extras = XposedHelpers.getObjectField(param.args[0], "mExtras");
Object sharedUser = XposedHelpers.getObjectField(extras, "sharedUser");
Set<String> grantedPerms = (Set<String>) XposedHelpers.getObjectField(sharedUser != null ? sharedUser :extras, "grantedPermissions");
Object settings = XposedHelpers.getObjectField(param.thisObject, "mSettings");
Object permissions = XposedHelpers.getObjectField(settings, "mPermissions");
XposedBridge.log(grantedPerms.toString());
if (!grantedPerms.contains("android.permission.INTERNET")) {
final Object pInet = XposedHelpers.callMethod(permissions, "get", "android.permission.INTERNET");
grantedPerms.add("android.permission.INTERNET");
int[] gpGids = (int[]) XposedHelpers.getObjectField(sharedUser != null ? sharedUser : extras, "gids");
int[] bpGids = (int[]) XposedHelpers.getObjectField(pInet, "gids");
XposedBridge.log("Extended GIDs with: " + bpGids.toString());
XposedHelpers.callStaticMethod(param.thisObject.getClass(), "appendInts", gpGids, bpGids);
}
}
}
});
XposedBridge.log("Granted extra permission.");
}
The funny thing is that android.permission.INTERNET did not have to be added. It was already in the list of granted permissions.
Code:
I/Xposed ( 6218): Called for package: com.android.systemui
I/Xposed ( 6218): [android.permission.SYSTEM_ALERT_WINDOW,
android.permission.GET_APP_OPS_STATS,
android.permission.REMOVE_TASKS,
android.permission.STATUS_BAR_SERVICE,
android.permission.CHANGE_WIFI_STATE,
android.permission.GET_ACCOUNTS,
android.permission.CAMERA,
android.permission.ACCESS_ALL_EXTERNAL_STORAGE,
android.permission.MEDIA_CONTENT_CONTROL,
android.permission.WRITE_DREAM_STATE,
android.permission.REMOTE_AUDIO_PLAYBACK,
android.permission.STOP_APP_SWITCHES,
android.permission.MANAGE_ACCOUNTS,
android.permission.BLUETOOTH_ADMIN,
android.permission.ACCESS_NETWORK_STATE,
com.android.alarm.permission.SET_ALARM,
android.permission.MANAGE_MEDIA_PROJECTION,
android.permission.DEVICE_POWER,
android.permission.START_TASKS_FROM_RECENTS,
android.permission.START_ANY_ACTIVITY,
android.permission.READ_PROFILE,
android.permission.WRITE_SECURE_SETTINGS,
android.permission.CHANGE_NETWORK_STATE,
android.permission.BIND_APPWIDGET,
android.permission.GET_DETAILED_TASKS,
android.permission.DUMP,
android.permission.MANAGE_APP_TOKENS,
android.permission.READ_EXTERNAL_STORAGE,
android.permission.SET_SCREEN_COMPATIBILITY,
android.permission.CONTROL_KEYGUARD,
android.permission.EXPAND_STATUS_BAR,
android.permission.DISABLE_KEYGUARD,
android.permission.READ_PHONE_STATE,
android.permission.MANAGE_USB,
android.permission.INTERACT_ACROSS_USERS,
android.permission.INTERNAL_SYSTEM_WINDOW,
android.permission.MODIFY_PHONE_STATE,
android.permission.READ_CONTACTS,
android.permission.ACCESS_KEYGUARD_SECURE_STORAGE,
android.permission.WAKE_LOCK,
android.permission.INTERACT_ACROSS_USERS_FULL,
android.permission.MASTER_CLEAR,
android.permission.READ_FRAME_BUFFER,
android.permission.REAL_GET_TASKS,
android.permission.GET_TOP_ACTIVITY_INFO,
android.permission.SET_ORIENTATION,
android.permission.INJECT_EVENTS,
android.permission.CONFIGURE_WIFI_DISPLAY,
android.permission.READ_DREAM_STATE,
android.permission.VIBRATE,
android.permission.CHANGE_COMPONENT_ENABLED_STATE,
android.permission.INTERNET,
android.permission.REORDER_TASKS,
android.permission.WRITE_SETTINGS,
android.permission.STATUS_BAR,
android.permission.MOUNT_UNMOUNT_FILESYSTEMS,
android.permission.WRITE_EXTERNAL_STORAGE,
android.permission.READ_NETWORK_USAGE_HISTORY,
android.permission.MANAGE_ACTIVITY_STACKS,
android.permission.MANAGE_USERS,
android.permission.CONNECTIVITY_INTERNAL,
android.permission.MANAGE_NETWORK_POLICY,
android.permission.TRUST_LISTENER,
android.permission.BLUETOOTH,
android.permission.RECEIVE_BOOT_COMPLETED,
android.permission.BIND_DEVICE_ADMIN,
android.permission.ACCESS_WIFI_STATE]
I'm not sure what to make of this difference between AOSP and my device. The only modifications I've made are installing TWRP, SuperSU, and Xposed. To my knowledge, none modify permissions by default. But then again, I could be wrong.
I'm curious whether you have any idea about this, C3C076.
Or anyone else for that matter ...
Did you take a look at the permission list before you were testing code for adding permission or after?
Because if you previously added permission during code testing then it will be there cached in the system.
Related
I tried to hook method "java.lang.System.loadLibrary", but it caused the process crashed.
My code is simple:
@Override
public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
if (!loadPackageParam.packageName.equals("com.shinybox.yongchuandixiachengfortx13"))
return;
XposedHelpers.findAndHookMethod("java.lang.System", loadPackageParam.classLoader, "loadLibrary",
String.class,
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
String libName = (String) param.args[0];
XposedBridge.log("XPOSED:" + libName);
XposedBridge.log("XPOSED:" + loadPackageParam.classLoader.toString());
super.beforeHookedMethod(param);
}
});
}
Click to expand...
Click to collapse
And I could got some output:
I/Xposed ( 1709): XPOSED:crypto
I/Xposed ( 1709): XPOSED:dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.shinybox.yongchuandixiachengfortx13-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.shinybox.yongchuandixiachengfortx13-1, /vendor/lib, /system/lib]]]
I/Xposed ( 1709): XPOSED:ssl
I/Xposed ( 1709): XPOSED:dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.shinybox.yongchuandixiachengfortx13-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.shinybox.yongchuandixiachengfortx13-1, /vendor/lib, /system/lib]]]
I/Xposed ( 1709): XPOSEDpenal
I/Xposed ( 1709): XPOSED:dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.shinybox.yongchuandixiachengfortx13-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.shinybox.yongchuandixiachengfortx13-1, /vendor/lib, /system/lib]]]
Click to expand...
Click to collapse
But the app crashed and here is the error info:
E/AndroidRuntime( 1709): java.lang.UnsatisfiedLinkError: Couldn't load openal from loader dalvik.system.PathClassLoader[DexPathList[[zip file "/data/data/de.robv.android.xposed.installer/bin/XposedBridge.jar"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]]: findLibrary returned null
E/AndroidRuntime( 1709): at de.robv.android.xposed.XposedBridge.invokeOriginalMethodNative(Native Method)
E/AndroidRuntime( 1709): at de.robv.android.xposed.XposedBridge.handleHookedMethod(XposedBridge.java:631)
E/AndroidRuntime( 1709): at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
Click to expand...
Click to collapse
The reason is that the app tried to load the library "openal" from xposed installer's class loader rather than its own's. How this happened?
SOLVED: I should not use the construction function...
Is it related to the construction function or static mathod?
PS:the [ CODE ] tag seems not very suitable for showing logs... Any better ideas?
Logs:
Code:
06-11 10:55:07.367 I/Xposed ( 303): Loading modules from /data/app/com.runapp.wakelockblocker-1/base.apk
06-11 10:55:07.617 I/Xposed ( 303): Loading class com.runapp.wakelockblocker.HookClass
06-11 10:55:07.647 E/Xposed ( 303): java.lang.IllegalAccessException: com.runapp.wakelockblocker.HookClass() is not accessible from class de.robv.android.xposed.XposedBridge
06-11 10:55:07.647 E/Xposed ( 303): at java.lang.Class.newInstance(Class.java:1569)
06-11 10:55:07.647 E/Xposed ( 303): at de.robv.android.xposed.XposedBridge.loadModule(XposedBridge.java:492)
06-11 10:55:07.647 E/Xposed ( 303): at de.robv.android.xposed.XposedBridge.loadModules(XposedBridge.java:447)
06-11 10:55:07.647 E/Xposed ( 303): at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:105)
Part of my code:
Code:
public class HookClass implements IXposedHookZygoteInit,IXposedHookLoadPackage {
private static XSharedPreferences prefs;
private static String[] appn;
private static String[] wln;
private static boolean reloadPref;
HookClass(){
Log.e("HookClass","Constructing!");
}
@Override
public void initZygote(IXposedHookZygoteInit.StartupParam paramStartupParam) throws Throwable {
prefs = new XSharedPreferences(Common.MY_PACKAGE_NAME, Common.MY_PREFERENCE_NAME);
loadPref();
}
public static void loadPref() {
...
HookClass(){
Log.e("HookClass","Constructing!");
}
This is code is useless and causes bugs. Simply remove it. You don't need it. You can place logging to initZygote.
seems like I placed that in a wrong section.Please ,move it to dev section
___
I'm hooking systemui to get data from updateAppMessage method. And I'm hooking method updateMessage method in package launcher. SystemUI's method invokes first (I checked).
All I need is to remember data from systemui hook to use it later in launcher hook. As it turns out it's a big problem to me. I wan't to compare package name from these two methods. But when it goes to updateMessage in launcher I see in log file that all variables from systemui hook reset to their initial values.
May be I miss just one crucial thing but I spend already the whole day so I'm begging for help.
I'm using xposed v87 for miui (android 6) by SolarWarez (also now I have flashed v86 and nothing changed)
here's the log
Code:
12-01 00:19:53.464 I/Xposed ( 5682): OMG [B]pkg= com.vkcoffee.androi[/B]d number=2
12-01 00:19:53.468 I/Xposed ( 5968): Launcher [B]pkg=com.vkcoffee.android[/B]
12-01 00:19:53.468 I/Xposed ( 5968): Launcher other= -1 [B]-string[/B]
12-01 00:20:58.544 I/Xposed ( 5682): OMG pkg= android number=0
12-01 00:20:58.555 I/Xposed ( 5968): Launcher pkg=android
12-01 00:20:58.555 I/Xposed ( 5968): Launcher other= -1 -string
12-01 00:20:58.816 I/Xposed ( 5682): OMG pkg= com.miui.securitycenter number=0
12-01 00:20:58.820 I/Xposed ( 5968): Launcher pkg=com.miui.securitycenter
12-01 00:20:58.820 I/Xposed ( 5968): Launcher other= -1 -string
12-01 00:22:24.126 I/Xposed ( 5968): Launcher pkg=de.robv.android.xposed.installer
12-01 00:22:24.126 I/Xposed ( 5968): Launcher other= -1 -string
and here's the code
PHP:
public class XposedMod implements IXposedHookInitPackageResources, IXposedHookZygoteInit, IXposedHookLoadPackage {
public static String MODULE_PATH = null;
public static int number=-1;
public static String notif_pkg="-string";
public static String pkg="-string";
public static ComponentName comp;
@Override
public void initZygote(IXposedHookZygoteInit.StartupParam startupParam) throws Throwable {
MODULE_PATH = startupParam.modulePath;
XModuleResources modRes = XModuleResources.createInstance(MODULE_PATH, null);
}
@Override
public void handleInitPackageResources(InitPackageResourcesParam resparam) throws Throwable {
}
@Override
public void handleLoadPackage(LoadPackageParam lpparam)
throws Throwable {
if (lpparam.packageName.equals("com.miui.home") ) {
findAndHookMethod("com.miui.home.launcher.ApplicationsMessage",lpparam.classLoader,"updateMessage",ComponentName.class, int.class, String.class,String.class, byte[].class, new XC_MethodHook()
{
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
comp = (ComponentName) param.args[0];
pkg=comp.getPackageName();
XposedBridge.log("Launcher pkg="+pkg);
XposedBridge.log("Launcher other="+ " "+number+" "+notif_pkg);
}
});
}
if (lpparam.packageName.equals("com.android.systemui")) {
findAndHookMethod("com.android.systemui.statusbar.phone.PhoneStatusBar",lpparam.classLoader,"updateAppMessage","com.android.systemui.statusbar.ExpandedNotification", new XC_MethodHook()
{
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
StatusBarNotification sbn =(StatusBarNotification) param.args[0];
number=sbn.getNotification().number;
notif_pkg=sbn.getPackageName();
XposedBridge.log("OMG pkg= "+notif_pkg+" number="+number);
}
});
}
}
}
Also I tried to store data in text File but with no luck as well. My own application Activity returns null context everytime I try to get it from XposedMod class. And I tried to use SystemUI context to store file in /data/data/com.android.systemui/files/ folder (with file.setReadable(true, false); on file creation) but later when I'm trying to read the file xposed log throws exception about "FileNotFoundException.... EACCES (Permition denied)
PHP:
public static String getStringFromFile(String fileName) throws IOException {
File file = new File("/data/data/com.android.systemui/files/", fileName);
int length = (int) file.length();
byte[] bytes = new byte[length];
FileInputStream in = new FileInputStream(file);
try {
in.read(bytes);
} finally {
in.close();
}
String contents = new String(bytes);
return contents;
}
I'm just dumb. If I create file in internal storage there's no access error. but still I want to deal only with variables inside my app..
Note, that you have hooks in 2 different processes. Those are "isolated" so when you set value of variable in one process (systemui) you won't be able to see that value in another process (launcher). Those variables are completely different and independent.
You will have to use some kind of shared storage or some kind of IPC communication method.
The easiest that comes to my mind is e.g. to use Settings.Global storage to save variable in one process and then read that variable in another process.
All you need to access Setting.Global is a valid context which gives you content resolver you need for Setting.Global.putString/getString methods.
C3C076 said:
Note, that you have hooks in 2 different processes. Those are "isolated" so when you set value of variable in one process (systemui) you won't be able to see that value in another process (launcher). Those variables are completely different and independent.
Click to expand...
Click to collapse
thanks for clarifying these things to me
Hello, I'm using a Nexus 4, running Android 5.0.0 build LRX21T, with Xposed (xposed-v87-sdk21-arm.zip). I'm trying to run a command early during Android startup. My code so far looks like this:
Code:
package com.example.test;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import de.robv.android.xposed.IXposedHookZygoteInit;
import de.robv.android.xposed.XposedBridge;
class RunCmdTask extends Thread {
private String cmd;
RunCmdTask(String c) {
cmd = c;
}
public void run() {
XposedBridge.log("task start");
Process proc = null;
try {
Runtime rt = Runtime.getRuntime();
proc = rt.exec(cmd);
proc.waitFor();
BufferedReader stdin = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String s;
while ((s = stdin.readLine()) != null)
XposedBridge.log(s);
stdin.close();
} catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
XposedBridge.log(sw.toString());
} finally {
if (proc != null)
proc.destroy();
}
XposedBridge.log("task end");
}
}
public class Main implements IXposedHookZygoteInit {
@Override
public void initZygote(StartupParam startupParam) throws Throwable {
XposedBridge.log("main start");
try {
RunCmdTask id = new RunCmdTask("id");
id.start();
id.join();
} catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
XposedBridge.log(sw.toString());
}
XposedBridge.log("main end");
}
}
The "id" gets invoked, since my logcat looks like:
Code:
I/Xposed (25305): main start
I/Xposed (25305): task start
I/Xposed (25305): uid=0(root) gid=0(root) context=u:r:zygote:s0
I/Xposed (25305): task end
I/Xposed (25305): main end
The problem is that the startup process hangs after this point. I just get the bootup animation looping over and over again. I've tried terminating the VM by calling the Runtime.halt() method, but that kills the whole Zygote, thus being equivalent to a soft reboot. I'm curious to see what I'm mistaking/overlooking. From what I understand, since both the thread and the main hook method finish, normal startup should resume.
I've been able to hook static methods using Xposed but can not figure out how to hook android classes such as android.bluetooth.BluetoothGatt. My goal is to log bluetooth payloads and then trace the static method within the given app responsible for said payload. I can access the desired payload using the JDB debugger as follows:
Code:
> stop in android.bluetooth.BluetoothGatt.writeCharacteristic
Set breakpoint android.bluetooth.BluetoothGatt.writeCharacteristic
>
Breakpoint hit: "thread=main",
android.bluetooth.BluetoothGatt.writeCharacteristic(), line=926 bci=0
main[1] dump characteristic.mValue
characteristic.mValue = {
116, 101, 115, 116, 49, 51, 51
}
This is my code for attempting to hook the android.bluetooth.BluetoothGatt.writeCharacteristic method:
Code:
package com.example.test.xposed3;
import java.lang.reflect.Method;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
import static de.robv.android.xposed.XposedHelpers.findClass;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
public class Xposed3 implements IXposedHookLoadPackage {
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("com.macdom.ble.blescanner"))
return;
XposedBridge.log("Loaded app: " + lpparam.packageName);
findAndHookMethod("com.macdom.ble.blescanner.a", lpparam.classLoader, "onStart", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("Calling com.macdom.ble.blescanner.a onStart()");
}
});
Class<?> BluetoothGatt = findClass("android.bluetooth.BluetoothGatt", lpparam.classLoader);
Method writeCharacteristic = XposedHelpers.findMethodBestMatch(BluetoothGatt, "writeCharacteristic");
XposedBridge.hookMethod(writeCharacteristic, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("Calling android.bluetooth.BluetoothGatt writeCharacteristic()");
}
});
The logs show I'm successfully hooking the static method com.macdom.ble.blescanner.a onStart() but outputs a java.lang.NoSuchMethodError when attempting to hook android.bluetooth.BluetoothGatt writeCharacteristic()
Code:
I/Xposed (11661): Loaded app: com.macdom.ble.blescanner
E/Xposed (11661): java.lang.NoSuchMethodError: android.bluetooth.BluetoothGatt#writeCharacteristic()#bestmatch
E/Xposed (11661): at de.robv.android.xposed.XposedHelpers.findMethodBestMatch(XposedHelpers.java:440)
E/Xposed (11661): at com.example.test.xposed3.Xposed3.handleLoadPackage(Xposed3.java:34)
E/Xposed (11661): at de.robv.android.xposed.IXposedHookLoadPackage$Wrapper.handleLoadPackage(IXposedHookLoadPackage.java:34)
E/Xposed (11661): at de.robv.android.xposed.callbacks.XC_LoadPackage.call(XC_LoadPackage.java:61)
E/Xposed (11661): at de.robv.android.xposed.callbacks.XCallback.callAll(XCallback.java:106)
E/Xposed (11661): at de.robv.android.xposed.XposedInit$2.beforeHookedMethod(XposedInit.java:116)
E/Xposed (11661): at de.robv.android.xposed.XposedBridge.handleHookedMethod(XposedBridge.java:314)
E/Xposed (11661): at android.app.ActivityThread.handleBindApplication(<Xposed>)
E/Xposed (11661): at android.app.ActivityThread.access$1500(ActivityThread.java:151)
E/Xposed (11661): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1364)
E/Xposed (11661): at android.os.Handler.dispatchMessage(Handler.java:102)
E/Xposed (11661): at android.os.Looper.loop(Looper.java:135)
E/Xposed (11661): at android.app.ActivityThread.main(ActivityThread.java:5254)
E/Xposed (11661): at java.lang.reflect.Method.invoke(Native Method)
E/Xposed (11661): at java.lang.reflect.Method.invoke(Method.java:372)
E/Xposed (11661): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
E/Xposed (11661): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
E/Xposed (11661): at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:102)
I/Xposed (11661): Calling com.macdom.ble.blescanner.a onStart()
The module should be usable for any given app that uses bluetooth BLE. I'm not sure if this is the best approach or if there is a way to dynamically discover the the app's instance of BluetoothGatt and hook it.
jostomp said:
I've been able to hook static methods using Xposed but can not figure out how to hook android classes such as android.bluetooth.BluetoothGatt. My goal is to log bluetooth payloads and then trace the static method within the given app responsible for said payload. I can access the desired payload using the JDB debugger as follows:
Code:
> stop in android.bluetooth.BluetoothGatt.writeCharacteristic
Set breakpoint android.bluetooth.BluetoothGatt.writeCharacteristic
>
Breakpoint hit: "thread=main",
android.bluetooth.BluetoothGatt.writeCharacteristic(), line=926 bci=0
main[1] dump characteristic.mValue
characteristic.mValue = {
116, 101, 115, 116, 49, 51, 51
}
This is my code for attempting to hook the android.bluetooth.BluetoothGatt.writeCharacteristic method:
Code:
package com.example.test.xposed3;
import java.lang.reflect.Method;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
import static de.robv.android.xposed.XposedHelpers.findClass;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
public class Xposed3 implements IXposedHookLoadPackage {
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("com.macdom.ble.blescanner"))
return;
XposedBridge.log("Loaded app: " + lpparam.packageName);
findAndHookMethod("com.macdom.ble.blescanner.a", lpparam.classLoader, "onStart", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("Calling com.macdom.ble.blescanner.a onStart()");
}
});
Class<?> BluetoothGatt = findClass("android.bluetooth.BluetoothGatt", lpparam.classLoader);
Method writeCharacteristic = XposedHelpers.findMethodBestMatch(BluetoothGatt, "writeCharacteristic");
XposedBridge.hookMethod(writeCharacteristic, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("Calling android.bluetooth.BluetoothGatt writeCharacteristic()");
}
});
The logs show I'm successfully hooking the static method com.macdom.ble.blescanner.a onStart() but outputs a java.lang.NoSuchMethodError when attempting to hook android.bluetooth.BluetoothGatt writeCharacteristic()
Code:
I/Xposed (11661): Loaded app: com.macdom.ble.blescanner
E/Xposed (11661): java.lang.NoSuchMethodError: android.bluetooth.BluetoothGatt#writeCharacteristic()#bestmatch
E/Xposed (11661): at de.robv.android.xposed.XposedHelpers.findMethodBestMatch(XposedHelpers.java:440)
E/Xposed (11661): at com.example.test.xposed3.Xposed3.handleLoadPackage(Xposed3.java:34)
E/Xposed (11661): at de.robv.android.xposed.IXposedHookLoadPackage$Wrapper.handleLoadPackage(IXposedHookLoadPackage.java:34)
E/Xposed (11661): at de.robv.android.xposed.callbacks.XC_LoadPackage.call(XC_LoadPackage.java:61)
E/Xposed (11661): at de.robv.android.xposed.callbacks.XCallback.callAll(XCallback.java:106)
E/Xposed (11661): at de.robv.android.xposed.XposedInit$2.beforeHookedMethod(XposedInit.java:116)
E/Xposed (11661): at de.robv.android.xposed.XposedBridge.handleHookedMethod(XposedBridge.java:314)
E/Xposed (11661): at android.app.ActivityThread.handleBindApplication(<Xposed>)
E/Xposed (11661): at android.app.ActivityThread.access$1500(ActivityThread.java:151)
E/Xposed (11661): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1364)
E/Xposed (11661): at android.os.Handler.dispatchMessage(Handler.java:102)
E/Xposed (11661): at android.os.Looper.loop(Looper.java:135)
E/Xposed (11661): at android.app.ActivityThread.main(ActivityThread.java:5254)
E/Xposed (11661): at java.lang.reflect.Method.invoke(Native Method)
E/Xposed (11661): at java.lang.reflect.Method.invoke(Method.java:372)
E/Xposed (11661): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
E/Xposed (11661): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
E/Xposed (11661): at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:102)
I/Xposed (11661): Calling com.macdom.ble.blescanner.a onStart()
The module should be usable for any given app that uses bluetooth BLE. I'm not sure if this is the best approach or if there is a way to dynamically discover the the app's instance of BluetoothGatt and hook it.
Click to expand...
Click to collapse
If the method have some args, Xposed won't find it. Can you share the source? And why you didn't use findandhookmethod?
Massi-X said:
If the method have some args, Xposed won't find it. Can you share the source? And why you didn't use findandhookmethod?
Click to expand...
Click to collapse
Thanks for the reply. This method does not take any arguments - https:[//]developer.android.com/reference/android/bluetooth/BluetoothGatt.html#writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic)
Using the findandhookmethod returns a similar error:
Code:
java.lang.NoSuchMethodError: android.bluetooth.BluetoothGatt#writeCharacteristic()#exact
The application I'm testing on is called BLE Scanner - I do not have the source for this.
jostomp said:
Thanks for the reply. This method does not take any arguments - https:[//]developer.android.com/reference/android/bluetooth/BluetoothGatt.html#writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic)
Using the findandhookmethod returns a similar error:
Code:
java.lang.NoSuchMethodError: android.bluetooth.BluetoothGatt#writeCharacteristic()#exact
The application I'm testing on is called BLE Scanner - I do not have the source for this.
Click to expand...
Click to collapse
Uhm from the page you share it says the method wants an argument of BluetoothGattCharacteristic type .
So, this is the problem!
Massi-X said:
Uhm from the page you share it says the method wants an argument of BluetoothGattCharacteristic type .
So, this is the problem!
Click to expand...
Click to collapse
Ahh yes you are completely right! Thanks
Here's the working code:
Code:
package com.example.djason.xposed3;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
import android.bluetooth.BluetoothGattCharacteristic;
public class Xposed3 implements IXposedHookLoadPackage {
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("com.macdom.ble.blescanner"))
return;
XposedBridge.log("Loaded app: " + lpparam.packageName);
findAndHookMethod("android.bluetooth.BluetoothGatt", lpparam.classLoader, "writeCharacteristic", BluetoothGattCharacteristic.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("Calling android.bluetooth.BluetoothGatt writeCharacteristic()");
}
});
}
}
Glad to help!