APP下载

基于ARM虚拟化扩展的Android内核动态度量方法

2018-10-16路子聪徐开勇肖警续

计算机应用 2018年9期
关键词:链表完整性内核

路子聪,徐开勇,郭 松,肖警续

(信息工程大学,郑州 450000)

0 引言

Android是基于Linux内核的开源操作系统,操作系统的安全性是Android安全体系中非常重要的一部分。内核是操作系统中最重要的组成部分,目前,针对Android系统内核的攻击日益增多。对于Android系统内核而言,它的安全威胁一方面是继承Linux 系统本身的漏洞,另一方面是由于Android系统本身不够完善[1]。有些学者对Android内核漏洞进行挖掘[2],但由于Android生态系统的复杂性,内核漏洞的修补通常需要很长的周期,这意味着内核防御技术对于Android来说至关重要。Android4.3版本之前,安全模型部分是基于应用沙盒的概念,系统可以为每个应用程序提供一个自己的沙盒并分配一个独有的UID(User IDentification),使每个应用在自己的沙盒中运行来保证应用的资源独立存储。Shabtai 等[3]提出将安全增强型 Linux(Security-Enhanced Linux, SELinux) 植入到Android 平台中,限制应用对系统资源的访问,增强Android 系统安全。从Android 4.3 版起,SELinux开始用于进一步定义 Android 应用沙盒的边界。虽然SEAndroid(Security-Enhanced Android)对基于应用程序的攻击有很好的防御效果,然而SEAndroid却依赖于操作系统内核完整性的假设。如果Linux内核受到威胁(或许还有未知的漏洞),则Android安全机制的SE (Security-Enhanced)可能被禁用并且效果不佳[4]。

有学者对在移动平台上增强Android系统内核的安全性进行了研究。针对Android设备大部分使用ARM处理器,利用ARM的安全扩展TrustZone[5]可以用来保护系统[4,6-10],尽管TrustZone是基于硬件进行数据保护,但其拦截能力的局限性使得它不适合作域内反思和域内保护。这就是Hypervision[4]在操作系统上作出显著改变的原因,但其在模式切换的消耗大,导致有一定局限性。

利用硬件辅助虚拟化技术可以用来保护系统安全[11],许多研究人员利用虚拟化技术来保护ARM平台上的系统安全。使用ARM上的虚拟化扩展,提出了Xen on ARM[12]、KVM(Kernel-based Virtual Machine) for ARM[13]等hypervisor;但是, Xen和KVM需要一个主机系统来处理一些重要的中断,这导致可信计算基 (Trusted Computing Base,TCB)包含主机系统的代码库,而系统的TCB越大就越脆弱,并且由于它们对性能影响较大不满足移动设备低功耗便捷的要求。L4Android[14]对每个场合的Android系统进行隔离,但对系统的攻击仍无法阻止。DroidVisor[15]对内核的静态关键对象进行完整性保护,并对进程和模块进行rootkit检测,但它无法检测对动态的熵池资源进行修改的rootkit。

针对以上问题,本文提出了一种利用ARM硬件辅助虚拟化的Android内核动态完整性度量 (Dynamic Integrity Measurement of Android,DIMDroid)方案。通过在任意时刻对Android内核的各种重要资源的值和数据结构进行动态完整性度量来保证Android内核的安全性。

要完成对Android内核进行完整性度量的目标,结合相关因素和面临的问题要考虑到以下几个方面的挑战:

1)度量模块的位置。如果度量模块与Android内核位于同一特权层,则进入Android内核的攻击可能会对度量模块造成一定威胁,所以要设置好度量模块的位置以解决度量模块与被度量Android内核的隔离问题。

2)度量对象的选取与重构。度量对象必须能表达当前Android内核的完整性信息,同时在Android内核外部对其实施动态度量,所以存在度量层与被度量内核之间的语义鸿沟问题。通过在度量层对选取的Android内核度量对象进行重构来解决该问题。

