PMS Hook

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有关的结构图如下,

《PMS Hook》

看结构图就一目了然了。

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方法,其他方法以此类推。

    原文作者:Achillisjack
    原文地址: https://blog.csdn.net/u012439416/article/details/76390368
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