扣吧力作,欢迎转载,转载请注明来自colbert337.github.io

最近扣吧忙成狗了,好久没更新博客,对不住大家了,今天趁天气暖和点,来一篇干货。

由于好久没搞Android了,写得不专业的地方,请见谅哈。

0.为什么要研究Binder fuzz

以目前最热门的指纹方案为例。

TZ:Trustzone(请自行百度)
CA:Trustzone框架中的Clinet App
TA:Trustzone框架中的Trustzone APP

上层APP通过Binder机制调用keystore和FingerprintService两个底层系统服务,来获取密钥存储和指纹的能力。底层服务再通过CA跟TZ驱动通信,调用TZ中TA提供的服务,如指纹识别等安全性要求较高的服务。

我们今天只看Android侧的Binder体系。

Binder其实是提供了一种进程间通信(IPC)的功能。这些系统服务,通过binder协议抽象出一个个的“接口”,供其他进程调用,是一个重要的潜在的攻击面。如果没有做好权限控制,会让低权限的第三方应用/病毒/木马利用,后果不堪设想。

其次,做Android的同学都知道,Binder是android一个非常重要的机制,夸张一点可以说是“Android的灵魂”,非常有必要进行细致的分析和漏洞挖掘。

插播一个扣吧总结的知识点,系统服务的分类

1.Binder体系的java服务(有Stub接口,也就是AIDL封装)
2.Binder体系的Native服务
3.socket体系的init服务(通常见于init.rc)
4.其他服务

OK,再谈谈为什么使用fuzz技术呢?

总的来说,是因为fuzz在协议和接口安全测试中比较简单粗暴,试错成本低。所以,“不管什么接口,先fuzz一把看看”。

Fuzzing是一种基于缺陷注入的自动软件测试技术。通过编写fuzzer工具向目标程序提供某种形式的输入并观察其响应来发现问题,这种输入可以是完全随机的或精心构造的。Fuzzing测试通常以大小相关的部分、字符串、标志字符串开始或结束的二进制块等为重点,使用边界值附近的值对目标进行测试。

主要有两种类型的fuzzing技术 :

1)dumb fuzzing 这种测试无需了解协议或文件本身格式,通过提供完全随机的输入或简单改变某些字节去发现问题。这种方法实现起来较简单,容易快速触发错误,但它的完全随机性会导致产生大量无效的输入或格式。

2)Intelligent fuzzing 研究目标应用程序的协议或文件格式、功能配置,了解各类漏洞的成因,有目的地编写fuzzer。编写有效的fuzzer需要花费时间,但能够对某些感兴趣的部分集中测试,因此更有效。

1.什么是Binder(有基础的可以略过这一部分)

Android系统采用Binder机制作为进程间通信机制,类似于COM和CORBA分布式组件架构,通俗来讲其实就是提供远程过程调用(RPC)功能。

在Binder机制中,由Client、Server、ServiceManger、Binder驱动这四个部分组成,其中Client、Server、ServiceManager运行在用户空间,Binder驱动运行在内核空间。Binder就是把这四个组件粘合在一起的粘合剂,核心组件是Binder驱动,ServiceManager提供了辅助管理的功能。Client和Server正是在Binder驱动和ServiceManager提供的基础设施上,进行CS通信。

下面这个流程图可以简单说明Client通过binder调用Server的一个过程,Client会通过Proxy(这里的Proxy不是单一实体,实际上是一系列的BpInterface、BpBinder等代理组件)去跟binder驱动通信,Proxy把数据打包成parcel类型数据再进行传输。

那么数据具体是怎么传输的呢?

我们继续深究一下,笔者总结了一个比较全的图。Java层服务其实也是在Native层服务BpBinder和BBinder的一个封装。如果屏蔽底层驱动来看,整个Binder代理的核心就是BpBinder和BBinder。

其中,BpBinder最重要的职责就是实现跨进程传输的传输机制,至于具体传输的是什么语义,它并不关心。我们观察它的transact()函数的参数,可以看到所有的语义都被打包成Parcel类型数据。(Parcel是轻量级的高效的对象序列化和反序列化机制,Android在Java空间和C++都实现了Parcel,由于它在C/C++中,直接使用了内存来读取数据,因此,它更有效率)

请记住这个伟大的函数——transact()

