

具體的流程是從右下角到中間再到左下角。
以Packagemanage的H ook為例:
具體的發(fā)起處理流程:
- IPackageManagerHook 使用動態(tài)代理生成一個代理對象,這里的代理類用到了它的父類ProxyHook
- ProxyHook 其實就是個動態(tài)代理類(ProxyHook)
- 首先在初始化時
ProxyHook.java
public ProxyHook(Context hostContext) {
super(hostContext);
}
Hook.java
protected Hook(Context hostContext) {
mHostContext = hostContext;
mHookHandles = createHookHandle();
}
在父類Hook的初始化中調(diào)用了createHookHandle,這個方法在具體的代理Hook中實現(xiàn),也就是IPackageManagerHook中
@Override
protected BaseHookHandle createHookHandle() {
return new IPackageManagerHookHandle(mHostContext);
}
看下這里的初始化IPackageManagerHookHandle,它繼承自BaseHookHandle,在BaseHookHandle中的初始化中,調(diào)用了init方法,
public BaseHookHandle(Context hostContext) {
mHostContext = hostContext;
init();
}
這個init是在具體的HookHandle中實現(xiàn)的,這里是指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這個基類中已經(jīng)實現(xiàn)了doHookInner方法,這個方法中會去依次嘗試調(diào)用beforeInvoke,反射invoke,afterInvoke。而beforeInvoke和afterInvoke就是在上面的getPackageInfo這個私有類中去實現(xiàn)的。
到這里,可以大致理解,把所有的方法以及具體的處理handle都放在map中。
這里在清醒一下,上面都是初始化操作。還沒有到具體的調(diào)用地方。
- 回到我們的
ProxyHook類中,在代理類中會調(diào)用到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);
}
.....
}
這里首先去調(diào)用Hook父類中的生成的mHookHandles去拿到他內(nèi)部Map中方法對應(yīng)的HookedMethodHandler
拿到處理Handler之后,再去調(diào)用它內(nèi)部的doHookInner方法,實現(xiàn)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,因為我們即將要生成這個對象的動態(tài)代理進行偷天換柱,所以要先把以前的保存下,以免失敗。
? 接著首先去拿到ActivityThread所有的接口,接著利用動態(tài)代理構(gòu)造一個代理對象,其中這里的invocationHandler用了this,其實是他的父類ProxyHook,具體可以看下ProxyHook的InVoke方法,這里就會到我們上面的解釋,這里其實是根據(jù)方法去分發(fā)具體的method代理實現(xiàn)。至此,可以拿到一個被代理后的PackageManager對象,并利用反射替換掉ActivityThread中的PackManager對象sPackageManager.
疑惑點:PackageManager這里為什么會有“mPM”這個對象,我暫時沒找到,后面回頭再看下。
這里舉了PackageManage 來分析,同樣的還有:
- IActivityManagerHook 代理ActivityManager
- IContentProviderHook 代理ContentProvider
- IWindowSessionHook 具體不明
至此,我們可以看下包結(jié)構(gòu):
hook
? --- handle
? ---IPackageManagerHookHandle 具體的處理方法代理等
? ---proxy
? ---Proxy,PackageMangerHook 具體的代理管理類
Hook