閱讀本文前,假設讀者已經看過Android Studio Xposed模塊編寫(一) 相關環境已經搭建完成。本文演示案例與上文環境一致,不在贅述。html
Xposed是很是牛叉的一款hook框架,本人也是剛剛接觸,在網上搜索一些資料,發現寫的都不是太全面,因而蒐集該框架的用法,總結出該文。若有紕漏,還請輕拍,主要內容包括java
1、如何Hook靜態變量 2、如何Hook構造方法 3、如何Hook複雜參數的方法 4、如何替換函數執行內容 5、如何Hook內部類中的函數 6、如何Hook匿名類的函數 七、如何獲取調用對象去調用函數,或者新建新建示例去調用方法
學會這些方法,在結合逆向smail的一些知識,應該能夠知足大多數java層的hook了。話很少說,上代碼!git
HookDemo.javagithub
abstract class Animal{ int anonymoutInt = 500; public abstract void eatFunc(String value); } public class HookDemo { private String Tag = "HookDemo"; private static int staticInt = 100; public int publicInt = 200; private int privateInt = 300; public HookDemo(){ this("NOHook"); Log.d(Tag, "HookDemo() was called|||"); } private HookDemo(String str){ Log.d(Tag, "HookDemo(String str) was called|||" + str); } public void hookDemoTest(){ Log.d(Tag, "staticInt = " + staticInt); Log.d(Tag, "PublicInt = " + publicInt); Log.d(Tag, "privateInt = " + privateInt); publicFunc("NOHook"); Log.d(Tag, "PublicInt = " + publicInt); Log.d(Tag, "privateInt = " + privateInt); privateFunc("NOHook"); staticPrivateFunc("NOHook"); String[][] str = new String[1][2]; Map map = new HashMap<String, String>(); map.put("key", "value"); ArrayList arrayList = new ArrayList(); arrayList.add("listValue"); complexParameterFunc("NOHook", str, map, arrayList); repleaceFunc(); anonymousInner(new Animal() { @Override public void eatFunc(String value) { Log.d(Tag, "eatFunc(String value) was called|||" + value); Log.d(Tag, "anonymoutInt = " + anonymoutInt); } }, "NOHook"); InnerClass innerClass = new InnerClass(); innerClass.InnerFunc("NOHook"); } public void publicFunc(String value){ Log.d(Tag, "publicFunc(String value) was called|||" + value); } private void privateFunc(String value){ Log.d(Tag, "privateFunc(String value) was called|||" + value); } static private void staticPrivateFunc(String value){ Log.d("HookDemo", "staticPrivateFunc(Strin value) was called|||" + value); } private void complexParameterFunc(String value, String[][] str, Map<String,String> map, ArrayList arrayList) { Log.d("HookDemo", "complexParameter(Strin value) was called|||" + value); } private void repleaceFunc(){ Log.d(Tag, "repleaceFunc will be replace|||"); } public void anonymousInner(Animal dog, String value){ Log.d(Tag, "anonymousInner was called|||" + value); dog.eatFunc("NOHook"); } private void hideFunc(String value){ Log.d(Tag, "hideFunc was called|||" + value); } class InnerClass{ public int innerPublicInt = 10; private int innerPrivateInt = 20; public InnerClass(){ Log.d(Tag, "InnerClass constructed func was called"); } public void InnerFunc(String value){ Log.d(Tag, "InnerFunc(String value) was called|||" + value); Log.d(Tag, "innerPublicInt = " + innerPublicInt); Log.d(Tag, "innerPrivateInt = " + innerPrivateInt); } } }
public class XposedHook implements IXposedHookLoadPackage { @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable { if (loadPackageParam.packageName.equals("com.example.xposedhooktarget")) { final Class<?> clazz = XposedHelpers.findClass("com.example.xposedhooktarget.HookDemo", loadPackageParam.classLoader); //getClassInfo(clazz); //不須要獲取類對象,便可直接修改類中的私有靜態變量staticInt XposedHelpers.setStaticIntField(clazz, "staticInt", 99); //Hook無參構造函數,啥也不幹。。。。 XposedHelpers.findAndHookConstructor(clazz, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { XposedBridge.log("Haha, HookDemo constructed was hooked" ); //大坑,此時對象尚未創建,即不能獲取對象,也不能修改非靜態變量的值 //XposedHelpers.setIntField(param.thisObject, "publicInt", 199); //XposedHelpers.setIntField(param.thisObject, "privateInt", 299); } }); //Hook有參構造函數,修改參數 XposedHelpers.findAndHookConstructor(clazz, String.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { param.args[0] = "Haha, HookDemo(str) are hooked"; } }); //Hook有參構造函數,修改參數------不能使用XC_MethodReplacement()替換構造函數內容, //XposedHelpers.findAndHookConstructor(clazz, String.class, new XC_MethodReplacement() { // @Override // protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable { // Log.d("HookDemo" , "HookDemo(str) was replace"); // } //}); //Hook公有方法publicFunc, // 一、修改參數 // 二、修改下publicInt和privateInt的值 // 三、再順便調用一下隱藏函數hideFunc //XposedHelpers.findAndHookMethod("com.example.xposedhooktarget.HookDemo", clazz.getClassLoader(), "publicFunc", String.class, new XC_MethodHook() XposedHelpers.findAndHookMethod(clazz, "publicFunc", String.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { param.args[0] = "Haha, publicFunc are hooked"; XposedHelpers.setIntField(param.thisObject, "publicInt", 199); XposedHelpers.setIntField(param.thisObject, "privateInt", 299); // 讓hook的對象自己去執行流程 Method md = clazz.getDeclaredMethod("hideFunc", String.class); md.setAccessible(true); //md.invoke(param.thisObject, "Haha, hideFunc was hooked"); XposedHelpers.callMethod(param.thisObject, "hideFunc", "Haha, hideFunc was hooked"); //實例化對象,而後再調用HideFunc方法 //Constructor constructor = clazz.getConstructor(); //XposedHelpers.callMethod(constructor.newInstance(), "hideFunc", "Haha, hideFunc was hooked"); } }); //Hook私有方法privateFunc,修改參數 //XposedHelpers.findAndHookMethod("com.example.xposedhooktarget.HookDemo", clazz.getClassLoader(), "privateFunc", String.class, new XC_MethodHook() XposedHelpers.findAndHookMethod(clazz, "privateFunc", String.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { param.args[0] = "Haha, privateFunc are hooked"; } }); //Hook私有靜態方法staticPrivateFunc, 修改參數 XposedHelpers.findAndHookMethod(clazz, "staticPrivateFunc", String.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { param.args[0] = "Haha, staticPrivateFunc are hooked"; } }); //Hook複雜參數函數complexParameterFunc Class fclass1 = XposedHelpers.findClass("java.util.Map", loadPackageParam.classLoader); Class fclass2 = XposedHelpers.findClass("java.util.ArrayList", loadPackageParam.classLoader); XposedHelpers.findAndHookMethod(clazz, "complexParameterFunc", String.class, "[[Ljava.lang.String;", fclass1, fclass2, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { param.args[0] = "Haha, complexParameterFunc are hooked"; } }); //Hook私有方法repleaceFunc, 替換打印內容 XposedHelpers.findAndHookMethod(clazz, "repleaceFunc", new XC_MethodReplacement() { @Override protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable { Log.d("HookDemo", "Haha, repleaceFunc are replaced"); return null; } }); //Hook方法, anonymousInner, 參數是抽象類,先加載所須要的類便可 Class animalClazz = loadPackageParam.classLoader.loadClass("com.example.xposedhooktarget.Animal"); XposedHelpers.findAndHookMethod(clazz, "anonymousInner", animalClazz, String.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { XposedBridge.log("HookDemo This is test"); param.args[1] = "Haha, anonymousInner are hooked"; } }); //Hook匿名類的eatFunc方法,修改參數,順便修改類中的anonymoutInt變量 XposedHelpers.findAndHookMethod("com.example.xposedhooktarget.HookDemo$1", clazz.getClassLoader(), "eatFunc", String.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { param.args[0] = "Haha, eatFunc are hooked"; XposedHelpers.setIntField(param.thisObject, "anonymoutInt", 499); } }); //hook內部類的構造方法失敗,且會致使hook內部類的InnerFunc方法也失敗,緣由不明 // XposedHelpers.findAndHookConstructor(clazz1, new XC_MethodHook() { // @Override // protected void beforeHookedMethod(MethodHookParam param) throws Throwable { // XposedBridge.log("Haha, InnerClass constructed was hooked" ); // } // }); //Hook內部類InnerClass的InnerFunc方法,修改參數,順便修改類中的innerPublicInt和innerPrivateInt變量 final Class<?> clazz1 = XposedHelpers.findClass("com.example.xposedhooktarget.HookDemo$InnerClass", loadPackageParam.classLoader); XposedHelpers.findAndHookMethod(clazz1, "InnerFunc", String.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { param.args[0] = "Haha, InnerFunc was hooked"; XposedHelpers.setIntField(param.thisObject, "innerPublicInt", 9); XposedHelpers.setIntField(param.thisObject, "innerPrivateInt", 19); } }); } } private void getClassInfo(Class clazz) { //getFields()與getDeclaredFields()區別:getFields()只能訪問類中聲明爲公有的字段,私有的字段它沒法訪問, //能訪問從其它類繼承來的公有方法.getDeclaredFields()能訪問類中全部的字段,與public,private,protect無關, //不能訪問從其它類繼承來的方法 //getMethods()與getDeclaredMethods()區別:getMethods()只能訪問類中聲明爲公有的方法,私有的方法它沒法訪問, //能訪問從其它類繼承來的公有方法.getDeclaredFields()能訪問類中全部的字段,與public,private,protect無關, //不能訪問從其它類繼承來的方法 //getConstructors()與getDeclaredConstructors()區別:getConstructors()只能訪問類中聲明爲public的構造函數 //getDeclaredConstructors()能訪問類中全部的構造函數,與public,private,protect無關 //XposedHelpers.setStaticObjectField(clazz,"sMoney",110); //Field sMoney = clazz.getDeclaredField("sMoney"); //sMoney.setAccessible(true); Field[] fs; Method[] md; Constructor[] cl; fs = clazz.getFields(); for (int i = 0; i < fs.length; i++) { XposedBridge.log("HookDemo getFiled: " + Modifier.toString(fs[i].getModifiers()) + " " + fs[i].getType().getName() + " " + fs[i].getName()); } fs = clazz.getDeclaredFields(); for (int i = 0; i < fs.length; i++) { XposedBridge.log("HookDemo getDeclaredFields: " + Modifier.toString(fs[i].getModifiers()) + " " + fs[i].getType().getName() + " " + fs[i].getName()); } md = clazz.getMethods(); for (int i = 0; i < md.length; i++) { Class<?> returnType = md[i].getReturnType(); XposedBridge.log("HookDemo getMethods: " + Modifier.toString(md[i].getModifiers()) + " " + returnType.getName() + " " + md[i].getName()); //獲取參數 //Class<?> para[] = md[i].getParameterTypes(); //for (int j = 0; j < para.length; ++j) { //System.out.print(para[j].getName() + " " + "arg" + j); //if (j < para.length - 1) { // System.out.print(","); //} //} } md = clazz.getDeclaredMethods(); for (int i = 0; i < md.length; i++) { Class<?> returnType = md[i].getReturnType(); XposedBridge.log("HookDemo getDeclaredMethods: " + Modifier.toString(md[i].getModifiers()) + " " + returnType.getName() + " " + md[i].getName()); } cl = clazz.getConstructors(); for (int i = 0; i < cl.length; i++) { XposedBridge.log("HookDemo getConstructors: " + Modifier.toString(cl[i].getModifiers()) + " " + md[i].getName()); } cl = clazz.getDeclaredConstructors(); for (int i = 0; i < cl.length; i++) { XposedBridge.log("HookDemo getDeclaredConstructors: " + Modifier.toString(cl[i].getModifiers()) + " " + md[i].getName()); } } }
Hook目標程序源碼https://github.com/Gordon0918/XposedHookTarget框架
Hook程序源碼https://github.com/Gordon0918/XposedHookide