谈Android PowerManager的Hook技术
2017-03-29 11:20
701 查看
在插件中,需要禁止插件调用系统原生接口持有WakeLock,Hook技术是不错的解决方案。
通过阅读系统源码,可以了解到PowerManager持有WakeLock操作最后都通过Binder跨进程调到系统服务中,我们只要拦截这个Binder的所有调用即可。
思路是先通过反射拿到这个IPowerManager的Binder,然后动态生成该Binder的代理对象,再覆盖原有的Binder即可。
以下BinderHook是一个关于Binder Hook的通用类,可用于各类Android系统服务的Binder的Hook。
接下来介绍一下Binder Hook的核心原理,我们拿到Binder对象之后,首先要将其转成业务接口类,通常是通过Stub.asInterface,而Binder对象可能是Binder实体,也可能是Binder Proxy,然而不管怎样它们都是IBinder对象。Stub.asInterface的实现是先通过queryLocalInterface获取本地接口,如果返回非空,则表示当前进程和Binder实体是同一个进程,直接返回本地接口即可。如果返回为空,则表示当前进程和Binder实体分属不同进程,此时会将BinderProxy封装一层业务接口返回。所以可见这里的关键在于queryLocalInterface函数,这个函数属于IBinder的接口,所以我们拿到Binder对象之后,生成一个代理对象,拦截这个queryLocalInterface,返回我们生成的代理接口。
源码 https://github.com/dingjikerbo/TechReports
通过阅读系统源码,可以了解到PowerManager持有WakeLock操作最后都通过Binder跨进程调到系统服务中,我们只要拦截这个Binder的所有调用即可。
思路是先通过反射拿到这个IPowerManager的Binder,然后动态生成该Binder的代理对象,再覆盖原有的Binder即可。
public class PowerManagerHook { public static void hook(Context context) throws Throwable { PowerManager manager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); Field field = FieldUtils.getField(PowerManager.class, "mService", true); BinderHook hook = new BinderHook(field.get(manager), new BinderHook.BinderHookInvoker() { @Override public Object onInvoke(Object original, Method method, Object[] args) throws Throwable { return method.invoke(original, args); } }); field.set(manager, hook.proxyInterface); } }
以下BinderHook是一个关于Binder Hook的通用类,可用于各类Android系统服务的Binder的Hook。
接下来介绍一下Binder Hook的核心原理,我们拿到Binder对象之后,首先要将其转成业务接口类,通常是通过Stub.asInterface,而Binder对象可能是Binder实体,也可能是Binder Proxy,然而不管怎样它们都是IBinder对象。Stub.asInterface的实现是先通过queryLocalInterface获取本地接口,如果返回非空,则表示当前进程和Binder实体是同一个进程,直接返回本地接口即可。如果返回为空,则表示当前进程和Binder实体分属不同进程,此时会将BinderProxy封装一层业务接口返回。所以可见这里的关键在于queryLocalInterface函数,这个函数属于IBinder的接口,所以我们拿到Binder对象之后,生成一个代理对象,拦截这个queryLocalInterface,返回我们生成的代理接口。
public class BinderHook { public Class<?> binderIntfClazz; public Object originalInterface; public IBinder originalBinder; public Object proxyInterface; public IBinder proxyBinder; public BinderHook(Object object, BinderHookInvoker invoker) { this.originalInterface = object; this.binderIntfClazz = BinderUtils.getBinderInterface(object); this.originalBinder = getOriginalBinder(); this.proxyInterface = getProxyInterface(invoker); this.proxyBinder = getProxyBinder(); } private IBinder getOriginalBinder() { Method method = MethodUtils.getAccessibleMethod(binderIntfClazz, "asBinder"); try { return (IBinder) method.invoke(originalInterface); } catch (Throwable e) { e.printStackTrace(); } return null; } private IBinder getProxyBinder() { return (IBinder) Proxy.newProxyInstance(IBinder.class.getClassLoader(), new Class<?>[]{IBinder.class}, new BinderHookHandler(originalBinder, "Binder") { @Override public Object onInvoke(Object original, Method method, Object[] args) throws Throwable { if (method.getName().equals("queryLocalInterface")) { return proxyInterface; } return method.invoke(original, args); } }); } private Object getProxyInterface(final BinderHookInvoker invoker) { return Proxy.newProxyInstance(originalInterface.getClass().getClassLoader(), ClassUtils.getAllInterfaces(originalInterface.getClass()).toArray(new Class<?>[0]), new BinderHookHandler(originalInterface, "Interface") { @Override public Object onInvoke(Object original, Method method, Object[] args) throws Throwable { return invoker.onInvoke(original, method, args); } }); } public interface BinderHookInvoker { Object onInvoke(Object original, Method method, Object[] args) throws Throwable; } abstract static class BinderHookHandler implements InvocationHandler, BinderHookInvoker { Object originalObject; String tag; public BinderHookHandler(Object originalObject, String tag) { this.tag = tag; this.originalObject = originalObject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (Object.class == method.getDeclaringClass()) { String name = method.getName(); if ("equals".equals(name)) { return proxy == args[0]; } else if ("hashCode".equals(name)) { return System.identityHashCode(proxy); } else if ("toString".equals(name)) { return proxy.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(proxy)); } else { throw new IllegalStateException(String.valueOf(method)); } } return onInvoke(originalObject, method, args); } } }
源码 https://github.com/dingjikerbo/TechReports
相关文章推荐
- Android下通过hook技术实现透明加解密保障数据安全
- Android通过hook技术实现透明加解密保障数据安全
- 深入Android源码系列(二) HOOK技术大作战
- 一个Demo了解android中的hook技术
- Hook技术activity启动过程中拦截(无需在androidmanifest文件注册即可使用)
- Android下通过hook技术实现透明加解密保障数据安全
- Android Hook View技术实践
- Android so注入(inject)和Hook技术学习(一)
- Android 5.0/5.1 HOOK技术探究
- Android Hook技术实践
- Android 5.0/5.1 HOOK技术探究
- Android Hook技术实践
- android Hook 技术剖析
- Android下通过hook技术实现透明加解密保障数据安全
- Android学习心得(20) --- Hook技术( 1 )
- android的hook技术之hook所有view的监听器
- Android逆向分析之Xposed的hook技术
- 浅谈android hook技术
- Android安全:Hook技术
- Android安全:Hook技术