Xposed 的原理
Android基于Linux,第一个启动的进程自然是init进程,该进程会启动所有Android进程的父进程——Zygote(孵化)进程,该进程的启动配置在/init.rc脚本中,而Zygote进程对应的执行文件是/system/bin/app_process,该文件完成类库的加载以及一些函数的调用工作。在Zygote进程创建后,再fork出SystemServer进程和其他进程。而Xposed Framework呢,就是用自己实现的app_process替换掉了系统原本提供的app_process,加载一个额外的jar包,然后入口从原来的com.android.internal.osZygoteInit.main()被替换成了de.robv.android.xposed.XposedBridge.main(),然后创建的Zygote进程就变成Hook的Zygote进程了,而后面Fork出来的进程也是被Hook过的。这个Jar包在/data/data/de.rbov.android.xposed.installer/bin/XposedBridge.jar。
Xposed代码的编写
新建一个项目,请注意如果你只是hook,那么可以选择add no activity,但是如果有和自身app交互,那么就选择empty activity。我为了给大家演示,是有展示的,所以我选择empty activity。
1.创建成功后找到AndroidManifest.xml中的application,在文件里面添加如下代码。
1 2 3 4 5 6 7 8 9
| <meta-data android:name="xposedmodule" android:value="true" /> <meta-data android:name="xposeddescription" android:value="XposedProject" /> <meta-data android:name="xposedminversion" android:value="53" />
|
第一个xposedmodule的属性为ture,证明这是一个xposed的module;
第二个xposeddescription,这是介绍项目的话语;
第三个xposedminversion则是说明该xposedmodule所支持的最小版本,而最低版本就是30。
添加到AndroidManifest.xml中的application里面。
2.加入xposed的依赖包到libs目录
https://bintray.com/rovo89/de.robv.android.xposed/api
3.接下来找到build.gradle(module:app是你app项目下的(不是外层的))文件,在里面添加如下代码。
1 2 3
| compileOnly 'de.robv.android.xposed:api:82' compileOnly 'de.robv.android.xposed:api:82:sources'
|
添加到buile.gradle中dependencies中
4.建一个Java类并且继承接口IXposedHookLoadPackage和重写handleLoadPackage方法。
1 2 3 4 5 6 7 8 9 10 11 12 13
| import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.callbacks.XC_LoadPackage; public class HookMain implements IXposedHookLoadPackage { @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { } }
|
5.在src/mian目录下添加一个assets目录,目录下添加一个xposed_init文件,里面的代码是你的Hook类的包名+类名。
而本项目就是:com.yymjr.android.xposedproject.HookMain。
注意的
不管是连接真机调试还是用模拟器调试,都不要直接点 Android Stduio的那个三角按钮直接运行!!! Build → Build APK, 要生成一个APK文件,未签名的也可以,然后放到模拟器或手机上运行再试试。
文档
https://api.xposed.info/reference/de/robv/android/xposed/package-summary.html
免重启
https://www.freebuf.com/sectool/167274.html
example
adb logcat命令
在cmd窗口中输入如下命令,就可以像Studio中的Logcat窗口中显示日志信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| //格式1:打印默认日志数据 adb logcat
//格式2:需要打印日志详细时间的简单数据 adb logcat -v time
//格式3:需要打印级别为Error的信息 adb logcat *:E
//格式4:需要打印时间和级别是Error的信息 adb logcat -v time *:E
//格式5:将日志保存到电脑固定的位置,比如D:\log.txt adb logcat -v time >D:\log.txt
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| public class HookTemplate implements IXposedHookLoadPackage{ @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { String HOOK_PACKAGE_NAME = ""; XposedBridge.log("【handleLoadPackage】" + lpparam.packageName); if (lpparam.packageName.equals(HOOK_PACKAGE_NAME)) { Class hook_clazz = lpparam.classLoader.loadClass( ""); XposedHelpers.findAndHookMethod(hook_clazz, "hook的方法名", int.class, int.class, new XC_MethodHook() { protected void beforeHookedMethod(MethodHookParam param) throws Throwable { XposedBridge.log("Called beforeHookedMethod"); Object thisObject = param.thisObject; XposedHelpers.getObjectField(thisObject, "") param.method; param.args; param.setResult() XposedBridge.log("Changed args 0 to " + param.args[0]); }
protected void afterHookedMethod(MethodHookParam param) throws Throwable { param.getResult(); XposedBridge.log("Called afterHookedMethod"); } }); } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public class HookDemo implements IXposedHookLoadPackage{ @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { XposedBridge.log("【handleLoadPackage】" + lpparam.packageName); if (lpparam.packageName.equals("com.tencent.mm")){ Class hook_clazz = lpparam.classLoader.loadClass( "com.tencent.wcdb.database.SQLiteDatabase"); XposedHelpers.findAndHookMethod("xxxx",lpparam.classLoader, "insertWithOnConflict", String.class, String.class, ContentValues.class, int.class, new XC_MethodHook() { protected void beforeHookedMethod(MethodHookParam param) throws Throwable { XposedBridge.log("Called beforeHookedMethod"); }
protected void afterHookedMethod(MethodHookParam param) throws Throwable { XposedBridge.log("帮你hook"); Object tableName = param.args[0]; Object oj = param.args[1]; ContentValues content = (ContentValues)param.args[2]; XposedBridge.log(String.format("hook tableName %s,%s", tableName, oj)); for (String key:content.keySet()){ XposedBridge.log(String.format("hook Key:%s | Value:%s",key, content.get(key))); }
} }); } } }
|