4. ServiceManager Hook原理
如果调用getSystemService方法获取系统服务对应的API接口,
mLoactionManager = (LoactionManager) getSystemService(Context.LOCATION_SERVICE);
获取系统服务的使用其实就分为两步
IBinder b = ServiceManager.getService("service_name"); // 获取原始的IBinder对象
IXXInterface in = IXXInterface.Stub.asInterface(b); // 转换为Service接口
4.1 IBinder代理的Hook
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
获取的是系统服务的IBinder代理对象,但是,进行Hook时,添加到sCache中的是对应的ServiceManagerCacheBinderHook对象。
也就是说, ServiceManagerCacheBinderHook Hook了IBinder代理对象。
4.2 queryLocalInterface方法的Hook
调用IBinder代理对象的方法时,其实就会调用ServiceManagerCacheBinderHook对象的invoke方法,调用流程图如下,
invoke方法主要逻辑如下,
1,获取原来的系统服务对应的IBinder对象,如果不可用的直接调用IBinder对象的方法,相当于未Hook 一样。
IBinder originService = MyServiceManager.getOriginService(mServiceName);
if (!isEnable()) {
return method.invoke(originService, args);
}
2,Hook方法的处理
HookedMethodHandler hookedMethodHandler = mHookHandles.getHookedMethodHandler(method);
if (hookedMethodHandler != null) {
return hookedMethodHandler.doHookInner(originService, method, args);
} else {
return method.invoke(originService, args);
}
首先获取Hook 的方法对应的对象,因为是按照方法来Hook的,一个方法对应一个Hook对象。
mHookHandles 一般在createHookHandle方法调用实际实现的Hook 的init方法中添加的,
这句话说的有点拗口,再次啰嗦一下,
ServiceManagerCacheBinderHook的createHookHandle方法如下,
protected BaseHookHandle createHookHandle() {
return new ServiceManagerHookHandle(mHostContext);
}
ServiceManagerHookHandle的init方法如下,
protected void init() {
sHookedMethodHandlers.put("queryLocalInterface", new queryLocalInterface(mHostContext));
}
说明仅仅Hook了IBinder对象的queryLocalInterface方法,其他方法都没有Hook。方法未Hook的还是调用原理IBinder
对象的方法,如果是queryLocalInterface就调用
queryLocalInterface类的doHookInner方法,
queryLocalInterface类的父类HookedMethodHandler的doHookInner方法如下,
boolean suc = beforeInvoke(receiver, method, args);
Object invokeResult = null;
if (!suc) {
invokeResult = method.invoke(receiver, args);
}
afterInvoke(receiver, method, args, invokeResult);
一般会调用子类的beforeInvoke方法,如果返回false,就相当于该方法未Hook一样。
最后会调用afterInvoke方法,该方法在此就不论述了,主要看beforeInvoke方法。
当然如果子类未实现beforeInvoke方法,就默认返回false,相当于该方法未Hook一样. HookedMethodHandler的beforeInvoke方法如下,
protected boolean beforeInvoke(Object receiver, Method method, Object[] args) throws Throwable {
return false;
}
queryLocalInterface类的定义如下,
class queryLocalInterface extends HookedMethodHandler {
public queryLocalInterface(Context context) {
super(context);
}
@Override
protected void afterInvoke(Object receiver, Method method, Object[] args, Object invokeResult) throws Throwable {
Object localInterface = invokeResult;
Object proxiedObj = MyServiceManager.getProxiedObj(mServiceName);
if (localInterface == null && proxiedObj != null) {
setFakedResult(proxiedObj);
}
}
}
这里仅仅实现了 afterInvoke方法。一般情况下,系统服务(例如LoactionManagerService)一般在queryLocalInterface方法中实现,
但是在前面的论述中,初始化时已经实现了,所以这里就没有覆盖beforeInvoke方法了。
在此也可以看出一些逻辑,调用IBinder对象的queryLocalInterface方法其实就是调用queryLocalInterface 类的beforeInvoke
和 afterInvoke方法。
4.3 结构图
ServiceManagerCacheBinderHook的结构图如下,
ServiceManagerCacheBinderHookHook了IBinder对象,有三个主要的方法,
1, onInstall方法,初始化。
2, invoke 方法,Hook的地方。
3,createHookHandle方法中真正创建执行Hook的类,类似于委托。
ServiceManagerHookHandle是ServiceManagerCacheBinderHook的内部类,主要有一个方法,
Init:构造Hook 方法执行的类。ServiceManagerHookHandle其实并不是执行类。
queryLocalInterface是ServiceManagerHookHandle的内部类,一般会实现beforeInvoke/afterInvoke方法。
这里的beforeInvoke/afterInvoke方法才是真正Hook IBinder对象的方法执行的地方。