Android Hook技术的简单实现
2023-06-13 09:11:29 时间
大家好,又见面了,我是你们的朋友全栈君。
一、什么是Hook 技术
Android 程序有一套特有的事件分发机制,都是按既定程序从前往后执行的。Hook 技术就是利用反射和代理,在既定程序中插入我们自己写的程序。比如,我们想在某个View的点击事件中添加播放音乐的效果。控件的点击事件,分发流程都是系统已经写好了,这时我们怎么做到在其中插入我们的播放音乐的效果呢?
二、如何寻找Hook点
1.尽量选择静态变量和单例对象,因为一旦创建对象,他们不容易变化,非常容易定位。 2.尽量Hook public的对象和方法
三、Hook过程
选中到了合适的Hook点后,选择合适的代理方式,如果是接口就可以用动态代理,然后偷梁换柱,用代理对象替换原始对象。
四、Hook View的点击事件
先看看View 点击事件的源码
public void setOnClickListener(@Nullable OnClickListener l) {
if (!isClickable()) {
setClickable(true);
}
getListenerInfo().mOnClickListener = l;
}
@UnsupportedAppUsage
ListenerInfo getListenerInfo() {
if (mListenerInfo != null) {
return mListenerInfo;
}
mListenerInfo = new ListenerInfo();
return mListenerInfo;
}
由代码可以看出,我们正常设置进去的OnClickListener是保存在ListenerInfo里面的。 如果我们可以通过反射将这个ListenerInfo里面的mOnClickListener 替换成我们自定义的OnClickListener是不是就可以实现我们目的了。接下来我们试试! 先看看通过反射修改对象属性的API
field.set(Object obj, Object value)
- field是我们要修改的变量的属性,也就是mOnClickListener
- obj就是要修改的对象,就是ListenerInfo
- value就是要替换mOnClickListener 的新值
接下来围绕准备这几个变量,我们来写代码
private void hookOnClickListener(View view) {
try {
// 得到待hook view 的 ListenerInfo 对象
Method getListenerInfo = View.class.getDeclaredMethod("getListenerInfo");
getListenerInfo.setAccessible(true);
Object listenerInfo = getListenerInfo.invoke(view);
// 得到 原始的 mOnClickListener 对象
Class<?> listenerInfoClz = Class.forName("android.view.View$ListenerInfo");
Field mOnClickListener = listenerInfoClz.getDeclaredField("mOnClickListener");
mOnClickListener.setAccessible(true);
View.OnClickListener originOnClickListener = (View.OnClickListener) mOnClickListener.get(listenerInfo);
// 用自定义的 hookedOnClickListener 替换原始的 mOnClickListener
View.OnClickListener hookedOnClickListener = new HookOnClickListener(originOnClickListener);
mOnClickListener.set(listenerInfo, hookedOnClickListener);
} catch (Exception e) {
Log.d(TAG, "hook clickListener failed!: ");
}
}
自定义的HookOnClickListener
class HookOnClickListener implements View.OnClickListener {
private View.OnClickListener origin;
HookOnClickListener(View.OnClickListener origin) {
this.origin = origin;
}
@Override
public void onClick(View v) {
Log.d(TAG,"执行点击事件之前");
if (origin != null) {
origin.onClick(v);
}
Log.d(TAG,"执行点击事件之后");
}
}
在MainActivity中的使用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvHook = findViewById(R.id.tv_hook);
tvHook.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG,"tvHook 的点击事件");
}
});
hookOnClickListener(tvHook);
}
点击tvHook 看看输出结果
/com.example.hook D/MainActivity: 执行点击事件之前
/com.example.hook D/MainActivity: tvHook 的点击事件
/com.example.hook D/MainActivity: 执行点击事件之后
看到这里我们已经成功Hook到了View的点击事件
五、Hook注意点
Android 的API版本比较多,各个厂家也对系统有不同程度的定制,所以类和方法有可能不太一样,这就要求我们做好兼容。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/143805.html原文链接:https://javaforall.cn
相关文章
- android开机动画多长时间_Android开机动画及黑屏[通俗易懂]
- android 空间分享到朋友圈,Android开发之微信分享到好友,朋友圈
- android bindservice方法,Android bindservice方法返回false
- android开发笔记之 Android代码混淆打包
- android 读取本地数据库db文件(Android sqlite)
- Linux安装Android Sdk「建议收藏」
- Android平台实现系统内录(捕获播放的音频)并推送RTMP服务技术方案探究
- android多级树形列表
- 【Android 插件化】VAHunt 引入 | VAHunt 原理 | VAHunt 识别插件化引擎
- 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 注入工具收尾操作 | 关闭注入的动态库 | 恢复寄存器 | 脱离远程调试附着 )
- 【Android 逆向】Dalvik 函数抽取加壳 ② ( 类加载流程分析 | ClassLoader#loadClass 分析 | BaseDexClassLoader#findClass 分析 )
- 【错误记录】Android Studio 编译时 lint 检查报错 ( WARNING: DSL element ‘android.dataBinding.enabled‘ is obsolet )
- 【错误记录】Android 应用安全检测漏洞修复 ( StrandHogg 漏洞 | 设置 Activity 组件 android:taskAffinity=““ )
- 【Android Gradle 插件】Android Module 模块 build.gradle 构建脚本 Groovy 语法分析 ① ( Gradle 二进制插件引入 | Gradle依赖配置 )
- 【Android Gradle 插件】组件化中的 Gradle 构建脚本实现 ⑤ ( 优化 Gradle 构建脚本 | 构建脚本结构 | 闭包定义及用法 | 依赖配置 | android 块配置 )
- 【Android Gradle 插件】热修复实现 ① ( Android 热修复系统组成 | 热修复工作流程 | 热修复使用到的技术 | 热修复框架选择注意事项 )
- 传微软打算推出Android版IE浏览器
- Android实现PHP连接MySQL进行数据交互(android通过php连接mysql)
- android图像绘制(三)画布刷屏问题记录