xposed框架

1、概述

hook是Windows中提供的一种用以替换DOS下“中断”的系统机制。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。

Xposed框架核心思想:在于将java层普通函数注册成本地JNI方法,以此来变相实现HOOk机制。

1.1 核心思想

一、Xposed框架的核心原理

修改/system/bin/app-process程序。在android执行第一个程序zygote进程之前进行截获,改变执行流程,进入到自身的Main函数体内。Main函数执行体内主要完成以下四步流程:

  1. initNative(). 为了方便Xposed框架的native方法对上层Java方法的调用,在该部分对相关native方法进行初始化工作。
  2. initXbrigdeZygote().主要hook几个涉及到应用进程创建,启动的关键类。
  3. loadModules,读取系统中放置的hook模块,然后把该模块的路径写进conf/moudules.list中。
  4. Xposed框架加载完毕后,将执行权还给第一个程序zygote,完成正常的系统启动流程。
    (XPOSED的安装器替换安卓系统的app_process文件,从而实现对系统的接管,通过回调模块的方式来达到不用修改APK就能改变其表现行为的目的。该框架比较成熟,对应的模块也非常多,常用的还有模拟地理位置,伪装手机设备信息等,脑洞是非常之大,基本上能想到的都能做到。)

app_process其实是一个程序,存放在systen/bin目录下的,作用就是启动一个程序,启动zygote进程,所有App启动。app_process只要找到需要运行程序的main函数,也就是入口函数,然后执行,他不仅能执行C/C++程序,也可以执行Java程序。

在Android中,zygote是整个系统创建新进程的核心进程。

Android系统是基于Linux内核的,而在Linux系统中,所有的进程都是Zygoteinit进程的子孙进程,也就是说,所有的进程都是直接或者间接地由Zygoteinit进程fork出来的。

由于Xposed框架Hook了Android的核心进程Zygote,而其他应用启动都是从Zygote进程fork而来,就够达到针对系统上所有的应用程序进程的Hook。

1.2 Xposed内部执行流程

  • 创建新应用,获取包名等信息。

  • 调用XC_LoadPackage.callAll,依次执行各hook模块的代码。

  • 如果有包名匹配的hook模块,则注册模块中要hook的方法为本地方法。

  • 当该方被调用的时候,转移到本地xposedCallHandler。

  • xposedCallHandler回调上层handlerHookedMethod(因为加载的hook模块代码,一些变量都存储在java层)。

  • handlerHookedMethod执行加载的各hook模块

beforeHookedMethod 该方法在hook目标方法执行前调用,其中,参数param指的是目标方法的相关参数、回调、方法等信息

afterHookedMethod该方法在hook目标方法执行后调用,其中,参数param指的是目标方法的相关参数、回调、方法等信息。

Xposed运行多个模块对同一个方法进行hook时,框架就会根据Xposed模块的优先级来排序,在具有a.before、a.after、b.before、b.after的情 况下,运行的先后顺序如下:(a优先级高于b)

before -> b.before ->originalMethod -> b.after -> a.after

1
2
3
4
5
6
7
1、如何Hook静态变量
2、如何Hook构造方法
3、如何Hook复杂参数的方法
4、如何替换函数执行内容
5、如何Hook内部类中的函数
6、如何Hook匿名类的函数
7、如何获取调用对象去调用函数,或者新建新建示例去调用方法

学会这些方法,在结合逆向smail的一些知识,应该可以满足大多数java层的hook了。

