扣吧力作,欢迎转载,转载请注明来自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. “三农”谋定金融 中国农民丰收节交易会金融服务研讨会

    "三农"谋定金融 中国农民丰收节交易会金融服务研讨会 新闻中国采编网 中国新闻采编网 谋定研究中国智库网 经信研究 国研智库 国情讲坛 哲商对话 万权采编:"我们将以此为 ...

  3. 工具及方法 - 斗地主技巧

    斗地主游戏起源 斗地主是流行于湖北武汉.汉阳一带的一种扑克游戏.游戏需由3个玩家进行,用一副54张牌(连鬼牌),其中一方为地主,其余两家为另一方,双方对战,先出完牌的一方获胜.斗地主起源于湖北武汉汉阳 ...

  4. 斗地主十句口诀技巧全解

    斗地主作为扑克游戏中的翘楚可谓是风靡全国,这款游戏最少由三名玩家一起进行,一副牌总共有54张,一名地主来对抗两名平民,先出完牌的一方为最终的获胜方.斗地主技巧一直以来都是广大玩家关心的问题,也是一些刚 ...

  5. Segment Anything CV界的GPT—prompt-based里程碑式研究成果

    一.计算机视觉界的里程碑式研究成果 - SAM与SA-1B综述 Segment Anything受chatGPT式的prompt-based思路启发,训练数据集涵盖10亿masks,根据提供的图片注释 ...

  6. 我国农村宅基地有偿退出机制构建研究

    我国农村宅基地有偿退出机制构建研究 [摘要]随着城镇化与工业化的不断发展,现行农村宅基地制度不能满足用地需求,并导致了大量土地资源的浪费,因此构建宅基地有偿退出制度是大势所趋.本文在明确农村宅基地.农 ...

  7. 数读文章丨以“农民专业合作社”为关键词检索知网,你发现了什么?

    查看原文:[数据seminar]https://mp.weixin.qq.com/s/6EQjR3C21drKW4VG1_Ssuw Part 1:文章被引 Top 5 1 新型农业经营主体:现状.约束 ...

  8. ​谷歌大神 Jeff Dean 领衔,万字展望5大 AI 趋势

    ‍‍ 作者 | 学术头条 来源 | 学术头条 对于关心人工智能技术进展的读者来说,每年年底来自整个谷歌 research 团队撰写的年终总结,可谓是必读读物. 今天,由谷歌大神 Jeff Dean 领 ...

  9. 调控微生物改善土壤,生物制剂能否开启农业新篇章?

    这是<肠道产业>第 593 篇文章 本文转自肠道产业,原文链接 https://mp.weixin.qq.com/s/U8ArQ2vF585ZC8_ag21LpQ 编者按 我们脚下的土壤中 ...

最新文章

  1. 一份来自亚马逊工程师的Google面试指南,GitHub收获9.8万星,已翻译成中文
  2. Bluetooth GAP介绍
  3. 跨境电商谋定重整新业态-李玉庭:数据驱动中国电商大会
  4. java 快速查找 list_面试官:小伙子,你连Java集合都讲不清楚,怎么就敢开口要8K呀?...
  5. Gitlab上传代码
  6. C# 与 VC Dll 传输信息
  7. jzoj3913-艰难的选择【差分,统计】
  8. bootstrap table中文文档_用Python完成一件小事:自动生成文档报告
  9. 校外实习-第三周总结
  10. Layer报错:TypeError n.sort is not a function
  11. mysql集群解决方案mysql复制原理
  12. 电脑录屏软件哪个好?快速录制高清视频的方法是什么?
  13. 大白话理解可达性分析算法
  14. STM32 USB Host 鼠标和键盘驱动 -- 原创
  15. 百词斩不复习_也说说百词斩的缺点
  16. html如何给标题设置边框和底纹,word如何设置文字边框和底纹
  17. 机器学习——图像分类
  18. HarmonyOS APP 开发入门
  19. 算法分析与设计——背包问题
  20. 矩阵 维度 axis

热门文章

  1. 【MySQL】MHA部署与MasterFailover代码分析
  2. [工具]Mac下非常好用的快捷终端Dterm
  3. TOPAS 命令详解
  4. 招聘webgis开发经理和程序员
  5. Python学习笔记:面向对象编程(1)
  6. EXCEL利用VBA自由控制图表绘图区大小
  7. [云炬创业管理笔记]第五章打磨最有效的商业模式测试5
  8. 云炬Android开发笔记 17商品详情功能开发
  9. 完结篇 | 吴恩达《序列模型》精炼笔记(3)-- 序列模型和注意力机制
  10. 简述Hadoop和Spark的异同