Group of Software Security In Progress

GoSSIP @ LoCCS.Shanghai Jiao Tong University

Nail: A Practical Tool for Parsing and Generating Data Formats

  • 出处:OSDI 2014
  • 作者:Julian Bangert, Nickolai Zeldovich

不同版本

Motivation

本文的主要目的:解决臭名昭著的Binary data输入格式解析(parsing)问题。

输入格式的解析导致的软件漏洞比比皆是,最近著名的如Android上stagefright的系列漏洞。 论文中给出的数据显示,在论文发表的最近三年间,有15个关于ZIP文件格式的CVE被登记,其中11个是memory corruption相关,4个是parser的不一致性(inconsistency),即相同的输入存在不同的解析方式(Android master key是一个著名的例子,Java层和Native层上的解析差异性导致了恶意的APK安装包能够通过校验)。 由于文件格式解析这个业务需求广泛存在于大量的系统中,又是相对独立的一个功能模块,如果能够用一些方法产生更为健壮安全的parser,则有望极大提升当前系统的安全性。

Solution

类似编译器前端生成的工作流程(such as lex and yacc),通过提供一个文件格式描述的Domain Specific Language(DSL)来自动化生成Parser,这样就可以保证少犯错误或者不犯错误。

当前的主要问题:

  1. 不要手写parser!不要手写parser!不要手写parser!
  2. 已有的一些DSL只能将输入转换成抽象语法树(AST),而AST离程序内部使用的数据描述结构(特别是C语言这种memory unsafe的情况)之间还有很多差异性,如果不能把这个gap填起来那么还是容易出错。
  3. 已有的文件结构描述方式不完善:
    • 不能表达复杂的文件结构;
    • 文件结构内部本身的冗余(比如checksum,是可以通过数据计算出来的,就没必要单独描述它);
    • c)当output和input是一样的格式的时候,最好能够直接重用input的格式而不是再把parsing过程反过去做一遍.

作者设计了一个叫做Nail的parser generator,这个generator做到了:

  • 规定了一套grammer可以方便地描述大部分常见的binary data format,而且最为重要的是,这个描述既是抽象的格式描述,同时又和low level的layout保持很高的兼容性,也就是作者说的using a single grammar to define both the external

Format and the internal representation

  1. 通过引入dependent fields和transformations两个重要的概念,极大地简化了输入格式的描述
  2. 自动化地产生出parser,提供良好的结果,将文件格式解析问题隔离为一个独立的操作,极大降低了安全风险
    • Using Nail, we implement an authoritative DNS server in C in under 300 lines of code and grammar, and an unzip program in C in 220 lines of code and grammar, demonstrating that Nail makes it easy to parse complex real-world data formats.

解读

视频解读

作者给出了一个非常清晰的presentation,介绍Nail是如何被用于一套数据格式处理的toolchain

Nail的设计目标涵盖了数据格式定义、parser生成以及generator生成三个点。Nail提供了一套grammer描述常见的数据格式,这里它的格式和C比较类似,但是增加了很多约束条件来保证每个域的安全。Nail能根据数据格式直接生成parser和generator,parser用来将binary input转换成程序内部的数据结构,而generator可以反过来将程序内部的数据结构转换成binary output(这里假定input和output的格式一致)

Nail抓住了real world input的重要特征,并用了三大特性来对应之:第一,Nail定义的dependent fields很好地描述了binary format里面那些length field、checksum field;第二,Nail将文件视为多个stream,很好地处理了复杂层级结构的文件格式;第三,Nail用了一个抽象的transformation概念去统一描述那些binary format里面的复杂数据类型(并且告诉你可以引入外部插件来解析他们,而Nail不去直接处理这些数据)

Evaluation

测试对象:

一些网络协议格式(DNS、Ethernet、ARP、IP、UDP和ICMP)包 ZIP格式 作者用了非常少量的描述代码就重写了这些包的格式描述,并自动化生成的解析代码;生成的ZIP处理器不再受到11个已知的CVE影响,而生成的DNS解析程序经过两天的fuzzing test也没有任何异常

Performance也很好,和其它程序如Bind比起来NailDNS的效率高许多(当然作者在作报告的时候也承认和其它程序比不太公平,因为他自己生成的是一个prototype simple parser,并没有做复杂的功能)

For Developers

Github(然而已经两年没有更新,感觉后续没维护了)

CVE-2016-3078 PHP ZipArchive Integer Overflow 分析

这个漏洞的影响范围是PHP 7.0.6版本以前的所有PHP 7.x 版本。PHP的源码可以在这里下到,https://github.com/php/php-src/