举一个例子:上层APP调用MediaRecorder对外提供的API,名字叫setCamera,实际上是执行了BpMediaRecorder中的setCamera方法中,remote()返回的就是BpBinder对象,这里会组装好parcel数据包,会传给BpBinder的transact函数。transact函数就会把数据发给对端,也就是另一个BBinder对象。

我们看一下具体是如何发送数据?

BpBinder的transact函数,通过层层调用,最终通过ioctl和binder驱动通信

嗯,上述的就是发送请求的过程。

下面来看接收方,Binder远程通信的目标端实体必须继承于BBinder类,该类和BpBinder相对,主要关心的只是传输方面的东西,不太关心所传输的语义。当收到回复后,会执行IPCTHreadState::waitForRespaonse函数的逻辑,并执行executeCommand(cmd)

executeCommand中,会取得一个合法的BBinder对象,并执行BBinder的transact函数。
(是不是有点奇怪,BBinder也有一个transact函数,请继续往下看吧)

BBinder::transact中会调用onTransact,这个onTransact才是真正处理业务的。需要注意的是,因为我们的binder实体在本质上都是继承于BBinder的,而且我们一般都会重载onTransact()函数,所以上面的onTransact()实际上调用的是具体binder实体的onTransact()成员函数。也就是说,onTransact的具体实现一般在上层的binder实体,而不在BBinder。

上面说了,BBinder没有实现一个默认的onTransact()成员函数,所以在远程通信时,BBinder::transact()调用的onTransact()其实是Bnxxx或者BnInterface的某个子类的onTransact()成员函数,举个例子,BnMediaRecorder中实现了一个onTransact函数,通过switch-case,根据不同code进行分发处理。

switch(code)中的code,其实就是前面说的BpBinder中transact函数传过来的int型的方法号。

2.Binder fuzz怎么作

经过上面的分析,我们已经对Binder有个全局的了解。fuzz的关键是选择好fuzz的目标和fuzz切入点(接口),那么应该如何选择呢?

思路就是农民斗地主!

前面也说了,系统服务(地主)具有高权限,是我们需要重点关注的对象,而低权限进程(农民)可以利用binder call去调用系统服务,从低权限到高权限,存在一个跨安全域的数据流,这里就是一个典型的攻击界面。所以,我们选择系统服务作为fuzz的目标。

那么Fuzz接口呢?选择fuzz接口需要满足这几个要求:

1)这个接口是开放的,是可以被低权限进程调用的
2)这个接口距离fuzz目标(系统服务)比较接近,中间路径最好透传,这样比较容易分析异常
3)从简原则

根据上面的分析,BpBinder中的transact函数就是一个很好的fuzz接口,但这货在底层无法直接调用。

怎么办呢?

我们从BpBinder往上层找,很容易发现,Java层IBinder的transact函数最终调用到BpBinder,且参数是原封不动的“透传”到底层,考虑到java层的可视化和扩展性,我决定选择IBinder的公有方法transact作为fuzz接口。

下图就是这个接口的定义:

请大家认真看看上图注释的说明:

code是int类型,指定了服务方法号
data是parcel类型,是发送的数据,满足binder协议规则,下面会有详述
reply也是parcel类型,是通信结束后返回的数据
flag是标记位,0为普通RPC,需要等待,调用发起后处于阻塞状态直到接收到返回,1为one-way RPC,表示“不需要等待回复的”事务,一般为无返回值的单向调用。

下面开始讲重点了,额。

接口不是你想fuzz就能fuzz。我们来解决几个关键问题:

1)如何取得服务的IBinder对象?

我们要取到对端的IBinder对象,才可以调用这个服务。系统其实有一些隐藏API可以利用。先通过反射出ServiceManager(hide属性)中的listServices获取所有运行的服务名称:

获取到String类型的服务名称后,再反射getService获取对应的服务IBinder对象:

是不是很犀利,其实是借用了上文说的ServiceManager的强大力量。

2)code如何生成?

code也称为TransactionID,标定了服务端方法号。

每个服务对外定义的方法都会分配方法号,而且是有规律的,第一个服务方法code使用1,第二个是2,,第三个使用3,依次类推,如果有N个方法,就分别分配1-N个连续的服务号。

有个小技巧,对于Java服务,必定有Stub类,可以通过反射出mInterfaceToken+”$Stub”类中所有成员属性,其中以”TRANSACTION_”开头的int型就是该方法对应的。