2. API

  1. IXposedHookLoadPackage

    方法: handleLoadPackage,这个方法用于在加载应用程序的包的时候执行用户的操作

    参数说明: final LoadPackageParam lpparam 这个参数包含了加载的应用程序的一些基本信息.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    方法: findAndHookMethod,这是一个辅助方法,可以通过静态导入使用

    参数说明: findAndHookMethod(Class<?> clazz, ClassLoader, methodName, Object…, parameterTypesAndCallback )


    Class<?> clazz, //需要 Hook 的类名;

    ClassLoader,//类加载器,可以设置为 null String;

    methodName, //需要 Hook 的方法名;

    Object…,//对象类型;

    parameterTypesAndCallback //回调方法
  2. XposedBridge

    方法: log(),打日志。

    该方法可以将 log 信息以及 Throwable 抛出的异常信息输出到标准的logcat 以及/data/xposed/debug.log 这个文件中

    无参方法: hookAllMethods/hookAllConstructors,该方法可以用来 hook 某个类中的所有方法或者构造函数,但是不同的Rom(非Android原生 Rom)会有不同的变种。

  3. XC_LoadPackage.LoadPackageParam

    fields type description
    packageName String 应用包名
    processName String 应用加载后的进程名
    classLoader ClassLoader 应用的classloader
    appInfo ApplicationInfo 应用的信息,包括verisonCode,uid等
  1. IXposedHookInitPackageResources

    XposedHookInitPackageResources的resparam参数有以下两个字段

    field type description
    packageName String 应用包名
    res XResources 资源相关
  1. XposedHelpers

    • 查找类

      1
      2
      3
      4
      //className  完整类名,classLoader 类加载器(app应用的类加载器)
      public static Class<?> findClass(String className, ClassLoader classLoader)

      public static Class<?> findClassIfExists(String className, ClassLoader classLoader)
    • 查找字段

      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
      // clazz 通过findClass获取,调用findFieldRecursiveImpl获取
      private static Field findFieldRecursiveImpl(Class<?> clazz, String fieldName) throws NoSuchFieldException {
      try {
      return clazz.getDeclaredField(fieldName);
      } catch (NoSuchFieldException e) {
      while (true) {
      clazz = clazz.getSuperclass();
      if (clazz == null || clazz.equals(Object.class))
      break;

      try {
      return clazz.getDeclaredField(fieldName);
      } catch (NoSuchFieldException ignored) {}
      }
      throw e;
      }
      }

      public static Field findFirstFieldByExactType(Class<?> clazz, Class<?> type)

      //获取实例字段的引用
      public static Object getObjectField(Object obj, String fieldName)

      /*获取Field的方法,具体实现是在findFieldRecursiveImpl方法里面获取,外部不能访问,Field是通过getDeclaredField获取,所以只能获取static类型的字段。indFirstFieldByExactType()方法是匹配Field的classType,如果类型一样,则返回该字段,该方法的局限性是只能获取到第一个匹配到的字段,后面相同类型的无法获取*/

    • 设置字段

      1
      2
      3
      4
      public static void setXXXField(Object obj, String fieldName, XXX value)
      public static void setStaticXXXField(Class<?> clazz, String fieldName, XXX value)
      public static Xxx getXxxField(Object obj, String fieldName)
      public static Xxx getStaticXxxField(Class<?> clazzj, String fieldName)
    • 查找方法

      1
      2
      3
      public static Method findMethodExact(Class<?> clazz, String methodName, Object... parameterTypes) 

      public static Method findMethodExactIfExists(Class<?> clazz, String methodName, Object... parameterTypes)
    • 调用方法

      1
      2
      3
      4
      5
      6
      7
      public static Object callMethod(Object obj, String methodName, Object... args)

      public static Object callMethod(Object obj, String methodName, Class<?>[] parameterTypes, Object... args)

      public static Object callStaticMethod(Class<?> clazz, String methodName, Object... args)

      public static Object callStaticMethod(Class<?> clazz, String methodName, Class<?>[] parameterTypes, Object... args)
    • 调用实例/静态Method,返回值为方法返回值

      1
      2
      3
      4
      5
      public static XC_MethodHook.Unhook findAndHookMethod(Class<?> clazz, String methodName, Object... parameterTypesAndCallback)

      //通过className和classLoader获取Class<?> ,再调用上面的方法
      public static XC_MethodHook.Unhook findAndHookMethod(String className, ClassLoader classLoader, String methodName, Object... parameterTypesAndCallback)

      Hook方法的一个方法,其中parameterTypesAndCallback和findConstructorExact方法的parameterTypes类似,不过这里可变数组最后一个对象必须为XC_MethodHook对象或者其子类,前面的对象为参数的ClassType或者类字符串,在hook成功后,当调用hook的方法时,会在XC_MethodHook回调。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      public abstract class XC_MethodHook extends XCallback {
      @Override
      protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
      //方法调用前的回调
      super.beforeHookedMethod(param);
      }

      @Override
      protected void afterHookedMethod(MethodHookParam param) throws Throwable {
      //方法调用后的回调
      super.afterHookedMethod(param);
      }
      }

      public abstract class XC_MethodReplacement extends XC_MethodHook{
      @Override
      protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
      //带返回值的方法执行时调用
      return null;
      }
      }

    • hook构造器

      1
      2
      3
      4
      5
      6
      public static Constructor<?> findConstructorExact(Class<?> clazz, Object... parameterTypes)

      public static Constructor<?> findConstructorExactIfExists(Class<?> clazz, Object... parameterTypes)

      public static Constructor<?> findConstructorBestMatch(Class<?> clazz, Class<?>... parameterTypes)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      /*获取Constructor方法,其中Object... parameterTypes 是一个Object的可变数组,parameterTypes由Class<?>的可变数组 ,完整类名字符串和XC_MethodHook抽象类 组成。XC_MethodHook为可选参数,并且总在最后一个。XC_MethodHook在这里并无实际意义,Class<?>[] 为相应的构造函数的类型,通过一个例子简单说明,有一个T类,构造函数有三个参数,可以用以下几种方式获取:*/

      public class T {
      String str;
      Context mContext;
      View mView;

      public T(String str, Context context, View view) {
      this.str = str;
      mContext = context;
      mView = view;

      }

      }

      //方式1:
      Constructor constructor = XposedHelpers.findConstructorExact(clazz, String.class, Context.class, View.class);

      //方式2:
      Constructor constructor = XposedHelpers.findConstructorExact(T.class, String.class, "android.content.Context", View.class);

      //方式3:(XC_MethodHook无实际意义)
      Constructor constructor = XposedHelpers.findConstructorExact(T.class, String.class, "android.content.Context", View.class, new XC_MethodHook() {});