PHP源码架构

  • PHP源码里的核心库是在Zend目录下。负责php脚本的解析,执行等核心功能。
  • TSRM目录下是关于PHP多线程的库。
  • ext目录下是实现各种PHP扩展功能的代码。如:ftp,ssl,xml等,也包括这次主要要分析的zip解析的功能。

漏洞详情

关于CVE-2016-3078,在社区上有人发过:http://seclists.org/bugtraq/2016/Apr/159

主要问题是,当PHP在x86的机器上编译的时候,其中的zend_ulong类型会被编译成不同的长度。

Fig

以上代码来自Zend/zend_long.h。可以看到,如果是在x64环境下编译的话,zend_ulong是64位长度的;如果是x86下的话,就是32位长度的。然后,在php_zip_get_from()函数里,会把一个64位的长度赋值给一个zend_ulong类型的变量,形成整型溢出,然后是堆溢出,通过合理构造输入可以达到任意地址写。

执行流程

一个可以触发漏洞的简单的php脚本如下:

Fig

在php脚本里,解析zip文件时,先调用ZipArchive::open()来把zip文件读到内存里。在php源码里对应的代码在php_zip.c里:

Fig

其中,open()初始化了一个_ze_zip_object结构体:

Fig

其中的za指向了一个zip结构体,这个结构体存放的是与被解析的zip文件的内容相关的东西。

Fig

其中的zip_source_t *src指向的结构体与zip文件里的数据相关的东西。

Fig

其中的cb是一个union结构体,里面放的是在解压zip压缩包里的文件时调用的回调函数。在open()函数里,这个回调函数会被初始化成read_data()

Fig

再转回php脚本。open()完成之后,然后调用getFromIndex()或者getFromName()读取zip压缩包里的具体文件数据。在php源码里,这两个函数的都直接调用了php_zip_get_from()函数,而这个就是存在漏洞的函数。

在php_zip_get_from()函数里,会先从Executor Globals里把传入的参数读出来。然后会解析zip文件的dirEntry对应的文件目录,然后更新一个zip_stat结构,存放结果。

Fig

其中size是uint64的,对应zip Entry里的UncompressedSize位。之后会检查从php脚本里传入的参数len是不是小于1,如果是就会把这个size赋值到len。注意,这里len的类型是zend_long。

Fig

然后,调用zip_fopen_index()来解析zip结构,然后更新zip结构体的数据。在解析过程中,这个函数会对zip文件的压缩方式做区分。分别是encrypted,compressed,和store。

encrypted是加密,需要password;compressed是压缩;store是不压缩,直接存放原始文件数据。然后会在原来的zip结构体之上再重新封装一层zip结构体,并把新的结构体的回调函数注册成相应的解密、解压、crc检查的函数。并返回这个新的结构体的指针。

接下来,回到php_zip_get_from()函数。zend_string_alloc()函数是触发整型溢出的点。然后下面的zip_fread()函数是堆溢出的点。

Fig

在zend_string()里会先对len做一个边界对齐,会在原始len的大小上加上0x14然后再mask 0xFFFFFFFC。攻击中可以把UncompressedSize设成0xFFFFFFFE,然后会分配一个0x10大小的堆。

Fig

这里面,调用了pemalloc分配堆块。它是php内部实现的一个Memory Allocator。源码在zend_alloc.c里,具体就不展开了。它里面对小的堆块的分配做了优化,所有小堆块都连续分布在一个或多个连续的内存页上,每个空闲的小堆块都用一个单向链表的形式组织起来。第一个空闲的小堆块的地址会放在全局的chunk head的free_slot里。

Fig

当要分配小堆块的内存的时候,会先从free_slot里拿出那个地址,然后根据链表,把下一个free的block地址放到free_slot里。代码如下:

Fig

所以,这就给堆溢出带来了机会。可以先溢出改写下一个free block的头,然后再分配一次,把构造的free block头写入free_slot,然后再分配一次,构造出任意地址写。

实际的堆溢出发生在后面的zip_fread()函数里。他会递归地调用之前提到的zip结构体里注册的回掉函数。于是,就会先调用之前提到的decrypt/inflate/crc check,然后再调用在open()的时候注册的read_data()函数。这里基本上可以看作是memcpy。

ASLR on the Line: Practical Cache Attacks on the MMU

论文下载

这篇文章发表在2017年NDSS上,作者是Vrije Universiteit Amsterdam的Ben Gras和Kaveh Razavi。文章中使用了一种EVICT+TIME的旁路攻击方式(AnC)来泄漏内存地址,用来降低ASLR的熵。项目网站:https://vusec.net/projects/anc

旁路攻击的条件比较苛刻,要求计时准确,内存访问的控制要求也很高,感觉应用上确实更适合浏览器攻击。

攻击原理

Fig

