最近反编译金山毒霸,分析其广告拦截功能是如何实现的。根据金山毒霸的介绍,采用了java虚拟机拦截技术,带着好奇去研究了一下。在查看代码过程中,会看到许多被hook的Java类,例如ActivityThread、ServiceManager等。在反编译的源码中,我主要追踪了有关iphonesubinfo服务拦截的实现。并通过代码测试通过,分享一下成果。
1.Java虚拟机拦截技术总体流程。
1)首先通过ptrace注入so到远程进程,例如金山就是注入libksrootclient.so到远程进程。
2)通过ptrace_call在远程进程中调用libksrootclient中的某一个静态方法,该方法主要完成加载封装的Java功能类jar包,并调用jar包中的类方法,完成进程中Java层的hook工作。比如金山毒霸中的加载jar包:ksremote.jar
2.关键技术
1)so注入
so注入式Java虚拟机拦截技术的第一步,注入成功与否决定了后面的拦截功能。
2)实现拦截Java API功能模块,并导出jar包。
比如如果想监控程序是否读取手机IMEI/ismi、电话号码、sim卡号。通过源码分析可知,获取这些信息需要TelephonyManager类的相关方法,方法中主要是通过获取iphonesubinfo服务类提供功能。因此,如果拦截到了iphonesubinfo服务的功能,就可以成功获取应用是否读取设备信息。
在java层,获取服务是通过ServiceManager的getService方法获取,分析getService方法,该方法首先会从sCache中查询是否存在服务,如果存在服务,就直接返回。因此,如果修改sCache中iphonesubinfo的ibinder引用,就可以实现拦截功能。
3)在注入的so中通过JNI动态加载jar包,并执行jar包中的关键类,完成Java层Hook。
JNI动态加载jar包原理可以查看贴子"Android中JNI方式调用Jar包"。
关于android中拦截技术总结:
1.android中API拦截技术有两种模式,一种是拦截C层API,另一种是拦截Java层API.
2.C层拦截API
在C层拦截API中最常研究的方式是拦截libbinder.so中的ioctl调用。在binder通信中,用户空间和内核空间需要ioctl系统调用,如果拦截该系统调用,然后对参数解析,可以实现lbe的主动防御功能。前提是必须非常熟悉binder机制以及binder的数据传输格式。
3.Java虚拟机拦截技术(Java层拦截)
Java层拦截需要自己实现关键方法的拦截,该中方式的拦截不需要对参数进行大规模解析。
例如我在实现拦截读取imei的过程中,只需在拦截Java api处直接返回false,应用获取的imei变成null。
转载于:https://my.oschina.net/fuckboogie/blog/201958