3. Hook加固APP

一.hook原理

使用加固之后的应用的classloader会被换成其加固应用本身的,所以只需要在hook的时候把classloader换成壳的就可以了。

二.具体操作和分析

被加固的应用是可以反编译的,反编译之后dex里面只有很少的几个类,比较重要的就是壳入口这个类,可以在这个类里面的里面去获取context参数,然后就可以通过context获得到壳的类加载器,之后只需要用这个类加载器来hook就可以成功的hook到加固的app

注:

Android源码中android.app.Applocation 188行,attachBaseContext方法在Application的attach方法被调用,基本上所有的壳都会在attachBaseContext里完成代码解密并且内存加载dex,所以在
attachBaseContext执行之后,拿到的classloader就已经加载过加固dex的classloader。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
               XposedHelpers.findAndHookMethod("com.tencent.StubShell.TxAppEntry", loadPackageParam.classLoader,
"attachBaseContext", Context.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
//获取到Context对象,通过这个对象来获取classloader
Context context = (Context) param.args[0];
//获取classloader,之后hook加固后的就使用这个classloader
ClassLoader classLoader =context.getClassLoader();
//下面就是强classloader修改成壳的classloader就可以成功的hook了
XposedHelpers.findAndHookMethod("xxx.xxx.xxx.xxx", classLoader, "xxx", String.class, String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
LogUtils.log( "key: " + (String) param.args[0]);
LogUtils.log( "value: " + (String) param.args[1]);
param.setResult((String) param.args[1]);
}
});

}

}
}