虚拟地址寻址时,会使用4级页表(PTL)来找到对应的物理地址。每级页表中存放指向下一级页表物理地址的PTE(Page Table Entry)。最后一级页表(PTL1)存放到目的物理地址的PTE。出于性能考虑,MMU和Cache中会缓存一部分最近经常访问的PTE,从而可以通过旁路攻击泄漏地址。

对64位的虚拟地址,12-20位确定PTL1中的PTE,21-29位确定PTL2中的PTE,30-38位确定PTL3中的PTE,39-46位确定PTL4中的PTE。64位系统中ASLR随机化了最多35bit熵,即虚拟地址的12-45位是随机的。

攻击时通过分配多个内存地址上连续(或者临近)的内存块,来暴破待泄漏内存地址的偏移。由于PTL对应的虚拟地址的分段特性,可以分配不同大小的内存块分段暴破。 攻击前需要清空cache中的PTE的缓存,通过多次访问一个偏远的内存空间来清cache。然后访问待泄漏的内存地址,因为cache已经清掉了,所有会进行一次Page Table Walk,目标虚拟地址对应的四级PTL都会装入cache。这时候再访问预先分配的相邻(或者临近)的内存块中的地址,并记录时间。因为,这两个内存块的虚拟地址高位都一样,只有低位不同,因此可以通过(比如)PTL1的cache miss来旁路泄漏出目标地址的偏移。然后逐次访问更远的内存,来泄漏更高位的(e.g. PTL4)的地址。

Challenge

  1. 准确测量时间:Firefox上用performance.now() 计时,精度是每5µs一次;chrome上因为performance.now()不太准,所以用shared memory counter来计时。
  2. 内存排列:以2GB为单位分配内存块。使用不同的步长来分段泄漏地址。使用步长4KB来泄漏PTL1,2MB泄漏PTL2,8GB泄漏PTL3,4TB泄漏PTL4。浏览器中,Firefox因为mmap的时候没有用MAP_POPULATE,所以可以顺利地分配到4TB的内存。但在Chrome中,mmap的时候会同时分配物理内存,所以攻击PTL3和PTL4时会有一定概率无法成功。

实验

作者在实验中对Chrome和Firefox进行了攻击。实验环境是Intel Skylake i7- 6700K CPU, 16 GB 内存,操作系统是 Ubuntu 16.04.1 LTS

Fig

上图攻击是成功率的图,Chrome因为内存排列随机化的原因,会有失败的概率。Firefox PTL4攻击时,4TB内存会和其他对象共享,产生噪声。

Fig

上图中,AnC攻击可以在50s内有效地降低ASLR的熵。

Fig

上表列举了可以被AnC攻击的CPU型号。

防御方法

攻击检测

可以针对攻击者使用的计时器进行检测防御,但是有可能有误报。

Cache分区

可以对每个程序划分LLC(Last Level Cache)进行进程隔离,防止其他进程受到攻击。但是这种方法可能会对计算机系统带来性能上的影响。

计时器修改

可以降低计时器的精度,来防止攻击者进行旁路信息收集。但是问题是,攻击者有很多其他的手段来构造出计时器,进行攻击。无法完全防御所有的计时器。

Cache隔离

可以加一个独立的cache把PTE都放进去,阻止旁路信息泄漏。但是这样的问题在于成本太高。

MARX: Uncovering Class Hierarchies in C++ Programs

论文下载

INTRODUCTION

  • 设计与实现了 MARX,一个可以直接重构没有RTTI信息和使用任意编译选项编译的二进制文件的class hierarchies 的框架
  • 使用超过80M的二进制代码进行实验,vtables可以以很高的精确率恢复出来
  • 实现了两个安全相关的应用:vtable protection; type-safe object reuse

TECHNICAL BACKGROUND

  • RTTI: 指向metadata数据结构的指针
  • Offset-to-Top: 多继承的时候需要的选项
  • vcall 结构 in Itanium C++ ABI on x86-64

    mov RDI, thisptr call [vtblptr + x]

Fig

Fig

ANALYSIS APPROACH

Vtable Extraction

采用了以下六个特征帮助提取vtable:

  • H-1 Vtables 在只读段上
  • H-2 只有最前面的function entries会被vtblptr引用
  • H-3 Offset-to-Top 有一个范围,而且其不是relocation entry
  • H-4 RTTI 指向数据段或者是0
  • H-5 function entry 指向代码段或者是 relocation entry
  • H-6 前两个function entries 可能是0

Static Analysis

Overwrite Analysis

  • 构造时,基类A的构造函数率先调用,之后C的构造函数调用,所以A的vtblptr会被C的vtblptr重写
  • 析构时,C的析构函数县调用,所以C的vtblptr会被A的vtblptr重写

