xposed开发环境搭建
创建一个无Activity的项目,切换到Project视图,在app目录下创建一个lib目录
将xposed的jar添加到lib目录下,选中这个jar包,然后右击,将这个添加为库(编译的时候,不需要打包这个jar包)
在build.gradle的dependencies中添加一行
provided files('lib/api-82.jar')
修改AndroidManifest.xml
<meta-data
android:name="xposedmodule"
android:value="true" />
<meta-data
android:name="xposeddescription"
android:value="my name is xiaojianbang" />
<meta-data
android:name="xposedminversion"
android:value="53" />
然后创建一个类Hook,输入内容
public class Hook implements IXposedHookLoadPackage{
// Xposed是一个全局的Hook
// 如果对一个app进行过滤,需要 参数XC_LoadPackage.LoadPackageParam loadPackageParam进行判断
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
Log.d("showme","hook start...");
if(!loadPackageParam.packageName.equals("com.xingin.xls")) return;
}
}
在main目录下创建一个assets目录,创建一个文本文件 xposed_init
指定入口类:在其中输入 Hook类的完整路径名(包名.类名)
点击Build
找到生成的apk,进行安装
安装好之后,激活模块,然后重启
hook构造函数
ClassLoader classLoader = loadPackageParam.classLoader;
Class StudentClass = classLoader.loadClass("com.showme.xposedhook01.Student");
XposedHelpers.findAndHookConstructor(StudentClass, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
XposedBridge.log("com.showme.xposedhook01.Student() is called!!beforeHookedMethod");
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
XposedBridge.log("com.showme.xposedhook01.Student() is called!!afterHookedMethod");
}
});
XposedHelpers.findAndHookConstructor(StudentClass, String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
java.lang.Object[] argsobjarray = param.args;
String name = (String) argsobjarray[0];
XposedBridge.log("com.showme.xposedhook01.Student(String) is called!!beforeHookedMethod--" + name);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
XposedBridge.log("com.showme.xposedhook01.Student(String) is called!!afterHookedMethod");
}
});
XposedHelpers.findAndHookConstructor("com.showme.xposedhook01.Student", loadPackageParam.classLoader, String.class, String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
java.lang.Object[] argsobjarray = param.args;
String name = (String) argsobjarray[0];
String id = (String) argsobjarray[1];
XposedBridge.log("com.showme.xposedhook01.Student(String,String) is called!!beforeHookedMethod--" + name + "---" + id);
}
});
ClassLoader pathClassLoader= loadPackageParam.classLoader;
final Class stuClass=pathClassLoader.loadClass("com.showme.xposedhook01.Student");
XposedHelpers.setStaticObjectField(stuClass,"teacher","teacher888");
String teachername2= (String) XposedHelpers.getStaticObjectField(stuClass,"teacher");
XposedHelpers.findAndHookConstructor(StudentClass, String.class, String.class, int.class,String.class,String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
java.lang.Object[] argsobjarray = param.args;
String name = (String) argsobjarray[0];
String id = (String) argsobjarray[1];
int age = (int) (argsobjarray[2]);
argsobjarray[1] = "2050";
argsobjarray[2] = 100;
String teacher= (String) argsobjarray[3];
String nickname= (String) argsobjarray[4];
XposedBridge.log("com.showme.xposedhook01.Student(String,String) is called!!beforeHookedMethod--" + name + "---" + id + "--" + age+"---"+teacher+"---"+nickname);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Object thisobj = param.thisObject;
/* Field nicknameField=stuClass.getDeclaredField("nickname");
XposedBridge.log(stuClass+"--nicknameField->"+nicknameField);
nicknameField.setAccessible(true);
nicknameField.set(thisobj,"bear");*/
XposedHelpers.setObjectField(thisobj,"nickname","chick");
Object returnobj = param.getResult();
XposedBridge.log(thisobj + "---" + returnobj);
XposedBridge.log("com.showme.xposedhook01.Student(String,String,int) is called!!afterHookedMethod");
}
});
hook系统类,DexClassLoader,应用加载了哪些插件
XposedHelpers.findAndHookConstructor(DexClassLoader.class, String.class, String.class, String.class, ClassLoader.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
Object array[]=param.args;
String dexpath= (String) array[0];
String optimizedDirectory= (String) array[1];
String librarySearchPath= (String) array[2];
XposedBridge.log("DexClassLoader beforeHookedMethod:"+dexpath+"---"+optimizedDirectory+"---"+librarySearchPath);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
DexClassLoader dexClassLoader= (DexClassLoader) param.thisObject;
XposedBridge.log("DexClassLoader afterHookedMethod:"+dexClassLoader);
}
});
hook属性:使用java反射和Xposed的API
ClassLoader classLoader = loadPackageParam.classLoader;
Class StudentClass = classLoader.loadClass("com.showme.xposedhook.Student");
// java反射
Field teacherField=stuClass.getDeclaredField("teacher");
teacherField.setAccessible(true);
teacherField.set(null,"teacher666");
String teachername1= (String) teacherField.get(null);
XposedBridge.log("teacherField->"+teachername1);
// Xposed中的实现和java反射一样,但是默认调用了 setAccessible(true);
XposedHelpers.setStaticObjectField(stuClass,"teacher","teacher888");
String teachername2= (String) XposedHelpers.getStaticObjectField(stuClass,"teacher");
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Object thisobj = param.thisObject;
XposedHelpers.setObjectField(thisobj,"nickname","chick");
Object returnobj = param.getResult();
XposedBridge.log(thisobj + "---" + returnobj);
}
hook一般方法
ClassLoader classLoader = loadPackageParam.classLoader;
Class StuClass = classLoader.loadClass("com.showme.xposedhook01.Student");
// 一般java函数的hook
XposedHelpers.findAndHookMethod("com.showme.xposedhook01.Student", loadPackageParam.classLoader, "privatefunc", String.class, int.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
Object[] objectarray = param.args;
String arg0 = (String) objectarray[0];
int arg1 = (int) objectarray[1];
XposedBridge.log("beforeHookedMethod11 privatefunc->arg0:" + arg0 + "---arg1:" + arg1);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
String result = (String) param.getResult();
XposedBridge.log("afterHookedMethod11 privatefunc->result:" + result);
}
});
// 内部类中的函数hook
Class personClass = XposedHelpers.findClass("com.showme.xposedhook01.Student$person", loadPackageParam.classLoader);
XposedHelpers.findAndHookMethod(personClass, "getpersonname", String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
XposedBridge.log("beforeHookedMethod getpersonname->" + param.args[0]);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
XposedBridge.log("afterHookedMethod getpersonname->" + param.getResult());
}
});
// 匿名内部类函数的hook - 匿名内部类总会有一个类名的,用那个类名就行了
// 类中JNI函数的hook - 和普通函数一样
主动调用函数
// java 反射的方式
ClassLoader classLoader = loadPackageParam.classLoader;
Class StuClass = classLoader.loadClass("com.showme.xposedhook01.Student");
Method publicstaticfunc_method = StuClass.getDeclaredMethod("publicstaticfunc", String.class, int.class);
publicstaticfunc_method.invoke(null, "InvokedByXposed", 100);
// Xposed 中的API
// public static java.lang.Object callMethod(java.lang.Object obj, java.lang.String methodName, java.lang.Object... args) { /* compiled code */ }
//
// public static java.lang.Object callMethod(java.lang.Object obj, java.lang.String methodName, java.lang.Class<?>[] parameterTypes, java.lang.Object... args) { /* compiled code */ }
//
// public static java.lang.Object callStaticMethod(java.lang.Class<?> clazz, java.lang.String methodName, java.lang.Object... args)
//
// public static java.lang.Object callStaticMethod(java.lang.Class<?> clazz, java.lang.String methodName, java.lang.Class<?>[] parameterTypes, java.lang.Object... args)
java.lang.Class<?>[] parameterTypes = {String.class, int.class};
XposedHelpers.callStaticMethod(StuClass, "publicstaticfunc", parameterTypes, "publicstaticfunc is called by XposedHelpers.callStaticMethod11", 100);
XposedHelpers.callStaticMethod(StuClass, "publicstaticfunc", "publicstaticfunc is called by XposedHelpers.callStaticMethod22", 200);
XposedHelpers.callStaticMethod(StuClass, "privatestaticfunc", parameterTypes, "privatestaticfunc is called by XposedHelpers.callStaticMethod11", 400);
XposedHelpers.callStaticMethod(StuClass, "privatestaticfunc", "privatestaticfunc is called by XposedHelpers.callStaticMethod22", 300);
Method privatestaticfunc_method = StuClass.getDeclaredMethod("privatestaticfunc", String.class, int.class);
privatestaticfunc_method.setAccessible(true);
String result = (String) privatestaticfunc_method.invoke(null, "privatestaticfuncIsInvokedByXposed", 200);
// public static java.lang.Object callMethod(java.lang.Object obj, java.lang.String methodName, java.lang.Object... args) { /* compiled code */ }
//
// public static java.lang.Object callMethod(java.lang.Object obj, java.lang.String methodName, java.lang.Class<?>[] parameterTypes, java.lang.Object... args) { /* compiled code */ }
// public static java.lang.Object newInstance(java.lang.Class<?> clazz, java.lang.Object... args) { /* compiled code */ }
//
// public static java.lang.Object newInstance(java.lang.Class<?> clazz, java.lang.Class<?>[] parameterTypes, java.lang.Object... args) { /* compiled code */ }
Object StuObjByXposed = XposedHelpers.newInstance(StuClass, "StuObjByXposed.newInstance", "500");
String result1 = (String) XposedHelpers.callMethod(StuObjByXposed, "publicfunc", "publicfunc is called by XposedHelpers.callMethod", 125);
XposedBridge.log("publicfunc XposedHelpers.callMethod result->" + result1);
XposedHelpers.callMethod(StuObjByXposed, "privatefunc", "privatefunc is called by XposedHelpers.callMethod", 130);
//Student cstudent = new Student("xiaohua", "2020");
XposedHelpers.findAndHookConstructor(StuClass, String.class, String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
XposedBridge.log("Student(String,String) is called beforeHookedMethod");
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
XposedBridge.log("Student(String,String) is called afterHookedMethod");
Object cstudent=param.thisObject;
XposedHelpers.callMethod(cstudent,"publicfunc","publicfunc is called XposedHelpers.findAndHookConstructor",666);
XposedHelpers.callMethod(cstudent,"privatefunc","privatefunc is called XposedHelpers.findAndHookConstructor",888);
}
});
// public String getNickname() {
// return nickname;
// }
XposedHelpers.findAndHookMethod(StuClass, "getNickname", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
Object obj=param.thisObject;
XposedHelpers.callMethod(obj,"publicfunc","beforeHookedMethod publicfunc is called XposedHelpers.callMethod",444);
XposedHelpers.callMethod(obj,"privatefunc","beforeHookedMethod privatefunc is called XposedHelpers.callMethod",333);
XposedBridge.log("getNickname is called beforeHookedMethod->"+obj);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Object obj=param.thisObject;
XposedHelpers.callMethod(obj,"publicfunc","afterHookedMethod publicfunc is called XposedHelpers.callMethod",222);
XposedHelpers.callMethod(obj,"privatefunc","afterHookedMethod privatefunc is called XposedHelpers.callMethod",111);
XposedBridge.log("getNickname is called afterHookedMethod->"+param.thisObject);
}
});
加壳APP处理
/*
1、对于有壳的apk,Xposed首先拿到的是壳的classloader
2、壳一般在,壳代码的OnCreate修成classloader
*/
public class HookShellApk implements IXposedHookLoadPackage {
public static Field getClassField(ClassLoader classloader, String class_name,
String filedName) {
try {
Class obj_class = classloader.loadClass(class_name);//Class.forName(class_name);
Field field = obj_class.getDeclaredField(filedName);
field.setAccessible(true);
return field;
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
public static Object getClassFieldObject(ClassLoader classloader, String class_name, Object obj,
String filedName) {
try {
Class obj_class = classloader.loadClass(class_name);//Class.forName(class_name);
Field field = obj_class.getDeclaredField(filedName);
field.setAccessible(true);
Object result = null;
result = field.get(obj);
return result;
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
public static Object invokeStaticMethod(String class_name,
String method_name, Class[] pareTyple, Object[] pareVaules) {
try {
Class obj_class = Class.forName(class_name);
Method method = obj_class.getMethod(method_name, pareTyple);
return method.invoke(null, pareVaules);
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
public static Object getFieldOjbect(String class_name, Object obj,
String filedName) {
try {
Class obj_class = Class.forName(class_name);
Field field = obj_class.getDeclaredField(filedName);
field.setAccessible(true);
return field.get(obj);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}
return null;
}
public static ClassLoader getClassloader() {
ClassLoader resultClassloader = null;
Object currentActivityThread = invokeStaticMethod(
"android.app.ActivityThread", "currentActivityThread",
new Class[]{}, new Object[]{});
Object mBoundApplication = getFieldOjbect(
"android.app.ActivityThread", currentActivityThread,
"mBoundApplication");
Application mInitialApplication = (Application) getFieldOjbect("android.app.ActivityThread",
currentActivityThread, "mInitialApplication");
Object loadedApkInfo = getFieldOjbect(
"android.app.ActivityThread$AppBindData",
mBoundApplication, "info");
Application mApplication = (Application) getFieldOjbect("android.app.LoadedApk", loadedApkInfo, "mApplication");
resultClassloader = mApplication.getClassLoader();
return resultClassloader;
}
public void GetClassLoaderClasslist(ClassLoader classLoader) {
//private final DexPathList pathList;
//public static java.lang.Object getObjectField(java.lang.Object obj, java.lang.String fieldName)
XposedBridge.log("start dealwith classloader:" + classLoader);
Object pathListObj = XposedHelpers.getObjectField(classLoader, "pathList");
//private final Element[] dexElements;
Object[] dexElementsObj = (Object[]) XposedHelpers.getObjectField(pathListObj, "dexElements");
for (Object i : dexElementsObj) {
//private final DexFile dexFile;
Object dexFileObj = XposedHelpers.getObjectField(i, "dexFile");
//private Object mCookie;
Object mCookieObj = XposedHelpers.getObjectField(dexFileObj, "mCookie");
//private static native String[] getClassNameList(Object cookie);
// public static java.lang.Object callStaticMethod(java.lang.Class<?> clazz, java.lang.String methodName, java.lang.Object... args) { /* compiled code */ }
Class DexFileClass = XposedHelpers.findClass("dalvik.system.DexFile", classLoader);
String[] classlist = (String[]) XposedHelpers.callStaticMethod(DexFileClass, "getClassNameList", mCookieObj);
for (String classname : classlist) {
XposedBridge.log(dexFileObj + "---" + classname);
}
}
XposedBridge.log("end dealwith classloader:" + classLoader);
}
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
Log.i("Xposed01", loadPackageParam.packageName);
XposedBridge.log("HookLebo->app packagename" + loadPackageParam.packageName);
if (loadPackageParam.packageName.equals("com.test.abc")) {
XposedBridge.log("showme " + loadPackageParam.packageName);
Class StubAppClass=XposedHelpers.findClass("com.test.abc.MyWrapperProxyApplication",loadPackageParam.classLoader);
Method[] methods=StubAppClass.getDeclaredMethods();
for(Method i:methods){
XposedBridge.log("com.test.abc.MyWrapperProxyApplication->"+i);
}
XposedHelpers.findAndHookMethod("com.test.abc.MyWrapperProxyApplication", loadPackageParam.classLoader, "onCreate", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
XposedBridge.log("com.test.abc.MyWrapperProxyApplication->onCreate beforeHookedMethod");
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
XposedBridge.log("com.test.abc.MyWrapperProxyApplication->onCreate afterHookedMethod");
ClassLoader finalClassLoader=getClassloader();
XposedBridge.log("finalClassLoader->" + finalClassLoader);
XposedHelpers.findAndHookMethod("com.orginal.apk.MainActivity", finalClassLoader, "onCreate", Bundle.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
XposedBridge.log("beforeHookedMethod com.orginal.apk.MainActivity.onCreate");
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
XposedBridge.log("afterHookedMethod com.orginal.apk.MainActivity.onCreate");
}
});
}
});
}
}
}
so中函数处理
1、创建android studio native项目,使用inhook框架,编写hook的内容
2、通过Xposed,在java.lang.Runtime.loadLibrary的时机加载so
// java.lang.System.loadLibrary,的下一级,会使用当前调用者的ClassLoader,所以会被使用成Xposed的ClassLoader
// 可以用java.lang.Runtimem,但是在不同版本的源码中,loadLibrary的名字不一样,需要适配
XposedHelpers.findAndHookMethod("java.lang.Runtime", loadPackageParam.classLoader, "loadLibrary", String.class,ClassLoader.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
String soname= (String) param.args[0];
XposedBridge.log("beforeHookedMethod Runtime.load("+soname+","+param.args[1]+")");
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
String soname= (String) param.args[0];
XposedBridge.log("afterHookedMethod Runtime.load("+soname+")");
if(soname.contains("native-lib")){
System.load("/data/data/com.showme.xposedhookso/files/hookso.so");
}
}
});
对于armv8,可以使用sandHook框架
指纹检测与简单定制