3)度量模块自身的安全性。对Android内核进行动态度量,首先要保证度量功能模块自身的安全启动并保证在运行时不受到在Android中获得root权限的恶意代码的攻击。

1 DIMDroid架构设计

1.1 ARM硬件辅助虚拟化

DIMDroid设计利用了ARM平台的虚拟化技术,为了便于理解,将简单介绍ARM平台上的虚拟化技术的相关背景。

最近的ARMv7-A架构在ARM处理器上引入了虚拟化扩展。具体来说,引入了一种称为hyp模式的新处理器模式,它比现有的非安全状态中的svc模式拥有更高的特权级别。Android操作系统和应用程序可以不经过任何修改就能分别运行在现有的svc模式和usr模式下。具有虚拟化扩展和安全扩展的ARM处理器的架构如图1所示。

图1 ARM处理器的架构

ARM虚拟化扩展使用两阶段页表转换来更好地控制客户的虚拟内存。Stage-1页表由客户操作系统维护,客户操作系统可利用Stage-1页表将客户虚拟地址(Virtual Address,VA)转换为中间物理地址(Intermediate Physical Address,IPA)。将IPA转换为物理地址(Physical Address,PA)的Stage-2页表由虚拟机管理程序维护,并且对客户操作系统保持透明。ARM 虚拟化扩展必须与大物理地址扩展和安全扩展同时使用。如表1所示大物理地址扩展的bit[7:6]为Stage-2的访问权限位HAP[2:1],通过对Stage-2页表项(Page Table Entry,PTE)中属性位的适当配置,客户操作系统的内存访问将处于管理程序的控制之下。

表1 Stage-2访问权限控制

1.2 DIMDroid体系架构

为了实现对Android内核的动态度量,利用ARM平台下的硬件辅助虚拟化技术,设计了如图2所示的DIMDroid体系架构。DIMDroid主要实现了度量模块与Android内核的隔离,利用度量代理对Android内核中的度量对象进行重构和动态度量。此外,还通过基于硬件的信任链启动保护和基于内存隔离的运行时保护来对DIMDroid自身安全进行保证。

图2 DIMDroid体系架构

其中,DIMDroid的度量模块置于hyp模式下(以下简称度量层)。Android操作系统控制第一阶段页表,DIMDroid控制第二阶段页表,进行第二阶段地址转换的页表对Android 操作系统是透明的。DIMDroid通过Stage-2页表将其和度量代理模块设置为内核不可访问并将其声明为直接内存访问 (Direct Memory Access,DMA)缓冲区,保证DIMDroid能够从Android内核外部进行系统运行时的完整性度量,解决了度量模块与被度量系统的隔离问题,降低了度量软件模块遭受攻击的可能性。

基准库提供度量的基准值,其中的主要内容为静态度量对象的Hash值与除子集约束对象外的动态度量的约束值,同时采用对基准值进行AES(Advanced Encryption Standard)加密保证基准值的安全性,为了防止AES密钥的泄露,将其存储在Trustzone中。基准库是在系统启动时构建的,此时的系统由Trustzone保证了基于硬件的可信链且不联网,即基准库的构建是在系统可信条件下进行的,同时避免其受到网络攻击。

DIMDroid的度量代理模块位于svc模式下,通过System.map文件获取度量对象的虚拟地址并将其传给度量模块,并在度量层下进行度量对象的语义重构并进行完整性分析。

2 DIMDroid 关键技术

2.1 内核度量对象的确定

为了使度量对象全面描述Android内核运行时的完整性,本文从Android内核的组成运行原理和内核恶意软件的攻击面等方面确定系统运行中度量对象的选取。

在分析加载Android操作系统内核的各种关键组成元素后,发现例如基本只读数据段、内核代码段、系统调用表、中断描述符表、异常向量表、内核模块代码等数据结构在Android系统运行中是静态不变的,一旦发现这些数据结构被篡改、发生变化,系统就不会以预期的方式运行。例如kbeast、enyelkm等rootkit可以篡改中断处理函数和系统调用表中的表项来执行恶意代码,因此这些静态数据结构的完整性在Android系统运行过程中至关重要。