利用以上的特点:

  • 通过观察一个vtblptr是否被另一个vtblptr重写,来判断两个类的关系。
  • 观察 构造函数和析构函数

Fig

Vtable Function Entries

  • 虚函数并不需要重写
  • 所以对于基类和继承类的vtables,可能有多个entries指向同一个函数
  • 通过判断vtables是否指向同一个函数,来判断两个类是否关联
  • 由于编译器优化,可能导致误报

Inter-Procedural Data Flow

  • Forward Edge
    • 虚函数通常是间接调用
    • 通过上下文关系来解析间接调用指令
    • 如果一个vcall被不同的vtable的对象引用,那么这些vtable是相关联的
  • Backward Edge
    • 考虑返回值,可能返回不同的对象

Fig

Inter-Modular Data Flow

首先分析共享库,并根据返回值和vtblptr重写关系建立数据流信息。如果一个共享库的函数被调用,那么这些信息被添加到当前相关的context中辅助分析。

IMPLEMENTATION

  • VEX-IR from the Valgrind project
  • table extraction: IDAPython CFG
  • static analysis: data tracking engine (基于中间语言)

确定入口点

Path Creation and Convergence

  • 值得深入分析的basic block(interesting block),满足三个条件中的一个:

    • an indirect call (i.e., a possible vcall)
    • a (direct) call to a new operator
    • an instruction operating on a vtblptr
  • 设立阈值t,一个函数有t个及以上的interesting block,生成路径深入分析

  • 保证循环只访问一次

Virtual Callsite Identification

  • conservative mode: an indirect call is only identified as vcall if the thisptr holds a known object and a vtable is involved when computing the target address

  • non-conservative mode: an indirect call is considered to be a vcall simply if the vtable is involved in the computation of the target address

APPLICATIONS

VTable Protection for Binaries

类似于CFI

在vcall之前会插入一个标签检查,检查函数类型是否一致

  • Dynamic Analysis
  • Slow Path:当函数类型检查失败时,深入分析

使用Dyninst进行插桩

Type-safe Object Reuse

  • an allocator with type-safe object reuse support
  • a library to instrument object allocations

保证同一个类型才能重用相同类型的内存pool

预先分析建立(location, size, type)信息,在runtime时并保存在hash table里,(location, size)为key,劫持new new[]对象

EVALUATION

  • GCC 4.8.5
  • Ubuntu 14.04 LTS
  • Intel Core i7- 2600 CPU with 16 GB of RAM.

Class Hierarchy Reconstruction

the ground truth is obtained by parsing the RTTI of the target application

Fig

Virtual Callsite Targets

使用 VTV (Virtual Table Verification) GCC pass 生成ground truth,MySQL Server 和 VBoxManage 在编译的时候失败,因此没有数据

Fig

VTable Protection And Type-safe Object Reuse

Fig

Understanding and Defending the Binder Attack Surface in Android

论文下载

密歇根大学 Huan Feng and Kang G. Shin

  • 最近几年诸多CVE都是与binder相关,但都是以之为入口点,没有真正讨论过binder的安全。
  • 作者发现这种攻击的本质在于攻击者可以直接通过操控binder接口来给系统服务注入错误,而系统并没有对数据来源做到很好的鲁棒性。
  • 为了解答这个问题,作者调查了98个google的服务,以及72个三星的服务,以及137个造成崩溃的漏洞。发现数据的校验仅仅在binder的客户端的API上做了,在binder的服务端并没有。例如没有通过public API暴露的RPC参数,以及后续针对这些参数的(反)序列化都没有保护。证明binder的信任边界出错了,这主要由于Android提供了AIDL能够帮助开发者自动生成接口。
  • 作者开发了bindercracker,用来fuzz binder的漏洞,并能够7倍于单纯的黑盒测试效果。并提供了系统及的诊断工具用来binder攻击。

Fig

  • 攻击模型为 APP开发者可以任意构造binder客户端,来调用系统服务端的binder。

Fig

人工审查了binder的漏洞,结果为

Fig

  • 漏洞大多由于由于数据检查发生在调用Public API上,而对于直接对binder发送的数据没有做校验。
  • 包括攻击者可以
    1. 直接给没有通过public API暴露给开发者的RPC方法传参,
    2. 以及有些RPC虽然暴露给public API,但检查也在public API之前,直接调用这些RPC也能导致崩溃
    3. 利用序列化和反序列化过程中校验不严格,直接修改序列化过的数据,导致服务端反序列化的崩溃。

例如IAudioFlinger提供了RPC方法REGISTER_CLIENT,这个方法只会被系统中间层调用,并没有暴露给开发者,所以对于这个RPC的参数,系统服务就不会校验。如果直接通过对binder driver发送一个空参数,就能让这个服务崩溃。系统开发者直接认为RPC接口是外部无法访问的,这个假设是错误的。

