Android之Hook入门讲解
目录
1.Hook是做什么的?(解决什么问题?)
2.HOOK技术如何改变API执行结果的?
3.使用Hook技术需要有实现Java反射和阅读源码的能力
3.1Java反射
3.2SDK源码
4.Hook实现的通用思路
5.Hook拦截点击事件加入统计点击次数
5.1确认需要hook操作对象OnClickListener实现的实例
5.2获取要hook干涉执行逻辑的拥有者(ListenerInfo对象);
5.3创建(hook对象)OnClickListener类实例代理类,在代理类内加入自己代码;
6.其他
1.Hook是做什么的?(解决什么问题?)
API HOOK百度百科解释如下:
API HOOK技术是一种用于改变API执行结果的技术,Microsoft 自身也在Windows操作系统里面使用了这个技术,如Windows兼容模式等。 API HOOK 技术并不是计算机病毒专有技术,但是计算机病毒经常使用这个技术来达到隐藏自己的目的。
Hook可以帮助我们在Android中在SDK源代码逻辑执行过程中,通过代码手动拦截执行该逻辑,加入自己的代码逻辑;
例如常见的一些业务统计功能或者方法执行的性能监测功能我们都可以通过Hook技术进行拦截,加入自己代码逻辑;
以前都是通过友盟,百度创建ID和描述,需要开发将事件记录一个一个加入到需要统计的点上,很容易出现漏记的情况,修改需要重新发包;在APP开发过程中通常需要统计用户点击了那些按钮,页面的打开关闭,页面停留时长都可以通过Hook技术大大减小开发工作量和出错率;
2.HOOK技术如何改变API执行结果的?
最初有些人对某些api函数的功能不太满意,就产生了如何修改这些api,使之更好的服务于程序的想法,这样api hook就自然而然的出现了。
HOOK技术的难点,并不在于hook技术,而在于对SDK源码的学习和理解,找到使用HOOK的入口函数,进行拦截然后加入自己的代码;
3.使用Hook技术需要有实现Java反射和阅读源码的能力
3.1Java反射
Java反射常用类Class,Method,Field等;
SDK源码类有很多用@hide被隐藏的方法,成员,类无法直接访问,需要通过反射访问方法,成员,类等;
TextView
/*** @return the size (in scaled pixels) of thee default text size in this TextView.* @hide*/@ViewDebug.ExportedProperty(category = "text")public float getScaledTextSize() {return mTextPaint.getTextSize() / mTextPaint.density;}
3.2SDK源码
需要阅读SDK源码找到入口函数,这样才能通过Hook技术进行拦截,添加自己的代码逻辑;当追踪源码时经常看见SDK源码大面积飘红;
所以,推荐从安卓官网下载整套源码,然后使用 SourceInsight
查看源码。
如果不需要跳来跳去的话,直接用 安卓源码网站 一步到位
4.Hook实现的通用思路
无论多么复杂的逻辑,当我们需要干涉执行,最终都是需要将自己的代码逻辑替换干涉执行的逻辑;
a.确认需要hook操作对象A:a;
b.获取要hook干涉执行逻辑的拥有者(B对象);
例如定义类A和B,B拥有A实例,假如需要操作A实例,需要先拿到B;
Class A{}
Class B{
A a;
}
c.创建(hook对象)A类实例代理类,在代理类内加入自己代码;
d.将创建的(hook对象)代理类A对象,替换B类中a对象;
5.Hook拦截点击事件加入统计点击次数
5.1确认需要hook操作对象OnClickListener实现的实例
tvone.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {}});
a.Hook操作onClickListener实例,需要获取onClickListener拥有者;
/*** Register a callback to be invoked when this view is clicked. If this view is not* clickable, it becomes clickable.** @param l The callback that will run** @see #setClickable(boolean)*/public void setOnClickListener(@Nullable OnClickListener l) {if (!isClickable()) {setClickable(true);}getListenerInfo().mOnClickListener = l;}
onClickListener拥有者是ListenerInfo;
b.onClickListener拥有者是mListenerInfo实例
ListenerInfo getListenerInfo() {if (mListenerInfo != null) {return mListenerInfo;}mListenerInfo = new ListenerInfo();return mListenerInfo;}
mListenerInfo是一个“伪实例“,我们看下ListenerInfo持有的OnClickListener实例:
static class ListenerInfo {/*** Listener used to dispatch click events.* This field should be made private, so it is hidden from the SDK.* {@hide}*/public OnClickListener mOnClickListener;...其他Listener实例,例如长按等;
}
5.2获取要hook干涉执行逻辑的拥有者(ListenerInfo对象);
5.3创建(hook对象)OnClickListener类实例代理类,在代理类内加入自己代码;
public class HookListener {/*** hook核心代码* 这个方法唯一目的:用自己的点击事件,替换掉View的点击事件* @param context* @param view*/public static void registerListener(Context context, View view){//反射执行View类的getListenerInfo()方法,拿到v的mListenerInfo对象,这个对象就是点击事件的持有者try {Method method = View.class.getDeclaredMethod("getListenerInfo");//由于getListenerInfo()方法并不是public的,所以要加这个代码来保证访问权限method.setAccessible(true);//拿到mListenerInfo,也就是点击事件的持有者Object listenerInfo = method.invoke(view);//找到mListenerInfo持有的点击事件对象//android.view.View$ListenerInfo内部类的表示方法Class<?> listenerInfoClz = Class.forName("android.view.View$ListenerInfo");Field field = listenerInfoClz.getDeclaredField("mOnClickListener");final View.OnClickListener onClickListenerInstance = (View.OnClickListener)field.get(listenerInfo);//创建自己点击事件的代理类//方式1:自己实现代理类//ProxyOnClickListener proxyOnClickListener = new ProxyOnClickListener(onClickListenerInstance);//方式2:由于View.OnClickListener是一个接口,所以可以直接用动态代理模式//参数:本地类的加载器,要代理实现的接口(用Class数组表示,支持多接口),代理类的实际逻辑封装在new出来的InvocationHandler内final Object proxyOnClickListener = Proxy.newProxyInstance(context.getClass().getClassLoader(),new Class[]{View.OnClickListener.class}, new InvocationHandler() {private int clickCount = 0;@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {clickCount++;Log.d("HookOnClickListener", ""+clickCount);return method.invoke(onClickListenerInstance, args);}});//替换持有者拥有的点击事件代理类,field.set(listenerInfo, proxyOnClickListener);//完成} catch (NoSuchMethodException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (NoSuchFieldException e) {e.printStackTrace();}}static class ProxyOnClickListener implements View.OnClickListener{private View.OnClickListener listener;private int clickCount = 0;ProxyOnClickListener(View.OnClickListener listener){this.listener = listener}@Overridepublic void onClick(View v) {clickCount++;Log.d("HookOnClickListener", ""+clickCount);if(this.listener != null){this.listener.onClick(v);}}}
}
代码逻辑:
a.借助于Method,Field,Class拿到点击事件的持有者mListenerInfo;
//由于getListenerInfo()方法并不是public的,所以要加这个代码来保证访问权限
method.setAccessible(true);
b.用点击事件的代理类替换持有者mListenerInfo点击事件
//替换持有者拥有的点击事件代理类,
field.set(listenerInfo, proxyOnClickListener);
c.用Proxy代理类的创建点击事件的代理类
包含三个参数:本地类的加载器,要代理实现的接口(用Class数组表示,支持多接口),代理类的实际逻辑封装在new出来的InvocationHandler内
测试代码:
tvone.setOnClickListener(this);
HookListener.registerListener(this, tvone);
拦击统计点击次数输出日志:
06-03 04:19:00.563 5603-5603/fan.fragmentdemo D/HookOnClickListener: 3
06-03 04:19:01.023 5603-5603/fan.fragmentdemo D/HookOnClickListener: 4
06-03 04:19:01.543 5603-5603/fan.fragmentdemo D/HookOnClickListener: 5
06-03 04:19:01.733 5603-5603/fan.fragmentdemo D/HookOnClickListener: 6
06-03 04:19:02.013 5603-5603/fan.fragmentdemo D/HookOnClickListener: 7
06-03 04:19:02.243 5603-5603/fan.fragmentdemo D/HookOnClickListener: 8
以上是Hook技术实现整理;
6.其他
实现Hook技术,第一需要先了解Hook实现流程,第二要熟悉SDK源码,才能帮助我们快速定位需要修改的业务代码;
参考:
https://baike.baidu.com/item/API%20HOOK?fr=aladdin
https://www.jianshu.com/p/74c12164ffca?tdsourcetag=s_pcqq_aiomsg
Android之Hook入门讲解相关推荐
- android retrofit入门,Android开发 retrofit入门讲解
前言 retrofit基于okhttp封装的网络请求框架,网络请求的工作本质上是 OkHttp 完成,而 retrofit 仅负责网络请求接口的封装.如果你不了解OKhttp建议你还是先了解它在来学习 ...
- 收藏 | Android开发从入门到精通系列书籍资料最全攻略!!!(最新更新)
很多人会私信给我提问,问安卓的学习路线是什么,因为之前没有写过系统的路线图,于是近期花了一些时间,把这块的知识,做成一个体系分享给大家,也算是自己在安卓这边做的一份贡献. 关于安卓如何来学习,安卓入门 ...
- 5G 时代的 Android App 开发入门与项目实战
随着移动互联网的持续发展,Android系统从智能手机逐步拓展到平板电脑.智能电视.车载大屏.智能家居.智能手表等诸多设备,Android开发依然是前景可期的IT岗位. 当然,整个社会正在迈向5G时代 ...
- android开发入门与实践_我的新书《Android App开发入门与实战》已经出版
前言 工作之余喜欢在CSDN平台上写一些技术文章,算下时间也有两三年了.写文章的目的一方面是自己对技术的总结,另一方面也是将平时遇到的问题和解决方案与大家分享,还有就是在这个平台上能和大家共同交流. ...
- Android Native Hook工具
前言 在目前的安卓APP测试中对于Native Hook的需求越来越大,越来越多的APP开始逐渐使用NDK来开发核心或者敏感代码逻辑.个人认为原因如下: 安全的考虑.各大APP越来越注重安全性,NDK ...
- Android SELinux开发入门指南之正确姿势解决访问data目录权限问题
Android SELinux开发入门指南之正确姿势解决访问data目录权限问题 Android SELinux开发多场景实战指南目录: Android SELinux开发入门指南之SELinux ...
- Android SELinux开发入门指南之如何增加Java Binder Service权限
Android SELinux开发入门指南之如何增加Java Binder Service权限 Android SELinux开发多场景实战指南目录: Android SELinux开发入门指南之 ...
- android地图入门,android 百度地图入门01 (史上最详没有之一)
最近一直和百度地图打交道,写几篇博客记录一下吧,目前最新版是4.0的 ,之前我用的是3.7的, 就以4.0的为例说一下最基本的配置流程吧. 一.准备工作 1.申请一个百度地图开发者账户--地址:htt ...
- Android Monkey测试入门:安装sdk、studio、模拟器,并分析monkey日志
Android Monkey测试入门:安装sdk.studio.模拟器,并分析monkey测试报告结果 1. 安装Java JDK和android SDK 2. 安装Andriod studio及模拟 ...
最新文章
- [deviceone开发]-do_Http组件示例
- Wijmo 更优美的jQuery UI部件集:运行时处理Wijmo GridView数据操作
- openpyxl模块介绍
- 【路由交换实验】OSPF
- Code Review工具Jupiter介绍
- js最简单数组去重_js简单数组去重
- linux 判断网卡是否异常_如何判断linux网卡故障?
- 解决Ubuntu中文件管理器死掉的情况
- 广域信息服务器,网络工程师之广域信息服务
- kafka python_kafka python
- 小米集团本周再回购1920万港元股票
- mysql哨兵机制_Redis 哨兵机制以及底层原理深入解析,这次终于搞清楚了
- linux字符界面下安装鼠标,Linux下有趣的命令:安装oneko实现小猫追鼠标
- 基于Hosted WebCore 方式部署Web Role
- caffemodel中的参数及特征的抽取
- 静态HTML网页设计作品我的家乡网站设计——我的家乡-绿城之都-南宁(9页) HTML+CSS+JavaScript 大学生简单个人静态HTML网页设计作品
- java数组三种排序方式
- 神经元模型图手工制作,神经元模型图手工模型
- (2)机械臂Simscape建模:模型导入MATLAB
- 二进制数的反码和补码