前言
LSPosed项目目前开发者仍在积极维护,在支持了使用Xposed API方式开发模块的同时,也支持不需重启就可让Hook代码生效,极大地提高了开发效率.
其Xposed API官方地址如下:
https://api.xposed.info/reference/packages.html
下面通过一个示例,来展示下LSPosed Java层的Hook流程.
测试Apk
Person.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
package com.example.luodst ;
public class Person {
private String name = "LuoHun" ;
private int age = 18 ;
public Person (){
}
public Person ( String name , int age ){
this . name = name ;
this . age = age ;
}
// Invoke
public String publicMethod (){
return String . format ( "publicMethod name:%s age:%d" , this . name , this . age );
}
private String privateMethod (){
return String . format ( "privateMethod name:%s age:%d" , this . name , this . age );
}
public static String publicStaticMethod (){
return "I'm from publicStaticMethod" ;
}
public String getName ( Person person ){
return "Person name is " + person . name ;
}
public String toString (){
return String . format ( "name:%s age:%d" , this . name , this . age );
}
public String replaceFunc (){
return String . format ( "replaceFunc name:%s age:%d" , this . name , this . age );
}
class Student {
String course = "Math" ;
public String getCourse (){
return course ;
}
}
}
MainActivity.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
package com.example.luodst ;
import androidx.appcompat.app.AppCompatActivity ;
import android.os.Bundle ;
import android.util.Log ;
import android.widget.TextView ;
import com.example.luodst.databinding.ActivityMainBinding ;
public class MainActivity extends AppCompatActivity {
private final String TAG = "[XiaLuoHun]" ;
// Used to load the 'luodst' library on application startup.
static {
System . loadLibrary ( "luodst" );
}
private ActivityMainBinding binding ;
@Override
protected void onCreate ( Bundle savedInstanceState ) {
super . onCreate ( savedInstanceState );
binding = ActivityMainBinding . inflate ( getLayoutInflater ());
setContentView ( binding . getRoot ());
// Example of a call to a native method
TextView tv = binding . sampleText ;
tv . setText ( stringFromJNI ());
Person person1 = new Person ();
Log . i ( TAG , person1 . toString ());
Person person2 = new Person ( "Luo" , 50 );
Log . i ( TAG , person2 . toString ());
String personName = person2 . getName ( person1 );
Log . i ( TAG , personName );
String strResult = person2 . replaceFunc ();
Log . i ( TAG , strResult );
}
/**
* A native method that is implemented by the 'luodst' native library,
* which is packaged with this application.
*/
public native String stringFromJNI ();
}
Hook构造函数
对Java中构造函数的Hook主要借助于Xposed API中XposedHelpers.findAndHookConstructor函数.
1
2
findAndHookConstructor ( Class <?> clazz , Object ... parameterTypesAndCallback )
findAndHookConstructor ( String className , ClassLoader classLoader , Object ... parameterTypesAndCallback )
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
package com.example.luoxposeddemo ;
import android.util.Log ;
import java.lang.reflect.Field ;
import de.robv.android.xposed.IXposedHookLoadPackage ;
import de.robv.android.xposed.XC_MethodHook ;
import de.robv.android.xposed.XposedBridge ;
import de.robv.android.xposed.XposedHelpers ;
import de.robv.android.xposed.callbacks.XC_LoadPackage ;
public class LuoHook implements IXposedHookLoadPackage {
private final String TAG = "[LuoXposed]" ;
@Override
public void handleLoadPackage ( XC_LoadPackage . LoadPackageParam lpparam ) throws Throwable {
if ( lpparam . packageName . equals ( "com.example.luodst" )) {
//寻找类 方式一
//Class personClass = lpparam.classLoader.loadClass("com.example.luodst.Person");
//寻找类 方式二
Class personClass = XposedHelpers . findClass ( "com.example.luodst.Person" , lpparam . classLoader );
//Hook Person()
XposedHelpers . findAndHookConstructor ( personClass , new XC_MethodHook () {
@Override
protected void beforeHookedMethod ( MethodHookParam param ) throws Throwable {
super . beforeHookedMethod ( param );
//输出日志的两种方式
Log . i ( TAG , "Enter Person()" );
XposedBridge . log ( "Enter Person()" );
}
@Override
protected void afterHookedMethod ( MethodHookParam param ) throws Throwable {
super . afterHookedMethod ( param );
Log . i ( TAG , "Leave Person()" );
XposedBridge . log ( "Leave Person()" );
}
});
//Hook Person(String name, int age)
XposedHelpers . findAndHookConstructor ( personClass , lpparam . classLoader , String . class , int . class , new XC_MethodHook () {
@Override
protected void beforeHookedMethod ( MethodHookParam param ) throws Throwable {
super . beforeHookedMethod ( param );
Log . i ( TAG , "Enter Person(String name, int age)" );
//获取值 方式一
/* String name = (String) param.args[0];
Log.i(TAG, name);*/
//设置值 方式一
/* param.args[0] = "Hun";
param.args[1] = 500;*/
}
@Override
protected void afterHookedMethod ( MethodHookParam param ) throws Throwable {
super . afterHookedMethod ( param );
Log . i ( TAG , "Enter Person(String name, int age)" );
//获取值 方式二
/* int age = XposedHelpers.getIntField(param.thisObject, "age");
Log.i(TAG, Integer.toString(age));*/
//获取值 方式三
Class clazz = XposedHelpers . findClass ( "com.example.luodst.Person" , lpparam . classLoader );
Field age = clazz . getDeclaredField ( "age" );
age . setAccessible ( true );
int age_value = ( int ) age . get ( param . thisObject );
Log . i ( TAG , Integer . toString ( age_value ));
//设置值 方式二
/* XposedHelpers.setObjectField(param.thisObject, "name", "Hun");
XposedHelpers.setIntField(param.thisObject,"age",600);*/
//设置值 方式三
/* Class personClass = XposedHelpers.findClass("com.example.luodst.Person", lpparam.classLoader);
Field age = personClass.getDeclaredField("age");
age.setAccessible(true);
age.set(param.thisObject, 600);*/
}
});
}
}
}
Hook普通函数
对Java中普通函数的Hook主要借助于Xposed API中XposedHelpers.findAndHookMethod函数.
1
2
findAndHookMethod ( Class <?> clazz , String methodName , Object ... parameterTypesAndCallback )
findAndHookMethod ( String className , ClassLoader classLoader , String methodName , Object ... parameterTypesAndCallback )
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
package com.example.luoxposeddemo ;
import android.util.Log ;
import java.lang.reflect.Field ;
import de.robv.android.xposed.IXposedHookLoadPackage ;
import de.robv.android.xposed.XC_MethodHook ;
import de.robv.android.xposed.XposedBridge ;
import de.robv.android.xposed.XposedHelpers ;
import de.robv.android.xposed.callbacks.XC_LoadPackage ;
public class LuoHook implements IXposedHookLoadPackage {
private final String TAG = "[LuoXposed]" ;
@Override
public void handleLoadPackage ( XC_LoadPackage . LoadPackageParam lpparam ) throws Throwable {
if ( lpparam . packageName . equals ( "com.example.luodst" )) {
//寻找类 方式一
//Class personClass = lpparam.classLoader.loadClass("com.example.luodst.Person");
//寻找类 方式二
Class personClass = XposedHelpers . findClass ( "com.example.luodst.Person" , lpparam . classLoader );
//Hook com.example.luodst.Person.toString()
XposedHelpers . findAndHookMethod ( personClass , "toString" , new XC_MethodHook () {
@Override
protected void beforeHookedMethod ( MethodHookParam param ) throws Throwable {
super . beforeHookedMethod ( param );
Log . i ( TAG , "Enter com.example.luodst.Person.toString()" );
}
@Override
protected void afterHookedMethod ( MethodHookParam param ) throws Throwable {
super . afterHookedMethod ( param );
Log . i ( TAG , "Leave com.example.luodst.Person.toString()" );
}
});
//Hook com.example.luodst.MainActivity.stringFromJNI()
XposedHelpers . findAndHookMethod ( "com.example.luodst.MainActivity" , lpparam . classLoader , "stringFromJNI" , new XC_MethodHook () {
@Override
protected void beforeHookedMethod ( MethodHookParam param ) throws Throwable {
super . beforeHookedMethod ( param );
Log . i ( TAG , "Enter com.example.luodst.MainActivity.stringFromJNI" );
}
@Override
protected void afterHookedMethod ( MethodHookParam param ) throws Throwable {
super . afterHookedMethod ( param );
param . setResult ( "Hello XiaLuoHun" );
}
});
}
}
}
主动调用
主动调用分为静态函数和实例函数.
Xposed 提供了关于主动调用的API,其相应函数签名分别为:
1
2
callMethod ( Object obj , String methodName , Class []<?> parameterTypes , Object ... args )
callMethod ( Object obj , String methodName , Object ... args )
下面主要展示下主动调用的几种形式.
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
package com.example.luoxposeddemo ;
import android.util.Log ;
import java.lang.reflect.Constructor ;
import java.lang.reflect.Field ;
import java.lang.reflect.Method ;
import de.robv.android.xposed.IXposedHookLoadPackage ;
import de.robv.android.xposed.XC_MethodHook ;
import de.robv.android.xposed.XposedBridge ;
import de.robv.android.xposed.XposedHelpers ;
import de.robv.android.xposed.callbacks.XC_LoadPackage ;
public class LuoHook implements IXposedHookLoadPackage {
private final String TAG = "[LuoXposed]" ;
@Override
public void handleLoadPackage ( XC_LoadPackage . LoadPackageParam lpparam ) throws Throwable {
if ( lpparam . packageName . equals ( "com.example.luodst" )) {
//寻找类 方式一
//Class personClass = lpparam.classLoader.loadClass("com.example.luodst.Person");
//寻找类 方式二
Class personClass = XposedHelpers . findClass ( "com.example.luodst.Person" , lpparam . classLoader );
//Invoke静态函数
//①反射
Method publicStaticMethod = personClass . getDeclaredMethod ( "publicStaticMethod" );
String strResult1 = ( String ) publicStaticMethod . invoke ( null );
Log . i ( TAG , strResult1 );
//②Xposed API
String strResult2 = ( String ) XposedHelpers . callStaticMethod ( personClass , "publicStaticMethod" );
Log . i ( TAG , strResult2 );
//Invoke实例函数
//①类原生方式
Object personObj1 = personClass . newInstance ();
String result1 = ( String ) XposedHelpers . callMethod ( personObj1 , "publicMethod" );
Log . i ( TAG , result1 );
//②通过构造函数进行调用
Constructor personConstructor = personClass . getConstructor ( String . class , int . class );
Object personObj2 = personConstructor . newInstance ( "Luo" , 1000 );
String result2 = ( String ) XposedHelpers . callMethod ( personObj2 , "toString" );
Log . i ( TAG , result2 );
//③Xposed API
//public method
Object personObj3 = XposedHelpers . newInstance ( personClass , "Hun" , 2000 );
String result3 = ( String ) XposedHelpers . callMethod ( personObj3 , "publicMethod" );
Log . i ( TAG , result3 );
//private method
Object personObj4 = XposedHelpers . newInstance ( personClass , "Hun" , 3000 );
String result4 = ( String ) XposedHelpers . callMethod ( personObj4 , "privateMethod" );
Log . i ( TAG , result4 );
//④反射
Object personObj5 = XposedHelpers . newInstance ( personClass , "Hun" , 4000 );
Method privateMethod = personClass . getDeclaredMethod ( "privateMethod" );
privateMethod . setAccessible ( true );
String resutlt5 = ( String ) privateMethod . invoke ( personObj5 );
Log . i ( TAG , resutlt5 );
//⑤Hook构造函数
XposedHelpers . findAndHookConstructor ( personClass , String . class , int . class , new XC_MethodHook () {
@Override
protected void beforeHookedMethod ( MethodHookParam param ) throws Throwable {
super . beforeHookedMethod ( param );
}
@Override
protected void afterHookedMethod ( MethodHookParam param ) throws Throwable {
super . afterHookedMethod ( param );
//publicMethod
String result = ( String ) XposedHelpers . callMethod ( param . thisObject , "publicMethod" );
Log . i ( TAG , result );
}
});
//⑥Hook参数
Class selfClass = XposedHelpers . findClass ( "com.example.luodst.Person" , lpparam . classLoader );
XposedHelpers . findAndHookMethod ( "com.example.luodst.Person" , lpparam . classLoader , "getName" , selfClass , new XC_MethodHook () {
@Override
protected void beforeHookedMethod ( MethodHookParam param ) throws Throwable {
super . beforeHookedMethod ( param );
Log . i ( TAG , "Enter Invoke com.example.luodst.Person.privateMethod" );
//privateMethod
String result = ( String ) XposedHelpers . callMethod ( param . args [ 0 ] , "privateMethod" );
Log . i ( TAG , result );
}
@Override
protected void afterHookedMethod ( MethodHookParam param ) throws Throwable {
super . afterHookedMethod ( param );
}
});
}
}
}
函数替换
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
package com.example.luoxposeddemo ;
import android.util.Log ;
import java.lang.reflect.Field ;
import de.robv.android.xposed.IXposedHookLoadPackage ;
import de.robv.android.xposed.XC_MethodHook ;
import de.robv.android.xposed.XC_MethodReplacement ;
import de.robv.android.xposed.XposedBridge ;
import de.robv.android.xposed.XposedHelpers ;
import de.robv.android.xposed.callbacks.XC_LoadPackage ;
public class LuoHook implements IXposedHookLoadPackage {
private final String TAG = "[LuoXposed]" ;
@Override
public void handleLoadPackage ( XC_LoadPackage . LoadPackageParam lpparam ) throws Throwable {
if ( lpparam . packageName . equals ( "com.example.luodst" )) {
//寻找类 方式一
//Class personClass = lpparam.classLoader.loadClass("com.example.luodst.Person");
//寻找类 方式二
Class personClass = XposedHelpers . findClass ( "com.example.luodst.Person" , lpparam . classLoader );
//进行函数替换
XposedHelpers . findAndHookMethod ( personClass , "replaceFunc" , new XC_MethodReplacement () {
@Override
protected Object replaceHookedMethod ( MethodHookParam methodHookParam ) throws Throwable {
Log . i ( TAG , "replaceFunc" );
return "LuoReplaceFunc" ;
}
});
}
}
}