Android原生代码中漏洞的利用和分析

关于Android原生代码中漏洞的利用和分析的一些基础实验和知识。

1.概述

(1)主要内容

  • 检查文件的权限
  • 交叉编译原生可执行程序
  • 竞争条件类漏洞的利用
  • 溢出漏洞的利用
  • 自动进行Android原生代码的fuzzing测试

(2)Android原生代码

  1. 原生代码(native)—即支持应用层组件的所有事物。
  2. 这些原生代码包括:系统守护进程、专为指定系统架构编译的二进制可执行文件以及文件系统组件和设备级配置。
  3. 为什么要研究原生代码中漏洞的利用技术呢?root技术的原理,一般都是通过滥用 Android设备里原生代码中的漏洞完成提取操作,使得我们能永久性地访问 Android设备上的root(或称超级用户)账户。

2.内容要点

(1)检查文件权限

1.背景知识

  1. 滥用操作系统在设置文件系统权限(或访问权限)上的差异和不足,是本地提权的最常见方式之一。定义Android原生系统的受攻击面时,明确的识别出文件系统中所有可能会成为攻击点的文件是一个良好的开端。

  2. 为了正确地认识厂商在设备的操作系统上增添的差异,接下来介绍一点“默认的”或标准的 Android文件系统在结构和访问权限设置方面的知识。

  3. 我们根据 Linux文件系统层次结构和 Jelly Bean( Android4.1的代号)中的 init.rc脚本,对默认的或标准的文件系统中,文件夹及其用途作的一个概述,如下图所示(下图只是一个参考,不同的厂商为他们的设备专门编译的Android版本之间还会有不同)

下面补充一些Linux或基于UNIX的操作系统中的文件权限相关知识。

2.具体步骤

  1. 在Android手机上安装find这个二进制可执行文件或for Android版的Busybox
  2. 在ADB shell中执行以下命令,按照访问控制权限,搜索相关的文件。

find [path-to-search] -perm 0444 -exec ls -al {} \;(列出手机指定目录下“所有用户均可读”的文件)

find [path-to-search] -perm 0444 -exec ls -al {} \; 2> dev/null(包括一个重定向至/dev/null的指令,被用来忽略由于权限不匹配而导致的错误输出)(dev/null的作用就好比是一个输出“黑洞”,允许 Linux/UNIX用户用它来放置他们不感兴趣的输出。一个额外的好处是,它会返回一个值让你知道写操作是否成功。)

find [path-to-search] -perm 0222 -exec ls -al {} \;(列出手机指定目录下“所有用户均可写”的文件)

find [path-to-search] -perm 0111 -exec ls -al {} \;(列出手机指定目录下“所有用户均可执行”的文件)

find [path-to-search] -perm a=r -exec ls -al {} \;(列出手机指定目录下“除组成员外所有用户均可读”的文件)

上面这条指令确保只有当权限完全匹配的文件才会被列出,也就是说,返回的文件的相应位肯定被设为1了。如果你要找规定的位被设为1,而其他的位设不设都没关系的文件—这可能是你最常做的事了—你可以在之前的例子里,在指定搜索权限的参数前面加上一个“-”符号作为前缀,如find [path-to-search] -perm -444 -exec ls -al {} \;

find [path-to-search] -user 0 -exec ls -al {} \;(列出手机指定目录下“属于root用户”的文件)

find [path-to-search] -user 1000 -exec ls -al {} \;(列出手机指定目录下所有“系统用户”的文件)

find [path-to-search] -group 0 -exec ls -al {} \;(列出手机指定目录下“指定组ID”的文件)

  1. 关于应用程序目录data/data。

3.补充说明

(2)交叉编译原生可执行程序

  1. 为你的代码准备一个目录。在建立这个目录之后,你还需要再创建一个名为JNI的子目录。这个子目录的名字必须是“JNI”,因为NDK的编译脚本将会专门寻找这个目录。
  2. 创建一个 Android.mk文件。把它创建在JNI目录中。 Android.mk文件基本上就是个Make文件,其中记录了一些编译相关的属性。它的内容应该是这样的。

  1. 同时在JNI目录下存放需要编译的.c文件(源代码)。
  2. 在JNI目录下执行ndk_build命令(需要将其添加到环境变量中),即可编译。

(3)竞争条件类漏洞的利用

  1. 在 Android平台上,竞争条件会引发不少问题和提权攻击,其中有许多能让恶意攻击者获得root权限。

  2. 从本质上讲,竞争条件问题是当进程运行在使用抢占式进程调度系统的多线程系统(允许多个进程同时运行的平台)中时,由于缺乏强制互斥条件(enforced mutual exclusion)而引发的。抢占式调度允许任务调度器强制中断一个正在运行中的线程或进程,也就是说,不用等到被中断进程准备好,就可以中断其运行。这就会产生竞争条件问题,因为开发人员无法不让进程调度器以这种任意的或不可预测测的方式中断正在运行中的应用程序。结果,那些依赖于访问诸如文件、环境变量或共享内存中的数据结构等潜在共享资源的进程,就要去“竟争”抢占和独占这些资源的访问权。攻击者通过抢先获得这些资源的访问权并改写资源内容的的方式,滥用这一情景,就能达到破坏进程的操作或恶意影响进程行为目的。

  3. 举个简单的例子:某个程序验证用户的方式是把所有已经认证的用户全部列在某个文件中。但这一操作方式不能适应抢占式任务调度,因为程序访问该文件之前,它可能已经被攻击者修改过了,把(未经认证的)他/她的名字加到了列表里,这样他/她就会被认为是认证用户了。

