论文笔记:《Bringing Balance to the Force Dynamic Analysis of the Android Application Framework》


概述

  本文发表在NDSS21上,作者是德国亥姆霍兹信息安全中心(CISPA)的Abdallah Dawoud和Sven Bugiel。

  自2011年至今,学术界对Android系统的Permission Mapping这一话题的研究从未停止过。但是除了这个话题的开山之作以外,其他工作无一例外使用的都是基于静态分析的技术。本文旨在将近年来日益发展壮大的动态测试工具及其思路,应用到这一领域,以弥补纯静态分析的不足。提出了一个叫Dymamo的动态测试工具,对Android Framework层的api进行Fuzz,从而建立Permission Mapping。基于这一工具得到的结果,作者将其于现有的来自Arcade的最新结果进行比对,从差异中发现各自的不足,并从而帮助其他工作更好的完善各自的工具。

简介

Permission Mapping

  Permission Mapping即权限映射,在本文中是指将Android Framework层提供的系统API以及调用该API时所需要申请的权限建立映射。

  Permission Mapping的意义有:

  • 帮助开发者编写符合最小特权原则的app
  • 可以用于恶意软件检测或者识别过量申请权限的app
  • 可以识别安卓系统中自带的权限漏洞

Motivation

  现有的工作基本上都是基于静态分析的,而静态分析尤其固有的缺陷,比如很难处理动态变量的值、IPC等。而目前的Permission Mapping结果几乎完全基于静态分析,这导致结果的不准确性,而对其他依赖于该结果的工作造成影响。因此作者认为有必要用动态测试的方法来重新审视这个结果。

Background

Android Framework API

  所有已注册的系统服务都能够在ServiceManager类中被找到,作者基于这一事实来提取系统API的入口点。

Binder IPC

  Binder是安卓系统特有的进程间通信机制,底层原理是使用内核内存贡献来在进程间通信。对于一些比较敏感的底层系统API,安卓系统通过Binder封装后对外提供一些High-Level的API用于调用,在调用时则会进行权限检查。

Permission

  安卓的权限管理可以分为3类:

  • UID检查: 只有指定UID的进程才能调用特定的API
  • 跨用户检查:对于使用手机分身的情况,不同分身代表不同用户,不同用户之前权限有差异
  • AppOps:权限申请(如相机权限)首先需要在Manifest中静态申请,而申请完成后的权限是否能够动态的调用则由AppOps进行管理

Research Questions

  本文想要设计一个动态测试工具来为Android Framework层API建立权限映射,主要有以下几个Research Questions:

  1. RQ1: 如何识别这些API的入口并触发它们。难点在于这些API分散在不同的Service之中,并且可能分别由Java或者C++代码实现。
  2. RQ2: 如何为这些API构建输入。属于时Fuzz的经典问题。
  3. RQ3: 如何衡量动态测试的覆盖率。同样也属于时Fuzz的经典问题。
  4. RQ4: 如何检测出不同类型的权限管理。有些是集中管理的很好识别,有些代码甚至是inline的,不容易发现。
  5. RQ5: 如何构建反馈通道。即怎样将某个API的测试结果反馈给Fuzzer
  6. RQ6: 如何保留不同权限检查之间的关系和顺序。

Implementation

Overview

  基于以上的Research Questions,作者设计的工具如下:

Overview

  它有三个主要组成部分:

  1. Testing Service(TS): 这是作者编写的一个app,安装在测试机上,用于接收TM的控制指令并调用系统API。作者提到,现有的Fuzzer都是建立在最高特权的基础上的,因此对于权限检查的API测试意义不大。
  2. Instrumentation Server(IS): 本质上是个Frida Server,可以对测试的API以及权限检查相关函数进行hook,打印调用栈并上报给TM
  3. Testing Manager(TM): 本质上是个Frida Client,运行在PC端,起到统筹全局的作用,可以为每个测试的API生成输入,发送给TS进行API调用,并接收由IS中收集到的调用结果反馈,通过Analyser Module来分析覆盖率情况,控制当前的测试状态。

Collecting Public APIs

  对于如何找到系统API的问题(RQ1),作者利用ServiceManager会维护所有注册的系统Service的这一事实,利用Java反射来从ServiceManager中获取所有能够找到的Service的Handle,并将其强转为对应Service的Proxy对象,在这些对象中就能找到这个Service的所有API的方法签名了。

  在测试这些API时,作者采用多台设备并行的方式进行,每台设备一次只测试一个API。

Generating Input

  对于如何生成输入的问题(RQ2),作者为Java基本类型和Android基本类型预定义了一些输入,其中部分输入由源码静态分析其入参名称得来。而对于复杂类型,作者使用递归的方式完成,通过为其传入基本类型来调用其构造函数从而生成输入。

Measuring Coverage

  对于如何衡量覆盖率的问题(RQ3),作者使用了一个叫WALA的工具,来对每个API进行可达性分析,对于每个API可以得到一个有限的方法集合,调用API可以最终到达这些方法。通过Hook这些方法,当其被调用时打印调用栈,如果确实是由该API所触发并且调用者为TS时(用于排除噪声),统计该Trace。最后覆盖率的计算公式为Unique Trace的数量比上集合中的方法数量。

DYNAMO’s Testing Strategies

  对于如何检测不同类型的权限检测的问题(RQ4),作者预定义了多种测试策略,每种策略旨在发现不同类型的安全检测。工作流程大致如下:

RQ4-1

  就是循环遍历不同inputs和Strategies,然后遇到安全检查没通过就hook一下尝试绕过。具体的case如下:

RQ4-2

  对于特定权限检查的情况(图中INTERACT_ACROSS_USERS)会有统一的函数完成(checkPermission函数),通过hook就能知道是否触发了这种检查以及具体的参数类型。

  对于inline检查UID的情况,作者通过Hook Binder.getCallingUid函数来不断变更自己的UID,如果发现某一次变更后通过了权限检查,则说明存在inline UID检查。

Instrumenting Targets

  对于构建反馈通道的问题(RQ5),作者使用了Frida动态Hook框架优点是能够兼容不同的系统,而无需修改安卓源码,能够满足对一些闭源的OEM厂商的测试需求。

Modeling of Permission Mapping

  最后是如何为Permission Mapping建模的问题(RQ6),作者想要得到下图中List2中的结果作为输出。

RQ6

  作者可以使用RQ4中的方法来得到具体UID值的检查以及具体权限检查的两种情况,但是对于UID是否等于入参的情况,作者通过不断变更入参的方式来检查。

Evaluation

Evaluation environment

Android versions

  • Android 6, 8.1, 10, and 11 of vanilla Android
  • other vendor images

hardware devices

  • Pixel 4, Nexus 5, and One+

Emulators

  • Cuttlefish and Android Studio emulators
  • running different CPU architectures(x86, x86_64, arm, and arm64)

Evaluating Previous Permission Mappings

Evaluation1

  与Arcade的对比结果大致如上图所示

Evaluation2

Evaluation3

Limatation

  • 部分Service并不在ServiceManager中,在API提取过程中被丢失
  • 人工预定义的测试策略是不完美的,容易忽视特定的情况
  • 对于FN需要人工验证,无法在大数据集上统计出正确的FN
  • 动态测试非常耗时
  • 要求手机ROOT或者系统以Debug Mode编译

文章作者: 大A
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 大A !
评论
  目录