Xposed,大名鼎鼎得Xposed,是Android平台上最负盛名的一个框架。在这个框架下,我们可以加载很多插件App,这些插件App可以直接或间接操纵系统层面的东西,比如操纵一些本来只对系统厂商才open的功能(实际上是因为Android系统很多API是不公开的,而第三方APP又没有权限)。有了Xposed后,理论上我们的插件APP可以hook到系统任意一个Java进程(zygote,systemserver,systemui好不啦!)。
lpparam.classLoader hook
- 静态field变量
静态field变量sMoney的值的修改和获取,可以直接使用xposed提供的XposedHelpers类相关功能函数。具体操作可以类比以下示例代码片段:
1 2 3 4 5 6 7 8 9 10
| Class clazz =XposedHelpers.findClass("com.example.inner_class_demo.demo",lpparam.classLoader); XposedHelpers.setStaticObjectField(clazz,"sMoney",110); Field sMoney = clazz.getDeclaredField("sMoney"); sMoney.setAccessible(true); System.out.println(sMoney.get(null));
|
- 隐藏函数hidden_fun
主动调用隐藏函数hidden_fun(这一类函数是指触发条件比较苛刻的函数,但是我们又需要了解它的输入、输出的大致关系),需要通过clazz来新建实例,最后将此实例与函数名组装成XposedHelpers.callMethod()的实参需求形式。具体操作可以类比以下示例代码片段:
1 2 3
| Class clazz =XposedHelpers.findClass("com.example.inner_class_demo.demo",lpparam.classLoader); XposedHelpers.callMethod(constructor.newInstance(),"hidden_fun");
|
以上代码仅适用于存在无参构造函数的类,如果目标类没有无参构造函数,那就麻烦一点了,需要根据构造函数参数类型,反射寻找构造函数,接着才能类似上述操作。具体操作可以类比以下示例代码片段:
假设此时的构造函数仅有以下函数,即public demo(){}不存在的情形:
1 2 3 4 5 6 7 8
| public demo(String str){...} Class clazz =XposedHelpers.findClass("com.example.inner_class_demo.demo",lpparam.classLoader); Constructor constructor = clazz.getConstructor(String.class); XposedHelpers.callMethod(constructor.newInstance("..."),"hidden_fun");
|
- 内部类inner_class
内部类inner_class作为Android编程过程常见的一种编程方式,这里为了demo的全面,也将其列出。其实内部类整个处理过程与普通类极其相似,具体操作可以类比以下示例代码片段:
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
| XposedHelpers.findAndHookMethod("com.example.inner_class_demo.demo$inner_class",lpparam.classLoader, "secret", String.class, boolean.class, new XC_MethodHook() { protectedvoid beforeHookedMethod(MethodHookParam param) throws Throwable { for (int i = 0; i < param.args.length; i++) { XposedBridge.log(" argument is:" + param.args[i]); } int field_result = (int)XposedHelpers.getObjectField(param.thisObject,"pMoney"); XposedBridge.log(String.valueOf(field_result)); } });
|
需要注意的是,这里打印目标函数参数列表的时候,用了XposedBridge.log()。这样的输出方式对日志的长度有限制,即长度不超过1024。特殊场合(比如:文件读取时,需要查看文件的内容)需要注意处理下,不然会出现截断的现象。
- 匿名内部类$inner
同内部类,一般是class_name$1之类,具体可以反编译目标程序查看下。常见的反编译工具,比如:apktool、jeb、baksmali均可以方便达到目的。
- 构造函数
构造函数demo()的处理,可以使用xposed提供的XposedHelpers类,具体操作可以类比以下示例代码片段:
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
| Class clazz =XposedHelpers.findClass("com.example.inner_class_demo.demo",lpparam.classLoader); XposedHelpers.findAndHookConstructor(clazz, new XC_MethodHook() { ... }); ``` 需要注意的是,由于构造函数不同于普通函数,函数名不需要提供(因为与类名相同,xposed框架处理函数名问题)。 6. 同时监控多函数 如果遇到某一类函数需要“批量”hook操作的时候,比如:需要同时监控多个构造函数、多个重载函数,我们此时不可能去挨个hook每个具体目标,那么应该怎么操作呢?我们可以这样来实现: ```java hookAllConstructors(clazz, new XC_MethodHook() { ... }); hookAllMethods(clazz, new XC_MethodHook() { ... });
|
hook重载函数时候,只需要忽略参数的具体类型即可。这种方式其实可以达到两种效果:1. 高效的处理函数重载问题 2.目标函数参数类型太复杂,自定义的类型太多。忽略参数类型,可以简化我们的hook工作。
- 替换方法
只要改变一下回调方式就行了,原来是用XC_MethodHook()回调函数,实现在调用方法前和方法后执行hook代码,而只要把这个回调函数变成XC_MethodReplacement()回调函数,就可以实现直接替换原方法的目的,那么只要在这个回调函数里不加任何代码,就可以实现调用原方法,而不执行其代码的目的。
attachBaseContext.classloader hook
- Multidex勾住技术
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 33 34 35 36 37 38 39 40
| findAndHookMethod(Application.class, "attach", Context.class, newXC_MethodHook() { @Override protectedvoid afterHookedMethod(MethodHookParam param) throws Throwable { findAndHookMethod(class, lpparam.classLoader, method, arg1, arg2, …new XC_MethodHook() { @Override protectedvoid beforeHookedMethod(MethodHookParam param)throws Throwable { Log.d("xposed", "劫持开始了~"); } @Override protectedvoid afterHookedMethod(MethodHookParam param)throws Throwable { } }); } });
|
- 加固APP的勾住
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 33 34 35 36 37 38 39 40 41 42
| if (lpparam.packageName.equals("com.XX.XXbank")) { XposedBridge.log("定位到hook程序"); XposedHelpers.findAndHookMethod("com.secneo.apkwrapper.ApplicationWrapper", lpparam.classLoader, "attachBaseContext", Context.class, new XC_MethodHook() { @Override protectedvoid afterHookedMethod(MethodHookParam param) throwsThrowable { super.afterHookedMethod(param); Context Ctx = (Context) param.args[0]; ClassLoader Clz = Ctx.getClassLoader(); XposedHelpers.findAndHookMethod("com.iss.sdpersonalbank.util.Log", Clz, "d", String.class, String.class, new XC_MethodHook() { @Override protectedvoid beforeHookedMethod(MethodHookParam param) throws Throwable { super.afterHookedMethod(param); String Str1 = (String) param.args[0]; String Str2 = (String) param.args[1]; Log.e(TAG, Str1 + ":" + Str2); } });
|
网络资源学习。。。。