AndroidHook相关基础实例
程序员文章站
2022-06-21 20:24:20
Android Hook基础例子前言Hook的流程Android Hook简单例子调用Hook后继续执行核心思想前言Hook是什么?举个例子,有一个人写了一封情书给你喜欢的女孩,在送信的路上你偷偷的把那封情书拿了换成你自己写的情书,再放了回去,那个人拿着你写的情书给了你喜欢的女孩。不要问为什么会有Hook。反正Hook是有广大的应用场景。Hook可以做很多常规开发中由于限制而认为不可能实现的事情。备注说明:前面写的《组件化》框架gradle部分源码已经被我改得面目全非,有空再写一篇文章说明一下。...
前言
Hook是什么?举个例子,有一个人写了一封情书给你喜欢的女孩,在送信的路上你偷偷的把那封情书拿了换成你自己写的情书,再放了回去,那个人拿着你写的情书给了你喜欢的女孩。
不要问为什么会有Hook。反正Hook是有广大的应用场景。
Hook可以做很多常规开发中由于限制而认为不可能实现的事情。
备注说明:前面写的《组件化》框架gradle部分源码已经被我改得面目全非,有空再写一篇文章说明一下。
Hook的流程
Hook 有3步
1.找到替换点
2.构建动态代理对象
3.替换
往往第一步会比较麻烦耗时,因为首先你得把你要Hook的整个流程,关键点都弄清楚,然后再分析出是否有可以Hook的点。
Android Hook简单例子
我们这个简单的例子是这样。
描述如下 (如何实现省略):
新建一个项目,里面很简单,添加一个按钮,点击按钮弹出 :我爱你
Button button = findViewById(R.id.btn_test);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(DebugActivity.this, "我爱你", Toast.LENGTH_SHORT).show();
}
});
我们通过Hook不修改上面的代码让点击按钮弹出:你是SB
如何分析代码部分省略找到Hook点部分省略。
private void hookClick(View button) throws Exception {
//获取到ListenerInfo
Class mViewClass = Class.forName("android.view.View");
Method mGetListenerInfoMethod = mViewClass.getDeclaredMethod("getListenerInfo");
mGetListenerInfoMethod.setAccessible(true);
Object mListenerInfo = mGetListenerInfoMethod.invoke(button);
//设置新OnClickListener的动态代理
Object mProxyOnClickListener = Proxy.newProxyInstance(getClassLoader(), new Class[]{View.OnClickListener.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Toast.makeText(DebugActivity.this, "你是SB", Toast.LENGTH_SHORT).show();
return null;
}
});
//替换
mOnClickListenerField.set(mListenerInfo, mProxyOnClickListener);
}
调用
调用上面这个方法把这个按钮传进去点击就弹出就变成了:你是SB
Hook后继续执行
如果你希望Hook后还能继续执行我爱你,
private void hookClick(View button) throws Exception {
//获取到ListenerInfo
Class mViewClass = Class.forName("android.view.View");
Method mGetListenerInfoMethod = mViewClass.getDeclaredMethod("getListenerInfo");
mGetListenerInfoMethod.setAccessible(true);
Object mListenerInfo = mGetListenerInfoMethod.invoke(button);
//获取原来已经设置好的mOnClickListener
Class mListenerInfoViewClass = Class.forName("android.view.View$ListenerInfo");
Field mOnClickListenerField = mListenerInfoViewClass.getDeclaredField("mOnClickListener");
mOnClickListenerField.setAccessible(true);
final Object mOnClickListener = mOnClickListenerField.get(mListenerInfo);
//设置新OnClickListener的动态代理
Object mProxyOnClickListener = Proxy.newProxyInstance(getClassLoader(), new Class[]{View.OnClickListener.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Toast.makeText(DebugActivity.this, "我是XXX", Toast.LENGTH_SHORT).show();
//继续调用这个是核心
method.invoke(mOnClickListener, args);
return null;//如果原来的调用是有返回值请 return method.invoke(mOnClickListener, args);
}
});
//替换
mOnClickListenerField.set(mListenerInfo, mProxyOnClickListener);
}
核心思想
核心思想就是构建一个View.OnClickListener 的动态代理
然后把之前设置好的替换掉
本文地址:https://blog.csdn.net/muxaioxie/article/details/110205606