转载:看雪论坛 堂前燕:https://bbs.pediy.com/thread-252153.htm
Xposed 模块编写的那些事:https://www.freebuf.com/articles/terminal/114910.html
看了很多 xposed的教程,自以为掌握了个大概,直到今天整理,练习时才发现自己不过是眼高手低,有太多的东西需要学习了。路漫漫,还需脚踏实地!
没有找到合适样本,自己写了个简单的类练手。
abstract class person{public int age=0;public void eat(String food){};
}public class HookGoal {private static String TAG="HookGoal:";private int hookGoalNumber;public HookGoal(int number){hookGoalNumber=number;Log.i(TAG,"HookGoal hookGoalNumber:"+hookGoalNumber);}public void func0(){Log.i(TAG,"welcome");}private void func1(){new person(){@Overridepublic void eat(String food) {Log.i(TAG,"eat "+food);}}.eat("apple");}private static void func2(String s){Log.i(TAG,"func2 "+s);}private void func3(DiyClass[] arry){for(int i=0;i<arry.length;i++)Log.i(TAG,"DiyClass["+i+"].getData:"+arry[i].getData());}private class InnerClass{private int innerNumber;public InnerClass(String s){innerNumber=0;Log.i(TAG,"InnerClass 构造函数 "+s);Log.i(TAG,"InnerClass innerNumber:"+innerNumber);}private void innerFunc(String s){Log.i(TAG,"InnerClass innerFunc "+s);}}public void show(){func1();func2("私有静态方法");DiyClass[] arry={new DiyClass(0),new DiyClass(0),new DiyClass(0)};func3(arry);InnerClass inner=new InnerClass("私有内部类");inner.innerFunc("内部类方法调用");}}public class DiyClass{private int data;public DiyClass(int data){this.data=data;}public int getData() {return data;}public void setData(int data) {this.data = data;}
}
要干下面几件事:
- hook HookGoal类的构造函数,修改静态属性TAG
- hook 私有成员方法func1内的匿名内部类的eat()方法 ,修改匿名内部类的age值
- hook 私有静态方法func2 ,调用成员方法func0()、调用DiyClass类的成员方法getData()
- hook 私有成员方法func3 参数为自定义类型数组,修改参数、 调用成员方法func0()
- hook 内部类InnerClass的构造函数(经论坛大哥指点已经可以),hook内部类innerFunc方法
public class HookMain implements IXposedHookLoadPackage {Context context;@Overridepublic void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {XposedBridge.log("HookMain begain");if (!lpparam.packageName.equals("com.example.goal")) {Log.i("失败", "未找到包");XposedBridge.log("未找到包" );return;}Log.i("begin","hook is begaining");//hook context 后面可使用ToastXposedHelpers.findAndHookMethod(ContextThemeWrapper.class, "attachBaseContext",Context.class, new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {context=(Context) param.args[0];}});final Class<?> clazz=findClass("com.example.goal.HookGoal",lpparam.classLoader);//hook 有参构造函数XposedHelpers.findAndHookConstructor(clazz,int.class,new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {//修改构造函数参数param.args[0]=666;//设置 TAG为hookingsetStaticObjectField(clazz,"TAG","hooking");}});Class nminner=findClass("com.example.goal.HookGoal$1",clazz.getClassLoader());//hook 匿名内部类的eat()方法findAndHookMethod(nminner, "eat",String.class, new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {param.args[0]="is hooking";//修改匿名内部类的age属性Log.i("nminner","修改前age值:"+getIntField(param.thisObject,"age"));setIntField(param.thisObject,"age",666);Log.i("nminner","修改后age值:"+getIntField(param.thisObject,"age"));}});final Class diy=findClass("com.example.goal.DiyClass",lpparam.classLoader);final Constructor init=diy.getConstructor(int.class);findAndHookMethod(clazz, "func2",String.class, new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {//hook 静态方法参数param.args[0]="is hooking";//调用func0方法XposedHelpers.callMethod(clazz.getConstructor(int.class).newInstance(666),"func0");Log.i("hooking","way1 (静态方法中)创建新对象调用func0");//调用外部 DiyClass的getData()int data=(int)callMethod(init.newInstance(666),"getData");Log.i("hooking","调用DiyClass中getData() 返回值:"+data);}});//hook 自定义类型数组参数Class diyClassArray= Array.newInstance(diy,3).getClass();findAndHookMethod(clazz, "func3", diyClassArray, new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {//调用func0方法XposedHelpers.callMethod(param.thisObject,"func0");Log.i("hooking","way2 (成员方法中)当前对象调用func0");//自定义类型数组Object a=Array.newInstance(diy,3);for(int i=0;i<3;i++)Array.set(a,i,init.newInstance(666));param.args[0]=diyClassArray.cast(a);Log.i("func3",param.args[0].toString());Log.i("hooking","func3修改参数");}});Class inner=findClass("com.example.goal.HookGoal$InnerClass",clazz.getClassLoader());findAndHookConstructor(inner,clazz, String.class, new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {//修改内部类构造函数中的参数param.args[1]="is hooking";Log.i("inner Constructor",""+param.args[1]);}@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {//在内部类构造函数中修改innerNumber值Log.i("inner Constructor","修改前的innerNumber:"+getIntField(param.thisObject,"innerNumber"));// Log.i("inner Constructor",""+param.thisObject);setIntField(param.thisObject,"innerNumber",6);Log.i("inner Constructor","修改后的innerNumber:"+getIntField(param.thisObject,"innerNumber"));}});findAndHookMethod(inner, "innerFunc", String.class, new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {param.args[0]="is hooking";Log.i("innerFunc","修改前的innerNumber:"+getIntField(param.thisObject,"innerNumber"));setIntField(param.thisObject,"innerNumber",666);Log.i("innerFunc","修改后的innerNumber:"+getIntField(param.thisObject,"innerNumber"));Log.i("innerFunc",""+param.args[0]);}});}
}
hook 前 Log
com.example.goal I/HookGoal:: HookGoal hookGoalNumber:0
com.example.goal I/HookGoal:: eat apple
com.example.goal I/HookGoal:: func2 私有静态方法
com.example.goal I/HookGoal:: DiyClass[0].getData:0
com.example.goal I/HookGoal:: DiyClass[1].getData:0
com.example.goal I/HookGoal:: DiyClass[2].getData:0
com.example.goal I/HookGoal:: InnerClass 构造函数 私有内部类
com.example.goal I/HookGoal:: InnerClass innerNumber:0
com.example.goal I/HookGoal:: InnerClass innerFunc 内部类方法调用
hook 后 Log
com.example.goal I/hooking: HookGoal hookGoalNumber:666
com.example.goal I/hooking: eat is hooking
com.example.goal I/hooking: HookGoal hookGoalNumber:666
com.example.goal I/hooking: welcome
com.example.goal I/hooking: 调用DiyClass中getData() 返回值:666
com.example.goal I/hooking: func2 is hooking
com.example.goal I/func3: [Lcom.example.goal.DiyClass;@4a89752c
com.example.goal I/hooking: func3修改参数
com.example.goal I/hooking: DiyClass[0].getData:666
com.example.goal I/hooking: DiyClass[1].getData:666
com.example.goal I/hooking: DiyClass[2].getData:666
com.example.goal I/inner Constructor: is hooking
com.example.goal I/hooking: InnerClass 构造函数 is hooking
com.example.goal I/hooking: InnerClass innerNumber:0
com.example.goal I/inner Constructor: 修改前的innerNumber:0
com.example.goal I/inner Constructor: 修改后的innerNumber:6
com.example.goal I/innerFunc: 修改前的innerNumber:6
com.example.goal I/innerFunc: 修改后的innerNumber:666
com.example.goal I/innerFunc: is hooking
com.example.goal I/hooking: InnerClass innerFunc is hooking
错误之处,还请不吝赐教,十分感谢!
同时也希望有疑惑的同学留下你的问题,大家多多交流。
实践是检验真理的唯一标准,今后还要勤加练习,多多实战。
计划:
- 掌握Java层xposed hook及原理
- 掌握native层frida hook及原理
- 自己实现hook框架
学如逆水行舟,不进则退。与君共勉!