点击蓝字 关注我们
通过Binder对
Android系统服务
进行Fuzz
最近逛论坛时,偶然发现了一个Android系统漏洞,且与Binder相关,于是顺势查阅了一些Android Fuzz Binder的文章,并复现了其中一篇的代码。写这篇文章旨在加深自己的理解,并分享一些学习到的知识。
Android Binder
Android系统通过进程隔离来保障应用的安全性,这样每个应用默认运行在独立进程,拥有独立的虚拟内存空间,如果直接跨进程访问会导致分段错误。为解决多进程协作问题,Android设计了Binder机制,其核心优势在于:
1. 性能优化:传统IPC需两次数据拷贝,而Android Binder用内存映射实现单次拷贝。
2. 安全机制:沿用Linux的身份验证机制,并结合权限控制列表。
3. 面向对象抽象:通过AIDL将远程调用封装为本地方法调用,隐藏底层通信细节。
其中,Binder通信框架为C/S(client/server)结构,如图1所示,共由四部分构成:
图1 Binder通信框架简图
Binder Driver(内核层):作为虚拟字符设备/dev/binder,管理进程间通信通道并维护事务队列,处理请求的编解码与转发实现死亡通知机制。
ServiceManager(系统服务):作为Binder的"电话簿",维护服务名与Binder引用的映射表。通过addService()/getService()接口管理服务生命周期。
Server:继承Binder类实现具体服务逻辑,通过onTransact()处理客户端请求。
Client:通过bindService()获取IBinder对象,使用AIDL(Android接口定义语言,供用户抽象化IPC的工具)生成的Proxy类调用远程方法。
Android AIDL
AIDL作为Binder的编程接口,通过三个核心组件实现跨进程调用。
01
接口定义文件(.aidl)
其作用为声明服务端暴露的方法签名。
支持数据类型:基本类型、String、CharSequence、Parcelable、List/Map(需元素类型支持)
02
Stub类(服务端实现)
继承了Binder类,实现了AIDL接口,包含onTransact()方法处理客户端请求,通过transaction code区分不同方法调用。
03
Proxy类(客户端代理)
继承IInterface接口,封装远程调用,通过transact()方法发起Binder事务,使用Parcel进行作为消息的容器进行通信。
Binder通信流程
这里以“数字相加”方法(exampleFunctionAdd(a,b))调用为例,完整通信流程如下:
01
客户端代理调用
Proxy类将方法调用转换为Parcel对象,写入方法标识符和参数数据,通过BinderProxy.transact()发送请求。
02
Binder Driver处理
校验客户端权限,分配事务标识,最后将数据拷贝至内核缓冲区。
03
服务端处理请求
Binder驱动唤醒服务端线程池,根据ID调用Stub.onTransact(),执行实际业务逻辑(如a+b计算)。
04
结果返回
服务端将结果写入回复Parcel,Binder驱动将数据拷贝回客户端进程,客户端从Parcel解析返回结果(a+b)。
Java层Fuzz Binder
通过查阅资料后,发现了一种可以通过Java反射机制来对Binder进行Fuzz的方法,原文见文章末尾引用。获取到许多类并调用其方法,实现起来的方法更简单一些,可获得的信息更多。当然也有缺陷,会经常遇到没有权限的问题。
根据上述介绍,该过程可分为4步:
1) 获取所有运行的services及对应服务的IBinder 对象,代码如下所示:
services=(String[]) Class.forName("android.os.ServiceManager").getDeclaredMethod("listServices").invoke(null);
serviceBinder=(IBinder)Class.forName("android.os.ServiceManager").getDeclaredMethod("getService",String.class).invoke(null, service);
2) 获取对应接口的所有code
Class<?> cStub = Class.forName(serviceBinder.getInterfaceDescriptor()+ "$Stub");
Field[] f = cStub.getDeclaredFields();
for (Field field : f) {
field.setAccessible(true);
String k= field.toString().split("\$Stub\.")[1];
if (k.contains("TRANSACTION")){
codes.put(k, (int)field.get(this));
}
3) 获取接口所有调用的参数类型
HashMap<String, List<String>> ret = new HashMap();
Class<?> cStub = Class.forName(serviceBinder.getInterfaceDescriptor()+ "$Stub$Proxy");
Method[] m = cStub.getDeclaredMethods();
for (Method method : m) {
int func_code = 0;
List<String> func_parameter = new ArrayList<>();
method.setAccessible(true);
String func_name = method.toString().split("\$Stub\$Proxy\.")[1];
func_parameter.add(func_name);
for (String key : codes.keySet()) {
if (func_name.contains(key.substring("TRANSACTION_".length())))
func_code = codes.get(key);
}
if (func_code == 0)
continue;
Class<?>[] ParameterTypes = method.getParameterTypes();
for (int k=0; k < ParameterTypes.length; k++) {
func_parameter.add(ParameterTypes[k].toString());
}
ret.put(Integer.toString(func_code), func_parameter);
4)Binder调用
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
IBinder serviceBinder = BinderInfo.getIBinder(service);
serviceBinder.transact(code, data, reply, 0);
在实际的测试过程中,发现普通应用权限在第二、三步中能获取的信息并没有期望中的那么多。所以后来直接在0~100中遍历code,然后直接向其发送空指针数据,并结合Android studio的Logcat工具,查看发生的报错情况。至于对于能返回接口调用的参数类型的服务,则会对应构造随机数据来调用服务。
同时,在实际使用过程中,为了防止测试应用发送大量数据导致的系统卡顿和报错不清晰的问题,会在每次发送一些数据后手动使应用休眠几秒。
总结
Binder安全其实是Android系统安全研究的一个重要方向,近几年也经常会看到一些与之相关的CVE漏洞,而且Fuzz的方法也不局限于应用层。Android Red Team在《How to Fuzz Your Way to Android Universal Root: Attacking Android Binder》中也介绍了一种通过LKL fuzz binder的方法,目前研究后发现其方法更加深入系统,未来也将持续研究,进一步提高自己的能力。
引用
1. https://developer.android.com/reference/android/os/Parcel
2. https://developer.android.com/develop/background-work/services/aidl
3. https://developer.android.com/reference/android/os/Binder
4. https://www.usmacd.com/cn/Android_binder_fuzzing
5. https://androidoffsec.withgoogle.com/posts/attacking-android-binder-analysis-and-exploitation-of-cve-2023-20938/offensivecon_24_binder.pdf
往期精彩合集
● ScreenCrab:蓝军悄无声息的窥探之举及其应对之策
● 第二届网络安全创新论坛启幕,联想集团荣列2025网络安全大讲堂首批共建单位
● 联想全球安全实验室 “放大招”:让AI换脸诈骗无处遁形!
● 首站补天白帽黑客城市沙龙圆满收官,全球安全实验室(中国)赋能AI安全新征程
长
按
关
注
联想全球安全实验室(中国)
原文始发于微信公众号(联想全球安全实验室):通过Binder对Android系统服务进行Fuzz
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论