与此同时,例如Android内核中进程链表、模块链表、初始化数据段、熵池资源等数据结构在Android系统运行过程中是动态变化的。考虑到某些直接对象操作(Direct Kernel Object Manipulation,DKOM)的rootkit,它们可以对某个模块从模块链表隐藏或者对某个进程从进程链表中隐藏,例如对ps、top等系统服务程序篡改或者进行文件替换,当监控软件或程序调用这些服务程序查看进程信息时过滤掉了恶意软件想要隐藏的进程,从而实现恶意软件对内核的攻击,但在这些内核数据结构动态变化中它们满足一定的特征约束。例如,Android内核中的进程满足running_list⊆all-tasks,即在运行链表running_list中的元素全都包含在进程链表all-tasks中,或者all-tasks==ps-tasks,即所有的进程都应该可以用ps系统服务程序观测到;adore-ng和wipemod等rootkit可以实现恶意模块隐藏和恶意进程隐藏,即不满足进程链表或模块链表的子集特征约束; Android内核使用伪随机数生成器(Pseudo Random Number Generator,PRNG)生成其他安全关键应用程序所需随机数,为了确保PRNG生成的数字是伪随机的,每次使用搅拌函数更新熵池的内容字节从熵池中提取,搅拌函数使用的多项式系数为在struct poolinfo数据结构的整数字段,这些整数字段的取值满足一定的边界约束,具体来说poolinfo.tap1∈{26, 103}, poolinfo.tap2∈{20, 76},poolinfo.tap3∈{14, 51},poolinfo.tap4∈{7, 25},poolinfo.tap5==1 等。

根据这些数据结构动态变化的特征,本文可将它们分为四种约束:固定长度约束、固定取值约束、子集约束和边界约束,如系统的最大线程数max_threads属于固定取值约束,进程、模块等属于子集约束,熵池结构属于边界约束等。

通过以上分析在Android系统运行过程中,内核度量对象包括静态度量对象和动态度量对象两大类。

2.2 内核度量对象的重构分析

如果将度量软件直接置于Android内核中,则与Android内核运行在同一个特权级,易受到恶意软件的攻击。而将度量软件置于hyp模式下,实现了度量软件与被度量的Android内核的分离,但hyp模式下的度量模块获取到的信息为底层的二进制信息,无法获取内核级的语义信息。因此,分析之前需要根据内核结构知识和底层的二进制信息在度量层进行度量对象的重构。

首先,由于Android内核是基于Linux内核的,可以通过内核提供的system.map 文件获取度量对象的虚拟地址,system.map 文件保存了成千上万个内核导出符号和其对应的虚拟地址。其中也包括本文在上一节分析得到的度量对象及其虚拟地址,例如内核代码段地址、初始化数据段地址、异常向量表虚拟地址、系统调用表虚拟地址、init进程地址等。由这些虚拟地址经过两阶段地址转换过程可以得到度量对象的物理地址,根据Android内核存储这些度量对象的方式(如链表、数组、树等),度量对象的类型和各个字段的偏移可以在度量层重构这些度量对象,方便对其进行分析。

其中经过两阶段地址转换得到的物理地址为该度量对象在物理设备中的起始地址,度量对象的类型为系统定义的链表、整型、长整型或者结构体等,度量对象中字段的偏移为该字段相对于结构体起始地址的偏移量。具体分析过程如下:

输入 度量对象的虚拟地址Va、中间地址Ipa、起始物理地址Pa、度量对象的类型定义SC[]、字段偏移量FS[]、内核符号表文件System.map;

输出 静态对象列表SML[]或动态对象列表DML []。

Va[]=Request_Proxy (System.map);

while (Va[i]!=0)

Ttbr=Read_Guest_TTBR();

Ipa=Translate_Stage1_Guest(Ttbr, Va);

Pa=Translate_Stage2(Ipa);