这些错误都因为系统开发者认为的信任边界是错误的,他们认为客户端的public API是开发者唯一可以调用的。这种假设也是因为Android提供的AIDL会自动生成代码,帮助开发者完成binder通信,序列化等,事实上,开发者或者攻击者可以完全不需要使用AIDL,而自己手动调用binder和RPC。

Fuzz工具开发

  • 主要问题在于参数的复杂性,以及input可能来自别的binder的output。
  • bindercracker开发了两个组件:
    • 一个记录组件,作为系统中的一部分,收集binder通信的信息
    • 而fuzz组件作为用户层的APP,用来重放和改变记录下来的binder通信内容。

记录组件在binder通信的序列化过程中进行插桩,可以动态的监控到所有的参数类型和结构,并记录下依赖关系。然后fuzz组件通过对最外部的那次通信数据进行修改来fuzz。主要通过修改binder_transaction_data结构体中数据来进行Fuzz。首先需要找到binder的对应系统服务和具体的RPC方法的关系,这个可以通过解析代码和动态的方式找到对应关系。其次是控制一次binder通信中的数据。

Fig

基本思路就是通过记录下来的binder通信数据可以获取数据结构和必要的依赖信息,最后精确的找到真正需要fuzz的参数数据,保持其他的都不变,只改变一个参数值,这样来fuzz。观察binder服务端的反应,如果服务端接受了数据,并且没有catch到异常导致崩溃,则认为fuzz成功。

结果运行了30个APP,抓取到了超过一百万个binder通信数据,通过对每个RPC接口的binder数据采样,最后fuzz了78个系统服务的445个RPC方法,找到了89个漏洞。7倍于同样时间的单纯黑盒测试效果。此外通过简单配置,可以直接对基于binder机制更高一层的Intent做fuzz,并找到了超过20个intent通信的漏洞,主要在反序列化的阶段。

防御

  • 作者认为静态的方法可以类似android目前已有的lint工具,作用在RPC函数上,或者使用bindercracker来做动态的测试都能提高安全性。
  • 接着介绍了bindercracker找到的一系列案例的安全问题,例如可以导致崩溃,或者重启系统,或者一些提权漏洞等等。以及他们的修补情况。

Fig

最后作者尝试了在现有系统中加入动态实时的防御措施,首先尝试对类似的漏洞的入侵检测/防御。这种方法作者认为不可能实现,因为这个需要监控每个binder的参数信息,手机上性能和计算量不行,以及参数变化多端,和用户体验差。接着作者尝试对该漏洞的诊断系统,就是一旦漏洞发生,立马用可视化形式告知用户。由于一个系统服务如果照此crash,系统只会显示服务崩溃,难以找到谁发出这次通信导致的崩溃。作者利用bindercracker的记录功能,做了个可以告警的工具,供用户使用,以弥补现在系统的不足。

Fig

DSCRETE: Automatic Rendering of Forensic Information From Memory Images via Application Logic Reuse

论文下载

本文是一篇内存取证方面的文章,来自普渡大学dongyan xu老师的团队,发表于2014年的USENIX Security上,是当年两篇best student paper之一。

一作saltaformaggio已经连续几年在四大上发表了和内存取证相关的文章,近两年的文章和Android有关。

  • 本文描述了一种通过自动化重用程序代码,从内存镜像中恢复出属于该程序的可以被人理解的数据(图片、pdf、文档文件等)的技术-DESCRETE。
  • 和磁盘取证不同,内存取证最大的难点在于内存中的数据是碎片化的,同时并没有普适的连续的结构化信息(类比磁盘取证中各种文件的格式信息)可以利用。但是,在内存中存在着大量的有利用价值的数据,这些数据一般以无法直接被人理解的数据结构的形式保存于内存中,而不同的应用程序所定义的数据结构也是不尽相同,这就给自动化取证带来的极大的挑战。本文的主要目的就是解决如何对这些content of data structure fileds进行取证的问题。
  • 作者认为,对于这些应用程序内部维护的数据结构,一般在应用程序中都已经带有针对这些数据的“解释器”,这样的解释器负责将这些碎片化、抽象的数据结构组合成人能够直接理解的数据呈现形式(比如,一个图像处理软件在读入一个图片文件时,会将图片文件转化成该软件的一些内部的数据结构,然后通过系统的GUIAPI将这些内部数据结构绘制成能够显示在屏幕上的“图片”)。通过利用这些应用程序自带的“解释器”,就能够完成对内存数据的自动化“解释”,从而取证得到人可以理解的信息。

下图是DESCRETE的一次标准的取证流程:

