1,PMS Hook
和一般服务不同的是,AMS和PMS使用了另外一种Hook方式,虽然Hook的代码结构完全相同。
PMS通过getPackageManager这个方法来获取, ContextImpl类的getPackageManager方法如下,
public PackageManager getPackageManager() {
if (mPackageManager != null) {
return mPackageManager;
}
IPackageManager pm = ActivityThread.getPackageManager();
if (pm != null) {
// Doesn't matter if we make more than one instance.
return (mPackageManager = new ApplicationPackageManager(this, pm));
}
return null;
}
可以看到,
1.真正的PMS的代理对象在ActivityThread类里面。
2.ContextImpl通过ApplicationPackageManager对它还进行了一层包装。
ActivityThread类的getPackageManager方法如下,
public static IPackageManager getPackageManager() {
if (sPackageManager != null) {
return sPackageManager;
}
IBinder b = ServiceManager.getService("package");
sPackageManager = IPackageManager.Stub.asInterface(b);
return sPackageManager;
}
ApplicationPackageManager的构造方法如下,
ApplicationPackageManager(ContextImpl context, IPackageManager pm) {
mContext = context;
mPM = pm;
}
变量mPM如下,
private final IPackageManager mPM;
如果需要Hook PMS,有两个地方需要Hook,
1.ActivityThread的静态变量sPackageManager
2.通过Context类的getPackageManager方法获取到的ApplicationPackageManager对象里面的mPM变量。
1.1 Hook过程解析
HookFactory的installHook有关PMS的代码如下,
installHook(new IPackageManagerHook(context), classLoader);
IPackageManagerHook有关的结构图如下,
看结构图就一目了然了。
IpackageManagerHook的createHookHandle会构造IpackageManagerHookHandle对象,
protected BaseHookHandle createHookHandle() {
return new IPackageManagerHookHandle(mHostContext);
}
IpackageManagerHook的onInstall方法主要逻辑如下,
1,获取ActivityThread的sPackageManager变量.
Object currentActivityThread = ActivityThreadCompat.currentActivityThread();
setOldObj(FieldUtils.readField(currentActivityThread, "sPackageManager"));
2,Hook sPackageManager变量
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);
3,获取ApplicationPackageManager对象里面的mPM变量。
FieldUtils.writeField(currentActivityThread, "sPackageManager", newPm);
PackageManager pm = mHostContext.getPackageManager();
Object mPM = FieldUtils.readField(pm, "mPM");
4,Hook mPM变量,
if (mPM != newPm) {
FieldUtils.writeField(pm, "mPM", newPm);
}
这样就完成了PMS的Hook初步过程。
1.2 Hook方法
和前面论述的完全一样,都是对方法进行Hook,看看Hook 了哪些方法。
IpackageManagerHookHandle的init方法Hook了几十种方法,部分代码如下,
sHookedMethodHandlers.put("getPackageInfo", new getPackageInfo(mHostContext));
sHookedMethodHandlers.put("getPackageUid", new getPackageUid(mHostContext));
sHookedMethodHandlers.put("getPackageGids", new getPackageGids(mHostContext));
•••
当然这些类都是IpackageManagerHookHandle的内部类,并且都继承于HookedMethodHandler。
这些类的beforeInvoke方法在此就不多分析了。
小结:PMS Hook之后,调用PMS的getPackageInfo方法其实是调用getPackageInfo的beforeInvoke方法,其他方法以此类推。