《Android安全攻防权威指南》 阅读学习
2 Android的安全设计与架构
Android 的总体架构由 5 个主要层次上的组件构成,这 5 层是:
- Android 应用层
- 允许开发者无须修改底层代码就对设备的功能进行扩展和提升
- Android 框架层
- 为开发者提供了用来访问 Android 设备各种必需设备的 API
- 充当 应用层 与 Dalvik 虚拟机层 之间的“粘合剂”
- Dalvik 虚拟机层
- 为底层操作系统提供一个高效的抽象层
- 用户空间原生代码层
- 包括系统服务(如 vold 和 DBus)、网络服务(如 dhcpd 和 wpa_supplicant)和程序库(如 bionic libc、WebKit 和 OpenSSL)
- Linux 内核层

API 中包含各种构件(building block)以允许开发者执行通用任务,比如管理 UI 元素、访问共享数据存储,以及在应用组件间传递信息等
2.2 理解安全边界和安全策略执行
安全边界,是系统中分隔不同信任级别的特殊区域
一个最直接的例子就是内核空间与用户空间之间的边界
- 内核空间中的代码可以对硬件操作并访问所有的虚拟和物理内存,
- 而用户空间中的代码则无法访问所有内存
Android 的双权限模型
- Linux 内核层权限模型
- 基于 用户/用户组 控制文件系统和资源访问(继承自 Linux)。
- 实现 Android 沙箱,隔离应用进程。
- Android 运行时权限模型
- 由 Dalvik/ART 虚拟机 和框架实现,安装时向用户声明。
- 通过权限限制应用能力(如摄像头、位置访问)。
- 映射关系:部分权限直接关联底层 Linux 用户组或权能(如
NET_ADMIN对应net_raw组)。
2.2.1 Android 沙箱
Android 基于 Linux 的 进程隔离 和 最小权限原则 构建沙箱,核心机制包括:
- Linux 进程隔离
- 每个进程运行在独立的用户环境,无法直接访问其他进程内存或发送信号。
- 唯一用户标识(UID)
- 大多数应用进程分配唯一 UID,实现权限隔离。
- 文件系统权限控制
- 严格限制文件访问权限(基于 Linux 的 UID/GID 模型)。
Android 特有实现
Android 沙箱通过 UID 隔离 和 文件权限控制 实现进程级安全,结合 AID 机制适配移动端需求,确保应用间资源隔离与系统稳定性。
AID(Android ID):
- 沿用了 Linux 的
UID/GID(用户组ID)权限模型 - 没有使用传统 Linux
passwd/group文件,而是定义了从名称到独特标识符Android ID (AID)的映射表 - 映射表中包含了一些与特权用户及系统关键用户(如 system用户/用户组) 对应的静态保留条目
- 保留特定 AID 范围用于系统服务(如
AID_SYSTEM=1000)和隔离进程(如 Chrome 沙箱)。
示例(简化 AID 定义):
#define AID_ROOT 0 // 传统的unix根用户
#define AID_SYSTEM 1000 // 系统服务器
#define AID_APP 10000 // 第一个应用用户
2.2.2 Android 权限模型
Android 权限分为三类,相互关联且可能映射到底层系统权能:
- API 权限:API权限用于控制访问高层次的功能,如控制访问=应用访问敏感功能=(如摄像头、位置)。
- 一个使用API权限的常见例子是
READ_PHONE_STATE---->允许“对手机状态的只读访问,应用若申请该权限,随后就会授予该权限,从而可以调用关于查询手机信息的多种方法 - 由于一些API权限与内核级的安全实施机制相对应,例如,被授予INTERNET权限,意味着申请权限应用的UID将会被添加到 inet用户组(GID 3003)的成员中
- 一个使用API权限的常见例子是
- 文件系统权限:基于 Linux 用户/组控制文件访问。
- 应用的唯一 UID 和 GID 都只能访问文件系统上相应的数据存储路径
- 相应地,由这些应用创建的文件也会拥有相应的权限设置
- 特定的辅助用户组 GID 用于访问共享资源,如 SD卡或其他外部存储器
- IPC 权限:限制跨应用或跨进程的组件访问(如禁止外部应用启动私有
Service)。- 用于控制应用组件(如
Activity、Service)及系统级 IPC 的交互安全 - 与 API 权限的重叠:部分 API 权限(如
INTERNET)可能隐含 IPC 权限需求
- 用于控制应用组件(如
权限管理机制
- 声明:权限在
AndroidManifest.xml中定义(如<uses-permission>)。 - 存储:安装时由
PackageManager提取权限,记录到/data/system/packages.xml。 - 应用:进程启动时根据
packages.xml设置 UID/GID,授予对应权限。
示例(packages.xml 中的 Chrome 权限配置):
<package name="com.android.chrome" uid="10086">
<uses-permission name="android.permission.INTERNET"/>
<uses-permission name="android.permission.ACCESS_NETWORK_STATE"/>
</package>
2.3 深入理解各个层次
2.3.1 Android 应用层
Android 应用层通过 签名机制 和 组件化设计 实现安全隔离,预装应用与用户应用权限差异显著,四大组件的 IPC 端点是安全分析的关键切入点。
应用分类
- 预装应用
- 路径:
/system/app - 来源:谷歌/OEM/运营商(如日历、浏览器)
- 特点:可能拥有高权限(如
system用户权限)
- 路径:
- 用户安装应用
- 路径:
/data/app - 来源:应用市场或手动安装(
adb install) - 签名:开发者私钥签名,防止篡改
- 路径:
密钥与签名
- 平台密钥:签署预装应用,赋予
system权限。 - 开发者密钥:签署第三方应用,确保更新合法性。
主要的应用组件
AndroidManifest.xml
- 基础信息
- 包名(如
com.example.app)、版本号 - 应用图标、安装位置等配置
- 包名(如
- 组件声明
Activity、Service、BroadcastReceiver、ContentProvider
- 权限管理
- 声明所需权限(如
<uses-permission>) - 定义自定义权限(如
<permission>)
- 声明所需权限(如
- 共享 UID 机制
- 相同签名的应用可通过
sharedUserId共享 UID,实现数据互通
- 相同签名的应用可通过
- 构建处理
- 开发工具(如 Android Studio)生成明文 XML,编译时转为二进制格式
IPC通信端点
Intent
Intent 是 Android 组件通信的枢纽,需结合权限与 IntentFilter 设计安全的交互逻辑。
- 本质
- 消息对象,用于组件间通信(跨应用/进程),类似轻量级 IPC/RPC。
- 关键属性
- 动作(Action):如
ACTION_VIEW、ACTION_SEND。 - 目标组件(可选):显式指定(包名+类名)或隐式匹配(通过
IntentFilter)。 - 附加数据:键值对形式传递参数(如链接、文本内容)。
- 动作(Action):如
- 权限控制
- 发送/接收方可声明权限(如
<activity android:permission="com.example.PRIVATE_ACCESS">)。 - 系统作为参考监视器,在传递时校验权限。
- 发送/接收方可声明权限(如
- 隐式 Intent 匹配
- 通过
IntentFilter声明组件能力(如处理http://链接)。 - 示例:
- 通过
<activity android:name=".InstallWidgetActivity"
android:permission="com.wiley.permission.INSTALL_WIDGET">
<intent-filter>
<action android:name="android.intent.action.INSTALL_WIDGET" />
</intent-filter>
</activity>
Activity
- 本质
- 用户界面(UI)组件,继承自
Activity基类,包含窗口和交互元素。 - 由 ActivityManagerService 统一管理生命周期和调用逻辑。
- 用户界面(UI)组件,继承自
- 关键配置(Manifest 声明)
- launchMode:控制实例化行为(如
singleTask保证全局唯一实例)。 - 其他属性:屏幕方向、主题等 UI 相关配置。
- launchMode:控制实例化行为(如
- 安全实践
- 显式设置
exported属性(避免未授权外部调用)。 - 敏感 Activity 应添加权限限制(如
android:permission)。
- 显式设置
BroadcastReceiver
BroadcastReceiver 通过权限和注册机制实现安全的广播通信,静态注册适用于持久监听,动态注册提供灵活性但需管理生命周期。
- 功能
- 接收系统或应用广播(如短信、电量变化),作为 IPC 端点。
- 注册方式
- 静态注册:在
AndroidManifest.xml声明,长期监听(如开机启动)。
<receiver android:name=".SmsReceiver" android:permission="android.permission.BROADCAST_SMS"> <intent-filter> <action android:name="android.provider.Telephony.SMS_RECEIVED" /> </intent-filter> </receiver>- 动态注册:代码中通过
registerReceiver()临时监听(需注意生命周期)。
- 静态注册:在
- 权限控制
- 发送方限制:通过
sendBroadcast(Intent, String)指定接收方所需权限。 - 接收方限制:在
BroadcastReceiver声明中设置android:permission。
- 发送方限制:通过
Service
Service 是后台任务和 IPC 的核心组件,通过 Intent 或 Binder 提供功能,需注意生命周期和权限控制以保障安全。
-
功能
- 后台执行任务(无UI),如播放音乐、下载文件。
- 支持跨进程通信(IPC),通过
Intent或Binder交互。
-
声明方式(Manifest)
<service android:name=".MyService" android:exported="false"> <intent-filter> <action android:name="com.example.START_SERVICE" /> </intent-filter> </service>exported:控制是否允许外部应用访问(默认值依赖IntentFilter存在性)。
-
启动方式
startService():启动后独立运行(需手动停止)。bindService():绑定后通过BinderIPC 交互(生命周期与调用方绑定)。
Content Provider
Content Provider 是 Android 数据共享的安全网关,通过权限和 URI 机制控制访问,需结合加密与最小权限原则设计。
-
功能
- 结构化数据共享接口(如联系人、媒体文件),基于 SQLite 或文件系统。
-
权限控制
<provider android:name=".MyProvider" android:authorities="com.example.data" android:readPermission="com.example.READ_DATA" android:writePermission="com.example.WRITE_DATA" />- 读写分离:通过
readPermission/writePermission精细化授权。 - URI 格式:
content://[authority]/[path](如content://com.example.data/contacts)。
- 读写分离:通过
2.3.2 Android 框架层
Android 框架层通过系统服务封装核心功能,为应用提供标准化接口,其安全设计基于 权限控制 和 进程隔离,确保资源访问受控。
-
定位与作用
- 纽带角色:连接应用层与运行时(Dalvik/ART),提供通用功能支持。
- 核心组成:
- 基础类库:
android.*(如android.content)、java.*、javax.*。 - 第三方库:Apache HTTP 客户端、SAX 解析器等。
- 基础类库:
-
关键系统服务(由
system_server管理)
| 服务名称 | 核心功能 |
|---|---|
| Activity管理器 | 管理应用生命周期、Intent 解析与跳转(如启动 Activity)。 |
| 视图系统 | 控制 UI 渲染与交互(如布局、控件事件)。 |
| 程序包管理器 | 处理应用安装、卸载及权限管理(读取 AndroidManifest.xml)。 |
| 电话管理器 | 提供通话状态、网络信号等蜂窝网络功能接口。 |
| 资源管理器 | 加载非代码资源(如图片、字符串、布局文件)。 |
| 位置管理器 | 集成 GPS/Wi-Fi/基站定位,提供经纬度数据。 |
| 通知管理器 | 管理状态栏通知(声音、震动、LED 提示等)。 |
- 安全关联
- 权限依赖:如位置管理器需
ACCESS_FINE_LOCATION权限。 - 进程隔离:服务运行于
system_server,通过 Binder IPC 与应用交互。
- 权限依赖:如位置管理器需
DalvikVM 与 Zygote 机制
DalvikVM 通过寄存器架构和 DEX 优化提升性能
Zygote 通过预加载和 ==fork() ==加速应用启动
二者共同构成 Android 运行时基础,但共享机制可能引入安全风险。
DalvikVM
-
与 Java 的区别
- 基于寄存器架构(非栈式),专为嵌入式设备优化(内存/CPU 受限)。
- 开发流程:
Java语法 → .class文件 → Dalvik字节码 → 合并为DEX → 解释执行 - DEX 优化:首次运行时生成 ODEX 文件(设备/版本依赖,不可移植)。
-
执行机制
- 使用约 64,000 个虚拟寄存器(常用前 16-256 个),模拟物理寄存器功能。
- 通过 JNI 与原生代码交互(如 C/C++)。
Zygote
-
启动与优化
- 设备启动时首个加载的进程,预加载框架核心库(如
android.*)。 - 进程孵化:通过
fork()快速派生新进程(如应用进程),共享只读内存,减少重复加载开销。
- 设备启动时首个加载的进程,预加载框架核心库(如
-
关键服务
- 启动
system_server进程(运行系统服务,如ActivityManagerService)。 - 终止
system_server会导致 Dalvik 子系统重启(类似软重启)。
- 启动
-
安全影响
- 共享内存机制可能引发跨进程数据泄露
2.3.4 用户空间原生代码层
这一层主要由两大类组件构成:程序库和核心系统服务。
1. 程序库
Android的底层功能通过共享程序库实现,分为厂商特定库(/vendor/lib)和系统通用库(/system/lib),主要特点包括:
- 开源库集成:如SQLite(本地存储)、WebKit(浏览器引擎)、FreeType(字体渲染)等,复用类Unix系统的成熟项目。
- 关键自定义库:
- Bionic:Android专属的C运行时库,优化内存占用并规避GPL授权问题,但功能较GNU libc更精简,包含自定义动态链接器和线程API。
- 硬件支持库:如蓝牙(
libbluetooth)、音频(libaudioalsa)、XML解析(libexpat)等,通过JNI供上层调用。
- 安全风险:原生代码开发的库易出现内存破坏漏洞,是安全研究的重点目标。
2. 核心服务
核心服务是Android用户空间的基础,主要包括以下关键组件:
(1)init进程
- 功能:通过解析
/init.rc和硬件特定的/init.[hw].rc文件,初始化用户空间环境,包括:- 启动守护进程(如
adbd、debuggerd)。 - 设置系统属性和用户权限。
- 响应事件(如文件系统挂载)。
- 启动守护进程(如
(2)Property服务
- 作用:提供持久化的键值对配置存储,影响网络、安全等核心功能。
- 访问方式:
- 命令行工具:
getprop/setprop。 - 编程接口:
libcutils原生函数或Java的SystemProperties类。
- 命令行工具:
(3)无线接口层(RIL)
- 功能:管理蜂窝通信(通话、短信、移动数据),是智能手机的核心服务。
(4)调试与崩溃处理
- debuggerd:捕获原生代码崩溃并生成报告,通过信号处理机制与链接器协作。
- ADB(Android调试桥):
- 包含设备端守护进程
adbd和主机端服务,支持Shell访问、应用调试、文件传输等。 - 默认监听5037端口,是开发与逆向分析的关键工具。
- 包含设备端守护进程
(5)Volume守护进程(vold)
- 功能:管理存储设备(如SD卡)的挂载/卸载,处理加密容器(ASEC/OBB)。
- 风险:以root权限运行,历史上是特权提升漏洞的高发点。
(6)其他服务
- 厂商定制服务:如HTC、三星等设备的特有服务,代码质量参差不齐,可能引入额外攻击面。
2.3.5 Android内核
Android基于Linux内核,但进行了多项关键修改以适配移动设备需求,包括IPC机制、内存管理和安全增强。以下是核心变更点:
1. Binder IPC机制
- 作用:Android的核心IPC框架,支持跨进程通信(如应用与系统服务交互)。
- 关键特性:
- 客户端-服务器模型:抽象为本地方法调用(类似RPC)。
- 权限控制:通过
Binder.getCallingUid()和checkCallingPermission()验证调用方身份。 - AIDL接口:定义标准化IPC接口(示例:
IRemoteService)。
- 安全意义:权限检查依赖调用方UID,漏洞可能导致越权访问(如
ACCESS_SURFACE_FLINGER权限滥用)。
2. 内存管理驱动
- ashmem(匿名共享内存):
- 功能:提供基于文件的共享内存,支持动态回收(低内存时自动释放)。
- 应用场景:Surface Flinger、AudioFlinger等核心组件。
- pmem(物理连续内存):
- 用途:分配大块物理连续内存(供GPU等硬件使用)。
- 限制:需显式管理文件描述符生命周期。
3. 日志系统(Logger驱动)
- 多缓冲区设计:
main(应用日志)、system(系统事件)、radio(基带模块)、events(低层事件)。
- 访问方式:
- 应用层:通过
android.util.Log类记录(如Log.i())。 - 命令行:
adb logcat或直接运行logcat。
- 应用层:通过
- 安全用途:监控系统行为,但敏感信息可能泄露(需过滤日志输出)。
4. 网络访问控制(Paranoid Networking)
- 机制:基于GID限制网络操作,权限与Manifest声明绑定:
- 例如:
INTERNET权限映射到GID 3003(AID_INET)。
- 例如:
- 配置文件:
- 内核头文件:
include/linux/androidaid.h。 - AOSP定义:
android_filesystem_config.h。
- 内核头文件:
进一步阅读:
- AOSP文档(
system/core/include/) - Linux内核源码(
drivers/staging/android/)
3 ROOT
- 在Android设备上获得超级用户权限的过程通常被称为root
- 这个特殊账号拥有对类UNIX系统上所有文件与程序的权限,能够对操作系统进行完全控制。
- root设备还允许用户卸载预装应用,执行完整的系统备份和恢复,或安装定制内核映像与模块
- 此外,有一类应用需要 root权限才能运行,这些应用通常称为 root app。包括基于 IPTables 的防火墙软件、广告拦截软件、超频软件及支持设置上网热点(Tethering)的应用等
- root设备将会损害设备的安全性。一个原因是所有用户数据都将暴露给被授予root权限的应用
3.1 理解 Android 分区布局
1. 分区定义与作用
分区是设备持久性存储中的逻辑存储单元,布局定义了分区的顺序、偏移量和尺寸。
不同设备的分区布局因硬件平台和厂商定制存在差异,但核心分区具有通用性。
2. 核心分区详解
(1) Bootloader 分区
- 作用:存储引导加载程序(如 U-Boot),负责硬件初始化、内核加载及启动模式选择(如 fastboot、recovery)。
- 特点:厂商通常加密此分区,若损坏可能导致设备变砖。
(2) Boot 分区
- 内容:包含 Linux 内核(zImage 或 Image)和初始 RAM 磁盘(initrd),用于启动 Android 主系统。
- 动态变化:Android 13 引入
init_boot分区,分离通用 ramdisk,优化启动流程。
(3) Recovery 分区
- 功能:独立的最小化 Android 系统,用于系统恢复、OTA 升级和工厂重置。支持自定义 Recovery(如 TWRP)。
(4) System 分区
- 内容:存放 Android 框架、系统应用和核心库(如
/system/app,/system/lib)。 - 动态分区化:Android 10+ 中可能被纳入
super动态分区,支持灵活调整大小。
(5) Data 分区
- 作用:存储用户数据(应用、媒体文件)和动态配置(如
/data/app,/data/data)。 - 加密机制:支持 FBE(基于文件的加密)和 FDE(全盘加密)。
(6) Cache 分区
- 用途:==临时存储 ==OTA 包、日志等,可擦除且不影响系统功能。动态分区设备中可能被弱化。
(7) Vendor 分区
- 内容:厂商专有组件(如 HAL 驱动、闭源固件),与芯片硬件强关联。
- 模块化:与
odm(设备制造商定制)和product(产品线定制)分区协同,实现分层解耦。
(8) Radio 分区
- 功能:存储基带固件(Modem),管理通信模块(如 4G/5G、Wi-Fi)。仅存在于支持通话的设备。
3. 扩展分区与新技术
(1) 动态分区(Super 分区)
- 机制:Android 10+ 引入,将
system、vendor等分区整合为逻辑子分区,支持 OTA 时动态调整大小。 - 优势:消除预留空间浪费,提升存储利用率。
(2) Metadata 分区
- 作用:存储动态分区的元数据(
lp_metadata)和加密密钥。大小为 16MB+,未加密但受 AVB 保护。
(3) Virtual A/B 分区
- 特点:Android 11+ 支持,实现无缝更新,通过共享数据块减少空间占用,升级过程对用户透明。
(4) Misc 分区
- 用途:存储 Bootloader 控制块(BCB),决定启动模式(主系统或 Recovery)。
4. 分区布局管理
- Bootloader 主导:多数设备由 Bootloader 解析分区表(如 GPT)。
- 内核参与:动态分区通过 Linux
device-mapper驱动实现逻辑映射,用户空间工具(如lpmake)生成super.img。 - 厂商定制:通过
BoardConfig.mk定义分区大小和类型(如BOARD_SYSTEMIMAGE_PARTITION_SIZE)。
3.2 理解 Android 引导过程
1. 引导加载程序(Bootloader)的核心功能
引导加载程序是设备开机后运行的首个代码模块,负责底层硬件初始化并启动操作系统。其核心功能包括:
- 硬件初始化:设置时钟、RAM、存储介质等基础硬件(如通过BootROM加载Bootloader);
- 操作系统引导:从存储介质中加载Android内核和initrd到RAM,并移交控制权;
- 模式切换支持:支持进入下载模式(如fastboot/ODIN)、恢复模式等特殊启动模式;
- 安全验证:通过签名验证(Secure Boot)确保固件合法性,防止恶意篡改。
厂商差异:不同厂商的Bootloader实现不同。例如:
- 高通设备通过
fastboot flashing unlock解锁; - 三星使用ODIN协议刷机;
- 联发科(MTK)通过音量键进入强制下载模式。
2. 内核启动与初始化流程
Linux内核启动后完成以下关键任务:
- 硬件驱动加载:初始化CPU调度器、内存管理、中断控制器等;
- 文件系统挂载:临时挂载initrd为可写根文件系统(如
tmpfs、proc); - 启动init进程:作为用户空间首个进程(PID=1),执行
/system/core/init/main.cpp的main()入口。
关键阶段:
- FirstStageMain:创建基础目录(如
/dev、/proc),挂载临时文件系统; - SetupSelinux:初始化安全策略;
- SecondStageMain:加载属性服务、解析
init.rc脚本。
3. init进程与init.rc脚本解析
(1) init.rc的核心结构
- Action:定义触发条件(如
on boot、on property:ro.debuggable=1)及执行命令; - Service:启动守护进程(如
zygote、servicemanager),配置重启策略(如oneshot、disabled); - Command:包含文件操作(
mount、chmod)、服务管理(start、stop)等指令。
(2) 关键服务启动顺序
- Zygote:通过
service zygote启动,预加载Java类库,孵化应用进程; - System Server:由Zygote fork而来,启动AMS、PMS等核心服务;
- SurfaceFlinger/MediaServer:处理图形渲染与多媒体功能。
4. 系统启动完成与广播事件
- BOOT_COMPLETED广播:通知应用系统启动完成,需在Manifest中声明
RECEIVE_BOOT_COMPLETED权限; - 用户空间初始化:完成Launcher启动、后台服务加载后进入交互状态。
5. 下载模式与刷机协议
(1) 进入下载模式的方法
- 按键组合:如三星长按
音量下+电源进入ODIN模式,小米音量下+电源进入fastboot; - ADB命令:
adb reboot bootloader或厂商专用指令(如高通adb reboot edl)。
(2) 刷机协议类型
- Fastboot:通用协议,通过
fastboot flash刷入分区镜像; - ODIN:三星专有协议,支持.tar格式固件包;
- SPRD/UFS:展讯平台专用模式,需短接特定GPIO。
安全限制:多数厂商默认锁定Bootloader,需官方工具解锁(如小米需开发者账号审核)。
6. 动态分区与fastbootd(Android 10+)
- Super分区:整合
system、vendor等逻辑分区,支持OTA动态调整大小; - fastbootd:在Recovery中实现用户态刷机,复用系统驱动提升兼容性。

浙公网安备 33010602011771号