Fig

  • 简单的说,DESCRETE的目的是寻找到一个测试函数P,P可以用来对内存镜像中的数据进行测试,判断输入的数据是否能够通过P来转换成人可以直接理解的信息。

首先,DESCRETE需要获得取证对象的创造程序的binary,DESCRETE会利用这个binary进行一些学习,从而制造出能够在内存镜像中扫描该应用程序内部数据结构的scanner。学习的第一步是运行该应用程序,确保在内存中有需要取证的数据结构的出现,以及完成一次对这些数据结构的解释输出(例如对于一个图像处理软件,需要先读入一些图片文件,然后将这些图片显示在屏幕上)。在这个过程中,DESCRETE会监控该应用程序对外部库接口以及系统API的调用,尤其是那些会将数据输出到磁盘或是其他设备上的接口。DESCRETE同时还会记录这些接口调用发生时栈和堆上的数据,供后续分析使用。在完成执行之后,descrete的使用者可以通过观察log下来的系统接口的输出,标记那些自己感兴趣的数据。之后使用传统的slicing技术,将所有和该数据生成过程有关的指令全部分离出来。

通过第一步,通过分析插装后的log记录,我们获得了很多个测试函数P的候选,下一步是确定测试函数P的截止点(closure point)。根据作者的定义,一个截止点是符合以下两个要求的一条指令:

  1. 截止点需要直接的对待取证数据结构进行操作。
  2. 在截止点之后的所有指令,对待取证数据结构的操作都基于该指令完成。符合以上两点的截止点能够确保我们在截止点出对待取证数据结构进行修改,就能够直接影响到最终输出的信息。这一步的筛选最终会产出多个截止点,根据作者的实验,截止点的个数一般在30以下,最多不超过102.

由于DESCRETE是一个全自动的取证工具,在过程中不应该有人的介入,所以接下来需要对第二步筛选出来的截止点进行自动化的测试,以此来选出真正能够使用的截止点。在这一步中,DESCRETE会使用不同于第一步的数据输入重新执行这个应用程序,当执行到一个候选截止点时,程序会fork出一个子进程,子进程初始化时,截止点所使用的数据指针会被替换,指针会被指向第一步提取出来的数据。然后子进程继续运行,当且仅当子进程顺利指令完毕并且输出和第一步相同的信息时,表示这个子进程对应的截止点是可用的,同时也意味着一个可用的P被发现了。

最后一步就是使用我们发现P去取证内存镜像,取证的过程和第三步类似。不同的是,在替换截止点数据时,使用的是待取证的内存镜像,对于镜像中的每一个字节,都会有一个子线程去验证。由于数据的特殊性,能够顺利执行完毕的子线程往往意味着成功完成了一次取证。当数据输出过程过于简单时,也会发生有很多子线程均完成执行的情况,这种时候需要人工介入对结果进行筛选。

作者使用了10款不同的真实的应用程序对DESCRETE进行了测试:

Fig

上面的表格显示了选取的10款应用程序的名字、调用的接口、取证人员关心的数据类型、调用接口时的数据大小、测试函数P候选占整个程序代码的比例、发现的截止点候选个数、能够顺利执行完毕的截止点个数、人工验证后正确的截止点个数。

Fig

上面的表格显示了在试验中,应用程序的名字、待取证的数据结构名称、数据大小、该数据结构的实例个数、DESCRETE输出结果的个数、True Positive、False Positive、False Negative。

Swords and Shields – a Study of Mobile Game Hacks and Existing Defenses

论文下载

分析mobile game hack的现状

Hacking Tools

General Hacking Tools

通用的hacking tool分两类:memory editing (GameKiller, GameCIH, and GameGuardian); local file editing (CheatDroid)

Specific Hacking Tools

还有一些为指定游戏设计的工具:例如Xmodgames,包含32个游戏的重打包版本,重打包的版本去除了原有的保护。

Analysis Techniques

Traffic Analysis

通过中间人,网络代理等来修改一些关键网络数据(金币,分数等)。难点如下:首先需要强制让APP的网络数据走分析者的代理。之后数据可能会加密。最后,网络数据可能还包括广告或数据统计的数据包,需要分析者区分。

Decompilers and Debugging Tools

反编译工具包括:dex2jar, ILSpy and JD-GUI。调试工具包括GDB,Android SSL Trustkiller等。

分析现有游戏的保护状况

  • 文章从四个方面来评估保护方法的好坏:安全,部署难度,网络流量消耗,运行效率。
  • 攻击场景:攻击者可以ROOT手机,攻击者分两类:业余选手,只会用现有工具。专业选手,可以深度分析。
  • 分析方法分四步:1)用现有工具改内存或本地文件 2)分析网络流量 3)静态分析 4)动态调试
  • 分析结果见table 1 和2。

