-
-
[原创]xposed新思路,伪代码都见鬼去吧
-
发表于:
2019-4-4 14:06
13797
-
最近研究了两天xposed,发现真实个神器。本人对java略懂皮毛,对so一窍不通。总结出几个新思路,发出来抛砖引玉。
/**
* HOOK一个类加载器中的所有类的所有方法
*
* @param classLoader 类加载器
*/
private void hookClassLoaderAnyMethod(ClassLoader classLoader) throws Exception {
Object[] dexElements = (Object[]) getFieldValue(classLoader, "pathList", "dexElements");
// 获取到dex文件
DexFile dexFile = (DexFile) getFieldValue(dexElements[0], "dexFile");
// 找到所有的类
Enumeration<String> enumeration = dexFile.entries();
while (enumeration.hasMoreElements()) {
String clsName = enumeration.nextElement();
Log.i(TAG, "hook ClassLoader By Class Name: " + clsName);
Class<?> cls = XposedHelpers.findClass(clsName, classLoader);
Method[] methods = cls.getDeclaredMethods();
for (Method method : methods) {
int paramSize = method.getParameterTypes().length;
Object[] objs = new Object[paramSize + 1];
System.arraycopy(method.getParameterTypes(), 0, objs, 0, paramSize);
// 最后一个参数设置为回调
objs[paramSize] = new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
StringBuilder builder = new StringBuilder();
builder.append("call method:").append(method.toString());
// 记录参数
if (param.args != null && param.args.length > 0) {
for (int i = 0; i < param.args.length; i++) {
builder.append('\n');
builder.append("arg").append(i).append(":");
builder.append(param.args[i]);
}
}
// 记录结果
builder.append("\n").append("result:").append(param.getResult());
Log.i(TAG, builder.toString());
}
};
XposedHelpers.findAndHookMethod(cls, method.getName(), objs);
}
}
}
/**
* HOOK一个类加载器中的所有类的所有方法
*
* @param classLoader 类加载器
*/
private void hookClassLoaderAnyMethod(ClassLoader classLoader) throws Exception {
Object[] dexElements = (Object[]) getFieldValue(classLoader, "pathList", "dexElements");
// 获取到dex文件
DexFile dexFile = (DexFile) getFieldValue(dexElements[0], "dexFile");
// 找到所有的类
Enumeration<String> enumeration = dexFile.entries();
while (enumeration.hasMoreElements()) {
String clsName = enumeration.nextElement();
Log.i(TAG, "hook ClassLoader By Class Name: " + clsName);
Class<?> cls = XposedHelpers.findClass(clsName, classLoader);
Method[] methods = cls.getDeclaredMethods();
for (Method method : methods) {
int paramSize = method.getParameterTypes().length;
Object[] objs = new Object[paramSize + 1];
System.arraycopy(method.getParameterTypes(), 0, objs, 0, paramSize);
// 最后一个参数设置为回调
objs[paramSize] = new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
StringBuilder builder = new StringBuilder();
builder.append("call method:").append(method.toString());
// 记录参数
if (param.args != null && param.args.length > 0) {
for (int i = 0; i < param.args.length; i++) {
builder.append('\n');
builder.append("arg").append(i).append(":");
builder.append(param.args[i]);
}
}
// 记录结果
builder.append("\n").append("result:").append(param.getResult());
Log.i(TAG, builder.toString());
}
};
XposedHelpers.findAndHookMethod(cls, method.getName(), objs);
}
}
}
getFieldValue方法,就是通过反射递归获取对象属性值
private Object getFieldValue(Object obj, String... fieldNames) throws Exception {
if (obj == null) {
return null;
}
for (String fieldName : fieldNames) {
obj = getFieldValue(obj, fieldName);
}
return obj;
}
/**
* 获取对象中的属性
*
* @param obj 对象
* @param fieldName 属性名称
* @return 属性值
* @throws Exception 异常信息
*/
private Object getFieldValue(Object obj, String fieldName) throws Exception {
Field field = getField(obj.getClass(), fieldName);
if (field == null) {
return null;
}
// 设置允许访问
field.setAccessible(true);
return field.get(obj);
}
/**
* 递归获取类的所有属性,直到找到指定属性为止
*
* @param cls 类
* @param fieldName 属性名
* @return 属性
*/
private Field getField(Class<?> cls, String fieldName) {
Field[] fields = cls.getDeclaredFields();
if (fields != null && fields.length > 0) {
for (Field field : fields) {
if (field.getName().equals(fieldName)) {
return field;
}
}
}
Class<?> supperCls = cls.getSuperclass();
if (!supperCls.equals(Object.class)) {
return getField(supperCls, fieldName);
}
return null;
}
private Object getFieldValue(Object obj, String... fieldNames) throws Exception {
if (obj == null) {
return null;
}
for (String fieldName : fieldNames) {
obj = getFieldValue(obj, fieldName);
}
return obj;
}
/**
* 获取对象中的属性
*
* @param obj 对象
* @param fieldName 属性名称
* @return 属性值
* @throws Exception 异常信息
*/
private Object getFieldValue(Object obj, String fieldName) throws Exception {
Field field = getField(obj.getClass(), fieldName);
if (field == null) {
return null;
}
// 设置允许访问
field.setAccessible(true);
return field.get(obj);
}
/**
* 递归获取类的所有属性,直到找到指定属性为止
*
* @param cls 类
* @param fieldName 属性名
* @return 属性
*/
private Field getField(Class<?> cls, String fieldName) {
Field[] fields = cls.getDeclaredFields();
if (fields != null && fields.length > 0) {
for (Field field : fields) {
if (field.getName().equals(fieldName)) {
return field;
}
}
}
Class<?> supperCls = cls.getSuperclass();
if (!supperCls.equals(Object.class)) {
return getField(supperCls, fieldName);
}
return null;
}
在此我们只需要一个东西,就是类加载器对象,这个只要hook目标app的启动类就可以拿到。
启动app这时我们的控制台会哗哗哗的打印方法调用日志
作用一:
比如说我们要hook一个按钮,等app进入到某个界面,把日志清理掉,点一下那个按钮,看下那些个方法被调用了。
作用二:
比如说我们要找一个加密方法或解密方法,直接看日志,那个方法是明文进去密文出来或者哪个方法是密文进去明文出来的。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2019-4-4 16:01
被菜鸟学术编辑
,原因: