基于学习和分享的目的,你可以自行下载,随意进行更改,但需要注明出处,版权属于我个人所有。
实现原理和思路:
1、核心原理是利用java反射+代理
2、在java层实现一个method,在jni层替换method结构指针
注意:
我当时使用的手机是google 原生Android6.0,可以在6.0手机跑通,其他版本的ArtMethod结构体头文件中有,
不过我代码中并没有添加对其他类型的实现,你可以自己添加,添加也很简单,仿照6.0的即可。
代码分为java部分和jni部分,有注释,相信你们应该能看得懂。
--------------------- ---------------------------------------------------------
java层代码:
辅助类:
import java.lang.reflect.Method;
import android.util.Log;
/**
* MethodHook辅助类, native 对应art_method.h 和 art_method.cpp
* 你最好不要直接调用这个类,hook功能都是通过MethodHook提供的
* @author sp00f
* @version 0.1
*/
public class ArtMethod {
// static {
// try {
// System.loadLibrary("hk");
// } catch (Error e) {
// throw new Error(e);
// } catch (Exception e1) {
// throw new RuntimeException(e1);
// }
// }
private String tag = ArtMethod.class.getName();
public ArtMethod() {}
被包围的函数是用来测试ArtMethod是哪种类型的
根据两个方法的之间宽度判断//
public static native void m0();
public void m1() {
Log.i("SimpleMethod", "m1");
}
public void m2() {
Log.i("SimpleMethod", "m2");
}
被包围的函数是用来测试ArtMethod是哪种类型的
/**
* 克隆方法用的,同时也是hook的主方法,此方法只完成native层method结构拷贝
* 利用此方法,origin对应的native层method结构将失去和java层method结构的联系
* @param origin 即将被hook的方法
* @param dst 替换原方法的方法
* @return 是否成功
*/
public static native boolean cloneMethod(Method origin, Method dst);
/**
* 设置api level,用于判断底层art method类型
* @param l 对于api level
*/
public static native void setApiLevel(int l);
}
实现类:
import java.lang.reflect.Method;
import android.util.Log;
/**
* hook功能类,你应该调用这里的方法,和初始化这个类,而不是ArtMethod
* @author sp00f
* @version 0.1
*
*/
public class MethodHook {
private String tag = "MethodHook";
private Method backedMethod = null;
public MethodHook() {
try {
backedMethod = this.getClass().getDeclaredMethod("back", new Class<?>[]{});
backedMethod.invoke(this, new Object[]{});
} catch (Exception e) {
e.printStackTrace();
}
}
//这个方法是为了占个坑
public void back() {
Log.i(tag, "[*] In order to occupy the pit, so keep this method");
}
/**
* 不带备份源函数的hook
* @param src,源函数
* @param dst,目标函数
* @return,是否成功
*/
public boolean hook(Method src, Method dst) {
return ArtMethod.cloneMethod(src, dst);
}
/**
* 带拷贝的源函数的hook
* @param src,源函数
* @param dst,目标函数
* @return,是否成功
*/
public boolean hookAndBack(Method src, Method dst) {
if (!backedMethod(src)) {
Log.e(tag, "[-] clone origin method failed");
return false;
}
return ArtMethod.cloneMethod(src, dst);
}
/**
* 函数备份
* 因为原来backed方法有原始方法对应,克隆后将丢失(这个提前预留的坑)
* @param origin,要被备份的方法,克隆后origin方法保持不变,只是backedMethod由原来的(本类中的back())
* 变成了origin方法(同一份拷贝)
* @return 成功返回true
*/
public boolean backedMethod(Method origin) {
return ArtMethod.cloneMethod(backedMethod, origin);
}
public Object callOrgin(Object receiver, Object...args) {
try {
return backedMethod.invoke(receiver, args);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 设置api level,用于判断底层art method类型
* @param l 对于api level
*/
public void setApiLevel(int l) { // int apilevel = Build.VERSION.SDK_INT;
ArtMethod.setApiLevel(l);
}
public Method getBackedMethod() {
return backedMethod;
}
}
JNI层代码:
头文件:
/**
* @Atuthor : sp00f
* @Version: 0.1
* @Desc: art hook
* @Theory: jave proxy, reflect
* 实现方式其实有很多种,这种或许最简单
* 另外检测是哪个版本也有很多种方式,如检测系统属性,检测apilevel
* 这里随便写了个(art method结构体大小)仅供参考
* 我本人之测过几部手机,对于兼容性不敢保证,此实现仅用于学习和讨论
* 如果用于产品由于兼容性问题请自发解决(因为原理很简单