Fig

  • 经分析,有如下几个主要防护手段:

Local Resource Protection

34%的游戏有如下保护手段:加密内存中的数据,检测内存修改行为,加密文件内数据。

Network Protections

26% HTTPS,加密网络数据,pinning,签名。还发现部分游戏网络数据不会通过代理。

Code Obfuscation and Hiding

24% 混淆

Compilation into Native Code

48% 用so

Client-Server Sync

25% 会一直同步服务器与本地的数据。

case study

Basic Memory Protection

地铁酷跑,将金币的数值与一个随机数异或,再存入内存,导致在内存中不容易定位到该数字。

Local File Protection

ZigZag,会将闯关数加密存在本地文件,因此无法直接在本地文件中搜索该数字。但是由于没保护内存中的数字,因此可以通过修改内存来修改闯关数。

Basic HTTPS

Rock Heroes用HTTPS,但是可以通过修改数据包欺骗服务器。同时作者发现这个游戏的排行榜有很多高分明显是假的。

HTTPS with Additional Protections

Game of War会做证书pinning,但是可以通过HOOK掉相关API来实现中间人。

Message Signing

Dragon City在native库中计算数据的SHA-256 HMAC作为签名。通过动态调试,在内存中发现key。最后修改数据包成功。

Communicating using Customized Protocol

Army of Toys用自定义协议,通过逆向分析,发现有双层加密。

Code Obfuscation

Kill Shot proguard混淆。

Code Hiding

Army of Toys会动态加载

Compilation into Native Code

Angry Birds会将加密函数放在SO中。作者找到了加密函数和密钥AES:StartEncryption from libAngryBirdsClassic.so.

Partial Client-Server Sync

Trivia Crack 会和服务器同步信息,但是本地还是有一些重要的计算,例如是否正确,金币是否足够等。

Full Client-Server Sync

Army of Toys时刻与服务器同步,且计算都在服务器,即使作者解密了自定义协议,还是无法hack成功。

建议

  • Local resource protection易部署,且没什么效率损耗。
  • Code obfuscation以及native code compilation依赖平台,如果开发平台支持的话也很简单,且会加速执行。
  • Traffic protection用HTTPS的话很简单,但是自定义一个好的协议就比较烦
  • Client-server sync最复杂。且效率低。

保护强度总结在table 3。

Fig

Curious Case of Rowhammer: Flipping Secret Exponent Bits Using Timing Analysis

论文下载

Sarani Bhattachary,Indian Institute of Technology,CHES’16

Combing Timing Analysis and Rowhammer

攻击模型

  • decryption oracle:RSA,对输入的密文解密,然后返回解密结果
  • Adversary:普通用户,已知明密文,可以和decryption oralce交互。目标是通过rowhammer让解密指数出错,因此需要知道secret在内存中的bank地址
  • spy:adversary引入的进程,监视解密过程,使得解密进程访问数据都是从内存中访问,并利用时间旁路确定secret所处的bank
  • k cores,k slices,c cache sets/slice, m way associative

Fig

确定evivtion set

  • Prime+Probe整体思想:由于cache组相连,攻击者可以占满一个cache set的所有组(Prime),当victim有cache进入这个set时,攻击者原有的cache被挤出,攻击者可以再次访问自己的数据看到时间差(Probe)。。

确定secret映射到的LLC slice

  • Prime+Probe可以确定secret所在的cacheset,攻击者可以找出m*k个映射到同一个set的地址,不断在这些地址上Prime+Probe,就可以把secret从缓存中逐出,保证decryption oracle每次都是从内存中取值

确定secret映射到的DRAM bank

  • row buffer collison的时间旁路(Drammer中也是利用这个来确定rowsize)
  • 当同时访问处于同一个bank中但在不同row的内存地址时,row buffer会清空,访问时间被比其他情况下的多 (两个进程的Collision只是理想中能发生的)

在bank中进行rowhammer

  • 在确定了secret所在的bank后,由于无法进一步获知secret所处的row,所以作者在其中进行随机的hammer,如果解密结果不对说明flip影响到了解密进程

Experimental Validation for Inducing Bit Flips On secret

  • 物理地址与cache slice的关系(RAID15)
  • 4核,12路组相连,4个cache slice,每个有2048个cache sets。
  • 攻击者mmap大块内存,通过pagemap得到物理地址,利用映射关系算出cache slice和cache set

Fig

Fig

Countermeasures and Discussion

  • hardware
  • software:ANVIL,统计cache miss
  • fault countermeasure: OpenSSL,计算两次,如果可以稳定的造出两次错误,这样的防护是无效的