如下图的例子,服务端greet方法对应的code就是TRANSACTION_greet:

如果是Native服务,就比较悲剧了,目前还没有好的自动化方法直接获取code。一般服务方法数不会太多,所以确定一个上限如50,从1到50循环生成code就可以把所有方法遍历。当然可以通过人工逆向分析出code,但这样成本比较高。

3)data如何构造?

通过大量的源码review和分析得知,data由“RPC header+参数1+参数2+….”来构成的。

举个例子,如下图,setDataSource这个API,首先调用data.writeInterfaceToken会写入一个RPC header,然后会依次写入调用方法的参数,比如setdataSource有3个参数,这里就会依次写入三个数据:

是不是很有规律!!

通过review writeInterfaceToken的实现,我们可以发现这个RPC header是由一个int型数据加上String类型的interface name来构成。

但我们不需要自己去构造RPC header,直接调用writeInterfaceToken函数,传入interface name就可以了。最后抽象出来的parcel类型的data应该是这样的:

那大家可能会问interface name是什么东西,如何获取?很简单,interface name是接口名称,只要取得IBinder对象,就可以直接getInterfaceDescriptor来获取interface name,也就是接口方法的描述符。

再看如何获取一个方法的参数和类型呢?

对于Java层服务的方法,可以通过反射获取method对象,然后用getParameterTypes获取所有的类型:

对于native层服务,无法直接获取方法参数类型,可以用过review调用者实现和反编译分析等方法来作。

4)fuzz系统和逻辑怎么设计?

直接上图吧。如下图,整个fuzz系统分为4个模块,分别是数据产生器,fuzz引擎,监视器和日志模块。

1)数据产生器就是用上述方法产生transact需要用到的数据

2)fuzz引擎用于执行具体的transact过程

3)监视器用于监控fuzz结果和异常

4)日志模块用于记录fuzz结果

这里笔者采用了3种fuzz方法

1)dumb fuzz:构造好RPC header后,直接塞入大量随机数据,code范围为1-100,比较暴力。

2)intelligent fuzz:构造好RPC header后,精准识别出code,并根据不同的code构造出类型正确的随机参数

3)simple fuzz:构造好RPC header后,精准识别出code,但每次请求只写入int类型“0”,通过返回值,快速识别fuzz目标的接口是否有权限校验

5)如何判断fuzz结果和识别安全漏洞?

一般来说,要做到“权限判断+数据有效性判断”两层防护才是安全的。

通过监控transact的返回值和系统log和系统状态,可以看到的fuzz现象主要有以下几种:

1)有SecurityException,则说明该接口有进行权限判断,做了一层防护

2)无Exception,说明该接口没有进行权限校验,默认对外暴露,是不安全的,可以深挖

3)异常现象,如系统重启、指纹服务挂死、屏幕无响应等,说明该接口不仅没有进行权限判断,而且fuzz数据导致了缓存区溢出/进程crash等异常,这类现象要再去进行人工分析,很有可能会严重的提权漏洞(比如root)

举个例子,看看到底是哪里出现安全漏洞。下图,ontransact函数中switch-case结构里,其中一个case中没有对数据进行判断就读到*device_address,而这个指针直接当成参数直接使用,当指针地址异常就会引起系统服务进程crash,从而导致系统重启,是一个典型的拒绝服务漏洞。也就是说,任意一个低权限的进程可以随时进行攻击,导致系统重启。

再举个例子,假设某手机厂家的系统指纹服务有个接口叫DeleteFingerPrint(),用于删除用户指纹,该服务的实现没有进行权限判断和参数校验,恶意攻击者就有可能构造参数,非法调用该服务的方法,把用户的指纹信息删除。

重要的事情要说三遍!

参数要做检查

参数要做检查

参数要做检查

今天先写到这里,写得有点乱,后续再更新一下。如果你喜欢扣吧的文章,请多多留言支持~

原文地址:http://colbert337.github.io/2016/01/25/binder-fuzz/