高通声卡驱动中的条件竞争漏洞分析(CVE-2017-7368)

(4)自动进行Android原生代码的fuzzing测试

接下来,我们将讨论如何把fuzzing测试工具Radamsa用到Android平台上,以及安装一些实用程序,以帮助编写一些专为Radamsa开发的,健壮的fuzzing测试脚本。

1.编译for Android版的Radamsa

  1. 下载radamsa

  2. 在jni目录下使用ndk-build命令,结果报错如下图。

这是一个定义(即有一个typedef,它把 in_addr_t定义为unsigned long的别名)无法传递到之后的代码中的问题。解决如下图——

解决之后就可以尝试将生成的可执行文件radamsa复制到手机的system/bin目录下了,具体步骤如下图。

android push文件到system/目录下
无法通过adb将文件push到system的问题

但是将radamsa复制到system/bin目录下后尝试运行时,报错如下图

经过查询,最开始以为是编译时带有指定具体版本的Application.mk文件中指定的android版本(android-21)过高,于是尝试不带此文件进行ndk-build编译,结果仍然报错。

解决方式一

后来猜测是手机系统版本的问题,于是将手机从4.4.4的版本换成5.1.1的,结果在将生成的可执行文件radamsa复制到手机的system/bin目录下时碰到问题。Android5.0及以上在remount system目录时会失败。

Android 6.0 adb remount后没有写权限,提示Read-only file system
在 Android 5.1.1 执行 remount system failed 解决方法
remount of /system failed: Read-only file system原因及解决
How to mount system rewritable or read-only? RW/RO
Read only file system on Android
Android 模拟器启动时参数设置
Android 文件系统分区挂载流程

上述这么多参考链接中的解答都没有解决我的问题。最终,是通过先将其push到data/local/tmp目录下,然后再在root的shell中将其复制到system/bin目录下解决问题的,如下图,然后上一个问题也解决了,果然是系统版本的问题。

解决方式二

参考以下链接,将Application.mk文件中指定的android版本进行改变再编译即可。

android cannot locate symbol ‘sigemptyset’问题解决

2.建立一个简单的fuzzing脚本,对dexdump做fuzzing测试

(1)测试目标

安装Busybox.apk后,其中的一个用于剖析Android DEX并输出其中代码的工具dexdump(位于目录/system/xbin/dexdump下)

(2)测试脚本及步骤

(3)对测试脚本的说明

3.扩展

可用于对Android系统代码进行fuzz的工具简介。

A.Android kernel fuzz

Syzkaller(一)fuzz Android kernel(安装编译Syzkaller、使用syzkaller fuzz Android kernel)
google/syzkaller

Syzkaller是是一款无监督的覆盖引导Linux内核模糊器,由Google团队开发的开源工具,目前还在不断的维护之中。
Syzkaller支持Android平台,搭配使用KASAN 排错和 KCOV 检测编译的内核版本,可以更有效的检测运行时内存错误以及获取代码覆盖率信息。

B.fuzzy_fastboot

Android(十一)fuzzy_fastboot(编译fuzzy_fastboot、使用fuzzy_fastboot、 fuzzy_fastboot原理、fuzz结果分析)
fuzzy_fastboot

fuzzy_fastboot是AOSP官方支持的fastboot fuzzer工具,主要用于给三方手机厂商进行出厂时安全测试。
fuzzy_fastboot工具通用测试会尝试进行51项测试,内容如下,包括usb连接、fastboot相关参数获取、oem锁状态、flash等基础功能以及一些其他测试。

#usb连接测试
USBFunctionality.USBConnect
#获取配置参数
Conformance.GetVar
Conformance.GetVarVersionBootloader
Conformance.GetVarVersionBaseband
Conformance.GetVarSerialNo
Conformance.GetVarSecure
Conformance.GetVarOffModeCharge
Conformance.GetVarVariant
Conformance.GetVarRevision
Conformance.GetVarBattVoltage
Conformance.GetVarBattVoltageOk
Conformance.GetVarDownloadSize
Conformance.GetVarAll
Conformance.UnlockAbility
Conformance.PartitionInfo
Conformance.Slots
Conformance.SetActive
Conformance.LockAndUnlockPrompt
#擦除测试
Conformance.SparseBlockSupport0
Conformance.SparseBlockSupport1
Conformance.SparseDownload0
Conformance.SparseDownload1
Conformance.SparseDownload2
Conformance.SparseDownload3
Conformance.SparseVersionCheck
#oem解锁状态测试
UnlockPermissions.Download
UnlockPermissions.DownloadFlash
#oem锁状态测试
LockPermissions.DownloadFlash
LockPermissions.Erase
LockPermissions.SetActive
LockPermissions.Boot
#fuzz测试
Fuzz.DownloadSize
Fuzz.DownloadPartialBuf
Fuzz.DownloadOverRun
Fuzz.DownloadInvalid1
Fuzz.DownloadInvalid2
Fuzz.DownloadInvalid3
Fuzz.DownloadInvalid4
Fuzz.DownloadInvalid5
Fuzz.DownloadInvalid6
Fuzz.DownloadInvalid7
Fuzz.DownloadInvalid8
Fuzz.GetVarAllSpam
Fuzz.BadCommandTooLarge
Fuzz.CommandTooLarge
Fuzz.CommandMissingArgs
Fuzz.SparseZeroLength
Fuzz.SparseTooManyChunks
Fuzz.USBResetSpam
Fuzz.USBResetCommandSpam
Fuzz.USBResetAfterDownload