Android Binder IPC机制

来源:互联网 发布:表格软件电脑版 编辑:程序博客网 时间:2024/04/30 06:37

之前有很多人问过我TaintDroid的内容,所以一点点吧涉及的思路整理一下。

今天又看了一遍,确实需要很多的技术支持以及扎实的功底,不管是Java的还是Android,从系统底层一直到顶层,涉及的知识点比较多。

以后会陆陆续续更新TaintDroid中涉及的知识点和实现的技术详解,当然了,是我个人的理解,未必是人家就这么实现的吧。

只是感觉可行。

在TaintDroid中涉及到Binder HOOK,虽然没有详解,但是原理感觉应该差不多吧。

首先Binder IPC这个是在C层的,也就是Native 层进行HOOK,为什么要进行BinderHOOK,这一层的监控是对信息流进行污点标记的。

因为使用变量级进行标记的话当遇到比较变态的接收器(Receiver)时就会发现溢出变量,使得已经被污点标记的变量被移除,因此需要使用信息层(message-level)来做保障。

两个运用程序之间的通信是通过Binder IPC来完成的。

之后的TaintDroid详解中会详细分析,现在先给出信息层实现原理。就是Binder HOOK。

1.Android Binder IPC机制

       Android系统中大量使用了基于C/S模式的通信方式。诸如短信操作,电话操作,视频音频捕获,传感器等都以服务(Service)的形式提供,并由相应的Server负责管理,

应用程序作为Client只需要与这些Server建立连接并发送请求便能使用这些服务。因此,开发者完全不必关心Service的实现细节,直接与Server建立连接然后使用其提供的接

口即可。Client和Server一般是运行在不同的进程中的,这就涉及到进程间通信(IPC,Inter-Process Communication)。为了保证系统安全性,提高通信效率以及提供对C/S

模式的支持,Android采用了一种基于共享内存的IPC机制——Binder机制。


2.Binder机制实现

为了实现Binder IPC机制,Android在Linux内核挂载了一个虚拟的设备/dev/binder。Client和Server进程运行在用户空间,使用Binder机制进行进程间通信时,双方看起来是“直接”通信的,

实际上通过/dev/binder的驱动程序即Binder驱动进行了数据的中转,如图1所示。Binder机制的本质是共享内存,共享内存区的管理完全由Binder驱动来完成,对应用层的Client和Server

来说是完全透明的。

                                                                                                                    
                                                                   图 1 Binder进程间通信模型



Client和Server均通过函数ioctl与Binder驱动进行数据交互。ioctl是Linux中用于控制I/O设备的函数,提供了一种同时向设备发送控制参数和数据的手段。它是一个可变参数的函数,原型为:

int ioctl(int fd, int cmd, ...);
 

fd是打开/dev/binder设备后得到的文件描述符,cmd是对设备的控制命令。该函数执行成功返回0,否则返回-1。


3.相关数据结构

当函数ioctl的第二个参数cmd为BINDER_WRITE_READ时,表示向Binder驱动发送一条读取或者写入/dev/binder设备的命令,Binder驱动会将对设备的读写“翻译”为对共享

内存区的读写。这条命令是Client和Server进行进程间通信时最重要、使用最频繁的控制命令。

传入BINDER_WRITE_READ的同时,会传入一个binder_write_read结构体的指针作为ioctl的第三个参数,该结构中的read_buffer和write_buffer字段分别指向将要读取或者写入的缓冲区。这两个缓冲区中的数据都是以“数据类型+数据内容”的格式顺序存放的,而且多条不同类型的数据连续存放,如图2所示。write_buffer中数据类型以“BC_”开头,而read_buffer中数据类型以“BR_”开头,图2中以write_buffer中的数据为例。在所有的数据类型中,又以BC(R)_REPLY和BC(R)_TRANSACTION最为重要:通过BC_TRANSACTION/BC_REPLY这对命令,发送方将数据发往接受方;通过BR_TRANSACTION/BR_REPLY,接收方读取发送方发来的数据。

数据的内容是一个binder_transaction_data结构。


图2 Binder IPC中各数据结构的关系

binder_transaction_data结构是对进程间通信数据的封装,可以看作网络通信中的一个数据包。其中的sender_uid,sender_pid成员变量指明了此数据发送方的用户ID和进程ID,buffer成员变量指向进程间通信最核心的有效负载数据,data_size是有效负载数据的长度。在Binder机制中,sender_uid和sender_pid是在内核中由Binder驱动填入的,无法被伪造,保证了身份标记的可靠性,由此可见Binder进程间通信机制进行是安全的。


4.Binder之间的数据行为关系

Client和Server使用Binder机制进行进程间通信时,通过分析Client发往Server的数据或者分析Server读取的Client的请求数据,便可以识别出Client的具体行为。

例如,当Client想要得到定位信息,请求LocationServer获取定位数据时,会访问LocationServer的ILocationManager接口,发往LocationServer中的有效负载数

据中包含“android.location.ILocationManager”字符串。所以我们分析LocationServer读取的Client发来的请求数据,判断其中是否包含“android.location.ILocationManager”,

我们就可以知道Client是否正在试图访问用户的地理位置信息。

由于Android系统中每个应用程序都有自己唯一的UID,因此根据binder_transaction_data中的sender_uid,我们就可以获取Client具体代表的应用程序。这样

就获得了具体软件的具体行为。

通过对Android系统的分析,我们发现:虽然系统提供的服务多达几十种,但是实际上只有三个Server进程负责管理

 Android系统Server进程与管理的服务

服务进程

管理的服务

com.android.phone

与通信功能相关的短信、电话服务

mediaserver

与媒体功能相关的视频、音频服务

system_server

其他服务,如地理位置、蓝牙、网络连接、程序安装卸载等







1 0
原创粉丝点击