if (Va[i]∈codesection|datasection|IDT

|System_call|others)

//静态度量对象重构

ML[]=getcode(Pa,SC[i]);

//内核代码段

ML[]=getdata(Pa,SC[i]);

//只读数据段

ML[]=getSys_call(Pa,SC[i]);

//系统调用表

ML[]=getIDT(Pa,SC[i]);

//中断向量表

ML[]=getOthers (Pa,SC[i]);

//异常向量表、全局描述符表等其他静态对象

return SML[i];

else if (Va[i]∈init_task|module_set|others)

//动态度量对象重构

ML[]=getTask(Pa,SC[i],FS[i]);

//进程

ML[]=getMoudle(Pa,SC[i],FS[i]);

//模块

ML[]=getOthers(Pa,SC[i],FS[i]);

//文件、线程数等其他动态对象

return DML[i];

end if

end while

由于内核代码、内核初始化数据、系统调用表和中断向量表等静态度量对象的内容是连续分布的,根据虚拟地址很容易得到,故重构分析过程相对单一,本文不再详细介绍,重点讨论动态度量对象的重构分析方法。下面以分析Android系统的进程为例说明度量对象的重构分析的基本思想。

如图3所示,单个进程的信息存储在该进程的任务结构task_struct中,Android内核中的所有进程通过一个双向循环链表all-tasks来前后链接,单个进程的信息存储在进程结构体task_struct中。为了获取全部进程信息,需要某个进程的信息,0号进程init_task是系统所有进程的父进程,即进程链表的链表头。通过在 system.map 文件查询标识为init_task的符号,找到数据结构 init_task 的虚拟地址Va,经过两阶段地址转换获取的物理地址Pa即为init_task对应task_struct结构的首地址,根据字段类型定义与地址偏移量就可获得例如pid、comm和tasks等对应的语义内容,存入pi[],pi[]即为在度量层重构的该进程信息,再以该tasks字段的值为下一个 task_struct 的虚拟地址继续循环该过程,直到发现某个进程 tasks 的值和init_task 的虚拟地址值相同时停止该过程,由于系统的进程链表是一个循环链表,可知当循环结束时已经遍历到了其余所有进程。

图3 在度量层对内核进程视图重构

与此同时,调度程序使用一个名为run-list的链表来调度进程以执行,采用与分析进程链表一样的方法分析runqueues结构体,将此时在CPU上运行队列上所有就绪进程信息存入pr[],将得到的pi[]与pr[]存入DML[]。

因为在系统中的进程需要满足running_list⊆all-tasks的约束关系,分析过程中则重点分析pr[]中的进程及其字段的元素是否全部包含在pi[]中。若满足该约束,即进程满足子集约束,此时进程无篡改。反之,系统进程被篡改,记录篡改日志并报告系统隐藏的进程。

2.3 DIMDroid度量过程

DIMDroid的度量步骤如下:

1)DIMDroid在度量时间点时刻进行一次完整性度量。度量点的选取采用随机化时间算法得到,保证系统度量的随机性。完整性度量首先在度量层进行度量对象的重构。具体来说,DIMDroid通过度量代理模块获取度量对象的虚拟地址,度量代理模块访问Linux内核提供的System.map文件获取度量对象的虚拟地址VA。然后,将该虚拟地址传递给度量模块后,由度量模块使用被度量系统的第一阶段页表结构获取VA对应的中间物理地址IPA;接着度量模块利用DIMDroid控制的第二阶段页表结构获取IPA对应的物理地址PA;最后,根据度量对象的物理地址、类型定义与各个字段的偏移重构该度量对象。

