LocationManagerService主要和定位有关,平时在android开发中,都是直接使用系统提供的API接口来间接使用系统服务,
这些API都是通过aidl跨进程调用系统服务的。使用定位服务步骤如下,
首先获取LocationManager,
mLocationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
然后调用requestLocationUpdates设置更新位置等信息,
mLocationManager.requestLocationUpdates(provider, 500, 0, mLocationListener);
最后看下LocationManager的requestLocationUpdates方法是如何实现的,
private void requestLocationUpdates(LocationRequest request, LocationListener listener,
Looper looper, PendingIntent intent) {
android.util.SeempLog.record(47);
String packageName = mContext.getPackageName();
// wrap the listener class
ListenerTransport transport = wrapListener(listener, looper);
try {
mService.requestLocationUpdates(request, transport, intent, packageName);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException", e);
}
}
此mService对象就是LocationManagerService对象。
HookFactory的installHook方法中关于IlocationManagerBinderHook的代码如下,
installHook(new ILocationManagerBinderHook(context), classLoader);
首先调用IlocationManagerBinderHook的构造方法,然后调用其onInstall方法。
IlocationManagerBinderHook继承于BinderHook,
public class ILocationManagerBinderHook extends BinderHook {
BinderHook继承于抽象类Hook,并且实现了InvocationHandler接口,
abstract class BinderHook extends Hook implements InvocationHandler {
IlocationManagerBinderHook的构造方法一直调用父类的构造方法,最终Hook的构造方法如下,
protected Hook(Context hostContext) {
mHostContext = hostContext;
mHookHandles = createHookHandle();
}
主要保存进程上下文,并且调用子类的createHookHandle方法,
IlocationManagerBinderHook的createHookHandle方法如下,
protected BaseHookHandle createHookHandle() {
return new ILocationManagerHookHandle(mHostContext);
}
构造IlocationManagerHookHandle对象,
IlocationManagerHookHandle继承于抽象类BaseHookHandle,
public class ILocationManagerHookHandle extends BaseHookHandle {
IlocationManagerHookHandle的构造方法也直接调用父类BaseHookHandle的构造方法,
BaseHookHandle的构造方法如下,
public BaseHookHandle(Context hostContext) {
mHostContext = hostContext;
init();
}
保存进程上下文,然后调用子类的init方法,
BaseHookHandle中有个哈希表sHookedMethodHandlers,定义如下,
protected Map sHookedMethodHandlers
= new HashMap(5);
还有一个getHookedMethodHandler方法,可以根据方法获取对应的Hook对象,
public HookedMethodHandler getHookedMethodHandler(Method method) {
if (method != null) {
return sHookedMethodHandlers.get(method.getName());
} else {
return null;
}
}
由此可见, DroidPlugin框架是基于方法的Hook,就是对服务中的方法进行Hook。
IlocationManagerHookHandle的init方法如下,
protected void init() {
sHookedMethodHandlers.put("requestLocationUpdates", new requestLocationUpdates(mHostContext));
sHookedMethodHandlers.put("removeUpdates", new removeUpdates(mHostContext));
sHookedMethodHandlers.put("requestGeofence", new requestGeofence(mHostContext));
sHookedMethodHandlers.put("removeGeofence", new removeGeofence(mHostContext));
sHookedMethodHandlers.put("getLastLocation", new getLastLocation(mHostContext));
sHookedMethodHandlers.put("addGpsStatusListener", new addGpsStatusListener(mHostContext));
sHookedMethodHandlers.put("removeGpsStatusListener", new removeGpsStatusListener(mHostContext));
sHookedMethodHandlers.put("geocoderIsPresent", new geocoderIsPresent(mHostContext));
}
对LocationManagerService中的8个方法进行了Hook,当然也不是全部的方法都Hook。
并且这些Hook对象(其实不是真正的Hook对象,只是一些Hook对象代理对象,姑且这么称呼吧)是形式大于内容,
只是为了做更细节的修改,从独立的方法进行修改,并且都是内部类。
其中requestLocationUpdates 和removeUpdates定义如下,
private class requestLocationUpdates extends BaseILocationManagerHookedMethodHandler {
public requestLocationUpdates(Context hostContext) {
super(hostContext);
}
}
private class removeUpdates extends BaseILocationManagerHookedMethodHandler {
public removeUpdates(Context hostContext) {
super(hostContext);
}
}
都继承于内部类BaseILocationManagerHookedMethodHandler, 接着继承于ReplaceCallingPackageHookedMethodHandler,
继承于HookedMethodHandler。
IlocationManagerBinderHook并没有实现自己的onInstall方法,因此直接看父类BinderHook的onInstall方法,
protected void onInstall(ClassLoader classLoader) throws Throwable {
new ServiceManagerCacheBinderHook(mHostContext, getServiceName()).onInstall(classLoader);
mOldObj = getOldObj();
Class> clazz = mOldObj.getClass();
List> interfaces = Utils.getAllInterfaces(clazz);
Class[] ifs = interfaces != null && interfaces.size() > 0 ? interfaces.toArray(new Class[interfaces.size()]) : new Class[0];
Object proxiedObj = MyProxy.newProxyInstance(clazz.getClassLoader(), ifs, this);
MyServiceManager.addProxiedObj(getServiceName(), proxiedObj);
}
关于服务管理的主要逻辑如下,
1,Hook ServiceManager的sCache 哈希表中对应服务的Ibinder对象。
都变为ServiceManagerCacheBinderHook对象.
2,Hook 系统服务的对象。
这两个点下个章节分析。
关于Hook服务对象的主要逻辑如下,
1,调用getOldObj方法获取LocationManagerService对象, getOldObj是一个抽象方法,因此肯定在子类中实现,而且必须在子类中实现。
IlocationManagerBinderHook的getOldObj方法如下,
Object getOldObj() throws Exception {
IBinder iBinder = MyServiceManager.getOriginService(SERVICE_NAME);
return ILocationManagerCompat.asInterface(iBinder);
}
MyServiceManager的getOriginService方法如下,
static IBinder getOriginService(String serviceName) {
return mOriginServiceCache.get(serviceName);
}
从mOriginServiceCache变量中获取LocationManagerService对应的Ibinder对象,
IlocationManagerCompat的asInterface方法如下,
public static Object asInterface( IBinder binder) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
Class clazz = Class.forName("android.location.ILocationManager$Stub");
return MethodUtils.invokeStaticMethod(clazz, "asInterface", binder);
}
利用反射获取LocationManagerService类。
2,Hook LocationManagerService
Class> clazz = mOldObj.getClass();
List> interfaces = Utils.getAllInterfaces(clazz);
Class[] ifs = interfaces != null && interfaces.size() > 0 ? interfaces.toArray(new Class[interfaces.size()]) : new Class[0];
Object proxiedObj = MyProxy.newProxyInstance(clazz.getClassLoader(), ifs, this);
这样, LocationManagerService的Hook类为IlocationManagerBinderHook。
3,将Hook类也对应放入MyServiceManager的mProxiedObjCache变量中,
MyServiceManager.addProxiedObj(getServiceName(), proxiedObj);
addProxiedObj方法如下,
static void addProxiedObj(String servicename, Object obj) {
mProxiedObjCache.put(servicename, obj);
}
mProxiedObjCache定义如下,
private static Map mProxiedObjCache = new HashMap(1);
这样, MyServiceManager就有三个哈希表,
private static Map mOriginServiceCache = new HashMap(1);
private static Map mProxiedServiceCache = new HashMap(1);
private static Map mProxiedObjCache = new HashMap(1);
mOriginServiceCache保存服务名称和对应的原始Ibinder对象。
mOriginServiceCache保存服务名称和对应的Hook Ibinder对象,ServiceManagerCacheBinderHook.
mProxiedObjCache保存服务名称和对应的API Hook对象。