说到Hook技术得先提到逆向工程,逆向工程源于商业及军事领域中的硬件分析,其主要目的是在不能轻易获得必要的生产信息的情况下,直接从成品分析,推导出产品的设计原理。
逆向分析分为静态分析和动态分析,其中静态分析指的是一种在不执行程序的情况下对程序行为进行分析的技术;动态分析是指在程序运行时对程序进行调试的技术。
Hook技术就属于动态分析,它不仅在Android平台中被应用,早在Windows平台中就已经被应用了。
14.1 Hook技术概述
我们知道应用程序进程之间是彼此独立的,应用程序进程和系统进程之间也是如此,想要在应用程序进程更改系统进程的某些行为很难直接实现,有了Hook 技术,我们就可以在进程间进行行为更改,如图所示。
可以看到Hook可以将自己融入到它所要劫持的对象(对象B)所在的进程中,成为系统进程的一部分,这样我们就可以通过Hook来更改对象B的行为。被劫持的对象(对象B),称作Hook点,为了保证Hook的稳定性,Hook点一般选择容易找到并且不易变化的对象,静态变量和单例就符合这一条件。
14.2 Hook技术分类
Hook技术知识点比较多,因此Hook技术根据不同的角度会有很多种分类,这里介绍其中的三种分类。
- 根据Hook的API语言划分,分为Hook Java和Hook Native。
- Hook Java主要通过反射和代理来实现,应用于在SDK开发环境中修改Java代码。
- HookNative则应用于在NDK开发环境和系统开发中修改Native代码。
- 根据Hook的进程划分,分为应用程序进程Hook和全局Hook。
- 应用程序进程Hook只能Hook当前所在的应用程序进程。
- 应用程序进程是Zygote进程fock出来的,如果对Zygote进行Hook, 就可以实现Hook系统所有的应用程序进程,这就是全局Hook。
- 根据Hook的实现方式划分,分为如下两种。
- 通过反射和代理实现,只能Hook当前的应用程序进程。
- 通过Hook框架来实现,比如Xposed, 可以实现全局Hook, 但是需要root。
Hook Native、全局Hook和通过Hook框架实现这些分类和插件化技术关联不大,本章主要需要学习的是Hook Java,想要更好地学习Hook Java,首先要了解代理模式。
14.3 代理模式
代理模式也叫委托模式,是结构型设计模式的一一种。在现实生活中我们用到类似代理模式的场景有很多,比如代购、代理上网、打官司等。
定义:为其他对象提供一种代理以控制对这个对象的访问称为代理模式。
在代理模式中有如下角色。
- Subject: 抽象主题类,声明真实主题与代理的共同接口方法。
- RealSubject: 真实主题类,定义了代理所表示的集体对象,客户端通过代理类间接调用真实主题类的方法。
- Proxy: 代理类,持有对真实主题类的引用,在其所实现的接口方法中调用真实主题类中相应的接口方法执行。
- Client: 客户端类。
14.3.1 代理模式简单实现
14.3.2 动态代理的简单实现
从编码的角度来说,代理模式分为静态代理和动态代理。
- 静态代理,在代码运行前就已经存在了代理类的class编译文件
动态代理则是在代码运行时通过反射来动态地生成代理类的对象,并确定到底来代理谁。Java 提供了动态的代理接口InvocationHandler,实现该接口需要重写invoke方法。
- 创建代理类,实现InvocationHandler接口
客户端类代码:
public class Client { public static void main(String[] args) {
//创建LiuWangShu
IShop liuwangshu = new LiuWangShu() ;
//创建动态代理
DynamicPurchasing mDynamicPurchasing = new DynamicPurchasing(liuwangshu) ;
//创建LiuWangShu的ClassLoader
ClassLoader loader = liuwangshu.getClass().getClassLoader() ;
//动态创建代理类
IShop purchasing = (IShop)Proxy.newProxyInstance(loader, new Class[] {IShop.class}, mDynamicPurchasing) ;
purchasing.buy() ;
}
}
14.4 Hook startActivity方法
我们知道Hook可以用来劫持对象,被劫持的对象叫作Hook点,用代理对象来替代Hook点,这样我们就可以在代理上实现自己想做的操作。这里以Hook常用的startActivity方法来举例,startActivity 方法分为两个,如下所示:
- startActivity (intent) ;
- getApplicationContext () . startActivity (intent) ;
第一个是Actvity的startActivity方法,第二个是Context的startActivity 方法。