分享一个曾经实现的ArtHook源码

本文分享了ArtHook的实现原理,主要利用Java反射和代理技术,在JNI层替换ArtMethod结构指针。适用于Android 6.0系统,代码包括Java和JNI部分,注释清晰,方便理解与扩展。
摘要由CSDN通过智能技术生成

基于学习和分享的目的,你可以自行下载,随意进行更改,但需要注明出处,版权属于我个人所有。

实现原理和思路:

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结构体大小)仅供参考
 * 我本人之测过几部手机,对于兼容性不敢保证,此实现仅用于学习和讨论
 * 如果用于产品由于兼容性问题请自发解决(因为原理很简单
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值