Binder fuzz安全研究相关推荐

  1. 农民斗地主——Binder fuzz安全研究

    扣吧力作,欢迎转载,转载请注明来自colbert337.github.io 最近扣吧忙成狗了,好久没更新博客,对不住大家了,今天趁天气暖和点,来一篇干货. 由于好久没搞Android了,写得不专业的地 ...

  2. 瑞士卢加诺大学(USI) Dynamic Analysis Group 博士招生

    关注公众号,获取更多AI领域发展机会 卢加诺大学(USI) 招募博士生职位,导师是 Walter Binder 教授. 研究课题: data processing; big data; paralle ...

  3. MPB:利用无菌植物和可培养细菌体系研究根系微生物组功能

    为进一步提高<微生物组实验手册>稿件质量,本项目新增大众评审环节.文章在通过同行评审后,采用公众号推送方式分享全文,任何人均可在线提交修改意见.公众号格式显示略有问题,建议电脑端点击文末阅 ...

  4. Android 核心分析 之六 -----IPC框架分析 Binder,Service,Se...

    2019独角兽企业重金招聘Python工程师标准>>> 我首先从宏观的角度观察 Binder,Service,Service Manager,并阐述 各自的概念.从 Linux 的概 ...

  5. MVC的Model Binder总结

    今年一直在做一个mvc的项目,现在已经初具规模,适时的总结一下,也算是对MVC框架的一次更深入的研究. 由于时间以及成员技术水平的原因,在开发过程中,一直秉持:完成功能为第一,然后再完善其他的准则.作 ...

  6. 红茶一杯话Binder(传输机制篇_上)

    2019独角兽企业重金招聘Python工程师标准>>> 红茶一杯话Binder (传输机制篇_上) 侯 亮 1 Binder是如何做到精确打击的? 我们先问一个问题,binder机制 ...

  7. 理解 Android 的 Binder 机制

    Binder机制的工作流程 1.客户端获取服务端的代理对象(proxy).我们需要明确的是客户端进程并不能直接操作服务端中的方法,如果要操作服务端中的方法,那么有一个可行的解决方法就是在客户端建立一个 ...

  8. Binder相关面试总结(七):AIDL内部的实现原理是什么

    AIDL的作用是实现跨进程通讯使用方法也非常的简单,他的设计模式是典型的C/S架构.使用AIDL只要在Client端和Server端的项目根目录下面创建一个aidl的文件夹,在aidl文件夹的下面用j ...

  9. 一次Binder通信最大可以传输多大的数据?

    本系列: Android-Binder进程间通讯机制-多图详解 一次Binder通信最大可以传输多大的数据?​​​​​​​ 关于Binder (AIDL)的 oneway 机制 前言 在第六章中,我通 ...

最新文章

  1. 宽带服务价值链之:ISP,ICP,ASP,IDC,CDN
  2. android vlc eclipse,在Eclipse下导入vlc-android并编译
  3. 高性能udp服务器架构,优秀的国产高性能TCP/UDP/HTTP开源网络通信框架——HP
  4. Vue监听器与监听滥用
  5. AttachThreadInput
  6. POJ 1661 Help Jimmy
  7. “面试不败计划”:集合总结
  8. windows下配置java
  9. Access to script at ‘xxx‘ from origin ‘null‘ has been blocked by CORS policy: Cross origin requests
  10. 转整型_SPI转can芯片CSM300详解、Linux驱动移植调试笔记
  11. login控件authenticate_asp.net Login控件基本属性及事件说明
  12. 深入浅出Shell编程: Shell 变量【ZT】
  13. 14、 Integer 与 int 的区别
  14. OpenCV --- CAMShift对象跟踪
  15. openlayer中的投影
  16. python自动化运维快速入门 pdf 郑征_Python自动化运维快速入门
  17. T-SQL 基础简介
  18. 看图识物_‎App Store 上的“认识动物-看图识物大全、学英语”
  19. 教你十种打领带的方法
  20. Java教程-Java 程序员们值得一看的好书推荐

热门文章

  1. 利用扩展事件进行调优和Troubleshooting PPT分享
  2. 还有Html.EditorFor和Html.Html.TextBox到底差什么呢
  3. Entity Framework 学习高级篇1—改善EF代码的方法(上)
  4. 机器学习导论(张志华):核定义(2)
  5. vivado实现异步复位的D触发器
  6. [云炬创业学笔记]第二章决定成为创业者测试14
  7. 学长毕业日记 :本科毕业论文写成博士论文的神操作20170413
  8. Chrome扩展程序——TabCopy:一键复制网页标题和网址
  9. python vscode_VScode 配置为Python编辑器
  10. Siamese Network (应用篇4) :块匹配中一致性特征和距离测度学习 CVPR2015