LocationManagerService API的Hook解析

2 LocationManagerService API的Hook解析

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方法。

2.1 BinderHook构造方法

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。

2.2 BinderHook onInstall方法

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对象。

你可能感兴趣的:(android,DroidPlugin)