2)判断度量对象为静态对象或者动态对象并对其进行完整性度量分析。若为静态对象的度量需要进行Hash后进行AES加密与基准库的基准值进行一致性比对,本文采用安全哈希算法 (Secure Hash Algorithm,SHA1)来计算对象的Hash值。动态对象的度量根据其相应的约束进行区分验证。若动态对象需要满足例如进程、模块等的子集约束,则需要同时构建两个集合列表,例如验证进程的完整性时构建pi[]与pr[]集合列表,通过这两个列表是否满足子集约束判断该动态对象的完整性;如果动态对象满足的约束为其他约束,则需将该度量动态对象链表长度或者相关内容与基准库中存储的固定长度约束值、固定取值约束值或者取值边界范围进行对比判断该动态对象的完整性。若度量对象满足对应的约束,报告系统的完整性;若不满足则及时报告系统对应关键内核对象的篡改情况并记录日志中。

DIMDroid的完整性度量的基本过程如图4所示。

2.4 DIMDroid自身安全

DIMDroid处于hyp模式中,在普通区域对资源拥有最高的访问权限,对处于svc模式中的Android内核进行动态度量,因此,DIMDroid自身的安全至关重要。DIMDroid建立基于硬件的信任链启动保护和基于内存隔离的运行时保护,同时,DIMDroid使用简单易懂的度量策略,方便进行形式化验证。

图4 DIMDroid的完整性度量过程

在实现中,本文使用加载时完整性检测来建立基于硬件的信任链。也就是说,TrustZone首先验证bootloader的完整性,然后由bootloader验证内核映像的完整性。DIMDroid所需的数据对象和资源为内核初始化的一部分,且在内核启动任何进程之前完成其初始化。在DIMDroid初始化结束时,通过配置Stage-2页面表,使其自身与内核隔离,以便内核在此之后不再拥有对DIMDroid的访问控制权限。该过程实现的细节如图5所示,灰色部分为系统的TCB。

步骤1 DIMDroid被组装到内核映象中并由bootloader加载。在TrustZone验证bootloader的完整性后,bootloader进入非安全状态中的hyp模式,将压缩的映象加载到内存中。

步骤2 设置hyp向量基址寄存器(HYP Vector Based Address Register, HVBAR)为异常向量。切换到svc模式中,解压内核映象并启动内核初始化。内核完成自己的地址空间设置后,准备好分离DIMDroid所需的所有资源。

步骤3 通过Trustzone安全保护技术验证DIMDroid在内核中的度量代理模块后加载该模块。具体来说,内核分配一个连续的物理内存区域作为DIMDroid的内存空间,例如存储Stage-2页表、DIMDroid的代码和数据部分。内核将未压缩的DIMDroid复制到分配的区域中,并使用具有三级翻译的长描述符转换表格式来配置定义从IPA到PA的标识映射的Stage-2页表。 Stage-2页面表不映射由内核为DIMDroid及其度量代理模块事先分配的内存区域。尽管如此,由于当前的ARM虚拟化扩展不支持I/O虚拟化,恶意内核可能会发起DMA攻击来侵入虚拟机管理程序空间。为了避免由于内核对该区域的良性访问(例如由于内存管理)而导致的异常,该区域被声明为DMA缓冲区,以致未损坏的内核不会试图释放或访问它。

步骤4 发出一个hypervisor调用进入hyp模式。DIMDroid通过将HCR.VM设置为0x1来启用Stage-2转换,并将虚拟化转换表基址寄存器(Virtualization Translation Table Base Register, VTTBR)设置为物理地址步骤3中由内核事先设置的Stage-2页表的根。

步骤5 设置HVBAR为异常向量返回到svc模式,恢复内核初始化。从此时起,所有的内核和用户空间代码执行都使用两级地址转换,因此,内核被排除在运行时TCB之外,大大降低了TCB的大小。DIMDroid能够通过Stage-2页面表在运行时从内核中保护自己。

图5 加载DIMDroid过程

3 实验及结果分析

