具体的流程是从右下角到中间再到左下角。
以Packagemanage的H ook为例:
具体的发起处理流程:
- IPackageManagerHook 使用动态代理生成一个代理对象,这里的代理类用到了它的父类ProxyHook
- ProxyHook 其实就是个动态代理类(ProxyHook)
- 首先在初始化时
ProxyHook.java
public ProxyHook(Context hostContext) {
super(hostContext);
}
Hook.java
protected Hook(Context hostContext) {
mHostContext = hostContext;
mHookHandles = createHookHandle();
}
在父类Hook的初始化中调用了createHookHandle
,这个方法在具体的代理Hook中实现,也就是IPackageManagerHook
中
@Override
protected BaseHookHandle createHookHandle() {
return new IPackageManagerHookHandle(mHostContext);
}
看下这里的初始化IPackageManagerHookHandle
,它继承自BaseHookHandle
,在BaseHookHandle
中的初始化中,调用了init
方法,
public BaseHookHandle(Context hostContext) {
mHostContext = hostContext;
init();
}
这个init
是在具体的HookHandle
中实现的,这里是指IPackageManagerHookHandle
,
@Override
protected void init() {
sHookedMethodHandlers.put("getPackageInfo", new getPackageInfo(mHostContext));
sHookedMethodHandlers.put("getPackageUid", new getPackageUid(mHostContext));
...
}
首先是这里的sHookedMethodHandlers
是一个Map对象,它是在BaseHookHandle中就声明并初始化过了,它的key值是方法名,value值是具体的处理handler。后面new的类都是一个私有的类,这里大致看下getPackageInfo
private class getPackageInfo extends HookedMethodHandler {
public getPackageInfo(Context context) {
super(context);
}
@Override
protected boolean beforeInvoke(Object receiver, Method method, Object[] args) throws Throwable {
//API 2.3, 4.01, 4.0.3_r1
/*public PackageInfo getPackageInfo(String packageName, int flags) throws RemoteException;*/
//API 4.1.1_r1, 4.2_r1, 4.3_r1, 4.4_r1, 5.0.2_r1
/*public PackageInfo getPackageInfo(String packageName, int flags, int userId) throws RemoteException;*/
if (args != null) {
final int index0 = 0, index1 = 1;
String packageName = null;
if (args.length > index0) {
if (args[index0] != null && args[index0] instanceof String) {
packageName = (String) args[index0];
}
}
int flags = 0;
if (args.length > index1) {
if (args[index1] != null && args[index1] instanceof Integer) {
flags = (Integer) args[index1];
}
}
if (packageName != null) {
PackageInfo packageInfo = null;
try {
packageInfo = PluginManager.getInstance().getPackageInfo(packageName, flags);
} catch (Exception e) {
e.printStackTrace();
}
if (packageInfo != null) {
setFakedResult(packageInfo);
return true;
} else {
Log.i(TAG, "getPackageInfo(%s) fail,pkginfo is null", packageName);
}
}
}
return super.beforeInvoke(receiver, method, args);
}
}
继承自HookedMethodHandler
,在HookedMethodHandler
这个基类中已经实现了doHookInner
方法,这个方法中会去依次尝试调用beforeInvoke
,反射invoke
,afterInvoke
。而beforeInvoke
和afterInvoke
就是在上面的getPackageInfo
这个私有类中去实现的。
到这里,可以大致理解,把所有的方法以及具体的处理handle
都放在map中。
这里在清醒一下,上面都是初始化操作。还没有到具体的调用地方。
- 回到我们的
ProxyHook
类中,在代理类中会调用到invoke
方法,
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (!isEnable()) {
return method.invoke(mOldObj, args);
}
HookedMethodHandler hookedMethodHandler = mHookHandles.getHookedMethodHandler(method);
if (hookedMethodHandler != null) {
return hookedMethodHandler.doHookInner(mOldObj, method, args);
}
return method.invoke(mOldObj, args);
}
.....
}
这里首先去调用Hook
父类中的生成的mHookHandles
去拿到他内部Map中方法对应的HookedMethodHandler
拿到处理Handler
之后,再去调用它内部的doHookInner
方法,实现Hook
。
- 再往上一层 ,回到起点IPackageManagerHook 的onInstall 方法。
@Override
protected void onInstall(ClassLoader classLoader) throws Throwable {
Object currentActivityThread = ActivityThreadCompat.currentActivityThread();
setOldObj(FieldUtils.readField(currentActivityThread, "sPackageManager"));
Class<?> iPmClass = mOldObj.getClass();
List<Class<?>> interfaces = Utils.getAllInterfaces(iPmClass);
Class[] ifs = interfaces != null && interfaces.size() > 0 ? interfaces.toArray(new Class[interfaces.size()]) : new Class[0];
Object newPm = MyProxy.newProxyInstance(iPmClass.getClassLoader(), ifs, this);
FieldUtils.writeField(currentActivityThread, "sPackageManager", newPm);
PackageManager pm = mHostContext.getPackageManager();
Object mPM = FieldUtils.readField(pm, "mPM");
if (mPM != newPm) {
FieldUtils.writeField(pm, "mPM", newPm);
}
}
分析一下:
首先拿到当前的ActivityThread,将这个ActivityThread保存到ProxyHook中的OldObj,因为我们即将要生成这个对象的动态代理进行偷天换柱,所以要先把以前的保存下,以免失败。
接着首先去拿到ActivityThread所有的接口,接着利用动态代理构造一个代理对象,其中这里的invocationHandler用了this,其实是他的父类ProxyHook,具体可以看下ProxyHook的InVoke方法,这里就会到我们上面的解释,这里其实是根据方法去分发具体的method代理实现。至此,可以拿到一个被代理后的PackageManager对象,并利用反射替换掉ActivityThread中的PackManager对象sPackageManager.
疑惑点:PackageManager这里为什么会有“mPM”这个对象,我暂时没找到,后面回头再看下。
这里举了PackageManage 来分析,同样的还有:
- IActivityManagerHook 代理ActivityManager
- IContentProviderHook 代理ContentProvider
- IWindowSessionHook 具体不明
至此,我们可以看下包结构:
hook
--- handle
---IPackageManagerHookHandle 具体的处理方法代理等
---proxy
---Proxy,PackageMangerHook 具体的代理管理类
Hook