DroidPlugin之Binder Hook机制
2018-01-05 本文已影响60人
LeonXtp
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一次,而IBinder
的queryLocalInterface
则会在每次调用系统服务的时候被hook代理,每次返回hook之后的IInterface
实例。