3. 获取所有类

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
43
44
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public String[] getClass(ClassLoader classLoader){
int i;
int j;
int k;
try {
//取得PathClassLoader的pathList的属性
Field pathList = classLoader.getClass().getSuperclass().getDeclaredField("pathList");
pathList.setAccessible(true);
// 取得PathClassLoader的pathList的属性真实值(得到一个DexPathList对象)
Object dexPathListObj=pathList.get(classLoader);
//获得DexPathList中的dexElements 属性
Field dexElementsField = dexPathListObj.getClass().getDeclaredField("dexElements");
dexElementsField.setAccessible(true);
// 获得DexPathList对象中dexElements 属性的真实值
Object dexElements_objs=dexElementsField.get(dexPathListObj);

for (i=0; i<Array.getLength(dexElements_objs);i++){
Object dexElements_obj=Array.get(dexElements_objs,i);
Field dexfileField =dexElements_obj.getClass().getDeclaredField("dexFile");
dexfileField.setAccessible(true);
Object clz=dexfileField.get(dexElements_obj);
Method[] methods=clz.getClass().getDeclaredMethods();
for (j=0;j<methods.length;j++){
Method method=methods[j];
if (method.getName().equalsIgnoreCase("getClassNameList")){
method.setAccessible(true);
Field mCookieField = clz.getClass().getDeclaredField("mCookie");
mCookieField.setAccessible(true);
Object classoes_bj=method.invoke(clz,mCookieField.get(clz));
int classes_len=Array.getLength(classoes_bj);
String[] classes=new String[classes_len];
for (k=0;k<classes_len;k++){
classes[k]= (String) Array.get(classoes_bj,k);
}
return classes;
}
}
}
} catch (NoSuchFieldException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return new String[0];
}

4. Hook所有方法

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package com.xposed.enumeratorClassHook;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XC_MethodHook.MethodHookParam;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;

// 自定义的回调函数接口
public class Module implements IXposedHookLoadPackage {

static String strClassName = "";

@Override
public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable {

// 被Hook操作的目标Android应用的包名,进行Hook操作的过滤
String strPackageName = "com.guji.loveparty";
if (lpparam.packageName.equals(strPackageName)) {

XposedBridge.log("Loaded App:" + lpparam.packageName);
findAndHookMethod(ClassLoader.class, "loadClass", String.class, new XC_MethodHook() {

// 在类方法loadClass执行之后执行的代码
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {

// 参数的检查
if (param.hasThrowable()) {
return;
}

// 获取指定名称的类加载之后的Class<?>
Class<?> clazz = (Class<?>) param.getResult();
// 获取加载的指定类的名称
String strClazz = clazz.getName();
XposedBridge.log("LoadClass : "+strClazz);
// 所有的类都是通过loadClass方法加载的
// 过滤掉Android系统的类以及一些常见的java类库
if (!strClazz.startsWith("android.")
&& !strClazz.startsWith(".system")
&& !strClazz.startsWith("java.")
&& !strClazz.startsWith("org.")
&& !strClazz.contains("umeng.")
&& !strClazz.contains("com.google")
&& !strClazz.contains(".alipay")
&& !strClazz.contains(".netease")
&& !strClazz.contains(".alibaba")
&& !strClazz.contains(".pgyersdk")
&& !strClazz.contains(".daohen")
&& !strClazz.contains(".bugly")
&& !strClazz.contains("mini")
&& !strClazz.contains("xposed")) {
// 或者只Hook加密算法类、网络数据传输类、按钮事件类等协议分析的重要类

// 同步处理一下
synchronized (this.getClass()) {

// 获取被Hook的目标类的名称
strClassName = strClazz;
//XposedBridge.log("HookedClass : "+strClazz);
// 获取到指定名称类声明的所有方法的信息
Method[] m = clazz.getDeclaredMethods();
// 打印获取到的所有的类方法的信息
for (int i = 0; i < m.length; i++) {

// 过滤掉指定名称类中声明的抽象方法
if (!Modifier.isAbstract(m[i].getModifiers())
// 过滤掉指定名称类中声明的Native方法
&& !Modifier.isNative(m[i].getModifiers())
// 过滤掉指定名称类中声明的接口方法
&& !Modifier.isInterface(m[i].getModifiers())
) {

// 对指定名称类中声明的非抽象方法进行java Hook处理
XposedBridge.hookMethod(m[i], new XC_MethodHook() {

// 被java Hook的类方法执行完毕之后,打印log日志
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {

// 打印被java Hook的类方法的名称和参数类型等信息
XposedBridge.log("HOOKED METHOD: "+strClassName+"-"+param.method.toString());
}
});
}
}
}

}
}
});
}

}

// 获取指定名称的类声明的类成员变量、类方法、内部类的信息
public void dumpClass(Class<?> actions) {

XposedBridge.log("Dump class " + actions.getName());
XposedBridge.log("Methods");

// 获取到指定名称类声明的所有方法的信息
Method[] m = actions.getDeclaredMethods();
// 打印获取到的所有的类方法的信息
for (int i = 0; i < m.length; i++) {

XposedBridge.log(m[i].toString());
}

XposedBridge.log("Fields");
// 获取到指定名称类声明的所有变量的信息
Field[] f = actions.getDeclaredFields();
// 打印获取到的所有变量的信息
for (int j = 0; j < f.length; j++) {

XposedBridge.log(f[j].toString());
}

XposedBridge.log("Classes");
// 获取到指定名称类中声明的所有内部类的信息
Class<?>[] c = actions.getDeclaredClasses();
// 打印获取到的所有内部类的信息
for (int k = 0; k < c.length; k++) {

XposedBridge.log(c[k].toString());
}
}
}

5、XposedHook程序源码

HookDemo.java

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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);
}
}
}
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
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,
// 1、修改参数
// 2、修改下publicInt和privateInt的值
// 3、再顺便调用一下隐藏函数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());
}
}
}

6.参考文献

hook所有方法

热修补