Draco: A System for Uniform and Fine-grained Access Control for Web Code on Android

论文下载

Webview的安全问题是android安全研究种的热门领域,根本问题在于系统提供的webview相关功能没有指定类似浏览器中的同源策略一样的安全策略,导致其他来源的web code执行的时候权限没有被限制,从而产生了安全问题。web code本质上类似于第三方库的代码,webview上不能完全去除非可信来源的代码,所以为了保障权限不被滥用,最好的办法就是控制其权限。

对比以前的Webview相关的工作,主要问题在于粒度较粗,不能控制域名对某种接口的访问权限。作者引用了一个攻击的论文,文章利用XSS的方式攻击了使用支持HTML5的PhoneGap app,之前所有的防御方式都无法阻挡这个类型的攻击。

作者提出了一种对于web code的细粒度访问控制。修改了android的Chromium系统app,实现这一个机制完善的访问控制系统,开发者只需要在原有的apk上添加一些权限规则,就可以防止其他来源的webcode访问apk的敏感资源。

Fig

作者提到,Webview中有问题的方面主要有三种:

  • 一种是JavaScript interface,暴露的js接口可以被恶意的web code调用
  • 一种是event handlers,例如onJsAlert(), onJsPrompt() and onJsConfirm()等回调函数
  • 一种是HTML5 APIs,通过html5的接口可以访问地理位置等个人信息。

作者举了三个需求例子,给出了Draco需要添加的规则 – CVS Caremark,医疗处方相关,需要根据不同的domain设置不同的JavaScript interface使用权限

Fig

  • Job Search by Indeed, 找工作的搜索引擎,需要取消非indeed.com的code使用JavaScript interface的权限。

Fig

  • MyStore example. 电商平台,商家提供产品链接以及各种描述信息,需要细粒度的控制每一个商家的interface调用权限,针对性开放html5的地理位置权限。

Fig

policy模型

Fig

框架模型

Fig

Fig

Evaluation

  • CVS Caremark 和 Job Search apps都是真实的APP,将他们放在真机中运行确实能够阻止不被授权的访问。
  • decompilation 60 to 90s
  • statically analyze 6s
  • The Parsing module a few miliseconds
  • Permission parsing < 1ms

Statistical Deobfuscation of Android Applications

论文下载

这篇文章提出一种Android上反混淆的技术,这里的混淆指的是layout obfuscation,即我们熟悉的用proguard对类名,方法名,变量名进行的混淆。反混淆的方式是通过大规模的学习未混淆的APK,来总结出一个概率模型(probabilistic model)。再用该model来识别混淆后的代码。

ProGuard

proguard大家都很熟悉,这里要强调一点是proguard不会混淆所有的program elements。例如一些Android API或manifest中声明的一些组件名是不会混淆的。

DeGuard

DeGuard是本文提出的反混淆系统。系统流程如下图:

Fig

整个过程分如下三步:

  1. 生成一个依赖关系图 (dependency graph based on program elements),图中每个点是program element,每条线代表依赖关系。
  2. 自动导出一些限制规则,这些限制规则保证恢复的APK是个正常的APK,且和原APK语义相同。
  3. 对混淆的元素的原始名字进行预测并恢复。

Background

文章在本章节介绍了一些概率学中的基本概念和方法。包括如何生成依赖图,如何生成权重,如何预测等等。

FEATURE FUNCTIONS

Program Elements

  • 关注的elements包括types,fields,packages,methods,expressions(常量数值或null),access modifiers(static private public…),operations(+,-..)。
  • 同时会区分已知的元素和未知的元素。
  • 为了识别继承的方法,还会计算每个method的签名(a method’s signature is dened by the method’s name along with the number and types of its parameters.)

Fig

CONSTRAINTS

Naming Constraints for Methods

举个例子:

Fig 注意如下几点:

  1. A.a不受其它method限制,因为只有它的参数是A
  2. 但A.b一定不能rename为equals(Object),因为A是隐性继承Object的,且存在java.lang.Object.equals(Object)。
  3. B.g和B.h的名字一定不一样,即使他们的access level和return type不同。
  4. B.g和A.c的名字一定不一样,B.h和A.c也一定不一样。否则就变为继承。
  5. B.h和C.x可以一样,因为B.h是private,不会被继承。

Naming Constraints for Fields, Classes, and Packages

  1. any two packages contained in the same package must have distinct names
  2. any two classes contained in the same package must have distinct names
  3. any two fields declared in the same class must have distinct names.

Evaluation

  • 1784个APK,选100个作为benchmark,其余1684作为训练集。
  • 恢复元素名字能够做到79.1%。
  • 识别三方库可以做到91.3%
  • 速度平均1min。
  • 且给出了两个分析恶意软件的case study。