本文实现了DIMDroid原型,实验环境是使用Intel Core i5- 3210M CPU @ 2.50 GHz处理器和8 GB主内存的PC上的Linux Ubuntu。在这个平台上,本文搭载了ARM FastModels(ARM,2011),FastModels是精确、灵活的ARM IP的程序员视图模型,允许芯片可用之前开发诸如驱动程序、固件、操作系统和应用程序等软件,它可以全控制模拟,包括分析、调试和跟踪ARM IP。本文使用FastModels搭载支持ARM虚拟化扩展的Cortex-A15x1处理器模拟平板电脑,在平板电脑中运行植入DIMDroid的Android5.0进行功能测试和性能测试,功能测试的目的在于检测强制访问控制机制能否有效执行,性能测试的目的在于测试系统的性能损耗。

3.1 功能测试

本实验针对现有Android系统的rootkit进行测试,在5个rootkit中:前两个修改了syscall_table子程序的若干字节来实现攻击;第三个修改了系统的异常向量表;第四个使用了inline hook技术拦截了proc_lookup 函数,执行恶意代码实现模块和进程隐藏;第五个对Android系统的熵池资源进行攻击,使得用于从池中提取字节的算法部分无效。

DroidVisor[15]也是利用硬件虚拟化对Android内核进行监控,使用DIMDroid与DroidVisor来对运行中的Android内核进行动态度量,结果如表2所示。

由度量结果可以看出,无论是针对系统调用表、中断调用表一类的内核静态度量对象篡改还是对进程链表、熵池资源等动态度量对象修改的rootkit都可以被检测出来,DIMDroid度量方法能够有效执行。DroidVisor不能够检测到rootkit 5是因为没有对Android内核的动态的熵池资源作完整性保护,DIMDroid可以利用熵池资源须满足的边界约束对rootkit 5进行检测。

表2 Android系统内核遭受rootkit攻击后的度量

3.2 性能测试

为了判断DIMDroid方法对Android系统的性能影响,本文采用了安兔兔测评(AnTuTu Benchmark)软件,它是专门给Android设备手机、平板电脑评分的专业软件。比较使用与未使用DIMDroid度量的性能指标来进行测试,性能指标主要选取几个现阶段主流的选项:RAM速度、CPU浮点计算性能和CPU整型计算性能。使用安兔兔软件测试DIMDroid度量内核100次,并取平均值。性能损耗比率为采用DIMDroid度量的性能指标项分值与未采用DIMDroid度量该指标项分值之差占未采用该指标项的百分比,结果如表3所示。

表3 使用安兔兔测试DIMDroid结果

由于本文实验在FastModels上进行测试,不能精确地模拟ARM处理器,但可以得到性能损耗比率。由表3可知,使用DIMDroid与未使用DIMDroid相比有一定性能损耗,但在可接受范围内,说明此方法对保证Android内核动态完整性有一定借鉴意义。

4 结语

本文介绍了一种在ARM硬件虚拟化上利用动态度量来保护Android内核实时完整性的方法DIMDroid。该方法通过分析Android内核的运行机制和被攻击对象得出了内核中哪些元素影响了Android内核的完整性,并在hyp层对内核中的度量对象进行重构后分析内核的完整性;与传统方法不同,本文的方法是可信的,因为它与度量的Android内核进行了隔离,并通过基于硬件的信任链启动保护和基于内存隔离的运行时防护来保证DIMDroid自身的安全。本文的实验表明,通过与其他保护方法结果的比较表明,DIMDroid在Android完整性验证上的综合性能更好,但DIMDroid没有突破一些攻击,例如有些攻击不对内核关键数据结构进行篡改实现权限提升、修改控制流等。接下来将通过对内核级的rootkit进行数据特征分析,进而完善DIMDroid度量内核完整性的准确性。

猜你喜欢

链表完整性内核
多内核操作系统综述①
强化『高新』内核 打造农业『硅谷』
关于防火门耐火完整性在国标、英标、欧标和美标中的比对分析
活化非遗文化 承启设计内核
如何用链表实现一元多项式相加
ELM及IS/OS完整性对年龄相关性黄斑变性预后视力的影响
更正说明
微软发布新Edge浏览器预览版下载换装Chrome内核
跟麦咭学编程
基于MTF规则的非阻塞自组织链表