文中肯定会有一些见识以及描述方面的错误,请各位大佬随意指正批评。
本篇介绍如何还原Android被Inline Hook的服务对象,以还原PMS为例。
我们分析Android系统源码:
android.app.ActivityThread发现类里面有这样一个方法:
如果sPackageManager字段为空就会调用IPackageManager类的内部Stub类的asInterface方法初始化IPackageManager对象,
那么Hook PMS就是将 sPackageManager 字段替换了,到这里我们就很容易得出一种还原PMS服务的方法:先将
sPackageManager 字段置空,然后反射调用getPackageManager方法,这样得到的IPM对象就是原始的服务对象,再
利用反射将PMS对象替换成原始的对象就好了。
但是,我们这里不采用这种方式,因为跟进asInterface这个方法我们不难发现: 这里的queryLocalInterface方法也是一个Hook点。
为什么说
queryLocalInterface方法也是一个Hook点呢?这里我以Hook queryLocalInterface方法的思路来阐述:
这个方法的意思就是:先查看本进程是否存在这个Binder对象,如果有那么直接就是本进程调用了;
如果不存在那么创建一个代理对象,让代理对象委托驱动完成跨进程调用。
观察这个方法,前面的那个if语句判空返回肯定动不了手脚;最后一句调用构造函数然后直接返回我们也是无从下手,
要修改asInterface方法的返回值,我们唯一能做的就是从这一句下手:
我们修改这个getService方法的返回值,让这个方法返回一个我们伪造过的IBinder对象;这样,
我们可以在自己伪造的IBinder对象的queryLocalInterface方法作处理,进而使得asInterface方法返回
在queryLocalInterface方法里面处理过的值,最终实现hook系统服务的目的。
在跟踪这个getService方法之前我们思考一下,由于系统服务是一系列的远程Service,它们的本体,
也就是Binder本地对象一般都存在于某个单独的进程,在这个进程之外的其他进程存在的都是这些Binder本地对象的代理。
因此在我们的进程里面,存在的也只是这个Binder代理对象,我们也只能对这些Binder代理对象下手。然后,
这个getService是一个静态方法,如果此方法什么都不做,拿到Binder代理对象之后直接返回;
那么我们就无能为力了:我们没有办法拦截一个静态方法,也没有办法获取到这个静态方法里面的局部变量(即我们希望修改的那个Binder代理对象)。
接下来就可以看这个getService的代码了:
不难发现,ServiceManager为了避免每次都进行跨进程通信,把这些Binder代理对象缓存在一张map里面。
我们可以替换这个map里面的内容为Hook过的IBinder对象,由于系统在getService的时候每次都会优先查找缓存,
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2020-3-8 09:13
被LivedForward编辑
,原因: