DroidPlugin之Binder Hook机制

hook的根基是反射,并且反射的根基是系统的方法或者属性是static的,这样才能拦截到系统的服务。之后才是基于动态代理修改系统行为。

系统服务获取原理:


常用的调用系统服务代码:

ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

各种Service都被ServiceManager统一管理,其伪代码:

IBinder b = ServiceManager.getService("service_name"); // 获取原始的IBinder对象
IXXInterface in = IXXInterface.Stub.asInterface(b); // 转换为Service接口
    public static android.os.IBinder getService(String name) {
        // ... omissions
        android.os.IBinder service = sCache.get(name);
        if (service != null) {
            return service;
        } else {
            return createService(name);
        }
    }
public static android.content.IClipboard asInterface(android.os.IBinder obj) {
 
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); // Hook点
    if (((iin != null) && (iin instanceof android.content.IClipboard))) {
        return ((android.content.IClipboard) iin);
    }
    return new android.content.IClipboard.Stub.Proxy(obj);
}

Binder Hook实现原理:


  • 使用反射hook到ServiceManager对象
  • 使用反射调用其getService()方法,获取到一个IBinder实例
  • 动态代理这个IBinder实例的queryLocalInterface()方法,在此方法invoke()执行时,先利用XXIInterface.Stub.asInterface(IBinder binder)static方法的便利,使用反射创建出一个IInterface的实例
  • 动态代理这个IInterface对象的指定的某些方法,达到修改系统服务的目的。
  • 通过反射,获取到ServiceManager的静态属性sCache,里面保存了已经创建过的IBinder对象实例
  • 将hook了的Ibinder保存进sCache

下面的只是推测,有待验证:

这样,在之后每次获取系统服务的时候,

IBinder b = ServiceManager.getService("service_name"); // 获取原始的IBinder对象

这里获取到的就已经是Hook之后的IBinder实例,那么,在下一步

IXXInterface in = IXXInterface.Stub.asInterface(b); // 转换为Service接口

中,由于b已经被hook,b返回的就会是hook之后的IInterface了,达到hook的目的。

因此,IBinder会被动态代理hook一次,而IBinderqueryLocalInterface则会在每次调用系统服务的时候被hook代理,每次返回hook之后的IInterface实例。

你可能感兴趣的:(DroidPlugin之Binder Hook机制)