安卓取证学习指南-全-
安卓取证学习指南(全)
原文:
annas-archive.org/md5/e5389ef3843690d1ee144f281791135b
译者:飞龙
序言
许多取证检查员依赖于商业的、一键式工具来检索和分析数据,尽管没有任何工具能够完美完成这两项任务。
学习 Android 取证 将向你介绍最新的 Android 平台及其架构,并提供 Android 取证概述。你将了解 Android 设备如何存储数据,并学习如何设置数字取证环境。在你阅读各章节时,将学习各种物理和逻辑技术,从设备中提取数据以获取取证证据。你还将学习如何恢复已删除的数据,并借助各种开源和商业工具进行应用数据的取证分析。在最后几章中,你将探索恶意软件分析,以便能够调查涉及 Android 恶意软件的网络安全事件。
到本书结束时,你将完全理解 Android 取证流程,探索开源取证工具,并调查移动网络安全事件。
本书的目标读者
如果你是取证分析师或信息安全专业人员,想要提升你对 Android 取证的知识,那么这本书适合你。期望你具备一些 Android 移动平台的基础知识。
如何最大化阅读此书的收益
本书涵盖了 Android 设备上的各种取证方法和技术。内容组织方式使任何用户都可以检查 Android 设备并进行取证调查。不需要任何先决知识。
因为所有主题都已解释,从基础到深入。对移动平台,特别是 Android 的了解,绝对会是一个优势。只要可能,使用工具执行各种取证活动所需的步骤都被详细说明。
下载彩色图片
我们还提供了一个 PDF 文件,其中包含本书中使用的屏幕截图/图示的彩色图像。你可以在此下载:www.packtpub.com/sites/default/files/downloads/9781789131017_ColorImages.pdf
。
使用的约定
本书中使用了许多文本约定。
CodeInText
:表示文本中的代码词、数据库表名、文件夹名称、文件名、文件扩展名、路径名、虚拟网址、用户输入和 Twitter 用户名。这里有一个例子:“启动恢复模式不会解密/data
分区。”
一段代码如下所示:
from subprocess import Popen
from os import getcwd
command = "adb pull /data/data " + getcwd() + "\data_from_device"
p = Popen(command)
p.communicate()
当我们希望引起你对代码块中特定部分的注意时,相关的行或项会用粗体显示:
from subprocess import Popen
from os import getcwd
command = "adb pull /data/data " + getcwd() + "\data_from_device"
p = Popen(command)
p.communicate()
任何命令行输入或输出都如下所示:
j7xelte:/ # cat /proc/filesystems
粗体:表示新术语、重要单词或在屏幕上看到的单词。例如,菜单或对话框中的单词在文本中会像这样显示。这里有一个例子:“从主恢复界面,选择挂载。”
警告或重要提示如下所示。
提示和技巧如下所示。
联系我们
我们始终欢迎读者的反馈。
一般反馈:如果您对本书的任何内容有疑问,请在邮件主题中注明书名,并通过customercare@packtpub.com
与我们联系。
勘误:尽管我们已尽力确保内容的准确性,但错误难免。如果您发现本书中的错误,我们将不胜感激,恳请您报告给我们。请访问www.packt.com/submit-errata,选择您的书籍,点击“勘误提交表格”链接,并填写相关详情。
盗版:如果您在互联网上发现我们作品的任何非法复制品,敬请提供其位置或网站名称。请通过copyright@packt.com
与我们联系,并附上该材料的链接。
如果您有兴趣成为作者:如果您在某个领域拥有专业知识,并且有兴趣写书或为书籍做贡献,请访问authors.packtpub.com。
书评
请留下评论。阅读并使用本书后,为什么不在您购买书籍的网站上留下评论呢?潜在读者可以看到并参考您的客观评价来做出购买决策,我们 Packt 公司可以了解您对我们产品的看法,而我们的作者也能看到您对其书籍的反馈。谢谢!
欲了解更多关于 Packt 的信息,请访问packt.com。
第一章:介绍 Android 取证
移动取证是数字取证的一个分支,正在当今的数字时代不断发展,并随着新手机的发布和操作系统的更新而不断变化。Android 取证涉及通过各种技术提取、恢复和分析 Android 设备上的数据。由于 Android 操作系统的开放性,这些取证技术和方法不仅适用于手机,还可以应用于更多设备:冰箱、汽车娱乐系统、电视、手表等许多设备都运行 Android 系统。
在我们深入了解如何提取数据之前,清晰理解平台及其他基础知识非常重要。本章将涵盖以下内容:
-
移动取证
-
移动取证方法
-
移动取证中的挑战
-
Android 架构
-
Android 安全
-
Android 硬件组件
-
Android 启动过程
当今世界正经历着前所未有的技术创新,这种增长在移动设备领域几乎呈指数级增长。科技研究和咨询公司 Gartner 在 2018 年 1 月发布的预测中估计,2017 年全球手机出货量为 22.8 亿部,预计 2018 年将增加到 23.2 亿部。仅这一统计数据就反映了移动设备前所未有的增长。手机不仅数量增加,而且在功能上也变得更加复杂。从 1997 年到 2018 年,手机用户数量的增长显著。
你可能不需要被告知,智能手机已成为移动电话中越来越大的一个子集。这些设备在计算能力和数据存储方面的改进,使我们能够执行各种活动,并且我们越来越依赖这些移动设备。除了执行日常任务,如打电话、发短信等,这些设备还支持其他活动,如发送电子邮件、浏览互联网、录制视频、创建和存储文档、通过全球定位系统(GPS)服务识别位置,以及管理业务任务。换句话说,移动设备现在已经成为敏感个人信息的存储库。
设备中的数据往往比设备本身更有价值。假设有一起涉及嫌疑恐怖分子智能手机的案件;如果执法机关能够访问嫌疑人发送或接收的每一条联系人、电话、短信或电子邮件,这将有多么有用?或者,更好的是,能够访问手机曾经所在的每一个位置?虽然大部分数据通常可以通过服务提供商获取,但这往往需要额外的搜查令或传票,而且可能需要相当长的时间。此外,考虑到第三方应用程序;例如,WhatsApp 聊天内容是端到端加密的,任何数量的传票都无法从 Facebook 恢复这些数据。本书将向你展示如何恢复一些数据,比如 WhatsApp 聊天内容,这些数据通过其他方法可能无法恢复。移动取证在解决 2010 年时代广场汽车炸弹袭击未遂事件和波士顿马拉松爆炸案等案件中发挥了关键作用,进一步证明了移动取证在许多案件解决中的日益重要性。
移动取证
移动设备取证是数字取证的一个分支,专门处理在取证环境下从移动设备中提取、恢复和分析数字证据或数据。简而言之,它涉及访问存储在设备上的数据,包括短信、联系人、通话记录、照片、视频、文档、应用程序文件、浏览历史等,并使用各种取证技术恢复设备中已删除的数据。如果证据必须在法庭上作为证据使用,那么恢复或访问设备详细信息的过程必须符合取证规范,以保持证据的完整性。如果证据需要在法庭上使用,重要的是只处理镜像文件,而不是原始设备本身。
取证规范这一术语常用于数字取证领域,用以澄清某一特定取证技术或方法的正确使用。由于 Android 设备在市场上占据 85%的份额(根据市场研究公司 IDC 的数据显示),移动取证,特别是 Android 取证,正在快速发展。
正如 Eoghan Casey 在他的书《数字取证与调查》中所解释的,取证的准确性不仅仅是保持原始证据不被更改。即使是使用硬件写入阻止器从硬盘驱动器获取数据的常规操作,也可能会导致硬盘上的更改(例如,使隐藏区域变得可访问)。取证准确性的关键之一是文档记录。从一开始就记录设备的处理方式非常重要。因此,如果获取过程能够保持原始数据,并且能够验证其真实性和完整性,那么调查就可以被认为是取证上有效的。证据完整性检查确保证据自收集以来没有被篡改。通过将收集时的证据数字指纹与当前状态下的证据数字指纹进行比较来进行完整性检查。
由于以下一些原因,移动取证的需求正在不断增长:
-
移动电话存储个人信息的使用
-
移动电话在执行在线活动中的使用增多
-
移动电话在多种犯罪中的使用
对特定设备的移动取证主要依赖于底层操作系统。因此,我们有不同的领域,如 Android 取证、iOS 取证等。
移动设备取证方法
一旦从设备中提取数据,根据案件的不同背景,使用不同的分析方法。由于每项调查都有其独特性,因此不可能为所有案件制定一个统一的确切程序。然而,整体过程可以分为五个阶段,如下图所示:
以下部分将详细讨论每个阶段。
调查准备
这一阶段从接收到检查请求时开始。它包括准备所有必要的文书和表格,以记录证据链、所有权信息、设备型号、目的、请求方所寻求的信息等。证据链指的是按时间顺序记录的文件或纸质档案,展示了物理或电子证据的扣押、保管、控制、转移、分析和处置。根据请求方提交的细节,重要的是要清楚地了解每项检查的目标。
扣押和隔离
扣押设备时的处理是执行取证分析中的一个重要步骤。证据通常通过防静电袋运输,这些袋子旨在保护电子元件免受静电损坏。设备一旦被扣押,必须小心确保我们的操作不会导致设备上的数据修改。同时,也不应错过任何有助于调查的机会。以下是处理安卓设备时需要注意的几点:
-
随着用户对安全性和隐私的关注不断增加,现在大多数设备默认启用屏幕锁定。在扣押期间,如果有机会(例如,手机恢复解锁状态),请禁用密码。一些设备在禁用锁屏选项时,不要求用户重新输入密码。
-
如果设备已解锁,尝试更改设备设置以允许更大的访问权限。以下是一些可以考虑的设置,以实现这一目标:
-
启用 USB 调试:启用此选项将通过安卓调试桥(ADB)连接为设备提供更大的访问权限。我们将在第二章《设置安卓取证环境》中详细介绍 ADB。这将大大帮助取证调查人员在数据提取过程中。在安卓设备中,这个选项通常可以在设置 | 开发者选项下找到,如下图所示。从安卓 4.2 开始,新的安卓版本默认隐藏开发者选项。要启用它们,请转到设置 | 关于手机(或在安卓 8.0 及更高版本中选择设置 | 系统 | 关于手机),然后点击“版本号”七次。
-
启用保持唤醒设置:启用此选项并在充电时将使设备保持唤醒状态;换句话说,它不会被锁定。在安卓设备中,这个选项通常可以在设置 | 开发者选项下找到,如下图所示:
-
-
- 增加屏幕超时:这是设备解锁后保持活动状态的时间。根据设备型号,这个时间最长可以设置为 30 分钟。在大多数设备中,可以通过设置 | 显示 | 屏幕超时进行访问。
请注意,访问这些选项的位置会因安卓手机的不同版本和型号而有所不同,某些版本可能没有该选项。
在移动取证中,保护被扣押设备至关重要,以确保我们与证据的互动(或者说攻击者试图远程与设备互动)不会改变证据内容。在计算机取证中,我们可以使用软件和硬件写保护器来执行此功能。但在移动取证中,由于我们需要与设备互动以提取数据,这些写保护器并不起作用。另一个重要方面是,我们还需要防止设备与无线电网络互动。如前所述,攻击者很可能会发出远程擦除命令,删除设备上的所有数据,包括电子邮件、应用程序、照片、联系人和其他文件。
Android 设备管理器和其他一些第三方应用程序允许远程擦除或锁定手机。这可以通过登录配置在手机上的 Google 账户来完成。使用这些软件,攻击者还可以定位设备,这可能带来安全风险。出于这些原因,将设备与所有通信源隔离非常重要。
你有没有考虑过不通过互联网进行远程擦除的选项?移动设备管理(MDM)软件,企业常用来管理公司设备,可以通过发送短信来提供远程擦除功能。将设备与所有通信选项隔离是至关重要的。
要将设备与网络隔离,如果我们能够访问该设备,可以将设备设置为飞行模式。飞行模式会禁用设备的无线传输功能,如蜂窝网络、Wi-Fi 和蓝牙。然而,由于现在飞机上也提供 Wi-Fi,一些设备在飞行模式下也允许连接 Wi-Fi。以下截图显示了通过从锁屏下拉顶部菜单栏访问的快速设置:
请注意,这些切换选项是可定制的,并且可能并非所有设备都能使用;有些设备可能还需要解锁设备才能进行这些更改。
另一种解决方案是使用法拉第袋或 RF 隔离盒,它们都能有效地屏蔽手机信号的收发。这些隔离方法的一个问题是,一旦使用了它们,手机的触摸屏或键盘无法正常使用,因为你无法透过隔离设备查看手机。为了解决这个问题,存在法拉第帐篷和房间,如下图所示:
即使采取了所有这些预防措施,某些自动功能,如闹钟,仍然可能会触发。如果遇到这种情况,必须正确记录。
获取阶段
获取阶段指的是从设备中提取数据。由于移动设备固有的安全特性,提取数据并不总是简单直接的。提取方法主要取决于操作系统、品牌和型号。以下是可以用于从设备中提取数据的获取方法类型:
-
手动获取是所有获取方法中最简单的一种。检查员使用手机的用户界面浏览和调查。这里不需要特殊的工具或技术,但其限制在于只能提取通过正常用户界面可见的文件和数据。通过其他方法提取的数据也可以通过这种方式进行验证。需要注意的是,这种选项非常容易修改设备上的数据(例如,打开未读的短信将其标记为已读),因此这些更改应尽可能详细地记录。
-
逻辑获取,也称为逻辑提取,通常指的是提取存在于逻辑存储中的文件,如文件系统分区。这包括从手机中获取如短信、通话历史记录和图片等数据类型。逻辑提取技术通过使用原始设备制造商的应用程序编程接口(API)来同步手机内容与计算机。这种技术通常涉及提取以下证据:
-
通话记录
-
短信
-
多媒体短信
-
浏览器历史记录
-
人物
-
联系方式
-
联系人扩展
-
联系人组
-
联系人电话
-
联系人设置
-
外部图像媒体(元数据)
-
外部图像缩略图媒体(元数据)
-
外部媒体、音频及杂项(元数据)
-
外部视频(元数据)
-
多媒体短信部分(包括通过 MMS 发送的完整图像)
-
位置详情(GPS 数据)
-
网络活动
-
组织
-
所有已安装应用及其版本列表
-
社交网络应用数据,如 WhatsApp、Skype 和 Facebook
-
-
文件系统获取是一个逻辑过程,通常指从移动设备中提取完整的文件系统。文件系统获取有时可以帮助恢复从设备中删除的内容(存储在 SQLite 文件中)。
-
物理获取涉及对整个闪存存储设备进行逐位复制,相当于对硬盘的完整镜像。通过此方法提取的数据通常是原始数据(以十六进制转储的形式),然后可以进一步解析以获取文件系统信息或可读数据。由于所有调查工作都是在此镜像上进行的,这一过程也确保了原始证据未被更改。
检查和分析
在此阶段,使用不同的软件工具从内存映像中提取数据。除了工具外,调查员可能还需要十六进制编辑器的帮助,因为工具并不总是能提取所有数据。没有单一工具能够在所有情况下使用。因此,检查和分析需要对各种文件系统、文件头等有扎实的知识。
报告
在整个过程中应进行考试文档记录,记录下每个阶段所做的工作。以下是检查员可能记录的一些要点:
-
考试开始的日期和时间
-
手机的物理状况
-
收到手机时的状态(开/关)
-
手机的品牌、型号和操作系统
-
手机及其各个组件的图片
-
调查过程中使用的工具(包括版本号)
-
在检查过程中记录的数据
从移动设备提取的数据应清晰地呈现给接收方,以便能够导入到其他软件中进行进一步分析。在民事或刑事案件中,尽可能地收集手机上存在的数据的图片,因为这些图片对陪审团来说具有视觉冲击力。
移动取证中的挑战
随着 Android 设备的使用增加以及它们支持的通信平台种类的扩展,对取证检查的需求自然也增加了。在与移动设备合作时,取证分析员面临着许多挑战。以下几点揭示了今天面临的一些移动取证挑战:
-
防止设备上的数据篡改:法医学中的一个基本规则是保留原始证据。换句话说,应用于设备上的法医技术提取任何信息时,不应改变设备上现有的数据。然而,在移动设备法医学中,这通常并不实际,因为仅仅开启设备也可能会改变设备上的某些状态变量。在移动设备中,后台进程始终在运行,从一种状态到另一种状态的突然过渡可能会导致数据的丢失或修改。因此,数据可能会被法医分析师故意或无意地篡改。除此之外,攻击者(或用户)有很大可能性能够远程更改或删除设备的内容。由于移动电话使用不同的通信通道(如蜂窝网络、Wi-Fi、蓝牙、红外等),应该消除通过这些通道进行通信的可能性。像远程数据擦除这样的功能使得攻击者能够通过发送短信或仅仅按下一个按钮来向 Android 设备发送擦除请求,从而远程擦除整个设备。与计算机法医学不同,移动设备法医学不仅仅是将设备与网络隔离,手机在检查期间不能总是保持关闭状态。
-
操作系统和设备型号的广泛性:市场上可用的各种移动操作系统使得法医分析师的工作更加困难。虽然 Android 是移动世界中最主流的操作系统,但仍有一些设备运行其他操作系统,包括 iOS、Blackberry 和 Windows,这些设备在调查中经常遇到。此外,对于给定的操作系统,有成千上万的移动设备可用,它们在操作系统版本、硬件以及其他各种特性上有所不同。根据制造商的不同,获取法医证据的方法也会有所变化。为了保持竞争力,制造商快速发布新型号和更新,难以追踪所有设备。有时,即使是同一操作系统中,数据存储选项和文件结构也会发生变化,这让工作变得更加困难。目前没有任何单一工具能够适用于所有类型的移动操作系统。因此,法医分析师必须保持对最新变化和技术的更新,并理解本书中的基本概念,以便在工具失效时仍能成功。
-
固有的安全特性:随着隐私概念日益重要,手机制造商正朝着在设备上实施强大安全控制的方向发展,这使得获取设备数据的过程更加复杂。例如,如果设备设置了密码保护,法医调查员必须首先找到绕过密码的方法。同样,许多现代设备上实施的全盘加密机制阻止了执法机构和法医分析人员访问设备上的信息。苹果的 iPhone 默认使用内置硬件密钥加密设备上的所有数据。从 Android Nougat 开始,Android 默认强制全盘加密(尽管如果操作系统被制造商修改,可能会有所不同)。在 2017 年 Google I/O 大会上,Google 宣布 80%的 Android 7.0 Nougat 设备已加密,70%的设备使用了安全锁屏。随着越来越多的制造商在初始设置过程中强制加密,这些数字可能会继续增长。对于检查员来说,使用暴力破解等技术打破这些加密机制是非常困难的。
-
法律问题:移动设备可能涉及跨越全球的犯罪,并可能跨越地理边界。为了应对这些跨司法管辖区的问题,法医检查员需要了解犯罪的性质和区域法律。
Android 架构
在我们深入研究 Android 法医之前,本节将向您介绍 Android 作为操作系统,并介绍一些必须理解的基本概念,这些概念是获得法医经验所必需的。
任何操作系统(桌面或手机)都负责管理系统资源,并为应用程序提供与硬件或物理组件进行交互的方式,以完成某些任务。Android 操作系统也不例外。它为手机提供动力,管理内存和进程,执行安全性,处理网络问题等等。Android 是开源的,大部分代码是根据 Apache 2.0 许可证发布的。实际上,这意味着手机设备制造商可以访问它,免费修改它,并根据任何设备的需求使用该软件。这是其普及的主要原因之一。
Android 操作系统由一层层叠加运行的层组成。要最好地理解 Android 架构,需要了解这些层是什么以及它们的作用。以下屏幕截图(由developer.android.com
提供)展示了 Android 软件堆栈中涉及的各个层:
Android 架构以软件栈的形式存在,包括内核、库、运行时环境、应用程序、中间件和服务。栈的每一层以及每一层中的元素,都是以一种最佳的方式集成在一起,为移动设备提供最佳的执行环境。接下来的章节将重点介绍 Android 软件栈中的不同层,从底层的 Linux 内核开始。
Linux 内核
Android 操作系统建立在 Linux 内核之上,并由 Google 做了一些架构上的改动。选择 Linux 是因为它是一个便于移植的平台,能够在不同硬件上轻松编译。Linux 内核位于软件栈的最底层,为设备硬件和上层之间提供了一个抽象层。它还充当了软件与设备硬件之间的抽象层。为了更好地理解这一点,考虑一下拍照的过程。当你按下手机上的摄像头按钮拍照时,实际发生了什么?在某个时刻,硬件指令(按下按钮)必须转换为软件指令(拍照并将照片存储到相册中)。内核包含的驱动程序可以帮助实现这一过程。当摄像头按钮点击被检测到时,指令会发送到内核中相应的驱动程序,该驱动程序向摄像头硬件发送必要的命令,类似于按下键盘上的某个键。简单来说,内核中的驱动程序控制着底层硬件。正如之前截图所示,内核包含与 Wi-Fi、蓝牙、USB、音频、显示等相关的驱动程序。
Android 的所有核心功能,如进程管理、内存管理、安全性和网络连接,都是由 Linux 内核管理的。Linux 是一个经过验证的、安全性和进程管理都非常可靠的平台。Android 利用了现有的 Linux 开源操作系统,为其生态系统构建了一个坚实的基础。每个版本的 Android 都有不同版本的底层 Linux 内核。目前,Google 要求运行 Android 8.0 Oreo 操作系统的设备至少要搭载 Linux 内核 4.4 版本。
硬件抽象层
硬件抽象层(HAL)允许更高层次的 Java API 框架通过标准接口与移动设备的硬件进行交互。这得益于多个库模块,它们为不同类型的硬件组件(如蓝牙或摄像头)提供接口。
Android 运行时
自 Android 5.0 起,每个应用程序都在自己的进程中运行,并且拥有独立的 Android 运行时(ART)实例。它通过执行 DEX(Dalvik 可执行文件)文件,使得在低内存设备上运行多个虚拟机成为可能。需要注意的是,在 5.0 版本之前,Dalvik 是 Android 运行时,因此为 Dalvik 开发的应用程序应该能在 ART 上正常运行。
原生 C/C++ 库
许多核心 Android 系统组件和服务,包括之前提到的 HAL 和 ART,都是由本地代码构建的,因此它们需要用 C 和 C++ 编写的本地库。
Java API 框架
Java API 框架允许开发者使用模块化的系统组件和服务作为构建块来创建应用程序:
-
视图系统允许构建应用程序的用户界面,包括列表、网格、文本框、按钮等。
-
资源管理器提供访问应用程序的非代码组件,如本地化字符串、图形和布局文件。
-
通知管理器允许应用程序显示自定义警报。
-
活动管理器管理应用程序的生命周期,以及它们的后退栈——即每个活动打开的顺序。
-
内容提供者允许应用程序访问其他应用程序的数据,并共享自己的数据。
应用程序层
Android 堆栈中的最上层由应用程序(称为 应用)组成,这些是用户直接交互的程序。这里讨论了两种类型的应用程序:
-
系统应用:这些是预装在手机上的应用程序,随手机一起出厂。像默认浏览器、电子邮件客户端和联系人等就是系统应用的例子。这些应用程序通常无法被用户卸载或更改,因为它们在生产设备上是只读的,尽管某些设备提供了禁用这些应用程序的功能。如果系统应用被禁用,应用程序及其所有数据仍然保留在设备的系统分区中,应用程序图标只是从用户界面中隐藏。这些应用程序通常可以在
/system
分区找到。在 Android 4.4 KitKat 之前,所有位于/system
分区的应用程序都被视为平等。但从 Android 4.4 开始,安装在/system/priv-app/
下的应用程序被视为特权应用,并被授予带有保护级别 signatureOrSystem 的权限。 -
用户安装的应用:这些是用户从各种分发平台(如 Google Play)下载并安装的应用程序。Google Play 是 Android 操作系统的官方应用商店,用户可以浏览和下载应用程序。根据 Statista 2017 年 12 月的统计数据,Google Play 商店中大约有 350 万款 Android 应用程序。这些应用程序位于
/data
分区。关于如何在它们之间执行安全性管理的更多信息将在接下来的章节中讨论。
Android 安全
Android 作为平台,其架构内置了某些功能,确保用户、应用程序和数据的安全性。尽管这些安全功能有助于保护数据,但有时它们会阻止调查人员访问必要的数据。从取证的角度来看,首先要了解内在的安全特性,以便清楚地了解在正常情况下可以访问哪些数据,哪些不能访问。所内置的安全功能和服务旨在实现三项目标:
-
保护用户数据
-
保护系统资源
-
确保一个应用程序无法访问另一个应用程序的数据
下一节将概述 Android 操作系统中的关键安全功能。
通过 Linux 内核在操作系统级别确保安全
Android 操作系统建立在 Linux 内核之上。在过去几十年中,Linux 已经发展成为一个安全的操作系统,全球许多企业信任其安全性。通过将 Linux 内核作为平台的核心,Android 试图确保操作系统级别的安全性。此外,Android 在 Linux 中内建了大量与移动环境相关的特定代码。随着每次 Android 发布,内核版本也随之变化。下表显示了 Android 版本及其相应的 Linux 内核版本:
Android 版本 | Linux 内核版本 |
---|---|
1.0 | 2.6.25 |
1.5 | 2.6.27 |
1.6 | 2.6.29 |
2.2 | 2.6.32 |
2.3 | 2.6.35 |
3.0 | 2.6.36 |
4.0 | 3.0.1 |
4.1 | 3.0.31 |
4.2 | 3.4.0 |
4.3 | 3.4.39 |
4.4 | 3.8 |
5.0 | 3.16.1 |
6.0 | 3.18.10 |
7.0 | 4.4.1 |
7.1 | 4.4.1 |
8.0 | 4.10 |
9.0 | 4.4.107, 4.9.84, 和 4.14.42 |
Linux 内核为 Android 提供以下关键安全特性:
-
基于用户的权限模型
-
进程隔离
-
可扩展的安全 IPC 机制
权限模型
Android 为单独的应用程序实现了权限模型。应用程序必须在清单文件中声明它们需要哪些权限。在 Android 的早期版本中,用户在安装之前会看到应用程序请求的完整权限列表。
Android 的新版本在每次应用程序需要权限时,都会提示用户。这种模型允许用户在不授予应用程序所要求的所有权限的情况下使用该应用,尽管功能可能会减少。
Android 中的示例权限模型
与桌面环境不同,这为用户提供了提前了解应用程序请求访问的资源的机会。换句话说,必须获得用户许可才能访问设备上的任何关键资源。通过查看请求的权限,用户能够更清楚地意识到安装应用程序时所涉及的风险。
如前所述,开发者需要在名为AndroidManifest.xml
的文件中识别权限。例如,如果应用需要访问互联网,则需要在AndroidManifest.xml
文件中使用以下代码指定INTERNET
权限:
<manifest
package="com.example.rohit">
…
<uses-permission android:name="android.permission.INTERNET" />
…
</manifest>
Android 权限分为四个等级:
权限类型 | 描述 |
---|---|
普通权限 | 这是默认值。此类权限属于低风险权限,不会对其他应用、系统或用户构成风险。此权限会在安装时自动授予用户,无需用户批准。 |
危险权限 | 这些权限可能会对系统和其他应用造成危害,因此在安装过程中需要用户授权。 |
签名权限 | 如果请求的应用与声明/创建此权限的应用使用相同证书签名,则此权限会自动授予该应用。此级别旨在允许一组应用或相关应用共享数据。 |
签名/系统权限 | 只有 Android 系统镜像中的应用或与声明此权限的应用使用相同证书签名的应用,才能获得系统授予的此类权限。 |
应用沙箱机制
为了将应用相互隔离,Android 利用了 Linux 基于用户的保护模型。在 Linux 系统中,每个用户都有一个唯一的用户 ID(UID),并且用户之间是隔离的,一个用户不能访问另一个用户的数据。特定用户下的所有资源都在相同权限下运行。同样,每个 Android 应用都分配有一个 UID,并以独立进程的方式运行。这意味着,即使已安装的应用尝试做一些恶意行为,它也只能在其自身的上下文中进行,并且只能在它拥有的权限范围内进行。这种应用沙箱机制是在内核层面实现的。应用与系统之间在进程级别的安全性是通过标准的 Linux 设施(如分配给应用的用户和组 ID)来确保的。例如,以下截图来自www.ibm.com/developerworks/library/x-androidsecurity/
展示了沙箱机制:
默认情况下,应用程序不能读取或访问其他应用程序的数据,并且对操作系统的访问权限受到限制。例如,如果应用程序 A 尝试读取应用程序 B 的数据,操作系统会对此进行保护,因为应用程序 A 没有适当的用户权限。由于应用程序沙箱机制是在内核级别实现的,它适用于本地应用程序和操作系统应用程序。因此,操作系统库、应用程序框架、应用程序运行时以及所有应用程序都在应用程序沙箱内运行。绕过此沙箱机制将需要破坏 Linux 内核的安全性。
Android 中的 SELinux
从 Android 4.3 开始,增强安全 Linux(SELinux)已被 Android 安全模型所支持。Android 安全基于自主访问控制,这意味着应用程序可以请求权限,用户可以授予或拒绝这些权限。因此,恶意软件通过获得权限可以对手机造成破坏。Android 使用 SELinux 强制实施强制访问控制,确保应用程序在隔离的环境中运行;这包括作为 root 或超级用户运行的应用程序。因此,即使用户安装了恶意应用,恶意软件也无法轻易访问操作系统并破坏设备。SELinux 用于在所有进程上强制实施强制访问控制(MAC),包括那些具有 root 权限的进程。SELinux 的运作原则是 默认拒绝。任何没有明确允许的操作都会被拒绝。SELinux 可以在两种全局模式下运行:宽容模式,在该模式下,权限拒绝会被记录,但不会强制执行;和强制模式,在该模式下,拒绝操作会被记录并强制执行。根据 Google 的文档,在 Android 5.0 Lollipop 版本中,Android 实现了对 SELinux 的全面强制执行。这是在 4.3 版本的宽容发布和 4.4 版本的部分强制执行基础上的进一步改进。简而言之,Android 正在从仅限于几个关键领域(installd
、netd
、vold
和 zygote
)的强制执行,转向对所有领域(超过 60 个领域)的全面强制执行。
应用程序签名
所有 Android 应用在安装到设备上之前都需要使用证书进行数字签名。使用证书的主要目的是识别应用的作者。这些证书不需要由证书授权机构签发,Android 应用通常使用自签名证书。应用开发者持有证书的私钥。开发者可以使用相同的私钥为应用程序提供更新,并在应用之间共享数据。在调试模式下,开发者可以使用 Android SDK 工具生成的调试证书为应用签名。你可以运行和调试以调试模式签名的应用,但该应用不能分发。要分发应用,应用需要使用你自己的证书进行签名。在此过程中使用的密钥库和私钥需要由开发者加以保护,因为它们对推送更新至关重要。以下截图显示了导出应用时显示的密钥库选择选项:
安全的进程间通信
如前所述,应用程序的沙盒机制是通过在不同的进程中以不同的 Linux 身份运行应用程序来实现的。系统服务在单独的进程中运行,并具有更多的权限。因此,为了组织这些进程之间的数据和信号,需要一个进程间通信(IPC)框架。在 Android 中,这是通过使用 Binder 机制来实现的。
Android 中的 Binder 框架提供了组织各种进程间通信所需的能力。Android 应用组件,如 Intents 和内容提供者,也都是建立在这个 Binder 框架之上的。通过使用这个框架,可以执行多种操作,如调用远程对象的方法,就像它们是本地的一样,支持同步和异步方法调用,以及在进程间传递文件描述符。假设进程 A 中的应用程序想要使用运行在进程 B 中的 Service 暴露的某些行为。在这种情况下,进程 A 是客户端,进程 B 是服务。使用 Binder 的通信模型如下图所示:
Binder 通信模型
使用 Binder 框架的所有进程间通信都通过 Linux 内核驱动程序/dev/binder
进行。对该设备驱动程序的权限设置为可供所有用户读取和写入,这意味着任何应用程序都可以读写该设备驱动程序。客户端和服务器之间的所有通信都通过客户端侧的代理和服务器侧的存根进行。代理和存根负责发送和接收通过 Binder 驱动程序发送的数据和命令。
每个通过 Binder 机制暴露的服务(也称为 Binder 服务)都会分配一个令牌。这个令牌是一个 32 位的值,在系统中所有进程中都是唯一的。客户端可以在发现这个值后开始与服务进行交互,这可以通过 Binder 的上下文管理器来实现。基本上,上下文管理器充当一个命名服务,使用服务的名称提供服务的句柄。为了使这个过程正常工作,每个服务必须向上下文管理器注册。因此,客户端只需要知道服务的名称即可进行通信。
名称由上下文管理器解析,客户端接收到令牌,该令牌随后用于与服务进行通信。Binder 驱动程序将发送方进程的 UID 和 PID 值添加到每个事务中。如前所述,系统中的每个应用程序都有自己的 UID,因此该值用于标识调用方。接收方可以检查获得的值,并决定是否完成该事务。因此,安全性得到了保障,Binder 令牌充当了安全令牌,因为它在所有进程中都是唯一的。
Android 硬件组件
Android 与多种硬件组件兼容。Linux 内核使这一切变得简单,因为 Linux 支持各种各样的硬件。这为制造商提供了很大的灵活性,因为他们可以根据自己的需求进行设计,而不必担心兼容性问题。这对法医分析师在调查过程中提出了重大挑战。因此,了解硬件组件和设备类型将大大有助于理解 Android 法医分析。
核心组件
设备中存在的组件因制造商和型号的不同而有所变化。然而,有一些组件在大多数移动设备中都有出现。以下章节提供了 Android 设备中常见组件的概述。
中央处理单元(CPU)
CPU,也称为处理器,负责执行手机上发生的所有操作。它告诉设备该做什么以及如何做。它的性能通过每秒可以完成的任务数量来衡量,这称为 周期。例如,一个 1 GHz 的处理器每秒可以处理十亿个周期。处理器的容量越大,手机的性能就会越流畅。在智能手机中,我们会遇到以下术语:ARM、x86(Intel)、MIPS、Cortex,以及 A5、A7 或 A9。ARM 是一家公司,授权其架构(品牌为 Cortex),每年推出不同的型号,如前面提到的 A 系列。基于这些架构,芯片制造商发布了自己的芯片系列(如 Snapdragon、Exynos 等),这些芯片被用于移动设备。较新的智能手机采用双核、四核甚至八核处理器。
基带处理器
现代智能手机支持多种移动通信协议,包括 GSM、3G、4G 和 LTE。这些协议非常复杂,需要大量的 CPU 计算能力来处理数据、生成数据包,并将其传输到网络提供商。为了处理这一过程,智能手机现在使用基带调制解调器,这是一种与主处理器通信的独立芯片。这些基带调制解调器拥有自己的处理器,称为基带处理器,并运行自己的操作系统。基带处理器管理多个无线控制功能,如信号生成、调制、编码以及频率偏移。它还可以管理信号的传输。
基带处理器通常位于与 CPU 相同的电路板上,但由一个独立的无线组件组成。
内存
安卓手机和普通计算机一样,使用两种主要的内存类型:RAM 和 ROM。尽管大多数用户对这些概念很熟悉,但在移动设备上,仍然存在一些混淆。
RAM 是随机存取存储器(Random Access Memory)的缩写。它是易失性的,意味着断电后内容会被删除。RAM 访问速度非常快,主要用于软件应用程序的运行时内存(包括设备的操作系统和所有应用程序)。换句话说,它被系统用来加载和执行操作系统及其他应用程序。可以同时运行的应用程序和进程的数量取决于 RAM 的大小。
ROM(通常被称为安卓 ROM)是只读存储器(Read-Only Memory)的缩写。它是非易失性的,这意味着即使断电,内容也会被保留。安卓 ROM 包含启动加载程序、操作系统、所有下载的应用程序及其数据、设置等。
注意,启动加载程序和安卓系统使用的那部分内存通常是锁定的,只有通过固件升级才能更改。其余部分的内存被一些厂商称为用户内存。这里存储的每个应用程序的数据不会被其他应用程序访问。一旦这部分内存被填满,设备的运行速度就会变慢。RAM 和安卓 ROM 通常被制造成一个单独的组件,称为多芯片封装(MCP)。
SD 卡
SD 卡在手机取证中具有重要意义,因为它上存储的数据常常是关键证据,即使设备被锁定或加密,也能访问。许多安卓设备具有可拆卸的存储卡,通常被称为安全数字(SD)卡。与此不同,苹果的 iPhone 没有 SD 卡的插槽。SD 卡是非易失性的,这意味着即使它们断电,数据仍然保存在其中。SD 卡使用闪存,这是一种电可擦可编程只读存储器(EEPROM),它以大块而非单个字节的方式进行擦写。大多数多媒体数据和大文件由应用程序存储在 SD 卡中。为了与其他设备互操作,SD 卡实现了特定的通信协议和规范。
在一些手机中,尽管存在 SD 卡接口,但部分机载 NAND 内存(非易失性)被划分出来,用于创建一个模拟的 SD 卡。这实际上意味着 SD 卡是不可拆卸的。因此,法医分析师需要检查他们处理的是实际的 SD 卡还是模拟的 SD 卡。SD 内存卡有几种不同的尺寸。迷你 SD 卡和微型 SD 卡与原始 SD 内存卡使用相同的技术,但尺寸更小。
显示屏
近年来,手机屏幕发展迅速。以下是一些常见手机屏幕类型的简要描述。
-
TFT LCD代表薄膜晶体管液晶显示屏,这是手机中最常见的屏幕类型。这些屏幕下面有一盏灯,透过像素使其可见。
-
AMOLED代表主动矩阵有机发光二极管;这是一种基于有机化合物的技术,以其优异的图像质量和低功耗而闻名。与 LCD 屏幕不同,AMOLED 显示器不需要背光—每个像素都会发光—因此使用 AMOLED 的手机可能更薄。
电池
电池是手机的命脉,也是现代智能手机用户最关心的因素之一。你使用设备及其组件的频率越高,电池消耗的速度就越快。以下是手机中使用的不同类型的电池:
-
锂离子(Li-Ion)电池是手机中最常用的电池,因为它们轻便易携带,且以高能量密度和低维护著称。然而,与其他类型的电池相比,它们的制造成本较高。
-
锂聚合物(Li-Poly)电池具有锂离子电池的所有特性,但具有超薄几何形状和简化的包装。它们是最新技术,只在少数移动设备中出现。
-
镍镉(NiCd)电池是旧技术电池,且会受到记忆效应的影响。因此,电池的整体容量和使用寿命都会降低。此外,镍镉电池由有毒材料制成,对环境不友好。
-
镍氢(NiMH)电池与镍镉电池相似,但可以容纳更高的能量,并且可以运行 30%到 40%更长的时间。它们仍然会受到记忆效应的影响,但相比于镍镉(NiCd)电池要少得多。它们广泛应用于手机,并且价格实惠。
电池类型可以通过查看其外壳上的详细信息来识别。
通常,SD 卡位于电池后面。在取证分析过程中,访问 SD 卡可能需要拆卸电池,这将关闭设备电源。这可能会产生一些后果,后续章节将详细讨论。
除了之前描述的组件外,以下是一些其他知名组件:
-
全球定位系统(GPS)
-
Wi-Fi
-
近场通信(NFC)
-
蓝牙
-
摄像头
-
按键盘
-
USB
-
加速度计和陀螺仪
-
扬声器
-
麦克风
Android 启动过程
了解 Android 设备的启动过程有助于我们理解涉及在不同层面与设备交互的其他取证技术。当 Android 设备首次开机时,会执行一系列步骤,帮助设备将必要的固件、操作系统、应用数据等加载到内存中。以下信息来自原文发布于community.nxp.com/docs/DOC-102546
。
以下是 Android 启动过程中涉及的步骤顺序:
-
启动 ROM 代码执行
-
启动加载程序
-
Linux 内核
-
初始化过程
-
Zygote 和 Dalvik
-
系统服务器
我们将详细研究每个步骤。
启动 ROM 代码执行
在设备开机之前,设备的 CPU 处于未进行任何初始化的状态。一旦 Android 设备开机,执行将从启动 ROM 代码开始。此启动 ROM 代码是特定于设备所用 CPU 的。如下图所示,此阶段包括 A 和 B 两个步骤:
-
步骤 A:当启动 ROM 代码执行时,它会初始化设备硬件并尝试检测启动媒体。因此,启动 ROM 代码会一直扫描,直到找到启动媒体。这与计算机启动过程中的 BIOS 功能几乎相同。
-
步骤 B:一旦启动序列建立,初始引导加载程序会被复制到内部 RAM 中。此后,执行权转移到加载到 RAM 中的代码:
引导加载程序
引导加载程序是一个在操作系统开始工作之前执行的小程序。引导加载程序存在于台式电脑、笔记本电脑和移动设备中。在 Android 引导加载程序中,有两个阶段——初始程序加载(IPL)和第二程序加载(SPL)。如下面的截图所示,这涉及到这里解释的三个步骤:
-
步骤 A:IPL 负责检测和设置外部 RAM。
-
步骤 B:一旦外部 RAM 可用,SPL 会被复制到 RAM 中,并且执行权转移到它。SPL 负责加载 Android 操作系统。它还提供访问其他引导模式的功能,如 fastboot 和 recovery。它会初始化多个硬件组件,如控制台、显示器、键盘、文件系统、虚拟内存和其他功能。
-
步骤 C:SPL 会尝试查找 Linux 内核。它会从引导媒体中加载该内核,并将其复制到 RAM 中。一旦引导加载程序完成这个过程,它将把执行权转移给内核:
Linux 内核
Linux 内核是 Android 操作系统的核心,负责进程管理、内存管理以及在设备上执行安全性控制。内核加载后,它会挂载根文件系统(rootfs),并提供对系统和用户数据的访问:
-
步骤 A:当内存管理单元和缓存初始化完成后,系统可以使用虚拟内存并启动用户空间进程。
-
步骤 B:内核将在
rootfs
中查找init
进程,并将其作为初始用户空间进程启动:
Init 进程
Init 是第一个启动的进程,是所有其他进程的根进程:
-
步骤 A:Init 过程会寻找一个名为
init.rc
的脚本。这个脚本描述了系统服务、文件系统以及需要设置的其他参数:-
init
进程可以在以下位置找到:<android source>/system/core/init
。 -
init.rc
可以在以下位置找到:<android source>/system/core/rootdir/init.rc
。
-
更多关于 Android 文件层次结构的详细内容将在第三章中讨论,理解 Android 设备上的数据存储。
- 步骤 B:Init 进程会解析 init 脚本并启动系统服务进程。在此阶段,你将在设备屏幕上看到 Android 标志:
Zygote 和 Dalvik
Zygote 是设备启动后创建的第一个初始化进程之一。它初始化 Dalvik 虚拟机,并尝试创建多个实例来支持每个 Android 进程。如前面章节所讨论,Dalvik 虚拟机是执行用 Java 编写的 Android 应用程序的虚拟机。
Zygote 通过在虚拟机中共享代码来实现,因此帮助节省内存并减轻系统负担。之后,应用程序可以通过请求新的 Dalvik 虚拟机来运行。Zygote 为 zygote 连接注册一个服务器套接字,并预加载某些类和资源。这个 zygote 加载过程已在 elinux.org/Android_Zygote_Startup
中更清晰地解释:
-
Load ZygoteInitclass
:加载ZygoteInit
类。源代码:`<Android Source> /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java`
-
registerZygoteSocket()
:此方法为zygote
命令连接注册一个服务器套接字。 -
preloadClasses()
:这是一个简单的文本文件,包含需要预加载的类列表,该文件将在此执行。该文件可以在以下位置找到:<Android Source>/frameworks/base
。 -
preloadResources()
:此方法处理本地主题和布局,并加载所有包含android.R
文件的内容:
系统服务器
设备的所有核心功能,如电话功能、网络功能以及其他重要功能,都是由系统服务器启动的,如下图所示:
以下是该过程中启动的一些核心服务:
-
启动电源管理器
-
创建活动管理器
-
启动电话注册表
-
启动包管理器
-
将活动管理器服务设置为系统进程
-
启动上下文管理器
-
启动系统上下文提供者
-
启动电池服务
-
启动警报管理器
-
启动传感器服务
-
启动窗口管理器
-
启动蓝牙服务
-
启动挂载服务
系统发送一个广播动作,称为 ACTION_BOOT_COMPLETED
,告知所有依赖进程启动过程已完成。之后,设备会显示主屏幕,并准备好与用户交互。
如前所述,多个厂商在其设备上使用 Android 操作系统。这些设备厂商大多数会根据其硬件和其他需求定制操作系统。当 Android 发布新版本时,这些设备厂商必须将其自定义软件和调整移植到最新版本。
总结
理解 Android 架构和安全模型对于正确理解 Android 取证至关重要。Android 操作系统中固有的安全功能,如应用程序沙箱和权限模型,能够保护设备免受各种威胁,同时也成为取证专家在调查过程中面临的障碍。掌握了 Android 内部结构的知识后,我们将在下一章讨论设备上存储了哪些数据,以及这些数据是如何存储的。
第二章:设置 Android 取证环境
在开始取证检查之前,您需要一台工作站。取证分析师需要时刻完全掌控他们的工作站。本章将带您了解建立用于检查 Android 设备的取证环境所需的一切。以下主题将在本章中讨论:
-
Android 取证设置
-
Android 调试桥
-
Rooting Android
Android 取证设置
在开始任何调查之前,建立一个健全且受控的取证环境至关重要。首先使用一台全新且取证无污染的计算机。取证无污染的计算机是指能够防止交叉污染并且不引入不必要数据的计算机。这是为了确保计算机上的软件不会干扰当前的调查。安装一些基本软件,如下所列,它们是连接设备和进行分析所必需的:
-
Android SDK
-
移动设备驱动程序
-
办公软件包
-
用于分析的工具
Android SDK
我们需要从 Android Studio 和 Android SDK 开始讨论。Android Studio 是一个功能齐全的 集成开发环境(IDE),包含从头开始构建完整应用所需的所有工具。Android 软件开发工具包(SDK)是 Android Studio 的一个子集,只包括通过命令行与设备通信所需的工具。它包括软件库、API、模拟器、参考资料以及许多其他工具,这些工具不仅有助于创建 Android 应用,还提供了有助于 Android 设备取证分析的文档和实用程序。对 Android SDK 有充分的了解,可以帮助您理解设备的特性,从而在调查过程中提供帮助。
在检查过程中,SDK 帮助我们连接到设备并访问数据。SDK 支持 Windows、Linux 和 OS X,可以从 developer.android.com/studio
免费下载。
本书仅需要 SDK。它可以在前面链接的 仅命令行工具 部分找到。
安装 Android SDK
以下是在 Windows 10 机器上安装 Android SDK 的逐步过程:
-
在开始安装 Android SDK 之前,确保系统已安装最新的Java 开发工具包(JDK),因为 Android SDK 依赖于 Java SE 开发工具包。可以从
www.oracle.com/technetwork/java/javase/downloads/index.html
下载 JDK。根据您的操作系统选择正确的下载版本。 -
从
developer.android.com/studio/#command-tools
下载最新版本的 SDK 工具包。 -
解压你刚刚下载的压缩包到你选择的位置。就是这样:你已经准备好开始使用了。
从法医角度来看,让我们看看 SDK 工具中最有趣的部分:
-
apkanalyzer
:这个工具允许你快速有效地检查 APK 文件的内容。例如,你可以收集有关应用程序 ID、版本号和版本名称的信息,并分析其清单文件、其中的 DEX 文件以及资源(如文本、图片和字符串)。你可以在\sdk\tools\bin
目录下找到它。 -
avdmanager
:这个工具允许你通过命令行创建和管理Android 虚拟设备(AVDs)。这些 AVD 可以帮助你进行恶意软件分析,或者如果你没有物理 Android 设备,但想研究不同的应用程序以及新的法医证据,也可以使用它。你可以在\sdk\tools\bin
目录下找到它。 -
emulator
:这是一个基于 QEMU 的设备仿真工具,允许你在实际的 Android 运行时环境中调试和测试应用程序,包括恶意应用。你可以在\sdk\emulator
目录下找到它。 -
sdkmanager
:这个工具帮助你保持 SDK 工具的更新。通过这个工具,你可以查看、安装、更新和卸载软件包。你可以在\sdk\tools\bin
目录下找到它。 -
adb
或 Android 调试桥:这是一个命令行工具,允许你与设备进行通信。它不仅可以用来安装应用或从设备中复制数据,还可以为法医检查员提供一个 Unix shell。你可以在\sdk\platform-tools
目录下找到它。 -
fastboot
:这个工具允许你为设备刷入不同的系统镜像。例如,它可以用来刷入自定义的恢复镜像——你将在本章后面了解它们。你可以在\sdk\platform-tools
目录下找到它。
需要注意的是,所谓的 SDK 平台工具默认并不包含在 SDK 工具中,你需要安装它;以下是安装方法:
sdkmanager.bat "platform-tools"
如果你认为不需要所有 SDK 工具,只想使用平台工具,你可以从 Android 开发者网站获取它:developer.android.com/studio/releases/platform-tools
。你只需要将下载的压缩包解压到你选择的目录,就可以开始使用这些工具了。
Android 虚拟设备
安装了 Android SDK 后,你可以创建一个 AVD,这是一个在工作站上运行的模拟器。开发者通常在创建新应用时使用模拟器。然而,模拟器在法医调查中也被认为是有用的,因为它可以帮助调查员了解某些应用的行为,以及理解应用的安装如何影响设备。另一个优点是,你可以设计一个带有所需版本的模拟器。这对于处理运行较旧版本 Android 的设备尤其有帮助。而且,AVD 默认带有 root 权限。
以下步骤将指导你如何在工作站上创建 AVD:
-
确保在
\sdk
目录下有emulator
子目录;如果没有,运行以下命令来安装它:sdkmanager.bat "emulator"
。 -
我们需要一个虚拟设备的系统镜像,例如
system-images;android-28;google_apis;x86
;你可以通过以下方式下载它:sdkmanager.bat "system-images;android-28;google_apis;x86"
。 -
现在我们可以使用
avdmanager
创建 AVD:avdmanager.bat create avd -k "system-images;android-28;google_apis;x86" -n test
。正如你可能已经猜到的,k
选项让你选择系统镜像,而n
选项让你为 AVD 选择名称。 -
现在是时候启动它了!使用
emulator.exe
来启动:emulator.exe -avd test
。以下是 AVD 启动成功后的屏幕截图:
运行 Android 9(Pie)的 Android 虚拟设备(AVD)
模拟器可用于配置电子邮件帐户、安装应用程序、浏览互联网、发送短信等。法医分析师和安全工程师可以通过利用模拟器,检查网络、文件系统和数据工件,了解关于 Android 及其操作的很多信息。在模拟器上工作的过程中创建的数据会存储在你的主目录下,名为.android
的文件夹中。例如,在我们的示例中,我们之前创建的测试 AVD 的详细信息存储在 C:\Users\0136\.android\avd\test.avd
中。该目录下有几个文件,以下是一些对于法医分析师有用的文件:
-
cache.img
:这是/cache
分区的磁盘镜像。 -
sdcard.img
:这是 SD 卡分区的磁盘镜像。 -
Userdata-qemu.img
:这是/data
分区的磁盘镜像。/data
分区包含有关设备用户的重要信息。 -
config.ini
:此文件包含所使用的系统镜像信息。 -
hardware-qemu.ini
:此文件包含模拟器的硬件选项,如架构、RAM 大小和屏幕类型。
连接和访问 Android 设备从工作站
为了从 Android 设备中提取信息,首先需要将其连接到工作站。如前所述,必须确保工作站是法医上干净的,并且仅用于调查目的。法医上干净的工作站指的是具有正确配置并且没有恶意软件的工作站。因此,如果你熟悉虚拟机和快照,使用虚拟机可能是进行移动取证(尤其是 Android 取证)的一个好主意,因为你每次需要检查新设备时,都可以拥有一个完全干净的工作站。
当设备连接到计算机时,可以对设备进行更改,因此法医检查员必须始终保持对设备的控制。在移动设备取证领域,使用写保护机制可能帮助不大,因为它们会阻止成功获取设备数据。这是因为在获取数据时,某些命令需要推送到设备上以提取必要的数据。而且,有时甚至需要安装小型应用程序来提取更多数据,或者例如为设备获取 root 权限。
确认正确的设备数据线
安卓设备可以通过设备的物理 USB 接口与工作站连接。这个物理 USB 接口允许设备与计算机连接、共享数据并进行充电。USB 接口的类型可能因制造商而异,也因设备而异。常见的类型有 micro-USB、USB-C 和一些不太流行的专有格式。以下是最广泛使用的连接器类型的简要描述:
连接器类型 | 描述 |
---|---|
Micro-USB | 它的大小约为 6 x 1.5 毫米,两个角被切割成梯形。 |
USB-C | 它的大小为 8.4 x 2.6 毫米,呈矩形带圆角的形状。 |
因此,获取数据的第一步是确定需要什么类型的设备数据线。
安装设备驱动程序
移动设备只有在计算机上安装了必要的设备驱动程序后才能与计算机进行通信。如果没有必要的驱动程序,计算机可能无法识别和与连接的设备配合使用。由于安卓系统允许制造商进行修改和定制,所以没有一个通用的驱动程序能够适用于所有安卓设备。每个制造商都有自己的专有驱动程序,并与手机一同分发。因此,确定需要安装的特定设备驱动程序非常重要。当然,一些安卓取证工具包会附带一些通用驱动程序或最常用的驱动程序集合,但它们可能无法与所有型号的安卓手机兼容。某些 Windows 操作系统能够在设备插入后自动检测并安装驱动程序,但往往失败。每个制造商的设备驱动程序可以在其官方网站上找到。
访问设备
安装必要的设备驱动程序后,使用 USB 数据线将安卓设备直接连接到计算机以进行访问。使用原厂专用数据线非常重要,因为通用数据线可能与某些设备不兼容,且调查人员可能会遇到驱动程序相关的问题。有些设备可能不兼容 USB 3.0,这可能导致驱动程序安装失败。在这种情况下,建议尝试切换到 USB 2.0 端口。一旦设备连接,它会显示为一个新驱动器,你可以访问外部存储中的文件。某些旧款安卓设备可能无法访问,除非在设备的“设置 | USB 实用工具”中启用“连接存储到 PC”选项。
在这种情况下,连接设备通过 USB 后,需要选择“开启 USB 存储”选项,如下图所示:
USB 大容量存储连接
这是因为旧款安卓设备需要 USB 大容量存储模式来在计算机和设备之间传输文件。最新的安卓设备使用 MTP 或 PTP 协议,因为 USB 大容量存储协议存在一些问题。使用 USB 大容量存储时,驱动器会完全向计算机开放,就像它是一个内部驱动器一样。但问题在于,访问存储的设备需要对其进行独占访问。换句话说,当设备驱动器连接到计算机时,必须与设备上的安卓操作系统断开连接才能正常工作。因此,当设备连接到计算机时,存储在 SD 卡或 USB 存储中的文件或应用程序将无法使用。在媒体传输协议(MTP)中,安卓设备不会将其整个存储暴露给 Windows。相反,当你将设备连接到计算机时,计算机会查询设备,设备会响应一个它提供的文件和目录列表。如果计算机需要下载某个文件,它会向设备发送请求,设备将通过连接发送该文件。图片传输协议(PTP)也与 MTP 类似,通常由数码相机使用。在这种模式下,安卓设备将与支持 PTP 但不支持 MTP 的数码相机应用程序一起工作。在最新设备上,你可以在“设置 | 存储 | USB 计算机连接”下选择 MTP 或 PTP 选项。
在某些安卓设备上,只有在将设备连接到计算机后,才会提供选择 MTP 和 PTP 协议的选项。连接设备后,观察屏幕顶部的通知栏,你会看到 USB 图标出现。下拉通知栏,你将找到一个可以在 MTP 和 PTP 之间切换的选项。
如下图所示,MTP 和 PTP 选项仅在连接设备到计算机并下拉通知栏后才会显示:
更改 Android 设备上的 USB 连接模式
默认选择是充电。当选择文件传输选项时,它将被挂载为磁盘驱动器。当设备作为磁盘驱动器挂载时,您将能够访问设备上的 SD 卡。
从法医学的角度看,SD 卡具有重要的价值,因为它可能包含对调查重要的文件。大多数与多媒体相关的图像和大文件存储在这种外部存储器中。SD 卡通常使用 FAT32 文件系统格式化,但您可能也会遇到一些使用 exFAT 和其他文件系统的情况。正如在第一章中讨论的介绍 Android 取证,请注意,大多数最新的设备具有模拟 SD 卡功能,使用设备的 NAND 闪存创建一个非可移动的 SD 卡。因此,可以通过这种方式访问外部存储器上存在的所有敏感文件。但是,存储在/data/data
下的核心应用数据将保留在设备上,不能通过这种方式访问。
Android 调试桥
在 Android 取证中,Android 调试桥(ADB)起着非常关键的作用。它位于<sdk_path>/platform-tools
位置。要使用 ADB,需要启用 USB 调试选项。在大多数 Android 手机和平板电脑上,您可以在设置 | 开发者选项下找到它,如下图所示:
USB 调试选项
然而,并非所有设备都是如此,因为不同的设备有不同的环境和配置功能。有时,检查人员可能需要使用某些技术来访问一些设备上的开发者选项。这些技术是特定于设备的,需要由法庭分析师根据设备类型和型号进行研究和确定。
在一些设备上,开发者选项菜单是隐藏的,可以通过点击生成号码字段(位于设置 | 系统 | 关于手机下)七次来启用。
一旦选择 USB 调试选项,设备将在后台运行 ADB 守护进程(adbd
),并持续寻找 USB 连接。该守护进程通常在非特权 shell 用户账户下运行,因此无法访问内部应用数据。但在已 root 的手机上,adbd
将在根账户下运行,因此可以访问所有数据。在安装了 Android SDK 的工作站上,adbd
将作为后台进程运行。此外,在同一工作站上,将运行一个客户端程序,可以通过发出adb
命令来调用该程序,我们将在以下部分看到。当启动 ADB 客户端时,它首先检查是否已运行 ADB 守护进程。如果没有,则启动一个新进程来启动 ADB 守护进程。守护进程通过它们的本地主机在5555
到5585
端口上进行通信。偶数端口用于与设备的控制台通信,而奇数端口用于 ADB 连接。ADB 客户端程序通过5037
端口与本地的adbd
通信。
使用 ADB 访问设备
正如前面所述,ADB 是一个强大的工具,允许您与 Android 设备通信。现在我们将看看如何使用 ADB 访问设备的某些无法正常访问的部分。重要的是要注意,通过 ADB 收集数据可能会根据各国法律而被接受或不被接受作为证据。以下部分列出了一些常用的 ADB 命令及其在逻辑顺序中的含义和用法。
检测连接的设备
将设备连接到工作站后,在发出其他 ADB 命令之前,了解 Android 设备是否正确连接到 ADB 服务器是很有帮助的。这可以通过 ADB devices 命令完成,该命令列出所有连接到计算机的设备,如下面的命令行所示。如果模拟器在发出命令时正在运行,则还会列出模拟器:
adb devices
List of devices attached
52037762b835835b device
请记住,如果未安装必要的驱动程序,则上述命令将显示空白消息。如果遇到这种情况,请从制造商处下载必要的驱动程序并安装它们。
如前面的命令行所示,输出包含设备的序列号,后跟连接状态。序列号是 ADB 用于识别每台 Android 设备的唯一字符串。可能的连接状态值及其含义在以下行中解释:
-
离线: 实例未连接到 ADB 或未响应。
-
设备: 实例已连接到 ADB 服务器。
-
无设备: 没有连接的设备。
-
未授权: USB 调试未授权。
将命令定向到特定设备
如果系统连接了多个设备,则在发出命令时必须指定目标设备。例如,考虑以下情况:
adb devices
List of devices attached
4df16ac5115e4e04 device
7f1c864544456o6e device
如前面的命令行输出所示,工作站上连接了两台设备。在这种情况下,adb
需要与 –s
选项一起使用,以向你选择的设备发出命令:
adb shell -s 4df16ac5115e4e04
类似地,d
开关可用于将 adb
命令定向到唯一连接的 USB 设备,e
开关可用于将 adb
命令定向到唯一运行的模拟器实例。
发出 shell 命令
如第一章中所述,Android 取证简介,Android 运行在 Linux 内核上,因此提供了访问 shell 的方式。使用 adb
,你可以访问一个 shell 来在 Android 设备上运行多个命令。对于不熟悉 Linux 环境的人来说,Linux shell 是一个特殊程序,允许你通过键盘输入特定命令与其交互;shell 会执行这些命令并显示其输出。有关 Linux 环境下的工作原理的更多细节,请参见本章中的 Rooting Android device 部分。
adb shell
命令可用于进入远程 shell,如以下命令行输出所示。进入 shell 后,你可以执行大多数 Linux 命令:
adb shell
shell@android:/ $
执行命令后,用户会看到 shell 提示符,可以在设备上执行命令。例如,如以下命令行所示,ls
命令可用于查看目录中的所有文件:
shell@android:/ $ ls
acct
adb_keys
bin
bugreports
cache
charger
config
d
data
default.prop
dev
etc
...
以下部分将解释一些在与 Android 设备交互时非常有用的 Linux 命令。
基本 Linux 命令
接下来我们将查看一些与 Android 设备相关的 Linux 命令及其用法:
ls
:ls
命令(无选项)列出当前目录中存在的文件和目录。使用l
开关时,此命令显示文件和目录的大小、修改日期和时间、文件所有者及其权限等,如以下命令行输出所示:
shell@android:/ $ ls -l
dr-xr-xr-x 64 root root 0 2018-09-16 13:21 acct
-rw-r--r-- 1 root root 724 2018-07-31 17:54 adb_keys
lrw-r--r-- 1 root root 11 2018-07-31 18:13 bin -> /system/bin
lrw-r--r-- 1 root root 50 2018-07-31 18:13 bugreports -> /data/user_de/0/com.android.shell/files/bugreports
drwxrwx--- 2 system cache 4096 2018-07-31 17:54 cache
lrw-r--r-- 1 root root 13 2018-07-31 18:13 charger -> /sbin/charger
drwxr-xr-x 4 root root 0 2018-09-16 13:21 config
lrw-r--r-- 1 root root 17 2018-07-31 18:13 d -> /sys/kernel/debug
drwxrwx--x 39 system system 4096 2018-09-16 13:21 data
lrw------- 1 root root 23 2018-07-31 18:13 default.prop -> system/etc/prop.default
drwxr-xr-x 15 root root 2580 2018-09-16 13:21 dev
lrw-r--r-- 1 root root 11 2018-07-31 18:13 etc -> /system/etc
...
类似地,以下是一些可以与 ls
命令一起使用的选项:
选项 | 描述 |
---|---|
a |
列出隐藏文件 |
c |
按时间戳显示文件 |
d |
仅显示目录 |
n |
显示长格式列表,包含 GID 和 UID 数字 |
R |
还显示子目录 |
t |
按时间戳显示文件 |
u |
显示文件访问时间 |
根据需求,调查人员可以使用一个或多个这些选项来查看详细信息。
cat
:cat
命令读取一个或多个文件,并将其输出到标准输出,如以下命令行所示:
shell@android:/ $ cat adb_keys
QAAAADeVcId5z+6WTzB5Qtyj4RMBmP3IsbHsiLC2Q8EpmIRDAHywZ45jjUENg+2NF4TUnXlBAU0LyycR/ER7/EZBUjTaLE09gWJuMbZQ4RcwFjM9nnhHquctYFNB4MzobWNDeZxdYXaDEqzycEij50ae3zZ3H5F7eVSoCvwaulOWf3oxwxaeWQsDBNt0EX0yqznfxO2GIPQhwzOdtYQsAxJye16OaazCHCsXLwMNcuZLDYpH37em71S/mUfz8hwDrDlnN0CqnpQcvXW6Q0dE1RdkJZP+FCmbYCMautkEJR5vx70Xrfv1PE+2rXzXw582h8i8Ctq8V567l7DDRLaoyO4FtST4Lw/toV3KgTcVmHo7FHhhuml5ZNUwAMtBxkw8sDOTaoU9o5LjcPZdxK+0Iik/XFFZz2IxlNxQsmn9zErA7mJghkEjuZ2L4ZxPPB38HuCiCBXjTNecX2S4QPeOTVSq+VTHi9tHwN+9fKcYIwhczMg7JSNIxHDVOlLudjwzISSmWfp2/0i9J8nUHHH8jmXOe+bHv6QvFvzUl/8wtyV+prS5EcJ6sAqoCqu1Xr+9FdKqmjyNyYK3K6fZTkAetjLFuTJat/lkqUfiIL1B3chQyRP09mEk8EklWpugo0chec17ZL3Vv0CPPJIy/2rTITZDj7MKwdZi7kEAo6Rgcg/ypAESuHlMWQEAAQA= android-eng@google
-
>
操作符可用于将多个文件合并为一个文件。>>
操作符可用于向现有文件追加内容。 -
cd
:cd
命令用于从一个目录切换到另一个目录。在从一个文件夹导航到另一个文件夹时,这个命令非常常用。以下示例展示了用于切换到系统文件夹的命令:
shell@android:/ $ cd /data
shell@android:/data $
cp
:cp
命令可用于将文件从一个位置复制到另一个位置。此命令的语法如下:
$ cp [options] <source> <destination>
以下是此命令的主要选项:
选项 | 描述 |
---|---|
s |
创建一个symlink 函数,而不是复制 |
l |
创建一个硬链接,而不是复制 |
R |
递归复制子目录中的文件 |
p |
保留时间戳、所有权和模式 |
chmod
:chmod
命令用于更改文件系统对象(文件和目录)的访问权限。它还可以更改特殊的模式标志。此命令的语法如下:
$ chmod [option] mode files
例如,chmod 777
给文件赋予所有人读、写和执行的权限。
dd
:dd
命令用于复制文件,并根据操作数进行转换和格式化。在 Android 中,dd
命令可以用于创建 Android 设备的逐位映像。有关映像的更多详细信息,请参阅第四章,从 Android 设备逻辑提取数据。以下是与此命令一起使用的语法:
$ dd if=/test/file of=/sdcard/sample.image
rm
:rm
命令可用于删除文件或目录。以下是此命令的语法:
$ rm file_name
grep
:grep
命令用于在文件或输出中搜索特定模式。以下示例展示了如何在default.prop
文件中搜索secure
:
shell@android:/ # cat default.prop | grep secure
ro.secure=1
pwd
:pwd
命令显示当前的工作目录。例如,以下命令行输出显示当前的工作目录是/data
:
shell@android:/data $ pwd
/data
mkdir
:mkdir
命令用于创建一个新目录。以下是此命令的语法:
$ mkdir [options] directory
使用p
开关,您还可以在需要时创建父目录。
exit
:exit
命令用于退出当前的 shell。只需在 shell 中输入exit
即可退出。
安装应用程序
在取证分析过程中,可能会有需要在设备上安装一些应用程序以提取数据的情况。为此,可以使用adb install
命令。与此命令一起,如以下命令行输出所示,需要指定要安装的.apk
文件的路径:
adb install C:\test.apk
Success
然而,重要的是要注意,安装第三方应用程序在法律上可能不被接受。因此,取证调查员在安装任何第三方应用程序之前需要谨慎。
从设备提取数据
您可以使用adb pull
命令将 Android 设备上的文件拉取到本地工作站。以下是使用此命令的语法:
adb pull <remote> <local>
<remote>
指的是文件在 Android 设备上的路径,而 <local>
指的是本地工作站上需要存储该文件的位置。例如,以下命令行输出显示了一个 Sample.png
文件从 Android 设备被拉取到计算机上的 temp
文件夹:
adb.exe pull /sdcard/Pictures/MyFolder/Sample.png C:\temp
[100%] /sdcard/Pictures/MyFolder/Sample.png
然而,在普通的安卓手机上,由于操作系统强制实施的固有安全特性,您无法使用 adb pull
命令下载所有文件。例如,在未获得 root 权限的 Android 设备上,无法以这种方式访问 /data/data
文件夹中的文件。关于这个话题的更多细节已经在 第四章 从 Android 设备逻辑提取数据 中进行了解释。
将数据推送到设备
您可以使用 adb push
命令将文件从本地工作站复制到 Android 设备。以下是使用此命令的语法:
adb push <local> <remote>
<local>
指的是文件在本地工作站上的位置,而 <remote>
指的是 Android 设备上需要存储该文件的路径。例如,以下命令行输出显示了 filetest.pngcopied
从计算机复制到 Android 设备的 Pictures
文件夹:
adb push C:\temp\test.png /sdcard/Pictures
[100%] /sdcard/Pictures/test.png
您只能将文件推送到用户帐户具有权限的那些文件夹。
重新启动 ADB 服务器
在某些情况下,您可能需要终止 ADB 服务器进程并重新启动它。例如,如果 adb
对某个命令没有响应,您可以终止服务器并重新启动它,这可能解决问题。
要停止 ADB 服务器,请使用 kill-server
命令。然后,您可以通过执行其他任何 adb
命令来重新启动服务器。
恢复模式与 fastboot
在处理 root 过程之前,有必要先了解 Android 中的引导加载程序、恢复和 fastboot 模式。以下各节将详细解释这些内容。
恢复模式
一部安卓手机可以看作是一个包含三个主要分区的设备:引导加载程序、Android ROM 和恢复分区。引导加载程序位于第一个分区,并且是手机开机时运行的第一个程序。这个引导加载程序的主要工作是处理低级硬件初始化,并启动其他分区。默认情况下,它通常会加载被称为Android ROM的 Android 分区。Android ROM 包含所有必要的操作系统文件,以使设备能够运行。恢复分区,通常称为原厂恢复,是用于删除所有用户数据和文件,或者执行系统更新的分区。
这两个操作都可以从正在运行的 Android 系统启动,或者通过手动启动进入恢复模式。例如,当你在手机上执行恢复出厂设置时,恢复模式会启动并擦除文件和数据。同样,进行更新时,手机会启动进入恢复模式,以安装直接写入 Android ROM 分区的最新更新。因此,恢复模式是你在设备上安装任何官方更新时看到的屏幕。
进入恢复模式
恢复映像存储在恢复分区,并由硬件按钮控制的简单用户界面组成的 Linux 映像。可以通过两种方式访问恢复模式:
-
在启动设备时按特定的按键组合(通常是启动时按住音量+、音量-和电源按钮)
-
通过向已启动的 Android 系统发出
adb reboot recovery
命令
以下是 Android 设备上官方恢复模式的截图:
Android 官方恢复
Android 的官方恢复模式故意在功能上非常有限。它提供了重新启动系统、通过 ADB 和 SD 卡应用更新、恢复出厂设置等选项。然而,定制恢复提供了更多选项。
定制恢复
定制恢复是由第三方创建的恢复环境。它可以用来替换目标设备上的默认官方恢复环境,提供一个定制的恢复环境。以下是定制恢复中常见的功能列表:
-
它提供完整的备份和恢复功能(如 NANDroid)。
-
它允许未签名的更新包,或者允许使用自定义密钥的签名包。
-
它会选择性地挂载设备分区和 SD 卡。
-
它提供对 SD 卡或数据分区的 USB 大容量存储访问。
-
它提供完整的 ADB 访问权限,且 ADB 守护进程以 root 身份运行。
-
它包含一个功能齐全的 BusyBox 二进制文件。BusyBox 是一个将多个强大的命令行工具集合在一个单一二进制可执行文件中的工具。
市面上有多种定制恢复映像可供选择,如 ClockworkMod 恢复、TeamWin 恢复项目等。以下截图显示了TeamWin 恢复项目 (TWRP) 3.0.0.0的可用选项:
TWRP 恢复
查看日志数据
在 Android 中,logcat
命令提供了一种查看系统调试输出的方法。来自各个应用程序和系统部分的日志被收集在一系列循环缓冲区中,然后可以使用此命令查看和过滤:
adb.exe logcat
--------- beginning of system
09-17 10:04:52.463 2477 2477 I vold : Vold 3.0 (the awakening) firing up
09-17 10:04:52.463 2477 2477 V vold : Detected support for: exfat ext4 f2fs ntfs vfat
09-17 10:04:52.475 2477 2482 D vold : e4crypt_init_user0
09-17 10:04:52.475 2477 2482 D vold : e4crypt_prepare_user_storage for volume null, user 0, serial 0, flags 1
09-17 10:04:52.475 2477 2482 D vold : Preparing: /data/system/users/0
09-17 10:04:52.476 2477 2482 D vold : Preparing: /data/misc/profiles/cur/0
09-17 10:04:52.476 2477 2482 D vold : Preparing: /data/system_de/0
09-17 10:04:52.477 2477 2482 D vold : Preparing: /data/misc_de/0
09-17 10:04:52.477 2477 2482 D vold : Preparing: /data/user_de/0
09-17 10:04:52.477 2477 2482 D vold : e4crypt_unlock_user_key 0 serial=0 token_present=0
09-17 10:04:52.712 2477 2480 D vold : Disk at 7:64 changed
09-17 10:04:52.933 2590 2590 I android.hardware.wifi@1.0-service: Wifi Hal is booting up...
09-17 10:04:53.023 2619 2619 I installd: installd firing up
09-17 10:04:53.166 2627 2627 I wificond: wificond is starting up...
09-17 10:04:53.285 2626 2666 I /system/bin/storaged: storaged: Start
09-17 10:04:55.120 2760 2760 I SystemServer: InitBeforeStartServices
09-17 10:04:55.122 2760 2760 I SystemServer: Entered the Android system server!
09-17 10:04:55.358 2760 2760 I SystemServer: StartServices
09-17 10:04:55.358 2760 2760 I SystemServer: Reading configuration...
09-17 10:04:55.358 2760 2760 I SystemServer: ReadingSystemConfig
09-17 10:04:55.359 2760 2760 I SystemServer: StartInstaller
09-17 10:04:55.360 2760 2760 I SystemServiceManager: Starting com.android.server.pm.Installer
09-17 10:04:55.362 2760 2760 I SystemServer: DeviceIdentifiersPolicyService
09-17 10:04:55.362 2760 2760 I SystemServiceManager: Starting com.android.server.os.DeviceIdentifiersPolicyService
09-17 10:04:55.363 2760 2760 I SystemServer: StartActivityManager
09-17 10:04:55.363 2760 2760 I SystemServiceManager: Starting com.android.server.am.ActivityManagerService$Lifecycle
09-17 10:04:55.382 2760 2760 I ActivityManager: Memory class: 192
09-17 10:04:55.406 2760 2760 D BatteryStatsImpl: Reading daily items from /data/system/batterystats-daily.xml
09-17 10:04:55.421 2760 2777 E BatteryExternalStatsWorker: no controller energy info supplied for telephony
...
这里显示的日志信息只是示例消息,在调查过程中,日志需要仔细分析,以收集位置信息、日期/时间信息、应用程序详细信息等。每条日志以消息类型指示符开头,如下表所示:
消息类型 | 描述 |
---|---|
V | 详细信息 |
D | 调试 |
I | 信息 |
W | 警告 |
E | 错误 |
F | 致命 |
S | 静默 |
获取 Android Root 权限
获取 Root 权限是一个与 Android 设备相关的常见术语。作为一名取证专家,了解这一点至关重要。这将帮助你获得必要的知识,以理解设备的内部结构,并在调查过程中获得处理若干问题的专业知识。获取 Android 手机的 Root 权限已成为一种常见现象,取证过程中常常会遇到已 Root 的手机。此外,根据不同的情况和需要提取的数据,取证专家本身也可能需要对设备进行 Root 以提取某些数据。接下来的部分将详细介绍获取 Android 设备 Root 权限以及其他相关概念。
什么是获取 Root 权限?
要理解获取 Root 权限,首先必须了解类 Unix 系统的工作原理。原始的 Unix 操作系统是 Linux 和其他类 Unix 系统的基础,它从一开始就被设计为多用户系统。之所以这样设计,主要是因为个人电脑当时尚未普及,因此需要一种机制来隔离并保护各个用户的资源,同时允许他们同时使用系统。但为了执行一些特权任务,比如授予和撤销普通用户的权限,或者访问关键的系统文件来修复或升级系统,就需要一个具有超级用户权限的系统管理员账户。因此,我们有两种类型的账户:具有较少权限的普通用户账户和具有所有权限的超级用户或root 账户。
因此,root 是指默认情况下具有对 Linux 或其他类 Unix 操作系统中所有命令和文件的访问权限的用户名或账户。它也被称为 root 账户、root 用户和超级用户。所以,在 Linux 中,root 用户有权限启动/停止任何系统服务、编辑/删除任何文件、更改其他用户的权限等。我们之前了解到 Android 使用的是 Linux 内核,因此 Linux 中的大多数概念也适用于 Android。然而,当你购买一部 Android 手机时,通常并不允许你以 root 用户身份登录。获取 Android 手机的 Root 权限就是通过获得该设备的 root 权限,执行通常不允许在设备上进行的操作。
还需要理解 rooting 和 jailbreaking 之间的区别,因为两者常常被误认为是相同的。对运行 Apple iOS 操作系统的设备进行越狱,可以移除 Apple 设置的一些限制和限制。例如,Apple 不允许在设备上安装未签名的应用程序。因此,通过越狱,你可以安装未经 Apple 批准的应用程序。相反,Android 在功能上允许侧载应用程序。越狱手机涉及同时绕过多个安全限制。因此,获取设备的 root 权限只是越狱设备的一个方面。
为什么要 root?
很多人 root Android 设备的目标是克服运营商和硬件制造商对 Android 设备的限制。通过 root 一个 Android 设备,你可以修改或替换系统应用程序和设置,运行需要管理员权限的专用应用程序,或者执行普通 Android 用户无法访问的操作,例如卸载手机自带的默认应用程序(特别是那些预装的垃圾应用)。Rooting 也常用于极限定制;例如,可以下载并安装新的自定义 ROM。然而,从取证分析的角度来看,root 的主要原因是访问那些通常无法访问的系统部分。大多数公共 root 工具会导致永久性 root,所做的修改即使设备重启后也会持续存在。而在临时 root 中,一旦设备重启,所做的修改将丢失。在取证案件中,应该始终优先选择临时 root。
如第一章《介绍 Android 取证》所述,在 Linux 系统中,每个用户都会分配一个唯一的用户 ID(UID),用户之间被隔离,以防一个用户访问另一个用户的数据。类似地,在 Android 中,每个应用程序都会分配一个 UID,并作为一个独立的进程运行。应用程序 UID 通常按照安装顺序分配,从 10001 开始。这些 ID 存储在 /data/system
目录下的 packages.xml
文件中。除了存储 UID 之外,该文件还存储了每个程序在其清单文件中描述的 Android 权限。每个应用程序的私有数据存储在 /data/data
位置,仅该应用程序可以访问。因此,在调查过程中,无法访问该位置下的数据。但通过获取 root 权限,可以访问任何位置的数据。需要注意的是,获取 root 权限会带来一些影响,具体如下:
-
安全风险:root 手机可能会使设备暴露于安全风险之中。例如,想象一下一个恶意应用,它可以访问整个操作系统以及设备上所有其他应用程序的数据。
-
变砖您的设备:如果 Root 操作不正确,可能会导致设备变砖。变砖是一个通常用于那些无法开机的手机的术语。
-
取消保修:根据制造商和运营商的不同,对设备进行 Root 可能会取消您的保修,因为它会使设备面临多种威胁。
-
取证影响:对 Android 设备进行 Root 可以让调查人员访问更多数据,但这涉及到对设备某些部分的更改。因此,只有在绝对必要时才应对设备进行 Root。
Fastboot 模式
Fastboot 是一种协议,可用于在设备上重新刷写分区。它是 Android SDK 随附的工具之一,是用于安装、更新和在某些情况下解锁启动加载器的替代方法。在 fastboot 模式下,您可以通过 USB 连接从计算机修改文件系统映像。因此,在某些情况下,这是安装恢复映像和仅仅启动的一种方式。一旦手机进入 fastboot 模式,您就可以向内部存储器刷写镜像文件。例如,可以以这种方式刷入之前讨论过的自定义恢复映像,如 TWRP 恢复。
您只需输入几个命令。首先,将设备重启至引导加载器/快速启动模式:
adb reboot bootloader
然后,使用以下命令刷入 TWRP:
fastboot flash recovery twrp.img
现在您可以使用以下命令重启设备:
fastboot reboot
在刷入 TWRP 之前,请确保您已阅读 XDA Developers 论坛关于目标设备的主题(forum.xda-developers.com/
)。
锁定和解锁的启动加载器
启动加载程序可以被锁定或解锁。锁定的启动加载程序不允许您通过在启动加载器级别实施限制(通常通过加密签名验证)对设备的固件进行修改。因此,无法向设备刷入未签名代码。换句话说,要运行任何恢复映像或自己的操作系统,首先需要解锁启动加载器。解锁启动加载器可能会导致严重的安全问题。如果设备丢失或被盗,攻击者可以通过上传自定义 Android 引导映像或刷入自定义恢复映像来恢复其中的所有数据。这样做后,攻击者就可以完全访问设备上包含的数据。因此,在解锁锁定的启动加载器时会在手机上执行出厂数据重置,以便擦除所有数据。因此,仅在绝对必要时执行此操作非常重要。某些设备有正式解锁它们的方法。对于这些设备,可以将设备置于 fastboot 模式并运行 fastboot oem unlock
命令来解锁启动加载器。这将解锁启动加载器并完全擦除 Android 设备。
其他一些制造商通过不同的方式提供解锁功能,例如通过其官网。以下截图显示了小米官网提供的解锁支持:
小米官网提供解锁引导加载程序的支持
如何获取 root 权限
本部分内容基于底层引导加载程序是锁定还是解锁。对于解锁的引导加载程序设备,获取 root 权限非常容易,而对于锁定的引导加载程序设备,获取 root 权限则相对复杂。接下来的部分将详细解释这一点。
获取 root 权限(针对解锁的引导加载程序)
在类 Unix 系统中,超级用户是一个用于系统管理的特殊用户帐户,具有访问和修改操作系统中所有文件的权限。root 权限的过程主要涉及将su
(超级用户)二进制文件复制到当前进程路径中的某个位置(/system/xbin/su
),并使用chmod
命令授予其可执行权限。因此,第一步是解锁引导加载程序。如引导加载程序的锁定与解锁部分所解释,根据设备的不同,解锁引导加载程序可以通过 fastboot 模式或按照厂商特定的引导加载程序解锁流程完成。
su
二进制文件通常会伴随一个 Android 应用程序,如 SuperUser,该应用程序在每次应用程序请求 root 权限时提供图形提示,如下图所示:
超级用户请求
一旦引导加载程序解锁,你就可以对设备进行所有想要的修改。因此,复制su
二进制文件并授予其可执行权限的方法有很多。最常见的方法是启动自定义恢复镜像,这样可以将su
二进制文件复制到系统分区,并通过自定义更新包设置相应的权限。
这里是如何获取三星 Galaxy S7(国际版 SM-G930F/FD/X、韩国版 SM-G930K/L/S 和加拿大版 SM-G930W8 Exynos 模型)root 权限的方法:
-
确保在开发者选项中启用OEM 解锁。
-
下载 ODIN(可以从此处获取:
build.nethunter.com/samsung-tools/Odin_3.12.3.zip
),并将压缩包中的内容解压到你选择的目录中。 -
下载 TWRP 镜像(可以从此处获取:
teamw.in/devices/samsunggalaxys7.html
)。 -
重启设备进入下载模式。方法是,在设备重启时按住[音量下] + [Home]按钮。当你看到下载模式警告屏幕时,按[音量上]继续。
-
启动 Odin 并将 TWRP 镜像放入[AP]插槽;不要忘记禁用自动重启。开始刷入恢复。
-
要退出下载模式,按住[音量下] + [Home] + [电源];当屏幕熄灭时,立即将[音量下]更改为[音量上]。
-
通过向右滑动来允许系统修改。
-
下载SuperSU(可在此处下载:
download.chainfire.eu/supersu
)。 -
通过 MTP 将 SuperSU 存档传输到设备,并通过相应的 TWRP 选项进行安装。
自 Android 4.1 版本起,引入了一项名为 sideload 模式的新功能。此功能允许通过 ADB 应用更新 ZIP,而无需事先将其复制到设备。要 sideload 更新,运行 adb sideload su-package.zip
命令,其中 su-package.zip
是你电脑上更新包的文件名。
或者,你也可以修改工厂镜像以添加 su
二进制文件。这可以通过解压缩一个 ext4 格式的系统镜像,添加 su
二进制文件并重新打包来完成。如果刷入该镜像,它将包含 su
二进制文件,并且设备将被 Root。
Root 是一个高度设备特定的过程,因此法医调查员在对任何 Android 设备应用这些技术之前需要谨慎。
解锁启动引导器进行 Root
当启动引导器被锁定并且无法通过任何可用方式解锁时,Root 设备需要找到可以利用的安全漏洞。但在此之前,首先要识别启动引导器锁的类型。它可能因制造商和软件版本而异。有些手机可能不允许通过 fastboot 访问,但你仍然可以使用制造商专有的闪存协议进行刷机,例如三星的 ODIN。一些设备只对特定分区(如 boot 和 recovery)强制执行签名验证。因此,可能无法进入自定义恢复模式。然而,你仍然可以修改出厂镜像以包括 su
二进制文件,如前一部分所述。
如果启动引导器无法通过任何方式解锁,那么唯一的选择是找到设备上的某个漏洞,利用该漏洞并添加su
二进制文件。漏洞可能存在于 Android 内核中,或者在以 root 身份运行的进程中,或其他任何问题。这是设备特定的,必须在尝试之前进行广泛的研究。
以下是最受欢迎的 Android 根权限应用:
-
Kingo (
www.kingoapp.com/
) -
Root Genius (
www.shuame.com/en/root/
) -
iRoot (
www.iroot.com/
)
在 Root 设备上的 ADB
我们已经看到如何使用 ADB 工具与设备交互并在设备上执行某些命令。然而,在正常的 Android 手机上,某些位置,例如/data/data
,是无法访问的。例如,以下是尝试访问正常设备上的/data/data
时的命令行输出:
adb shell
shell@android:/ $ cd /data/data
cd /data/data
shell@android:/data/data $ ls
ls: .: Permission denied
这是因为所有应用程序的私人数据都存储在此文件夹中,Android 会对其进行安全性保护。只有 root 用户才能访问此位置。因此,在 root 设备上,你将能够看到此位置下的所有数据,正如以下命令行所示:
adb shell
shell@android:/ $ su
shell@android:/ # ls /data/data
android
com.android.backupconfirm
com.android.bips
com.android.bluetooth
com.android.bluetoothmidiservice
com.android.calllogbackup
com.android.camera2
com.android.captiveportallogin
com.android.carrierconfig
com.android.carrierdefaultapp
com.android.cellbroadcastreceiver
com.android.certinstaller
com.android.companiondevicemanager
com.android.contacts
com.android.cts.ctsshim
com.android.cts.priv.ctsshim
com.android.defcontainer
com.android.development
com.android.dialer
com.android.documentsui
com.android.dreams.basic
com.android.dreams.phototable
com.android.egg
com.android.email
com.android.emergency
com.android.externalstorage
com.android.facelock
com.android.gallery3d
...
如前面的代码所示,现在可以轻松地通过导航到相应的文件夹来查看所有应用程序的私人数据。因此,在 root 设备上,ADB 工具非常强大,允许检查员访问设备上所有已安装应用程序的数据,前提是设备没有设置图案锁或 PIN 码保护,或没有通过 RSA 密钥注册到计算机。
有时候,即使在已获得 root 权限的手机上,你也会看到权限被拒绝的提示。在这种情况下,执行adb shell
命令后,可以尝试通过输入su
进入 SuperUser 模式。如果 root 权限已经启用,你将看到#
,且不需要输入密码。
总结
在对 Android 设备进行调查之前,搭建一个合适的取证环境至关重要。安装 Android SDK 是必要的,因为其中包含了 ADB 等工具。通过 ADB,检查员可以与设备进行通信,查看设备上的文件夹,提取数据,并将数据复制到设备上。然而,并非所有文件夹都能在普通手机上通过这种方式访问,因为设备的安全措施会阻止检查员查看包含私人数据的位置。因此,root 设备可以解决这个问题,因为它提供了对设备上所有数据的无限访问权限。解锁引导加载程序的设备 root 过程相对简单,而锁定引导加载程序的设备 root 则涉及到利用一些安全漏洞。
在掌握了如何访问设备的知识后,我们将继续讨论第三章,理解 Android 设备上的数据存储中有关数据如何组织以及其他许多细节。
第三章:理解安卓设备的数据存储
法医分析的主要目的是从设备中提取必要的数据。因此,为了有效的法医分析,必须知道设备上存储了什么类型的数据,数据存储的位置,存储的方式,以及数据存储的文件系统的详细信息。对于法医分析员来说,这些知识非常重要,可以帮助他们做出明智的决定,了解在哪些位置寻找数据,并且可以使用哪些技术来提取数据。本章我们将学习以下内容:
-
安卓分区布局
-
安卓文件层次结构
-
设备上的应用数据存储
-
安卓文件系统概述
安卓分区布局
分区是设备持久存储内存中创建的逻辑存储单元。分区允许你将可用空间逻辑地划分为多个可以独立访问的部分。
安卓中常见的分区
分区布局在不同厂商和版本之间有所不同,但所有安卓设备都存在一些共同的分区。以下是大多数安卓设备中常见的一些分区:
-
BOOT
:顾名思义,此分区包含了手机启动所需的信息和文件。它包含内核和 RAMDisk,因此没有这个分区,手机无法启动其进程。 -
CACHE
:此分区用于存储经常访问的数据以及其他各种文件,如恢复日志和通过空中下载的更新包。 -
RECOVERY
:恢复分区允许设备启动到恢复控制台,通过该控制台可以执行如手机更新及其他维护操作。为此,存储了一个最小的安卓启动镜像,作为故障安全保护。 -
SYSTEM
:此分区包含除内核和 RAMDisk 以外的所有主要组件。此处的安卓系统镜像包含安卓框架、库、系统二进制文件和预安装应用程序。如果没有这个分区,设备无法正常启动。 -
USERDATA
:此分区通常称为数据分区,是设备的内部存储,用于存储应用程序数据。大量的用户数据存储在此,并且这是我们大多数法医证据所在的位置。它存储了所有的应用数据和标准通讯记录。
识别分区布局
对于给定的安卓设备(如三星 Galaxy J7),可以通过多种方式确定分区布局。/proc
下的分区文件将提供关于设备上所有可用分区的详细信息。
以下截图显示了分区文件的内容:
安卓中的分区文件
上面的条目仅显示了分区名称。要获取这些分区与其逻辑功能的映射,请查看位于/dev/block/platform/13540000.dwmmc0
目录下的目录内容。以下截图显示了该目录的内容:
块与其逻辑功能的映射
如前面的输出所示,SYSTEM
和USERDATA
等多个分区出现在分区布局中。
安卓文件层次结构
要对任何系统(桌面或移动设备)进行取证分析,理解底层的文件层次结构非常重要。基本理解安卓如何在文件和文件夹中组织数据,有助于取证分析师将研究范围缩小到特定位置。如果你熟悉类 Unix 系统,你会非常了解安卓的文件层次结构。在 Linux 中,文件层次结构是一个单一的树形结构,树的顶端表示为/
,称为根目录。这与 Windows 中按驱动器组织文件的概念不同。
无论文件系统是本地的还是远程的,它都将位于根目录下。安卓的文件层次结构是现有 Linux 层次结构的定制版本。根据设备制造商和底层的 Linux 版本,该层次结构可能会有一些不太显著的变化。要查看完整的文件层次结构,您需要 root 权限。以下截图显示了安卓设备上的文件层次结构:
安卓根目录下的文件夹
目录概览
以下各节概述了安卓设备文件层次结构中的目录。
acct 目录
这是acct
控制组(cgroup
)的挂载点,它提供了用户计费功能。
cache 目录
这是 Android 存储经常访问的数据和应用组件的目录(/cache
)。清除缓存不会影响你的个人数据,只是删除了其中现有的数据。此文件夹中还有另一个名为lost+found
的目录,用于存储因文件系统损坏(如未卸载直接移除 SD 卡)而恢复的文件(如果有的话)。缓存中可能包含与取证相关的文件,如图像、浏览历史记录和其他应用数据。
config 目录
该目录包含 SDCardFS(内核中的 FAT32 仿真层)和 USB 小工具的配置文件。
数据目录
/data/data
分区包含所有应用程序的私有数据。大多数属于用户的数据存储在此文件夹中。该文件夹从取证角度来看具有重要意义,因为它保存了有价值的数据。此分区在内部存储部分中有详细介绍。以下截图显示了数据分区的内容:
安卓设备的数据分区内容
dev 目录
该目录包含所有设备的特殊设备文件。这是tempfs
文件系统的挂载点,该文件系统定义了应用程序可用的设备。
mnt 目录
该目录作为所有文件系统(包括内外部 SD 卡等)的挂载点。以下截图显示了该目录中存在的挂载点:
proc 目录
这是 procfs
文件系统的挂载点,它提供对内核数据结构的访问。多个程序使用 /proc
作为信息来源。它包含有关进程的有用信息。例如,以下截图所示,/proc
下的 meminfo
文件提供有关内存的信息:
Android 中 proc 文件夹下的 meminfo 文件
sbin 目录
该目录包含多个重要守护进程的二进制文件。从取证角度来看,它并不特别重要。
存储目录
在这里,你可以找到 SD 卡的内容。请注意,这张 SD 卡可以是可拆卸存储或不可拆卸存储。任何具有 WRITE_EXTERNAL_STORAGE
权限的应用程序都可能在此位置创建文件或文件夹。大多数手机中都存在一些默认文件夹,如 Android
、DCIM
和 Downloads
。以下截图显示了 /storage/self/primary
位置的内容:
/storage/self/primary 的内容(/sdcard 是一个符号链接)
数码相机图像(DCIM)是数码相机、智能手机、平板电脑及相关固态设备的默认目录结构。一些平板电脑有一个 Photos
文件夹,指向相同的存储位置。在 DCIM 文件夹内,你会找到你拍摄的照片、视频和缩略图(缓存文件)。照片存储在 /DCIM/Camera
中。
Android 开发者参考资料中解释了有一些公共存储目录,这些目录并不绑定到特定的程序。以下是这些文件夹的快速概览:
-
Music
:媒体扫描器将此位置下的所有媒体分类为用户音乐 -
Podcasts
:媒体扫描器将此位置下的所有媒体分类为播客 -
Ringtones
:此处的媒体文件被归类为铃声 -
Alarms
:此处的媒体文件被分类为闹钟 -
Notifications
:该位置下的媒体文件用于通知声音 -
Pictures
:所有照片,除了用相机拍摄的,都会存储在此文件夹中 -
Movies
:所有电影,除了用相机拍摄的,都会存储在此文件夹中 -
Download
:杂项下载
系统目录
该目录包含库、系统二进制文件和其他与系统相关的文件。与手机一起预安装的应用程序也存储在此分区中。以下截图显示了 Android 设备上系统分区中的文件:
Android 设备系统分区的内容
设备上的应用数据存储
Android 设备通过应用存储大量敏感数据。虽然我们之前将应用分为系统应用和用户安装的应用,但这里有一个更详细的划分:
-
随 Android 附带的应用
-
制造商预装的应用
-
无线运营商预装的应用
-
用户安装的应用
所有这些都在设备上存储不同类型的数据。应用数据通常包含大量与调查相关的信息。以下是 Android 设备上可能找到的一些数据的示例:
-
短信
-
彩信
-
聊天信息
-
备份
-
电子邮件
-
通话记录
-
联系人
-
图片
-
视频
-
浏览器历史
-
GPS 数据
-
下载的文件或文档
-
属于已安装应用的数据(如 Facebook、Twitter 和其他社交媒体应用)
-
日历预约
不同应用的数据可以存储在内部或外部。在外部存储(SD 卡)的情况下,数据可以存储在任何位置。但在内部存储的情况下,位置是预定义的。具体来说,设备上所有应用的内部数据(无论是系统应用还是用户安装的应用)会自动保存在 /data/data
的一个以包名命名的子目录中。例如,默认的 Android 邮件应用的包名为com.android.email
,其内部数据存储在/data/data/com.android.email
。我们将在后续章节中详细讨论这一点,但目前这些知识足以理解以下细节。
Android 为开发者提供了一些选项来将数据存储到设备上。可以使用的选项取决于要存储的底层数据。属于应用的数据可以存储在以下位置之一:
-
共享首选项
-
内部存储
-
外部存储
-
SQLite 数据库
-
网络
以下各节提供了有关这些选项的详细说明。
共享首选项
共享首选项提供了一个框架,用于以 XML 格式存储原始数据类型的键值对。原始数据类型包括布尔值、浮动、整数、长整型和字符串。字符串以Unicode 转换格式(UTF)存储。这些文件通常存储在应用的/data/data/shared_pref
路径下。例如,Android 邮件应用的shared_pref
文件夹包含以下三个 XML 文件:
Android 邮件应用的 shared_prefs 文件夹内容
如第二章《设置 Android 法医环境》中所解释的,可以使用cat
命令查看这些文件的内容。以下截图显示了UnifiedEmail.xml
文件的内容:
Android 邮件应用的共享首选项文件内容
不同的 XML 文件可能包含不同的有用信息,例如帐户名甚至密码,这对法医检查非常有帮助。
内部存储
这里存储的文件位于内部存储中。它们通常位于应用的 /data/data
子目录中。存储在这里的数据是私有的,其他应用无法访问。即使是设备所有者也无法查看这些文件(除非他们具有 root 权限)。
然而,根据需求,开发者可以允许其他进程修改和更新这些文件。以下截图展示了应用在 /data/data
目录下以包名存储的详细信息:
Android 中的 /data/data 文件夹内容
每个应用的内部数据存储在各自的文件夹中。例如,下面的截图展示了 Android 设备上属于 YouTube 应用的内部存储:
Android YouTube 应用的内部存储
通常,databases
、lib
、shared_pref
、cache
文件夹会为大多数应用创建。以下表格简要描述了这些文件夹:
子目录 | 描述 |
---|---|
shared_prefs |
共享偏好设置的 XML 文件 |
lib |
应用所需的自定义库文件 |
files |
开发者保存的文件 |
cache |
应用缓存的文件 |
databases |
SQLite 和日志文件 |
除这些文件夹外,其他文件夹是应用开发者创建的自定义文件夹。databases
文件夹包含对司法调查至关重要的数据。如以下截图所示,这个文件夹中的数据以 SQLite 文件形式存储:
Android 浏览器应用中 databases
文件夹下的 SQLite 文件
可以使用如 DB Browser for SQLite 等工具查看这些数据。关于如何提取数据的更多细节,请参考第四章,从 Android 设备中逻辑地提取数据。
外部存储
应用也可以将文件存储在外部存储中。外部存储可以是可移动的媒体,如 SD 卡,或者是手机自带的不可移动存储。在可移动 SD 卡的情况下,只需移除 SD 卡并插入其他设备,数据就可以在其他设备上使用。SD 卡通常采用 FAT32 文件系统格式,但越来越多的使用 EXT3 和 EXT4 文件系统。与内部存储不同,外部存储没有严格的安全措施。换句话说,存储在这里的数据是公开的,其他应用可以访问,只要请求应用具有必要的权限。
SQLite 数据库
SQLite 是一种流行的数据库格式,广泛应用于许多移动系统中,用于结构化数据存储。SQLite 是开源的,并且与许多其他数据库不同,它具有紧凑性并提供丰富的功能。Android 通过专用的 API 支持 SQLite,因此开发者可以利用这一特性。SQLite 数据库是法医数据的重要来源。应用程序使用的 SQLite 文件通常存储在 /data/data/<ApplicationPackageName>/databases
路径下。例如,在 Android 邮件应用中,以下截图展示了其数据库文件夹中的 SQLite 文件。我们将在接下来的章节中进一步探讨这些细节。从法医的角度来看,这些文件非常有价值,因为它们通常存储了应用程序处理的大量重要数据。
网络
你可以使用网络存储和检索你自己基于 Web 的服务中的数据。要进行网络操作,可以使用 java.net.*
和 android.net.*
包中的类。这些包为开发者提供了与网络、Web 服务器等交互所需的低级 API。
Android 文件系统概述
在 Android 法医分析中,理解文件系统非常重要,因为它帮助我们了解数据是如何存储和检索的。关于文件系统的属性和结构的知识在法医分析中非常有用。文件系统指的是数据如何存储、组织和从存储设备中检索的方式。一个基本的安装可能基于一个卷划分成多个分区;在这种情况下,每个分区可以由不同的文件系统管理。Microsoft Windows 用户通常熟悉 FAT32 或 NTFS 文件系统,而 Linux 用户则更熟悉 EXT2 或 EXT4 文件系统。正如在 Linux 中一样,Android 使用挂载点而非驱动器(即 C:
或 E:
)。每个文件系统都定义了自己管理卷上文件的规则。根据这些规则,每个文件系统在文件检索、速度、安全性、大小等方面提供不同的表现。Linux 使用多种文件系统,Android 也如此。从法医角度来看,了解 Android 使用了哪些文件系统,并识别对调查具有重要意义的文件系统非常重要。例如,存储用户数据的文件系统对我们来说是主要关注点,而用于启动设备的文件系统则较为次要。
如前所述,Linux 以支持大量文件系统而闻名。系统使用的这些文件系统不是通过驱动器名称访问的,而是合并成一个单一的层级树结构,代表了一个整体的文件系统。每当一个新的文件系统被挂载时,它就被加入到这个单一的文件系统树中。
在 Linux 中,挂载是将一个额外的文件系统附加到当前可访问的计算机文件系统的过程。
因此,文件系统被挂载到一个目录上,位于该文件系统中的文件现在成为该目录的内容。这个目录称为挂载点。无论文件系统存在于本地设备上还是远程设备上,都没有区别。一切都整合到一个以根目录为起点的单一文件层级中。每个文件系统都有一个单独的内核模块,它将其支持的操作注册到一个叫做虚拟文件系统(VFS)的东西中。VFS 使得不同的应用程序可以以统一的方式访问不同的文件系统。通过将实现与抽象分离,添加新的文件系统变得只是编写另一个内核模块的问题。这些模块要么是内核的一部分,要么是在需要时动态加载。Android 内核提供了一个包含从日志文件系统(JFS)到 Amiga 文件系统等多种文件系统的子集。所有的后台工作都由内核处理,当文件系统被挂载时。
查看 Android 设备上的文件系统
可以通过检查proc
文件夹中存在的filesystems
文件的内容来确定 Android 内核支持的文件系统。可以使用以下命令查看该文件的内容:
j7xelte:/ # cat /proc/filesystems
nodev sysfs
nodev rootfs
nodev tmpfs
nodev bdev
nodev proc
nodev cgroup
nodev devtmpfs
nodev debugfs
nodev securityfs
nodev sockfs
nodev pipefs
nodev ramfs
nodev configfs
nodev devpts
ext3
ext2
ext4
nodev sdcardfs
cramfs
vfat
msdos
sdfat
nodev ecryptfs
fuseblk
nodev fuse
nodev fusectl
f2fs
nodev pstore
nodev selinuxfs
nodev functionfs
在前面的输出中,带有nodev
属性的文件系统未被挂载到设备上。
常见的 Android 文件系统
Android 中存在的文件系统可以分为三大类:
-
闪存文件系统
-
基于媒体的文件系统
-
假文件系统
可以通过逻辑方式恢复哪些数据?
在大多数情况下,任何和所有的用户数据都可以通过逻辑方式恢复:
-
联系人
-
通话记录
-
短信/MMS
-
应用数据
-
系统日志和信息
这些数据的绝大部分存储在 SQLite 数据库中,因此通过逻辑提取恢复大量删除的数据成为可能。
闪存文件系统
闪存是一种持续供电的非易失性存储器,它可以在称为块的内存单元中被擦除并重新编程。由于闪存的特殊性质,写入媒体并处理某些块长时间擦除的文件系统需要特殊设计。虽然不同的 Android 设备支持的文件系统各不相同,但常见的闪存文件系统如下:
-
扩展文件分配表(exFAT)是微软专有的文件系统,专为闪存驱动器优化。由于许可要求,它不包含在标准 Linux 内核中。但仍然有一些厂商提供对该文件系统的支持。
-
闪存友好文件系统(F2FS)是三星推出的一种开源文件系统。其基本目的是构建一个考虑到基于 NAND 闪存存储设备特性的文件系统。
-
日志闪存文件系统版本 2(JFFS2)是 Android 使用的一种日志结构化文件系统。自冰淇淋三明治版本以来,JFFS2 一直是Android 开源项目(ASOP)的默认闪存文件系统。像 LogFS、UBIFS、YAFFS 等文件系统已经被开发出来,作为 JFFS2 的替代方案。
-
另一个闪存文件系统版本 2(YAFFS2)是一个开源的单线程文件系统,发布于 2002 年。它主要设计用于在处理 NAND 闪存时具有较高的速度。YAFFS2 利用带外(OOB)存储,而在法医数据采集过程中,这些信息往往无法正确捕获或解码,这使得分析变得困难。YAFFS2 曾一度是最受欢迎的版本,至今在 Android 设备中仍广泛使用。YAFFS2 是一个日志结构化文件系统,即使在突然断电的情况下,数据完整性也能得到保证。2010 年,发布的公告称,在 Gingerbread 版本之后,设备将从 YAFFS2 迁移到 EXT4。目前,YAFFS2 不再在更新的内核版本中得到支持,但某些手机制造商可能仍会继续支持它。
-
强大的文件系统(RFS)支持三星设备上的 NAND 闪存。RFS 可以总结为一个启用了事务日志的 FAT16(或 FAT32)文件系统。许多用户抱怨三星应该坚持使用 EXT4。已知 RFS 存在滞后问题,减缓了 Android 的功能表现。
基于媒体的文件系统
除了前述的闪存文件系统,Android 设备通常还支持以下基于媒体的文件系统:
-
EXT2/EXT3/EXT4(扩展文件系统),是 1992 年专为 Linux 内核推出的文件系统,是最早的文件系统之一,使用了虚拟文件系统。EXT2、EXT3 和 EXT4 是后续版本。EXT3 相比 EXT2 的主要优势是引入了日志功能。使用 EXT3 时,在发生意外关机时,不需要验证文件系统。EXT4 文件系统,作为第四版扩展文件系统,在实现双核处理器的移动设备中变得尤为重要。已知 YAFFS2 文件系统在双核系统上存在瓶颈。随着 Android Gingerbread 版本的发布,YAFFS 文件系统被 EXT4 取代。
-
FAT(文件分配表)文件系统,如 FAT12、FAT16 和 FAT32,由 MSDOS 驱动程序支持。
-
VFAT(虚拟文件分配表)是 FAT16 和 FAT32 文件系统的扩展。微软的 FAT32 文件系统被大多数 Android 设备支持。它几乎可以被所有主要操作系统(包括 Windows、Linux 和 macOS)支持。这使得这些系统能够轻松读取、修改和删除 Android 设备上 FAT32 分区中的文件。大多数外部 SD 卡都是使用 FAT32 文件系统格式化的。
虚拟文件系统
除了这些文件系统外,还有伪文件系统,可以将其视为文件的逻辑分组。以下是一些在 Android 设备中常见的重要伪文件系统:
cgroup
伪文件系统提供了一种访问和定义多个内核参数的方法。存在许多不同的进程控制组。如以下命令行输出所示,可以在/proc/cgroups
文件中查看到组的列表:
Android 设备使用该文件系统来跟踪它们的工作。它们负责聚合任务并跟踪任务的状态。
-
rootfs
文件系统是 Android 的主要组成部分之一,包含启动设备所需的所有信息。当设备启动时,它需要访问许多核心文件,因此会挂载根文件系统。此文件系统挂载在/
(即root
文件夹)下。因此,这是所有其他文件系统逐步挂载的文件系统。如果该文件系统损坏,设备将无法启动。 -
Procfs
文件系统包含有关内核数据结构、进程和其他系统相关信息,这些信息存储在/proc
目录下。例如,/proc/filesystems
文件显示设备上可用文件系统的列表。以下命令显示设备 CPU 的所有信息:
sysfs
文件系统挂载了/sys
文件夹,其中包含有关设备配置的信息。以下输出显示了 Android 设备中sys
目录下的各个文件夹:
j7xelte:/sys # ls -1
bcm-dhd
block
bus
class
dev
devices
firmware
fs
kernel
mms_ts
module
power
由于这些文件夹中的数据大多与配置相关,通常对法医调查员来说并没有太大意义。但在某些情况下,我们可能需要检查手机上是否启用了某个特定设置,分析这个文件夹可能会在这种情况下有用。请注意,每个文件夹包含大量文件。通过法医获取这些数据是确保在检查过程中数据不会被更改的最佳方法。
tmpfs
是设备上的一种临时存储设施,将文件存储在 RAM(易失性内存)中。通常,它会挂载在/dev
目录下。使用 RAM 的主要优点是访问和检索速度更快。但是,一旦设备重启或关闭,这些数据将不再可访问。因此,对于法医调查员来说,在设备重启之前检查 RAM 中的数据或提取数据非常重要。
你可以使用 mount
命令查看设备上可用的不同分区及其文件系统,命令如下:
j7xelte:/ # mount
rootfs on / type rootfs (ro,seclabel,size=850052k,nr_inodes=212513)
tmpfs on /dev type tmpfs (rw,seclabel,nosuid,relatime,mode=755)
devpts on /dev/pts type devpts (rw,seclabel,relatime,mode=600)
proc on /proc type proc (rw,relatime,gid=3009,hidepid=2)
sysfs on /sys type sysfs (rw,seclabel,relatime)
selinuxfs on /sys/fs/selinux type selinuxfs (rw,relatime)
/dev/block/mmcblk0p20 on /system type ext4 (ro,seclabel,relatime,errors=panic,data=ordered)
none on /acct type cgroup (rw,relatime,cpuacct)
tmpfs on /mnt type tmpfs (rw,seclabel,relatime,mode=755,gid=1000)
none on /config type configfs (rw,relatime)
none on /dev/cpuctl type cgroup (rw,relatime,cpu)
pstore on /sys/fs/pstore type pstore (rw,seclabel,relatime)
/dev/block/mmcblk0p3 on /efs type ext4 (rw,seclabel,nosuid,nodev,noatime,discard,journal_checksum,journal_async_commit,noauto_da_alloc,data=ordered)
adb on /dev/usb-ffs/adb type functionfs (rw,relatime)
tmpfs on /storage type tmpfs (rw,seclabel,relatime,mode=755,gid=1000)
/dev/block/mmcblk0p4 on /cpefs type ext4 (rw,seclabel,nosuid,nodev,noatime,data=ordered)
/dev/block/mmcblk0p21 on /cache type ext4 (rw,seclabel,nosuid,nodev,noatime,discard,journal_checksum,journal_async_commit,noauto_da_alloc,errors=panic,data=ordered)
/dev/block/mmcblk0p24 on /data type ext4 (rw,seclabel,nosuid,nodev,noatime,discard,journal_checksum,journal_async_commit,noauto_da_alloc,errors=panic,data=ordered)
tmpfs on /sbin type tmpfs (rw,seclabel,relatime)
/dev/block/mmcblk0p20 on /sbin/.core/mirror/system type ext4 (ro,seclabel,relatime,errors=panic,data=ordered)
/dev/block/mmcblk0p24 on /sbin/.core/mirror/bin type ext4 (rw,seclabel,nosuid,nodev,noatime,discard,journal_checksum,journal_async_commit,noauto_da_alloc,errors=panic,data=ordered)
/sbin/.core/block/loop08 on /sbin/.core/img type ext4 (rw,seclabel,relatime,data=ordered)
/dev/fuse on /mnt/runtime/default/emulated type fuse (rw,nosuid,nodev,noexec,noatime,user_id=1023,group_id=1023,default_permissions,allow_other)
/dev/fuse on /storage/emulated type fuse (rw,nosuid,nodev,noexec,noatime,user_id=1023,group_id=1023,default_permissions,allow_other)
/dev/fuse on /mnt/runtime/read/emulated type fuse (rw,nosuid,nodev,noexec,noatime,user_id=1023,group_id=1023,default_permissions,allow_other)
/dev/fuse on /mnt/runtime/write/emulated type fuse (rw,nosuid,nodev,noexec,noatime,user_id=1023,group_id=1023,default_permissions,allow_other)
/dev/block/mmcblk0p24 on /sbin/.core/db-0/magisk.db type ext4 (rw,seclabel,nosuid,nodev,noatime,discard,journal_checksum,journal_async_commit,noauto_da_alloc,errors=panic,data=ordered)
如前述命令行输出所示,不同的分区有不同的文件系统,它们会根据需要进行挂载。
总结
熟悉 Android 的分区布局、文件系统和重要位置,将有助于取证调查员在从设备中提取数据的过程中进行工作。Android 设备上的 userdata 位置包含大量用户信息,这些信息对任何取证调查都可能至关重要。然而,这些文件大多数只能在已 root 的手机上访问(尤其是/data/data
目录下的文件)。我们还讨论了 Android 数据存储选项、Android 使用的各种文件系统及其重要性。
有了这些知识,我们将在接下来的章节中学习如何从 Android 设备中逻辑和物理地提取数据。
第四章:从安卓设备中逻辑提取数据
本章将涵盖逻辑数据提取,尽可能使用免费和开源工具。本章中大多数内容将使用之前在第二章中讨论过的Android 调试桥(ADB)方法,设置安卓取证环境。
到本章结束时,读者应熟悉以下内容:
-
逻辑提取概述
-
手动 ADB 数据提取
-
ADB 备份提取
-
ADB dumpsys
-
绕过安卓锁屏
-
安卓 SIM 卡提取
逻辑提取概述
在数字取证中,逻辑提取一词通常用于指不恢复删除数据或不包括证据的完整逐位复制的提取方法。然而,逻辑提取的更准确定义,也在第一章中定义,介绍安卓取证,是任何需要与基本操作系统进行通信的方法。由于与操作系统的交互,取证员不能确定是否已恢复所有可能的数据;操作系统在决定允许取证员访问哪些数据。因此,在传统的计算机取证中,逻辑提取类似于复制和粘贴一个文件夹来提取系统中的数据;此过程仅会复制用户可以访问和看到的文件。如果在被复制的文件夹中有任何隐藏或已删除的文件,它们将不会出现在粘贴的文件夹中。
然而,正如你将看到的,在移动设备取证中,逻辑提取和物理提取之间的界限,比传统计算机取证中更为模糊。例如,由于 SQLite 数据库广泛用于存储数据,删除的数据通常可以从移动设备的逻辑提取中恢复。此外,几乎所有的移动提取都需要与安卓操作系统进行某种形式的交互;没有类似于拔出硬盘并对其进行镜像而不启动硬盘的简单等效物。就我们而言,我们将逻辑提取定义为获取用户可见数据的过程,并可能包括已标记为删除的数据。
Root 访问权限
在进行安卓设备的取证分析时,限制因素通常不是所寻求的数据类型,而是检查员是否能够访问数据。Root 访问权限在第二章中已做过详细讨论,设置安卓取证环境,但这一点足够重要,值得重复。之前列出的所有数据,当存储在内部闪存中时,都受到保护,并且需要 Root 权限才能读取。唯一的例外是存储在 SD 卡上的应用数据,本书后续将进行讨论。
没有 root 访问权限,取证检查员无法简单地从 /data
分区复制信息。检查员将不得不找到某种方法来提升权限以访问联系人、通话记录、短信/MMS 和应用程序数据。这些方法通常伴随着许多风险,如可能销毁或砖化设备(使其无法启动),并可能修改设备上的数据以获得永久性。
方法通常因设备而异,没有通用的一键方法可以获取每台设备的 root 访问权限。商业移动取证工具如 Oxygen Forensic Detective 和 Cellebrite UFED 具有内置功能,可以临时和安全地 root 许多设备,但不涵盖所有 Android 设备的广泛范围。
在本章中,我们将注意到每个技术演示所需的 root 权限位置。
决定对设备进行 root 是根据您当地的操作程序和法院意见。通过 root 获取的证据的法律接受度因司法管辖区而异。
手动 ADB 数据提取
adb pull
命令可用于直接从设备将单个文件或整个目录拉到取证检查员的计算机。这种方法在涉及短信消息的严格调查中尤其有用,检查员可以选择仅拉取相关文件,如果可能的话。
USB 调试
在本书中先前已讨论了设置 ADB 环境。但是,检查的设备也必须正确配置。USB 调试是取证员计算机与设备通信的实际方法。USB 调试位于设置菜单中的开发者选项下。然而,截至Android 8.1,开发者选项菜单是隐藏的;要显示它,用户必须转到设置 | 系统 | 关于手机,然后点击构建号字段七次。返回到上一个屏幕—现在可以找到开发者选项了;简单地打开这个菜单并选择启用 USB 调试。
除了 USB 调试外,检查员计算机上必须安装正确的驱动程序。通常可以在线找到它们,要么是从制造商的网站,要么是从www.xda-developers.com。如果在机器上安装了商业取证工具,则可能已经安装了适当的驱动程序。
在 Android 4.2.2 之前,启用 USB 调试是与设备通过 ADB 通信的唯一要求。在 Android 4.2.2 中,Google 添加了安全 USB 调试。安全 USB 调试增加了在设备屏幕上选择连接到计算机的额外要求;这可以防止来自不受信任计算机的 ADB 访问已锁定设备:
RSA 指纹对话框(Android 8.1)
一旦启用了 USB 调试并且通过了 安全 USB 调试 检查(根据 Android 版本的不同),设备就可以开始检查了。为了验证设备是否已连接并准备好使用 ADB,可以执行以下命令:
adb devices
如果选择了“始终允许此计算机连接”,设备将存储计算机的 RSA 密钥,并且未来连接该计算机时,即使设备处于锁定状态,也不会再次出现提示。
如果设备状态显示为 离线 或 未授权,需要在屏幕上选择安全调试提示:
如果一切正常,设备 状态应该显示如下界面:
恢复模式
为了确保法医取证的有效性,ADB 数据提取不应在手机开启时进行。设备在运行时,时间戳可能会被修改,应用程序也可能在后台运行并更新文件。为了避免这种情况,审查员应尽可能将设备置于自定义恢复模式,如第二章《设置 Android 法医环境》中所示。标准 Android 恢复模式下无法进行 ADB 访问。通常,刷入自定义恢复模式是获取设备 ROOT 权限过程中的第一步,以便在出现问题时能够修复设备。ROOT 设备更可能包含自定义恢复模式,但也可以将自定义恢复模式刷入非 ROOT 设备。这种方法还可以让审查员避开新版 Android 中的安全 USB 调试提示,尽管我们的测试表明,这在 Android Lollipop 及更高版本中不起作用。恢复模式通常不需要启用 USB 调试,这使得它成为绕过锁定设备的理想选择。
该方法无法在启用了完整磁盘加密的设备上使用。启动恢复模式时不会解密 /data
分区。
启动恢复模式的过程因设备而异。通常,需要关机并同时按住音量键和电源键。针对特定型号的指南可以轻松在线查找。
标准恢复模式通常会显示一个正在操作的 Android 图标:
标准恢复模式
需要注意的是,恢复模式下将无法进行 ADB 通信;运行 adb devices
会显示没有设备。
许多设备的自定义恢复镜像可以在以下位置找到:
如果设备处于自定义恢复模式,并且在审查员的计算机上已安装正确的驱动程序,设备可以像实时设备一样通过 ADB 访问。请注意,使用 adb devices
命令时,它的状态现在显示为处于恢复模式:
在检查员可以开始通过 ADB 提取数据之前,还有一个最后步骤:必须挂载/data
分区才能访问用户数据。一些自定义恢复可能会自动挂载此分区,而其他的可能不会。如果使用前面提到的网址中的Team Win Recovery Project镜像,可以通过选择 Mount 然后选择/data
分区来挂载。恢复菜单通常可以通过使用音量键上下移动,电源键选择,或者根据使用的自定义恢复镜像可能是触摸操作的方式进行导航。
对于 TWRP 恢复,请按照以下步骤操作:
- 从主恢复屏幕,选择 Mount:
- 选择 Mount 后,选择要挂载的分区:
一旦/data
分区(以及检查员想要调查的其他分区)被挂载,检查员就可以进行 ADB 数据提取,如本章前面所示。
在许多运行 Android 6.0(Marshmallow)或更高版本的设备上,userdata 分区默认加密,因此无法使用自定义恢复镜像挂载和提取。
如果设备没有自定义恢复,以下部分将展示如何启动到自定义恢复或如何刷入自定义恢复镜像。
启动到自定义恢复镜像
一旦确认引导加载程序已解锁,检查员将需要从一个自定义恢复镜像启动。一个很好的恢复镜像来源是 twrp.me/Devices/
。
选择正确的恢复镜像对于被检查的设备至关重要;它们不可互换,启动错误的镜像可能会使设备变砖。
一旦选择并下载了恢复镜像,设备需要进入 fastboot 模式。这可以通过以下两种方式之一实现:
-
ADB
-
物理设备按钮
要通过 ADB 进入 fastboot 模式,设备必须已经启用 USB 调试。以下是通过 ADB 进入 fastboot 模式的命令:
adb reboot bootloader
如果无法启用 USB 调试或无法使用 ADB,通常也有一组按键可以在设备启动时按下,类似于进入恢复模式。每个设备的确切组合可以在网上查找。
一旦设备进入 fastboot 模式,运行以下命令将验证设备是否已连接并准备好进行通信:
fastboot devices
以下命令将把自定义恢复镜像加载到 RAM 中并启动设备进入恢复模式:
fastboot boot 'path to image'
设备现在应该重新启动并进入恢复模式。如恢复模式部分所示,可能需要挂载/data
分区才能访问用户数据。
如果 fastboot boot 命令失败,可能表示设备的引导加载程序已锁定。
使用 adb shell 来确定设备是否已 root
确定设备是否已 root 的最简单方法是使用 adb shell
。这将在设备上打开一个 shell,并将其访问权限传递到检查员的计算机;这意味着在 shell 中运行的任何命令都将在设备上执行。一旦启用了 USB 调试并绕过了安全 USB 调试(或从恢复模式,如后续讨论的那样),在本地计算机上打开终端并运行以下命令:
adb shell
shell 可能以两种方式之一出现,要么是 $
,要么是 #
:
在 Linux 系统上,#
用于表示 root 用户;$
表示非 root 用户。如果 shell 返回显示 #
,则说明 shell 已具有 root 权限:
在一些已 root 的设备上,可能需要进一步的步骤。如果 shell 返回 $
,尝试运行 su
命令(如前面的截图所示):
su
如果设备上安装了 su
二进制文件(通常是 root 过程的一部分),则如果 shell 没有以 root 权限打开,这将提升 shell 的权限为 root。
请注意,一些旧设备会自动以 root 权限运行 shell;只需打开 adb shell
可能就足以给检查员 root 权限。
adb pull
如第二章中所述,设置 Android 法医环境,adb pull
用于将文件从设备传输到本地工作站。以下显示了 adb pull
命令的格式:
adb pull [-p] [-a] <remote> [<local>]
可选的 –p
标志显示传输的进度,而可选的 –a
标志将复制文件的时间戳和模式。<remote>
参数是设备上文件的确切路径。可选的 <local>
参数是文件将在检查员的工作站上写入的路径。如果没有指定本地路径,文件将写入当前工作目录。一个示例 adb pull
命令可能如下所示:
adb pull –p /sdcard/Pictures/1.png D:\Test
让我们看看以下截图:
该命令将从设备中提取图像文件并将其写入我们选择的目录。同样,请注意,如果您希望提取例如 mmssms.db
数据库(该数据库包含已发送和接收的 SMS 和 MMS),设备必须是 root 的;否则,输出只会显示提取了 0
个文件。
输出显示文件大小为 599401
字节。根据我们的命令,1.png
现在位于 Test
文件夹中。
类似地,如果调查员希望提取整个应用程序的文件,也可以使用 adb pull
:
这次,adb pull
命令提取了 Pictures
目录中的每个文件。如前面的截图所示,提取了三个文件。传输的总大小显示为 1310468
字节。
甚至可以执行以下操作:
adb pull –p /data/data/ D:\Test
这将从 /data/data
目录中提取所有可用的逻辑文件,并将它们放入检查员的 Test
文件夹中。这与物理镜像不同,因为某些文件会被跳过,已删除的文件不会被复制,但它是提取用户大部分应用数据的简单方法。
adb pull
命令的另一个优势是它对脚本化非常有用。经验丰富的检查员可以维护一个常见文件路径的列表,并编写一个脚本,自动从设备中提取这些文件,甚至让脚本自动提取整个 /data/data
目录。以下是执行此功能的简单 Python 代码示例:
from subprocess import Popen
from os import getcwd
command = "adb pull /data/data " + getcwd() + "\data_from_device"
p = Popen(command)
p.communicate()
请注意,代码并不精细;它的唯一目的是说明 adb
命令脚本化的简便性。至少,正确实现代码应该包括指定输出目录的选项并处理任何错误。然而,之前展示的六行代码足以在启用 USB 调试并且设备已获取 root 权限的情况下,逻辑上提取整个 /data/data
目录。
Fastboot 模式
Fastboot 是 Android 软件开发工具包中内置的另一种协议工具,用于直接与设备的引导加载程序进行交互。从本质上讲,它是 ADB 的更低级版本,常用于将新镜像刷入设备。那么,这对检查员有什么帮助呢?
Fastboot 允许检查员从自定义恢复镜像启动设备,并临时获得 root 权限,从而访问通常无法获得的数据。Fastboot 不要求启用 USB 调试或 root 权限。将自定义引导加载程序加载到设备上的过程通常被商业取证工具用来临时获取设备的 root 权限,但熟练的检查员也可以手动执行该过程。使用这种方法,恢复镜像被加载到 RAM 中;设备上的任何永久性数据都不会以任何方式被更改。
使用 fastboot 的最重要要求是解锁引导加载程序;锁定的引导加载程序不允许设备从没有被制造商专门签名的代码启动。不幸的是,对于取证目的,大多数设备现在都不再出厂时解锁引导加载程序,因为这会带来严重的安全风险,而手动解锁引导加载程序通常会清除用户数据。因此,这种方法可行的设备数量有限。但当它有效时,它对检查员来说是一个非常宝贵的工具。
如果设备启用了全盘加密,这种方法将无法使用。启动到恢复模式将不会解密 /data
分区。
确定引导加载程序状态
与所有涉及 Android 取证的内容一样,没有一种方法可以百分百确定引导加载程序是否被锁定,因为这取决于制造商。要启动到引导加载程序,请使用 adb
命令:
adb reboot bootloader
设备应启动到显示引导加载程序信息的屏幕。通常,这个屏幕会显示引导加载程序的状态,如下图所示。
以下是来自 Nexus 5 的通用标准 fastboot 菜单。请注意,锁定状态指示引导加载程序已解锁:
以下是标准的三星 Odin 模式屏幕;Odin 是三星专有的 fastboot 等效模式:
三星 Odin 模式屏幕
ADB 备份提取
Google 从 Android 4.0(冰淇淋三明治)开始实现了 ADB 备份功能。它允许用户(以及取证检查员)通过 ADB 将应用程序数据备份到本地计算机。这一过程不需要 root 权限,因此对取证非常有用。然而,它并不会获取设备上所有安装的应用程序。当开发者创建一个新应用时,默认情况下允许备份,但开发者可以修改这一设置。实际上,大多数开发者会保持默认设置,这意味着备份会捕获大多数第三方应用程序。不幸的是,大多数 Google 应用禁用了备份功能;像 Gmail 和 Google Maps 这样的应用的完整数据将不会被包含在内。大多数消息应用也存在同样的问题——它们的数据无法通过 ADB 备份获取。
此方法在设备被锁定时无效;需要用户与屏幕进行交互。
通过 ADB 提取备份
adb backup
命令的格式如下所示:
adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]
可用的标志如下:
-
-f
:指定输出文件的路径。如果未指定,默认为当前工作目录中的backup.ab
。 -
[-apk|noapk]
:选择是否备份.apk
文件。默认值为–noapk
。 -
[-obb|-noobb]
:选择是否备份.obb
(APK 扩展)文件。默认值为–noobb
。 -
[-shared|-noshared]
:选择是否备份共享存储和 SD 卡中的数据。默认值为–noshared
。 -
[-all]
:包含所有已启用备份的应用程序。 -
[-system|-nosystem]
:选择是否包括系统应用程序。默认值为–system
。 -
[<packages>]
:明确指定要备份的应用程序包。如果使用–all
或–shared
,则无需指定。
一个示例adb backup
命令,用于捕获所有可能的应用程序数据如下:
adb backup –f C:/Users/0136/Test/backup.ab –shared –all
或者,一个示例adb backup
命令,用于捕获特定应用程序的数据如下:
adb backup –f C:/Users/0136/Test/facebook.ab com.facebook.katana
你应该看到类似以下内容的屏幕:
在执行备份时,用户必须在设备上批准备份;这意味着在绕过屏幕锁定之前无法执行备份:
根据安装的应用程序数量,备份过程可能会花费相当长的时间。
解析 ADB 备份
生成的备份数据以.ab
文件的形式存储,但实际上是一个经过 Deflate 算法压缩的 TAR 文件。如果在备份创建时在设备上输入了密码,文件还会进行 AES 加密。还应该提到,这些文件可能存在于嫌疑人的计算机上,并可以使用相同的方法进行分析。
有许多免费的工具可以将.ab
备份文件转换为可以查看的.tar
文件。一个这样的工具是 Android Backup Extractor,网址为:sourceforge.net/projects/adbextractor/
。
要使用 Android Backup Extractor,只需将其文件提取到备份所在的目录中。运行该工具的命令如下所示:
java –jar abe.jar unpack backup.ab backup.tar
.tar
文件将位于命令行指定的路径中,如果没有指定路径,则位于当前工作目录中。可以在 Linux 命令行手动解压.tar
文件,也可以使用诸如 WinRAR 或 7Zip 等 Windows 压缩工具:
备份中的目录,在 7-Zip 中查看
ADB 备份中的数据位置
现在,备份已被转换为.tar
文件并提取出来,检查员可以查看备份中包含的数据。在我们的示例中,备份根目录下发现了两个目录:
-
apps
:包含备份中包含的应用程序的/data/data
中的数据 -
shared
:包含来自 SD 卡的所有数据;仅在命令行传递了 shared 参数时才会出现
请注意,apps 目录中的文件按其包名存储在目录中(就像在adb shell
中看到的/data/data
),shared 目录则是用户将 SD 卡插入计算机后看到的内容。以下是从备份中提取的用户数据的良性示例,显示了用户的 Pandora 活动。Pandora 是一款在 Google Play 商店下载量达到百万的流媒体音乐服务。Pandora 的应用数据将包含在备份的apps
文件夹中,文件夹名为com.pandora.android
:
来自备份的 Pandora 目录
这是 Android 应用程序的一个标准布局,如第二章《设置 Android 取证环境》中所讨论的那样。应用程序的数据库将位于db
文件夹中:
Pandora 备份的 db 文件夹中的文件
XML 配置设置将位于sp
文件夹中:
Pandora 备份的 sp 文件夹中的文件
使用数据库查看器查看pandora.db
可以查看用户创建的电台以及创建时间戳:
从备份中的 pandora.db 内容
查看 XML 配置文件,可以在 firstInstallId
下找到应用安装的时间戳。注意,转换时间戳的确切方法在第七章,Android 应用程序的法医分析中有展示:
XML 配置文件内容
如果由于某些奇怪的原因,用户的 Pandora 使用情况在调查中是一个重要问题,那么检查员可以从这两个看似无害的文件中得出什么结论?
首先,lastTransmission
和 firstInstallID
时间戳的毫秒级差异表明,应用程序安装后从未被使用。此外,每个站点的创建日期早于应用程序的安装日期,有些情况下提前几年。这可能表明用户在其他设备上使用过 Pandora;这可能对调查高度相关。
虽然 Pandora 通常与数字法医调查无关,但它是可以通过简单的 ADB 备份获取的数据的一个示例。更详细的应用程序分析将在第七章,Android 应用程序的法医分析中介绍。
ADB dumpsys
Dumpsys 是 Android 操作系统中内置的工具,通常用于开发目的,显示设备上正在运行的服务的状态。然而,它也可能包含法医分析中有趣的信息。Dumpsys 不需要 root 权限,但像所有 ADB 命令一样,需要在设备上启用 USB 调试并绕过安全 USB 调试。
可查看的精确服务因设备和 Android 版本而异。要查看所有可能的可转储服务列表,请运行以下命令:
adb shell service list
命令的输出将显示为一个列表,如下所示:
位于冒号前的服务名称是我们将传递给 dumpsys
的参数。一个有效的 dumpsys
命令,使用前面提到的服务编号七(iphonesubinfo
),如下所示:
adb shell dumpsys iphonesubinfo
在下文中,我们看到 iphonesubinfo
服务的输出包括设备 IMEI:
有许多在法医分析中有趣的 dumpsys
服务;以下是几个示例。由于 dumpsys
服务可能因操作系统版本和设备而有所不同,此列表并非全面,旨在展示 dumpsys
对法医检查员的实用性:
-
iphonesubinfo
-
batterystats
-
procstats
-
user
-
appops
-
wifi
-
notification
Dumpsys batterystats
Batterystats 用于显示正在运行的应用程序的使用情况。其输出可能非常冗长,具体取决于使用的应用程序数量;在以下截图中,由于输出内容太多,无法在 Windows 命令行中显示,因此将输出重定向到文件:
这显示了我们 Google Chrome 的网络使用情况。此信息可用于证明该应用程序最近被使用,即使 Chrome 在隐身模式下使用,也不会在其他地方留下取证证据,这些信息仍然存在。
注意,Wakelock 部分对于检测恶意软件非常有用。Wakelock 是一种保持设备处于唤醒状态(即不进入睡眠模式)的方法,通常表示某个应用程序试图保持在后台运行。
Dumpsys procstats
Procstats 是一个显示运行中的应用程序处理器使用情况的服务。与 batterystats 类似,它是另一种可以用来显示某个应用程序最近在设备上被使用的方法:
Dumpsys 用户
从 Android Jelly Bean 开始,谷歌为平板设备添加了多用户支持。随着 Lollipop 的发布,谷歌将这一支持扩展到手机设备。在数字取证中,长期以来最具挑战性的问题之一就是证明在进行有罪行动时,设备由谁使用,也就是:谁在键盘后面?
对用户服务运行 dumpsys
将显示所有用户的最后登录信息:
由于一次只能登录一个用户,因此查看最近登录的用户可以识别当前在设备上使用的账户。
Dumpsys App Ops
App Ops 可能是最有趣的 dumpsys
服务。App Ops 这个术语通常用来指代应用程序可以访问的权限。在 Android 的早期版本中,有传言称谷歌将为用户提供撤销特定权限的功能,虽然这一功能从未实现,但这个服务至少保留了下来,并显示应用程序最后一次使用每个可访问权限的时间。以下是来自 Google Chrome 的另一个示例:
在前面的输出中,我们可以看到大约 appops
被 dumpsys
导出前的 1 小时 7 分钟,Chrome 使用了 TAKE_AUDIO_FOCUS
权限,之后又使用了 AUDIO_MEDIA_VOLUME
。这表明 Chrome 被用来听某些东西,并且说明了它发生的时间。
一个更有趣的例子是电话应用:
44 分钟前,用户使用了电话应用并要求 READ_CONTACTS
权限,随后立即使用了 WRITE_CALL_LOG
权限。我们可以推测,用户在 44 分钟前打了一个电话;即使他们之后删除了通话记录。
Dumpsys Wi-Fi
Wi-Fi 服务将显示已保存连接的所有 SSID 列表。例如,这对于证明用户曾经在某个位置是有用的。更详细的 Wi-Fi 信息也可以在文件系统中找到,但需要 root 权限才能查看。使用 dumpsys
,我们可以无需 root 权限就能访问这些数据:
Dumpsys 通知
通知服务将提供当前活动通知的信息。这对于记录设备在被扣押时的状态或识别哪个应用正在显示特定通知可能会很有用。每个通知可能非常大,包含大量信息,其中只有一部分可能有用。以下是一个来自 Gmail 应用的来邮件通知示例,其中包含主题(这是测试邮件
)和正文(查看测试通知
):
Dumpsys 结论
运行不带服务名称的dumpsys
命令将对所有可用服务运行dumpsys
。然而,输出将非常大,应该将其重定向到文本文件中。在大多数平台上,执行此操作的命令通常如下:
adb shell dumpsys > dumpsys.txt
这将把输出写入当前工作目录下的dumpsys.txt
文件。然后可以搜索该输出或运行解析脚本以提取已知的相关字段。
Dumpsys 是一个非常强大的工具,可以显示设备上无法通过其他方式获得的信息。我们建议在每个 Android 设备被扣押后,关闭前运行dumpsys
。这样可以保存各种有可能后续使用的信息,并且不需要 root 权限。
Helium 备份提取
根据开发者的说法,Helium 是Android 设备缺失的应用同步和备份解决方案。它不需要 root 权限,可以提取一些 ADB 备份无法获取的数据;例如,短信和通话记录。
实际上,检查员需要两个应用:一个 Android 应用和一个 PC 应用。Android 应用可以从 Google Play 下载:
play.google.com/store/apps/details?id=com.koushikdutta.backup
。
桌面版本可以在这里获取:
让我们按照以下步骤提取数据:
- 一旦你打开 Android 应用,你将看到以下界面:
-
打开桌面应用并启用 Helium。你将看到一条消息,提示 Helium 已在你的 Android 设备上启用。
-
你可以选择你想备份的数据;在我们的例子中,是消息和通话记录:
- 由于我们希望将备份保存到法医工作站,让我们进入右上角的菜单,选择适当的选项,PC 下载:
- 检查 Helium 服务器的 IP 地址和端口;在我们的例子中,它是
192.168.1.71
和5000
:
- 从你选择的网页浏览器访问该地址,选择你要备份的应用程序,然后点击“开始备份”:
在你的默认下载文件夹中,你会找到一个名为 backup.zip
的 ZIP 压缩包。
压缩包中有三个文件:
-
backup.json
:它包含有关备份的信息,如包名、备份日期和智能手机的操作系统版本。 -
com.android.providers.telephony.ab
:它本身是一个备份,包含提取的数据,在我们的案例中,是短信和通话记录。 -
com.android.providers.telephony.png
:它备份了应用程序的图标。
同样,要提取 com.android.providers.telephony.ab
的内容,我们需要使用 Android Backup Toolkit(sourceforge.net/projects/adbextractor/
)中的某个工具,这次使用 Helium Backup Extractor:
java -jar hbe.jar -force com.android.providers.telephony.ab
现在,在当前的工作目录中,有一个 app
文件夹,在 apps\com.android.providers.telephony\cb
目录下,我们可以找到 custom.cb
文件。这个文件包含了以 JSON 格式备份的应用程序数据;这是一个例子:
{"number":"+79165555555","new":1,"duration":10,"date":1540479309458,"type":1}
number
字段显示电话号码,new
字段(如果是最近的通话),duration
(通话时长),date
(通话日期,采用 Unix 时间戳格式——毫秒),以及 type
(通话类型);在我们的案例中,它是 1
,即来电。
当然,这种方法可能在法医上不太可靠,因为我们需要在目标移动设备上安装一个应用程序,但有时这是提取宝贵数字证据的唯一方法。更重要的是,许多商业移动法医工具使用小型应用程序,即所谓的代理,在逻辑获取过程中提取更多数据。你将在第八章中了解更多关于 Android 法医工具的内容,Android 法医工具概述。
绕过 Android 锁屏
锁屏是 Android 法医检查中最具挑战性的部分。调查的整个过程通常取决于检查员是否能够访问被锁定的设备。虽然有一些绕过的方法,但这往往取决于操作系统版本、设备设置以及检查员的技术能力。没有任何一种方法能够在所有设备上每次都奏效。像 Cellebrite 和 Oxygen 这样的商业法医工具具有相当强大的绕过能力,但远非万无一失。本章将展示检查员如何利用免费工具和方法提高绕过锁定设备的几率。
检查员绝不应尝试猜测设备上的图案/PIN/密码。许多制造商实现了一种设置,在多次失败尝试后会擦除设备。许多厂商还允许用户减少这个失败次数。
锁屏类型
用于保护设备的方法有很多,绕过每种方法的方式各不相同:
-
无/滑动
-
图案
-
PIN
-
密码
-
智能锁:可信面部、可信声音、可信位置、可信设备、身体检测
可能还存在其他安全选项;由于 Android 是开源的,可能性仅受开发者想象力的限制。这些是 Google 发布的 Android Oreo 系统原生版本中提供的选项。大多数厂商使用的安全选项通常都使用其中一种原生选项作为备用,以防用户无法使用其独特选项登录。首次使用该设置的版本也被称为原生 Android;不同厂商可能会更早实现这些选项。
无/滑动锁屏
滑动解锁 屏幕是大多数 Android 设备的默认设置。它不提供任何安全性,通过在屏幕上按指示方向滑动手指即可绕过。
图案锁屏
图案锁屏是 Android 的标志性安全方法。通常被称为 滑动密码 或类似名称,这要求用户用手指在设备上划出一个图案。绕过此锁定的常见方法是 污迹攻击,通过观察用户手指留下的图案来破解。
密码/PIN 锁屏
熟悉苹果 iOS 的用户会识别此选项。它要求用户输入密码或 PIN 码才能解锁设备。它们被归为一类,因为从取证角度来看,它们是相同的:它们以相同的方式存储密码。
智能锁
智能锁是 Android Lollipop 中引入的术语,尽管面部解锁选项之前已经存在。它们需要特定条件来解锁设备:用户的面部必须被识别,用户必须处于已知位置,或者必须有特定的其他设备在附近。
信任面部
面部解锁按字面意思工作:它通过面部识别来判断用户是否已经设置为信任用户。较早版本的面部锁定容易被信任用户的照片欺骗,尽管较新的版本可能需要用户眨眼才能解锁设备。
信任语音
OK Google 语句可被用户用来解锁手机。这种类型的锁定并不适用于许多设备,因为手机需要在屏幕关闭时持续监听用户的声音,这会消耗电池。
信任位置
信任位置也常被称为 地理围栏。如果用户处于已标记为可信的位置(如家或工作地点),设备将不会锁定。用户无需任何输入,但必须启用 GPS。
信任设备
信任设备通过蓝牙工作;如果设置为信任设备的设备在附近,锁屏将被禁用。这可以与智能手表、通过蓝牙配对的车辆、蓝牙耳机或任何其他支持蓝牙的设备一起使用。
体感检测
体感检测利用手机的运动传感器,例如加速度计和陀螺仪,当设备处于用户手中、口袋或包内时,保持解锁状态。
所有智能锁选项都需要图案/PIN/密码作为备用安全方法。这意味着我们只需要学习如何绕过图案/PIN/密码,就能破解所有的安全选项。
一般绕过信息
在所有情况下,绕过锁屏将需要从设备中获取文件。图案锁以哈希值存储在/data/system/gesture.key
,而 PIN/密码锁以哈希值存储在/data/system/password.key
(直到 Android 5.0,Lollipop)。此外,password.key
的哈希值是加盐的;盐值存储在 Android 4.4 之前的设备中/data/data/com.android.providers.settings/databases/settings.db
,在 Android 4.4 及更高版本的设备中则存储在/data/system/locksettings.db
。
Android 6.0(Marshmallow)引入了 Gatekeeper 密码存储——一种新的 PIN 和图案锁的混淆层。现在,锁存储在gatekeeper.pattern.key
和gatekeeper.password.key
中,不再使用哈希值。Gatekeeper 使用基于哈希的消息认证码(HMAC)和硬件支持的密钥来管理和验证密码。
如果设备被锁定,检查员该如何访问这些文件?再次强调,没有一个能够每次都有效的魔法解决方案,但以下是一些可选方案:
-
ADB:
-
需要 root
-
需要 USB 调试
-
需要安全的 USB 调试配对(取决于操作系统版本)
-
-
启动进入自定义恢复模式:
-
不需要 root(root 将通过恢复镜像提供)
-
不需要 USB 调试(通过 fastboot 实现)
-
不需要安全的 USB 调试(这一点完全被绕过)
-
需要解锁的引导加载程序
-
不适用于加密 userdata 分区的设备
-
-
JTAG/芯片脱机:
-
高度复杂
-
不需要任何特定的设备设置或选项
-
不适用于加密 userdata 分区的设备
-
移除 Android 锁屏
PIN 或密码可以通过简单地覆盖或删除文件来绕过。然而,这会改变原始证据,在你的管辖范围内可能不具有法医效力。
使用 ADB 移除 PIN/密码
根据你正在检查的设备及其操作系统版本,可能需要删除不同的文件。如果设备中包含*.key
文件在/data/system/
目录下,你需要删除这些文件;如果没有此类文件,可能需要删除locksettings.db
,如果可能的话,或者更新其中的一些记录(请参见下一节)。
下面是如何通过 ADB 删除感兴趣的文件:
adb shell
su
cd /data/system
rm *.key
现在设备应该重新启动。重启后,将不再需要 PIN 或密码。
使用 ADB 和 SQL 移除 PIN/密码
最近的 Android 设备上没有*.key
文件,如运行 Oreo 或 Pie 的设备,但仍然存在/data/system
目录下的lockscreen.db
数据库。
下面是如何删除此数据库中用于更改的 PIN 或密码的方法:
adb shell
su
cd /data/system
sqlite3 locksettings.db
update locksettings set value=0 where name='lockscreen.password_salt';
update locksettings set value=0 where name='sp-handle';
.quit
重启设备,屏幕锁将被移除。
Android SIM 卡提取
传统上,SIM 卡用于在设备之间传输数据。过去,SIM 卡用于存储多种类型的数据,如下所示:
-
用户数据
-
联系人
-
短信
-
拨打的电话
-
网络数据
-
集成电路卡标识符(ICCID):SIM 卡的序列号
-
国际移动用户身份(IMSI):将 SIM 卡与特定用户账户绑定的标识符
-
MSISDN:分配给 SIM 卡的电话号码
-
位置区域标识符(LAI):标识用户所在的基站
-
认证密钥(Ki):用于认证移动网络
-
其他各种网络特定信息
随着设备存储容量、SD 卡和云备份的增加,将数据存储在 SIM 卡上的必要性已经减少。因此,大多数现代智能手机通常不会在 SIM 卡上存储大量甚至任何用户数据。前面提到的所有网络数据仍然保留在 SIM 卡上,因为 SIM 卡是连接所有现代(4G)蜂窝网络所必需的。
然而,像所有 Android 设备一样,虽然没有明确规定不能将用户数据存储在 SIM 卡上,但默认情况下它不会发生。各个设备制造商可以轻松决定将用户数据写入 SIM 卡,个人用户也可以下载应用程序来提供该功能。这意味着在取证检查过程中,设备的 SIM 卡应始终进行检查。这是一个非常快速的过程,绝不能忽视。
获取 SIM 卡数据
SIM 卡应始终从设备中取出并单独检查。虽然一些工具声称可以通过设备接口读取 SIM 卡,但这可能无法恢复已删除的数据或 SIM 卡上的所有数据;取证人员要确保所有数据已被获取,唯一的方法是通过经过测试和验证的独立 SIM 卡读取器读取 SIM 卡。
SIM 卡的位置因设备而异,但通常存储在电池下方或位于设备侧面的托盘中。移除 SIM 卡后,应将其放入 SIM 卡读取器中。市场上有数百种 SIM 卡读取器可供选择,所有主要的移动取证工具都配有与其软件兼容的读取器。通常,取证工具还会支持第三方 SIM 读取器。
出人意料的是,市场上缺乏完善且免费的 SIM 卡读取软件。任何使用的软件在实际取证调查之前,应该始终在一个已填充已知数据的 SIM 卡上进行测试和验证。此外,请注意,许多免费的软件适用于较旧的 2G/3G SIM 卡,但可能无法在现代 4G SIM 卡上正常工作。我们在以下截图中使用了 Mobiledit! Lite,这是 Mobiledit!的免费版本。可以在以下网址下载:www.mobiledit.com/downloads
。
以下是从运行 Android 4.4.4 版本的 Android 手机中提取的 4G SIM 卡示例;请注意,尽管该 SIM 卡已活跃使用超过一年,但未获取任何可视为用户数据的内容,尽管诸如 ICCID、IMSI 和 MSISDN(本机号码)等字段可能对传票/令状或调查的其他方面有所帮助:
SIM 卡提取概述
以下截图突出了 SIM 卡上的短信:
以下截图突出了 SIM 卡的通讯录:
以下截图突出了 SIM 卡的电话号码(也称为 MSISDN):
SIM 卡安全
由于 SIM 卡符合既定的国际标准,所有 SIM 卡提供相同的安全功能:一个 4 到 8 位的 PIN。通常,必须通过设备上的菜单来设置此 PIN。在 Android 设备上,这个设置可以在“设置”|“安全”|“设置 SIM 卡锁定”中找到。SIM PIN 完全独立于任何锁屏安全设置,只有在设备启动时才需要输入。SIM PIN 仅保护 SIM 上的用户数据;即使 SIM 卡被 PIN 锁定,所有网络信息仍然是可以恢复的。
SIM 卡允许三次输入 PIN 尝试;如果其中一次正确,计数器将重置。另一方面,如果所有尝试都失败,SIM 卡将进入个人解锁密钥(PUK)模式。PUK 是由运营商分配的 8 位数字,通常可以在购买 SIM 卡时的文档中找到。通过任何商业法医软件都无法绕过 PUK;因此,检查员绝不应尝试在设备上输入 PIN,因为设备不会显示剩余尝试次数,直到 PUK 激活为止。检查员可能会不小心将 SIM 卡锁定在 PUK 模式,无法访问设备。然而,法医工具会显示在 PUK 激活前剩余的尝试次数,如前面的截图所示。
SIM 卡的常见运营商默认 PIN 是 0000 和 1234。如果在激活 PUK 前剩余三次尝试,检查员可能会使用这些默认 PIN 成功解锁 SIM 卡。
运营商在发放 SIM 卡时通常会保留 PUK 密钥。这些密钥可能通过对运营商发出的传票或令状获得。
SIM 卡克隆
SIM PIN 本身几乎不会提供额外的安全性,并且可以通过 SIM 克隆轻松绕过。SIM 克隆是几乎所有商业移动取证软件都提供的功能,尽管“克隆”这个术语有点误导。在移动取证的情况下,SIM 克隆是指将网络数据从一个锁定的 SIM 卡复制到一个法医干净的 SIM 卡上,这个 SIM 卡没有激活 PIN。手机会基于这些网络数据(通常是 ICCID 和 IMSI)识别克隆的 SIM 卡,并认为它与之前插入的 SIM 卡相同,但这次没有 SIM PIN。此克隆 SIM 卡也无法访问蜂窝网络,这使得它成为类似于飞行模式的有效解决方案。因此,SIM 克隆将允许检查员访问设备,但原始 SIM 卡上的用户数据仍然无法访问,因为它被 PIN 保护。
我们不知道任何可以执行法医 SIM 克隆的免费软件。然而,几乎所有商业移动取证工具包都支持此功能。这些工具包通常包括一个 SIM 卡读取器、用于执行克隆的软件以及多个空白 SIM 卡用于克隆过程。
总结
本章讨论了与 Android 设备的逻辑提取相关的多个主题。作为总结,以下是各种方法及其要求:
方法 | 要求 |
---|---|
ADB 拉取 |
-
启用 USB 调试
-
在 4.2.2+ 版本中绕过安全 USB 调试
-
获取 root 权限以获取用户数据
|
从恢复模式下拉取 ADB |
---|
-
必须使用自定义恢复模式才能启用 ADB 访问
-
获取 root 权限以获取用户数据
|
从自定义恢复镜像启动 Fastboot |
---|
-
解锁的引导加载程序
-
设备的启动镜像
|
ADB 备份 |
---|
-
启用 USB 调试
-
在 4.2.2+ 版本中绕过安全 USB 调试
-
必须从正在运行的设备执行(不能在恢复模式下)
|
ADB Dumpsys |
---|
-
启用 USB 调试
-
在 4.2.2+ 版本中绕过安全 USB 调试
-
必须从正在运行的设备执行(不能在恢复模式下)
|
SIM 卡提取 |
---|
- 无要求,应该独立于设备执行
|
此外,用户的有价值数据还可以从 SD 卡恢复,这将在第五章中讨论,从 Android 设备中物理提取数据。
如果屏幕被锁定,检查员可以通过前面列出的方法,从 locksettings.db
数据库中删除关键文件或删除某些记录。
本章包含了大量数据,为了简化理解,下面展示了一个建议的 最佳实践 流程图:
Android 取证流程图
第五章:从 Android 设备中物理提取数据
本章将介绍物理数据提取,尽可能使用免费和开源工具。本章中大多数内容将使用我们之前在本书中讨论的Android 调试桥(ADB)方法。到本章结束时,读者应熟悉以下内容:
-
物理提取意味着什么
-
使用
dd
、nanddump
和 Magnet ACQUIRE 进行物理数据提取 -
RAM 成像和分析
-
SD 卡数据获取
-
JTAG 和芯片拆卸方法
物理提取概述
在数字取证中,物理提取是电子媒体的精确位对位镜像,这一定义同样适用于移动设备。在传统计算机取证中,这通常涉及从嫌疑人的计算机中取出证据硬盘,并通过写保护器进行成像,而不启动该硬盘,从而得到一个包含嫌疑人硬盘精确副本的镜像文件。输出通常称为原始镜像,或简而言之是二进制(.bin
)文件。物理提取与逻辑提取的区别在于,物理提取是设备内存的精确副本,包括未分配的空间、文件空白、卷空白等。
在移动取证中,结果是相同的——设备的精确位对位镜像——但方法略有不同。例如,将闪存从设备中拆卸下来进行成像既费时又昂贵,而且需要大量专业知识(尽管这可以做到,正如本章后面的芯片拆卸部分所讨论的那样)。此外,除非使用先进的 JTAG 或芯片拆卸方法,否则设备必须至少启动一定程度(并且在许多情况下写入)才能访问数据。最后,找到一个可以解析最终镜像文件的工具可能非常困难。硬盘镜像和文件系统早已被文档化和研究,而移动镜像和文件系统则经常变化;在某些情况下,移动文件系统甚至是特定厂商独有的。知道获取镜像后该怎么处理,可能和获取镜像本身一样具有挑战性!
在第四章中讨论的许多技术,从 Android 设备中逻辑提取数据,在这里仍然适用:启动自定义恢复模式仍然是最符合取证要求的过程;如果可能的话,应避免物理获取一个活跃的设备。
可以通过物理方式获取哪些数据?
简短的回答是:一切。由于物理采集是设备的精确映像,设备上的每一比特数据都会出现在映像文件中。如前所述,在物理提取中,检查员通常仅受限于他们找到相关数据的能力。通常,这是因为移动取证领域缺乏良好的映像分析工具。更糟糕的是,应用程序已知会对用户数据进行编码或其他形式的混淆,因此仅仅通过十六进制编辑器浏览映像往往会错过宝贵的证据。本章将介绍各种挂载或以其他方式查看物理提取文件系统的方法,而第七章《安卓应用程序取证分析》将专注于分析来自特定应用程序的数据。
Root 权限
再次强调,就像逻辑提取一样,root 权限在物理提取中也至关重要。为了手动创建设备映像,我们必须通过 ADB shell 在设备上执行命令,而这些命令需要 root 权限。如果无法获得 root 权限,SD 卡通常仍然可以创建映像。除此之外的唯一备选方法是 JTAG 或芯片拆除方法。
使用dd
命令提取物理数据
dd
命令对于任何做过传统硬盘取证的检查员来说应该都很熟悉。dd
是一个 Linux 命令行工具,定义上用于转换和复制文件,但在取证中常常用于创建整个硬盘的逐比特映像。dd
有很多变种,如dcfldd
、dc3dd
、ddrescue
和dccidd
,这些工具在实际操作中也很常见。由于dd
是为 Linux 系统设计的,它经常包含在 Android 平台中。这意味着,创建设备映像的方法往往已经存在于设备上!
dd
命令有许多可设置的选项;以下列表中仅涵盖与取证相关的重要选项。可以在man7.org/linux/man-pages/man1/dd.1.html
查看完整的命令选项列表。dd
命令的格式如下:
dd if=/dev/block/mmcblk0 of=/sdcard/blk0.img bs=4096 conv=notrunc,noerror,sync
让我们定义dd
命令的前述格式:
-
if
:指定输入文件的路径。 -
of
:指定输出文件的路径。 -
bs
:块大小。数据按指定的块大小读取和写入,如果未指定,则默认大小为 512 字节。 -
conv
:转换选项:-
notrunc
:不截断输出文件。 -
noerror
:遇到错误时继续生成映像。 -
sync
:与 no error 配合使用时,对于发生错误的块,它会写入\x00
。这对于保持映像中的文件偏移量非常重要。
-
不要混淆if
和of
标志,因为这可能会导致覆盖目标设备!
请注意,bs
、noerror
和sync
标志之间有一个重要的关系:如果遇到错误,将会为读取到的整个块写入\x00
(这由块大小决定)。因此,较小的块大小会在发生错误时减少丢失的数据。缺点是,通常较小的块大小会导致较慢的传输速率。检查员需要根据是否优先考虑及时性或更准确的获取来做出决定。
如前一章所述,进入恢复模式进行成像处理是最具法医证据效力的方法。
确定要成像的内容
在对计算机进行成像时,检查员首先必须确定磁盘的挂载位置,例如/dev/sda
。对 Android 设备的成像也是如此。第一步是启动 ADB shell,并通过以下命令查看/proc/partitions
文件:
cat /proc/partitions
输出将显示设备上的所有分区:
在之前的输出中,mmcblk0
是设备上整个闪存的代表。为了提取整个闪存的镜像,我们可以使用/dev/blk/mmcblk0
作为dd
命令的输入文件标志(if
)。接下来的内容,由 p1-24 表示,是闪存的各个分区。每个分区的大小以块为单位显示。在本例中,块大小为 1,024 字节,总内存大小约为 16 GB。为了获取设备内部存储的完整镜像,我们需要运行dd
命令,并将mmcblk0
作为输入文件。
当然,我们并不关心设备上的每个分区,因为大多数分区几乎不包含任何相关信息。正如你所知道的,最感兴趣的部分是/data
分区。通常它是最大的,所以它可能是mmcblk0p24
,即 11,784,192 个块。让我们通过运行df
命令来了解更多关于它的信息:
从前面的截图中可以看到,我们的判断是正确的——mmcblk0p24
就是 userdata 分区。
写入 SD 卡
dd
的输出文件可以写入设备的 SD 卡。只有在嫌疑人的 SD 卡可以移除并替换为法医无菌 SD 卡的情况下,才应进行此操作。这样可以确保dd
输出不会覆盖证据。显然,如果你正在写入 SD 卡,确保 SD 卡的容量大于要成像的分区。
在较新的设备中,/sdcard
分区实际上是一个指向/storage/self/primary
的符号链接。在这种情况下,使用dd
将/data
分区复制到 SD 卡上是行不通的,且可能会损坏设备,因为输入文件实际上会被写入到自身。
让我们看看在/storage
下还可以找到什么:
如你所见,我们还找到了6264-3264
和emulated
子目录。那么我们的 SD 卡挂载在哪里呢?我们来运行mount
命令:
我们正在使用 128 GB 的 SD 卡,因此它必须安装在 6264-3264
下。现在我们已准备好开始镜像 /data
分区的过程:
现在,在 SD 卡上存在 /data
分区的镜像。可以使用 adb pull
将其拉取到检查人员的机器上,或者直接从 SD 卡中读取。
直接使用 netcat 将数据写入检查人员的计算机
如果无法将镜像写入 SD 卡,检查人员可以使用 netcat
将镜像直接写入其计算机。netcat
是用于通过网络连接传输数据的 Linux 工具。建议在 Linux 或 macOS 计算机上使用 netcat
,因为它是内置的,尽管 Windows 版本也存在。以下示例是在 SIFT 工作站(Linux Ubuntu)上执行的。
在设备上安装 netcat
在过去,几乎没有任何 Android 设备预装了 netcat
。要检查,只需打开 ADB shell 并键入 nc
。如果返回 nc
未找到,则必须手动在设备上安装 netcat
。可以在许多在线资源中找到为 Android 编译的 netcat
;例如,github.com/MobileForensicsResearch/netcat
。
如果我们回顾上一节中挂载命令的结果,可以看到 /dev
分区被挂载为 tmpfs
。tmpfs
是 Linux 的一个术语,意味着该分区被视为设备上的实际文件系统,但实际上只存储在 RAM 中。这意味着我们可以在不对设备进行任何永久更改的情况下,将 netcat
推送到这里,使用以下命令在检查人员的计算机上进行操作:
adb push nc /dev/Examiner_Folder/nc
该命令应该在 /dev
中创建了 Examiner_Folder
,并在其中放置了 nc
。可以通过在 ADB shell 中运行以下命令来验证:
ls /dev/Examiner_Folder
在当前版本的安卓系统(从 Marshmallow 开始),Toybox ——一款免费且开源的软件,实现了一些 Unix 命令行实用程序,包括 netcat
——已经预装,因此检查人员无需再次安装它。
使用 netcat
我们需要打开两个终端窗口,其中一个要打开 ADB shell。另一个用来监听从设备发送的数据。
现在,我们需要通过 ADB 在检查人员的计算机上启用端口转发:
adb forward tcp:9999 tcp:9999
9999
是我们选择用于 netcat
的端口;在 Linux 或 macOS 系统上,它可以是介于 1023
和 65535
之间的任意端口号(1023
及以下保留给系统进程,需要 root 权限才能使用)。Windows 则允许分配任何端口。
在具有 ADB shell 的终端窗口中运行以下命令:
dd if=/dev/block/mmcblk0p24 bs=1024 | toybox nc –l –p 9999
mmcblk0p24
是此设备上的 userdata 分区,但也可以使用此方法对整个闪存或其他任何分区进行镜像。在大多数情况下,最佳实践是对整个闪存进行镜像,以便获取设备中的所有可能数据。一些商业取证工具可能也要求整个内存镜像,并且可能无法正确处理单个分区的镜像。
在另一个终端窗口中,运行以下命令:
nc 127.0.0.1 9999 > userdata.dd
应该已经在检查员计算机的当前目录中创建了userdata.dd
文件。当数据传输完成后,两个终端中的netcat
将终止并返回命令提示符。这个过程可能需要相当长的时间,具体取决于镜像的大小。
使用 nanddump 物理提取数据
在我们迄今为止涵盖的所有示例中,分区都是 MMC 块,这通常出现在较新的设备中。然而,旧设备更有可能由内存技术设备(MTD)块组成。我们过去见过dd
无法正确镜像 MTD 块的情况,尽管通常情况下它工作正常。如果dd
失败,有一个广泛分发的工具叫做 MTD-Utils,用于读取和写入 MTD 块;nanddump
是 MTD-Utils 的一部分,可以像dd
一样用于从 MTD 块中读取。在dd
失败的情况下,nanddump
总是能够成功。
适用于 Android 的nanddump
版本可以在许多地方找到;我们使用的是在此处找到的版本:github.com/jakev/android-binaries/blob/master/nanddump
。
将nanddump
放置到设备上的过程与之前使用netcat
的方法相同:
adb push nanddump /dev/Examiner_Folder/nanddump
chmod +x /dev/Examiner_Folder/nanddump
就像dd
一样,nanddump
也可以通过netcat
写入 SD 卡或检查员的计算机:
- 从终端窗口运行以下命令:
adb forward tcp:9999 tcp:9999
- 在 ADB Shell 中的另一个终端窗口中运行以下命令:
/dev/Examiner_Folder/nanddump /dev/block/mmcblk0p34 | /dev/Examiner_Folder/nc –l –p 9999
- 在第一个终端窗口中,使用
adb forward
时,运行以下命令:
nc 127.0.0.1 9999 > data_partition.img
使用 Magnet ACQUIRE 物理提取数据
ACQUIRE 是 Magnet Forensics 提供的一款免费工具,可以用于获取各种潜在的数字证据来源,从硬盘和智能手机到云数据。当然,它支持对 Android 设备进行逻辑和物理提取,直到最新的运行 Android Pie 的设备。注册后可以在此处下载该工具:www.magnetforensics.com/magnet-acquire/
。
在这个示例中,我们将对一部运行 Android Oreo 的 rooted 智能手机进行镜像:
- 从列表中选择合适的设备:
如您所见,我们的设备具有特权访问权限 — 这意味着它已 root。此外,我们立即获得了一些元数据,如操作系统版本、设备序列号等。如果因某种原因要镜像的设备未列出,可以使用“没有显示我要查找的设备”选项。这包含了关于如何使工具检测到它的逐步指南。
- 一旦选择了正确的设备,您可以选择镜像类型:
-
有两个选项:完整和快速。第一个是物理获取,不总是可用,而第二个是逻辑获取,适用于任何 Android 设备。由于我们的设备已 root,因此我们可以选择完整选项。
-
最后,选择文件夹和镜像名称,目标以及必要时填写其他字段:
- 单击获取按钮将启动获取过程。在我们的示例中,对 16 GB 存储的成像仅需 10 分钟。如果查看日志文件 (
activity_log.txt
),您会注意到实际使用了相同的工具 —dd
和toybox
:
如您所见,使用 Magnet ACQUIRE 对 Android 设备进行影像的方式比使用 dd
和 netcat
要简单得多,但在底层,这个过程是相同的。有时,该工具甚至可以帮助您对非 root 设备进行物理获取,因为它包含多个能够获取临时特权访问权限的漏洞,以及可用于获取未加密设备完整镜像的 TWRP 自定义恢复。
验证完整的物理镜像
验证图像文件与设备相同是传统数字取证中的关键步骤。在 Android 设备上,这可能有点棘手,甚至不可能。可以使用检查人员通常使用的任何工具对已创建的图像进行哈希处理。通过 ADB shell 可以通过以下命令验证设备上的内存,其中给定的路径是已镜像的块或分区:
md5sum /dev/block/mmcblk0
然而,并非所有 Android 设备都包含 md5sum
命令。如果没有包含在内,鉴定人员可以尝试在网上找到适用于其设备的编译版本,并将其推送到设备的 tmpfs
分区中,就像之前展示的那样,使用 netcat
和 nanddump
。
另一个问题是如果图像是在现场获取的,即不是在恢复模式下获取的,如前一章讨论的。可以几乎肯定地说,MD5 散列值将不匹配,因为设备上的数据不断变化(即使是 RF 屏蔽或处于飞行模式)。在这种情况下,鉴定人员必须记录设备在获取时处于活动状态,并解释散列值不匹配是预料之外的情况。
分析完整的物理镜像
一旦通过前面的方法获取了镜像,检查员可能会手动浏览镜像并提取每个分区,但通常会更倾向于避免这样做。幸运的是,有各种各样的移动取证工具可以处理物理镜像,例如 Cellebrite UFED、Oxygen Forensic、Magnet AXIOM、Belkasoft Evidence Center 等等。不幸的是,这些工具都不是免费的或开源的;目前最流行的免费开源分析工具是由 Basis Technology 开发的 Autopsy。
Autopsy
Sleuth Kit 最初是一套基于 Linux 的命令行工具,用于取证;后来,加入了一个名为 Autopsy 的基于浏览器的 GUI。最近,Autopsy 被作为独立平台在 Windows 上发布,并支持分析 Android 镜像。以下截图展示的是版本 4.9.0。加载和分析镜像的完整过程将在第八章中介绍,Android 取证工具概览。
可以从www.sleuthkit.org/autopsy/download.php
下载 Autopsy。
图像加载完成后,展开图像会显示 Autopsy 找到的所有卷:
这些卷之一将是数据分区,如以下截图所示:
请注意,前面截图中的媒体目录就是 SD 卡,因为它与数据分区进行了符号链接。/data
分区中的 data
文件夹将包含应用程序数据:
每当安装一个应用程序时,系统会为其创建一个目录。
请注意,文件夹上显示红色 X 图标表示该文件夹已被删除,这意味着应用程序已从设备中移除。
最后,Autopsy 能够自动提取一些数据供检查员使用,但和所有取证工具一样,这些信息应手动验证。我们将在第七章中介绍,Android 应用程序的取证分析:
分析物理转储时的问题
我们在许多取证论坛和邮件列表上看到的最常见问题是,检查员获取了物理转储后,无法将其加载到声称支持该设备的工具中。绝大多数情况下,这是因为检查员没有考虑到带外(OOB)区域。
OOB 区域,有时称为备用区域,是闪存中的一小部分,专门保留用于元数据。元数据通常包含错误纠正码(ECC)、坏块信息,有时还包含文件系统信息。这对检查员来说是一个问题,因为大多数移动取证工具没有考虑 OOB 区域;它们假设图像中不包括此区域。当工具遇到包含备用区域的图像时,通常不知道该如何处理,导致无法正确解析数据。
工具无法考虑 OOB 区域的原因是,OOB 区域未包含在dd
图像中,而大多数工具使用dd
来创建图像。当使用nanddump
时,OOB 区域可能会被包含在内,但根据使用的二进制文件,可能会有一个选项来排除它。OOB 区域通常会包含在芯片脱离和 JTAG 图像中。
为了正确地将图像加载到取证工具中,首先需要去除 OOB 区域。一个常见的经验法则是,OOB 大小基于设备的页面大小;每 512 字节的页面大小会有 16 字节的 OOB 空间。例如,一个页面大小为 2,048 字节的设备,可能会在每个页面的末尾有 64 字节的 OOB 区域。然而,这完全取决于内存制造商。在尝试移除 OOB 区域之前,检查员应该查找特定内存芯片的数据手册,以确认页面和 OOB 区域的大小。通常可以通过在手机的电路板上找到内存芯片,并搜索该芯片的型号来完成此操作。
以下是一个 Python 脚本示例代码,用于从图像中移除 OOB 区域。正如上一章所述,我们并不声称自己是 Python 专家,我们确信有更好、更高效的方法来实现这一点,但它确实有效:
import sys
file_to_parse = open(sys.argv[1],'rb')
file_after_removal = open('file_out.bin','wb')
while file_to_parse:
lines_out = file_to_parse.read(2048)
if lines_out:
file_after_removal.write(lines_out)
file_to_parse.seek(64,1)
if not lines_out:
break
print 'Done'
file_to_parse.close()
file_after_removal.close()
如果该文件名为OOB_Remover.py
,则可以使用以下命令执行:
python OOB_Remover.py C:\Users\Android_Examiner\physicaldump.bin
输出文件将命名为file_out.bin
,并存放在执行脚本的目录中,该文件不包含 OOB 区域。原始文件不会以任何方式进行编辑或修改。
请注意,代码的编写假设页面大小为 2,048 字节,OOB 大小为 64 字节;这两个数字需要根据图像所提取的内存芯片的具体大小进行编辑。之后,输出文件应该能够加载到商业移动取证工具中。
映像和分析 Android 内存
由于需要 root 权限,提取 Android 内存在许多情况下是不可行的。大多数公共 root 过程涉及重启手机,这会清除易失性 RAM,这意味着当检查员获得 root 权限以进行 RAM 成像时,已经太晚,因为 RAM 已经被清除。因此,由于这个原因,可能还有其他原因,商业取证领域对 Android RAM 成像和分析的支持并不强大。然而,也有一些情况可以使用 RAM 成像,并可能对案件至关重要。如果设备在被扣押时已经 root,那么 RAM 成像应该成为扣押过程中的必备步骤。由于关闭手机会清除 RAM,因此设备应该设置为飞行模式(并禁用所有其他网络连接,如 Wi-Fi 和蓝牙),并应立即对 RAM 进行成像,以避免设备电池耗尽前无法提取 RAM。
RAM 分析的主要挑战是数据处理。RAM 是完全原始的、无结构的数据;没有文件系统。当在十六进制编辑器中查看时,RAM 看起来只是一个巨大的数据块,几乎没有任何规律或提示来帮助检查员理解他们正在查看的内容。这个难度因现代设备通常有数 GB 的 RAM 而加剧。RAM 可以使用传统的取证工具和方法通过关键词进行搜索,但这要求检查员完全知道他们在寻找什么。
在 RAM 中可以找到什么?
任何写入闪存的数据都必须经过 RAM;处理器与闪存的通信只能通过 RAM 进行。这意味着,几乎所有在设备上进行的操作都可能出现在 RAM 转储的内容中。根据设备的使用情况,数据可能会在 RAM 中无限期存在,直到需要被覆盖。RAM 转储通常包含设备上输入的文本,包括用户名和密码,以及没有永久存储在设备上的应用数据。例如,Facebook 应用程序曾将用户新闻源的内容存储在其应用文件夹中的数据库里。新版本不再保存用户的新闻源,但它仍然存在于 RAM 中。
使用 LiME 对 RAM 进行成像
Android RAM 获取最常用的工具是Linux 内存提取器(LiME),之前称为 DMD。LiME 是免费的开源工具,但并不是非常用户友好,因为它要求用户从源代码编译,这只能在 Linux 系统上完成。编译过程还必须为每个被检查的设备的每个 Android 版本单独进行,这在一定程度上限制了它在实际应用中的可用性。这是必要的,因为 LiME 不是二进制工具(像我们之前使用的netcat
和nanddump
工具);相反,它是一个内核模块,必须为每个将要加载的内核专门编译。
为了确保正确的内核源代码被下载,我们需要确定设备的型号和软件版本,可以通过滚动手机菜单至设置 | 系统 | 关于手机来完成。或者,这些信息也可以通过在 ADB shell 中运行以下命令来获取:
cat /system/build.prop
型号的软件版本应该位于文件顶部的前几行。
幸运的是,大多数 Android 厂商都会发布他们的内核源代码;通过快速的 Google 搜索,通常可以找到每个型号和软件版本的源代码。以下是一些主要厂商的开源发布网站:
-
谷歌(Nexus 设备):
source.android.com/source/building-kernels.html
必须使用正确的型号和版本源。使用错误的内核源来编译 LiME 至少会导致设备无法运行。加载不兼容的内核模块也可能导致设备崩溃。
要获取 LiME 的源代码,请访问 github.com/504ensicsLabs/LiME
,选择“Download ZIP”选项,然后解压 .zip
文件。
网上有许多优秀的资源解释了如何为特定内核编译 LiME,甚至如何创建自定义的 Volatility 插件来检查生成的 RAM 转储,因此这里不会重复介绍:
-
Linux 内存提取器:
github.com/504ensicsLabs/LiME/tree/master/docV
-
波动性:
github.com/volatilityfoundation/volatility/wiki/Android
获取 Android SD 卡
如本章及之前章节所讨论的,SD 卡可以指物理的外部 SD 卡或闪存内的一个分区。可拆卸的外部 SD 卡可以通过写保护器与典型的计算机取证工具分开成像,或者使用之前展示的 dd/nanddump
技术进行成像,尽管前者通常由于不需要通过 netcat
写入数据而更快。
物理成像 SD 卡与我们之前讨论的物理成像非常相似;事实上,如果 SD 卡与 /data
分区符号链接,它将作为 /data
分区的一部分被获取,如 Autopsy 部分的截图所示。唯一的不同之处在于,如果正在对 SD 卡进行成像,输出文件不能写入到 SD 卡中!这意味着,使用我们之前讨论的 netcat
方法是进行内置 SD 卡物理成像的最佳选择。
SD 卡上可以找到什么?
默认情况下,SD 卡通常用于存储大文件,包括下载的内容和用设备拍摄的照片。许多应用程序还会在 SD 卡上创建自己的目录,用于存储通过聊天应用发送或接收的图像等数据。在某些情况下,正如在第八章《Android 取证工具概述》中所看到的,甚至有些应用程序会定期将所有数据备份到 SD 卡。这对取证检查员特别有用,因为他们可能无法访问内部存储器,原因可能是安全设置或无法获取 root 权限,但他们可能能够访问 SD 卡。
常见的 SD 卡位置包括但不限于以下内容:
-
/Alarms
: 可能包含自定义闹钟 -
/Android/data
: 一些应用程序数据的存储位置 -
/DCIM/Camera
: 包括用设备相机拍摄的照片 -
/Download
: 可能包含下载的文件 -
/Movies
: 可能包含下载的视频文件 -
/Notifications
: 可能包含自定义通知 -
/Pictures
: 可能包含不同的图像,包括在设备上拍摄的截图 -
/Podcasts
: 可能包含下载的播客 -
/Ringtones
: 可能包含自定义铃声
即使应用程序已被删除,/Android/data
文件夹仍然可能存在。文件夹的内容将被删除,但文件夹可能会保留,这表明该应用程序之前曾安装在设备上。
这些只是常见的默认位置;如果设备已获取 root 权限,用户可以将任何内部存储的数据转移到 SD 卡上。
第六章:从 Android 设备恢复已删除的数据
本章将介绍数据恢复技术,使我们能够查看已从设备中删除的数据。已删除的数据可能包含高度敏感的信息,因此数据恢复是移动取证中的一个关键方面。
本章将涵盖以下主题:
-
数据恢复概述
-
从 SD 卡中恢复已删除的数据
-
从 SQLite 数据库中恢复数据
-
从手机内部存储中恢复删除的数据
-
使用文件雕刻恢复已删除的数据
数据恢复概述
数据恢复是数字取证中的一个强大概念。它是从设备或 SD 卡中检索已删除数据的过程,当这些数据无法正常访问时,恢复数据至关重要。能够恢复用户已删除的数据有助于解决民事或刑事案件。这是因为许多被告只是删除设备上的数据,希望证据被销毁。因此,在大多数刑事案件中,已删除的数据可能至关重要,因为它可能包含用户希望从 Android 设备中擦除的信息。例如,考虑一下从恐怖分子那里查获的手机。如果知道他们删除了哪些项目,岂不是最为重要吗?获取任何已删除的短信、图片、拨打的号码等信息可能至关重要,因为它们可能揭示大量敏感信息。
从普通用户的角度来看,恢复已删除的数据通常意味着参考操作系统内置的解决方案,比如 Windows 中的回收站。虽然从这些位置恢复数据是可能的,但由于用户意识的提高,这些选项往往不再有效。例如,现在人们在桌面计算机上使用Shift + Del来完全删除文件。同样,在移动环境中,用户知道应用程序提供的恢复操作等。尽管存在这些情况,数据恢复技术仍然使法医调查员能够访问已从设备中删除的数据。
就 Android 而言,可以恢复大部分已删除的数据,包括短信、图片、应用程序数据等。但重要的是要以正确的方式查封设备并遵循某些程序,否则数据可能会被永久删除。为确保已删除的数据不丢失,建议牢记以下几点:
-
查封手机后,切勿进行任何操作。已删除的短信仍存在于设备中,直到某些其他数据占用该空间,因此必须避免对手机进行任何操作,以防止数据被覆盖。
-
即使手机没有使用,且没有我们干预,数据仍然有可能被覆盖。例如,接收的短信会自动占用空间,从而覆盖已删除的数据。此外,远程清除命令也可以擦除设备上存在的内容。为了防止这种情况发生,可以考虑将设备放入法拉第袋中,正如第一章《介绍 Android 取证》一文中所解释的那样。这样,应特别小心避免通过任何通讯方式传送新消息或数据。
如何恢复已删除的文件?
当用户从设备中删除任何数据时,数据并不会被实际擦除,而是继续存在于设备上。被删除的是指向该数据的指针。所有文件系统都包含元数据,它保存有关文件层次结构、文件名等的信息。删除操作并不会真正擦除数据,而是移除文件系统的元数据。因此,当文本消息或其他文件从设备中删除时,它们只是对用户不可见,但文件仍然存在于设备上,只要没有被其他数据覆盖。因此,在新数据添加并占用空间之前,仍有恢复它们的可能。删除指针并标记空间为可用的操作与实际擦除设备上的所有数据相比是一个极其快速的操作。因此,为了提高性能,操作系统仅删除元数据。
恢复 Android 设备上已删除数据涉及三种情况:
-
恢复从 SD 卡删除的数据,如照片、视频等
-
恢复已删除的 SQLite 数据库数据,如短信、聊天记录、网页历史等。
-
恢复已删除的设备内部存储数据
以下章节将介绍可以用于从 SD 卡、SQLite 数据库和 Android 设备内部存储中恢复已删除数据的技术。
从 SD 卡恢复已删除的数据
存储在 SD 卡上的数据能够揭示许多在法医调查中有用的信息。事实上,照片、视频、语音录音和应用数据都存储在 SD 卡上,这进一步证明了这一点。如前几章所述,Android 设备通常在其 SD 卡上使用 FAT32 或 exFAT 文件系统。这样做的主要原因是这些文件系统被包括 Windows、Linux 和 macOS X 在内的大多数操作系统广泛支持。FAT32 格式化驱动器上的最大文件大小约为 4GB。随着现在越来越高的分辨率格式的出现,这一限制常常被突破,这就是为什么较新的设备支持 exFAT:这种文件系统没有这样的限制。如果外部 SD 卡可以作为驱动器挂载,恢复已删除的数据相对容易。
如果 SD 卡是可移动的,可以通过使用卡读器将其连接到计算机,从而将其作为驱动器挂载。在挂载时,可以向 SD 卡转移任何文件。某些使用 USB 大容量存储的旧设备也会在通过 USB 电缆连接时将设备挂载为驱动器。如前所述,在取证中,为确保原始证据不被修改,通常会对磁盘进行物理镜像,所有后续实验也都在镜像文件上进行。类似地,在 SD 卡分析中,也需要制作 SD 卡的镜像。镜像过程与第五章中解释的从 Android 设备中物理提取数据相似。一旦镜像完成,我们将得到一个原始镜像文件。在我们的示例中,我们将使用 AccessData 的 FTK Imager,这是一个镜像工具。除了创建磁盘镜像外,它还可以用来探索磁盘镜像的内容。
以下是使用此工具恢复 SD 卡内容的步骤:
- 启动 FTK Imager,点击菜单中的“文件”,然后选择“添加证据项...”,如以下截图所示:
向 FTK Imager 添加证据来源
-
在“选择源”对话框中选择“映像文件”,然后点击“下一步”。
-
在“选择文件”对话框中,浏览到下载
sdcard.dd
文件的位置,选择它,然后点击“完成”,如下面的截图所示:
在 FTK Imager 中选择用于分析的图像文件
-
FTK Imager 的默认显示将展示 SD 卡内容,显示在右下角的查看窗格中。你还可以点击左下角的属性标签查看磁盘镜像的属性。
-
现在,在左侧窗格中,驱动器已打开。可以通过点击加号打开文件夹。当选中一个文件夹时,右侧窗格会显示其内容。选择一个文件后,其内容会显示在底部窗格。
-
如下图所示,被删除的文件会在其文件扩展名图标上方显示一个红色的
X
:
被删除的文件在图标上显示红色 X
- 如下图所示,要导出文件,请右键点击包含图片的文件,然后选择“导出文件...”:
有时,只能恢复文件的一部分,这部分无法直接读取或查看。在这种情况下,我们需要查看空闲或未分配空间中的更多数据。文件雕刻技术可以用来从空闲和未分配的空间中恢复文件。PhotoRec 是可以帮助你完成此操作的工具之一。接下来的部分你将学习如何使用 PhotoRec 进行文件雕刻。
从 SQLite 数据库恢复已删除的记录
安卓中大部分的应用数据都存储在 SQLite 数据库中。与短信、电子邮件以及大多数应用数据相关的数据都存储在 SQLite 数据库中。这些数据库可以在数据库内部存储已删除的数据。用户标记为删除的记录不再出现在活动的 SQLite 数据库文件中。因此,通过分析这些 SQLite 文件,可以恢复已删除的数据,例如短信、联系人等。SQLite 页面中有两个区域可以包含已删除的数据:未分配块和空闲块。大多数商业取证工具通过扫描 SQLite 页面的未分配块和空闲块来恢复已删除的数据。解析已删除的数据可以使用例如 Belkasoft Evidence Center 等工具进行。该商业取证工具的试用版可以在这里下载:belkasoft.com/get
。
在我们的例子中,我们将从安卓设备中恢复已删除的短信。恢复已删除的短信是设备取证分析中常见的请求,主要因为它是最流行的通信方式。有不同的方法可以恢复安卓设备上的已删除短信。但是,就解析 SQLite 文件来进行恢复而言,我们需要了解短信存储在设备上的位置。在第四章,从安卓设备中逻辑地提取数据,我们解释了安卓设备上存储用户数据的重要位置。
让我们来查看bugle_db
,这是一个包含通过 Android 消息应用程序发送或接收的短信的 SQLite 数据库。该数据库位于/data/data/com.android.messaging/databases
目录下。如果你有设备的物理镜像,你可以使用 FTK Imager 提取数据库,就像提取已删除的文件一样。如果你想直接从设备中提取,可以使用adb pull
命令(设备必须已经 root)。
找到已删除记录的最简单方法是使用商业移动取证工具,如 Belkasoft Evidence Center、Cellebrite UFED Physical Analyzer、Oxygen Forensic Detective 等,但也有一些开源工具能够从未分配空间和空闲列表中恢复数据。一个这样的工具是由 Mari DeGrazia 开发的 SQLite Deleted Records Parser。你可以在她的 GitHub 上下载这个工具:github.com/mdegrazia/SQLite-Deleted-Records-Parser
。
该工具有三种版本:Python 脚本、命令行版本和 GUI 版本。为了演示,我们将使用 GUI 版本,如下所示的例子所示:
使用该工具非常简单,您只需要选择源数据库和目标文件,然后点击处理。结果将得到一个 TSV 文件(如果选择了格式化输出),其中包含恢复的记录,包括其来源(未分配空间或空闲块)、偏移量和长度。
SD 卡安全
在旧版安卓系统中,简单地将手机插入计算机,通常会自动挂载 SD 卡并允许检查员访问其数据。在某个版本的安卓系统(可能是 3.0 版)中,这一行为发生了变化,尽管我们在多个变更日志中没有找到具体版本的描述。新版本的安卓系统如果启用了屏幕锁定,将不会自动允许从计算机访问 SD 卡,这意味着需要绕过屏幕锁定才能访问 SD 卡。唯一的例外是,物理外部 SD 卡仍然可以被取出,并使用传统的计算机取证方法进行分析。
SD 卡也可以被加密,如果是内置 SD 卡,则通过设备的全盘加密进行加密;如果是外部 SD 卡,则通过第三方应用程序进行加密。在某些情况下,启用全盘加密会使 SD 卡保持未加密状态,尽管这取决于设备制造商。
在安卓 Lollipop 系统中引入的全盘加密也对 SD 卡进行了加密。
高级取证方法
除了前几章中讨论的方法,还有一些更先进的、专业化的方法可供使用。JTAG 和芯片拆卸方法在许多常见情况下是非常有用的工具,但它们需要高级培训(并且在处理实际证据之前需要大量的实践!)。最后一种高级方法——冷启动攻击以恢复加密密钥,更加理论化。
JTAG
JTAG,联合测试行动小组(JTAG)是由电气和电子工程师协会(IEEE)制定的标准。在设备生产过程中,JTAG 用于通过专用接口与处理器进行通信,进行测试。幸运的是,对于取证检查员来说,它还允许他们直接与处理器通信,并获取闪存的完整物理映像。
要执行 JTAG 提取,设备必须拆开,直到电路板。电路板上将包含多个接点(设备电路板上的物理接触点),虽然它们通常没有标签,且接点数量通常远多于 JTAG 所需的数量。为了确定正确的接点,检查员必须查找引脚图(可以在网上找到,或随所选工具提供),或使用电子测试设备确定每个接点的功能。
检查员接下来需要将一根线焊接到每个接点上,或者使用商业上可用的适配器(有时称为夹具),并通过提供的适配器将其连接到 JTAG 盒子:
HTC Evo 在连接 JTAG 前后的情况(感谢 http://lowcostwin4n6.blogspot.com/)
JTAG 听起来可能很复杂(因为它确实很复杂),但它有许多有用的用途:
-
它不需要设备开机:
-
即使设备损坏,也可能成功
-
无射频屏蔽问题
-
-
它不需要 root、ADB 或 USB 调试:
-
可用于绕过设备的 PIN 码/密码
-
可以映像整个闪存
-
许多制造商生产 JTAG 工具,许多用于移动取证的常见工具可以在 teeltech.com/mobile-device-forensic-software/teel-tech-jtag-box-sets/
找到。该网站上列出的 RIFF box 可能是最常用于移动取证的工具,因为它支持(包括针脚排布)多种设备。
JTAG 并不总是成功,甚至有时无法实现。尽管接口几乎总是在电路板上,制造商可以选择在设备制造后禁用它。
拆芯片
拆芯片涉及加热设备的电路板,直到固定组件的焊接点融化,然后拆除闪存芯片。随后,可以使用商业工具读取内存芯片,从而获得完整的物理映像。拆芯片技术,像 JTAG 一样,源自商业电子生产过程。熔化焊料的过程(通常称为回流或返工)用于将组件放置到电路板上或从电路板上移除,读取内存所使用的设备用于读取和写入内存芯片,通常以批量形式进行操作:
从损坏的手机中取出的内存芯片(感谢 www.binaryintel.com)
拆芯片具有与 JTAG 相同的优点:它不需要设备开机,并且可以用来绕过锁定设备的 PIN 码/密码。拆芯片通常被视为一种破坏性过程。虽然内存芯片可以被替换,但这是一个技术要求较高的过程,需要进一步的培训。但是,作为最后的手段,拆芯片是对于那些否则无法检查的设备来说是一个极好的替代方案。
拆芯片比 JTAG 显著更昂贵,因为需要专用的返工站和商业内存读卡器。有数十种返工站可供选择,它们提供的功能基本相同。也有多种内存读卡器,尽管我们在使用这个价格合理的型号时取得了很大成功:www.dataman.com/programmers/universal/dataman-48pro2-super-fast-universal-isp-programmer.html
。返工站和读卡器并不是拆芯片唯一的成本;大多数读卡器还需要为每个要读取的芯片型号配备特定的适配器。
总结
本章中,我们讨论了几种用于物理成像内部存储或 SD 卡的技术,以及它们相关的一些常见问题:
技术 | 相关问题 |
---|---|
dd |
-
通常预安装在设备上
-
可能无法在 MTD 块上使用
-
无法获取带外区域
|
nanddump |
---|
-
设备上通常没有此功能,必须将其推送到设备上
-
与 MTD 块配合良好
-
可以基于使用的二进制文件中的选项获取带外区域
|
此外,每种成像技术可以用于将图像保存到设备上(通常是 SD 卡),或使用netcat
将文件写入检查员的计算机:
技术 | 特性 |
---|---|
写入 SD 卡 |
-
简单,不需要将额外的二进制文件推送到设备上
-
对大多数检查员来说很熟悉
-
如果 SD 卡与正在成像的分区存在符号链接,则无法使用
-
如果正在成像整个内存,则无法使用
|
使用netcat |
---|
-
通常需要将另一个二进制文件推送到旧设备上
-
稍显复杂,必须严格按照步骤操作
-
无论成像的是什么,都能正常工作
-
可能比写入 SD 卡更费时
|
还介绍了一些可以用于 RAM 成像的工具:
工具 | 特性 |
---|---|
LiME |
-
必须为每个被检查的设备编译
-
非常复杂的过程
-
具有已知且良好文档化的分析程序
-
输出是所有 RAM 的转储
|
最后,我们简要讨论了芯片拆卸和 JTAG 技术的入门级内容。
在下一章中,我们将演示如何从物理镜像(如本章创建的镜像)中恢复已删除的数据。
恢复内部存储已删除的数据
从 Android 的内部存储中恢复已删除的文件,如应用数据等,并不像从 SD 卡和 SQLite 数据库中恢复这些数据那样简单,但当然并非不可能。许多商业取证工具能够从 Android 设备中恢复已删除的数据,当然,前提是物理获取是可能的,并且 userdata 分区没有加密。但对于现代设备,尤其是运行最新操作系统版本(如 Oreo 和 Pie)的设备,这并不常见。
大多数安卓设备,尤其是现代智能手机和平板电脑,使用 EXT4 文件系统来组织其内部存储中的数据。该文件系统在基于 Linux 的设备中非常常见。因此,如果我们想从设备的内部存储中恢复已删除的数据,我们需要一款能够从 EXT4 文件系统中恢复已删除文件的工具。一个这样的工具是 extundelete。该工具可以在此下载:extundelete.sourceforge.net/
。
为了恢复一个 inode 的内容,extundelete 会在文件系统的日志中查找该 inode 的旧副本。inode 中包含的信息帮助工具定位文件在文件系统中的位置。为了恢复文件的内容及其名称,extundelete 可以在目录中查找已删除的条目,将文件的 inode 编号与文件名匹配。
要使用这个工具,你需要一台 Linux 工作站。大多数法医 Linux 发行版已经自带该工具。例如,下面是来自SIFT Workstation的截图——这是一个由 Rob Lee 和他的 SANS 学院团队创建的流行数字取证和事件响应 Linux 发行版(digital-forensics.sans.org/community/downloads
):
extundelete 命令行选项
在开始恢复过程之前,你需要挂载一个之前已镜像的 userdata 分区。在这个示例中,我们将使用通过芯片脱离技术镜像的 Android 设备——你已经在第五章中了解过这种技术,物理提取 Android 设备数据。
首先,我们需要确定 userdata 分区在镜像中的位置。为此,我们可以使用来自Sleuth Kit的mmls
,如下所示的截图:
Android 设备分区
如截图所示,userdata 分区是最后一个,起始扇区为9199616
。为了确保 userdata 分区是 EXT4 格式的,我们可以使用fsstat
,如下所示的示例:
fsstat 输出的部分内容
现在你需要做的是挂载 userdata 分区并运行 extundelete,如下所示的示例:
extundelete /userdata/partition/mount/point --restore-all
所有恢复的文件将被保存在当前目录的子目录RECOVERED_FILES
中。如果你有兴趣恢复指定日期之前或之后的文件,可以使用--before date
和--after-date
选项。请注意,这些日期必须采用 UNIX 纪元格式。有很多在线和离线工具可以转换时间戳,例如,你可以使用www.epochconverter.com/
。
如你所见,这种方法不太简单且速度较慢,但有一种更好的方法:使用 Autopsy,这是一款开源数字取证工具,已在第三章中介绍过,理解 Android 设备上的数据存储。
在下面的示例中,我们使用了内置的文件扩展名过滤器,找到了 Android 设备上的所有图片,并发现了大量已删除的文件:
使用 Autopsy 从 EXT4 分区恢复已删除的文件
使用文件系统日志恢复已删除的文件并不总是可能的,这正是文件雕刻派上用场的地方。
使用文件雕刻恢复已删除的数据
文件雕刻是取证中一种非常有用的方法,因为它可以恢复已删除或隐藏的数据进行分析。简而言之,文件雕刻是从没有文件系统元数据的碎片中重新组装文件的过程。在文件雕刻中,会在二进制数据中搜索并提取指定的文件类型,从而创建分区或整个磁盘的取证镜像。文件雕刻仅基于文件结构和内容,从驱动器的未分配空间中恢复文件,而不依赖任何匹配的文件系统元数据。
未分配空间是指驱动器中不再包含任何文件信息的部分,这些信息由文件系统结构如文件表指示。
通过扫描磁盘的原始字节并重新组装它们,可以恢复或重建文件。这可以通过检查文件的头部(前几个字节)和尾部(最后几个字节)来完成。
文件雕刻方法是根据所使用的底层技术进行分类的。头尾雕刻方法依赖于根据文件的头部和尾部信息恢复文件。例如,JPEG 文件以 0xffd8
开头,以 0xffd9
结尾。头部和尾部的位置被识别出来,介于这两个端点之间的内容会被雕刻出来。类似地,文件结构雕刻方法基于文件的内部布局来重建文件。但传统的文件雕刻技术,如我们已经解释过的那些,如果数据是碎片化的,可能无法奏效。为了克服这一问题,新的技术,如 智能雕刻,利用多种流行文件系统的碎片特征来恢复数据。
一旦手机映像完成,就可以使用如 PhotoRec 等工具进行分析。PhotoRec 是一个强大的免费工具,可以雕刻文件。该工具分析块数据库存储,识别已删除的文件并恢复它们。Scalpel 是文件系统无关的,并且已知能够在多种文件系统上工作,包括 EXT4、exFAT、FAT32 等。以下步骤说明了如何在 Windows 工作站上使用 PhotoRec 恢复文件:
-
从
www.cgsecurity.org/wiki/TestDisk_Download
下载工具。将压缩包解压到你选择的目录中。 -
使用管理员权限打开命令提示符,并运行
photorec.exe
,并将 Android 物理镜像作为参数。 -
选择你想从中雕刻数据的分区,在我们的例子中是
USERDATA
。如下截图所示:
在 PhotoRec 中选择分区
- 如果你只想雕刻特定的文件类型,可以前往
File Opt
。在我们的例子中,我们只关心 JPG 图像,因此我们只选择了一种文件类型,如下图所示:
在 PhotoRec 中选择文件类型
- 选择文件系统类型,在我们的例子中是 EXT4,如以下示例所示:
在 PhotoRec 中选择文件系统类型
- 现在,你应该选择工具是只扫描空闲空间,还是扫描整个分区。第二个选项会给你带来更多的数据,但它将与那些未被删除的文件混合在一起。以下示例展示了这些选择:
选择是否需要分析所有空间
- 最后,选择恢复的文件将存储的文件夹。你可以使用箭头键来完成此操作,然后按 C,如以下截图所示:
恢复的文件将保存在所选目录下名为 recup_dir
的子目录中。
总结
数据恢复是从设备中恢复已删除数据的过程,因此它是取证中非常重要的概念。在本章中,我们介绍了从 SD 卡和内部存储中恢复已删除数据的各种技术。虽然从可移动 SD 卡恢复数据相对容易,但从内部存储中恢复数据则涉及一些复杂性。SQLite 文件解析和文件雕刻技术有助于取证分析人员恢复 Android 设备内部存储中已删除的项目。
在下一章中,我们将尝试理解取证视角以及对 Android 应用程序的分析。
第七章:Android 应用程序的法医分析
本章将覆盖应用程序分析。本章将重点分析通过 第四章 从 Android 设备中逻辑提取数据 和 第五章 从 Android 设备中物理提取数据 中详细描述的任何逻辑或物理技术恢复的数据。本章还将大量依赖于 第二章 设置 Android 法医环境 中讨论的存储方法;我们将看到来自该章节中描述的文件层次结构内不同位置的 SQLite 数据库、XML 文件以及其他文件类型。到本章结束时,读者应当熟悉以下内容:
-
应用程序分析概述
-
为什么要进行应用程序分析?
-
第三方应用程序以及流行应用程序用于存储和混淆数据的各种方法
应用程序分析概述
法医分析应用程序既是一门科学,也是一门艺术。应用程序可以通过各种方式存储或混淆其数据。即便是同一版本的应用程序,其数据存储方式也可能不同。开发者在选择数据存储方式时,实际上只受限于他们的想象力(以及 Android 平台的限制)。正因为这些因素,应用程序分析是一项不断变化的工作;分析人员今天使用的方法,明天可能就完全不再适用。
法医分析应用程序的最终目标始终是相同的:了解应用程序的用途,并找到用户数据。
本章将探讨许多常见应用程序的当前版本。由于应用程序可能会通过更新更改其数据存储方式,本章中的内容并不是分析这些应用程序的权威指南。相反,我们将查看各种不同的应用程序,以展示它们存储数据时所使用的多种不同方法。大多数情况下,我们将重点关注非常常见的应用程序(例如,Google Play 上有数百万次下载的应用程序),除非在分析一些冷门应用时能揭示出有趣的新数据存储方式。
为什么要进行应用程序分析?
首先,Android 设备上的标准电话功能,如联系人、通话和短信,都是通过应用程序来实现的,因此即使是获取基本数据也需要分析应用程序。其次,一个人使用的应用程序可以告诉你很多关于他们的信息:他们去过哪里(以及何时去的),他们与谁沟通过,甚至他们未来可能会有什么计划。
许多手机预装了超过 20 个应用程序。检查员实际上无法知道这些应用中哪些可能包含对调查有用的信息,因此必须对所有应用进行分析。检查员可能会想跳过那些看起来似乎没有什么有用数据的应用,如游戏。然而,这样做是个坏主意;许多流行的游戏都有内置聊天功能,可能会提供有价值的信息。我们的分析将重点关注消息应用程序,因为我们的经验表明,这些应用在法医分析中通常最有价值。
本章布局
对于我们检查的每个应用程序,我们将提供一个包名和相关文件。所有应用默认将其数据存储在 /data/data
或 /data/user_de/0
(较新的设备)目录下;如果应用在安装时请求此权限,应用也可以使用 SD 卡。包名是该应用在这些目录中的文件夹名称。相关文件 部分中的路径是从包名根目录开始的。SD 卡上的数据路径以 /sdcard
开头。请不要期望在应用的 /data/data
或 /data/user_de/0
目录中找到以 /sdcard
开头的数据路径!
我们将从一些谷歌应用程序开始,因为这些应用通常预装在大多数设备上(尽管并非必须如此)。然后,我们将查看可以在 Google Play 上找到的第三方应用程序。
确定安装了哪些应用
若要查看设备上有哪些应用程序,检查员可以导航到 /data/data
并运行 ls
命令。但这并不会提供格式良好的数据,无法在法医报告中显示得很好。我们建议提取 /data/system/packages.list
文件;该文件列出了设备上每个应用的包名和其数据路径(如果该文件在设备上不存在,adb shell pm list packages –f
命令是一个不错的替代选择)。例如,以下是 Google Chrome 的一条记录(我们测试设备上的完整文件包含 120 条记录):
这是数据存储方法 1:纯文本。我们常常看到应用以纯文本形式存储数据,甚至包括一些你意想不到的数据(例如密码)。
也许更有趣的是 /data/system/package-usage.list
文件,它显示了某个包(或应用)最后一次被使用的时间。这个文件并不完美;文件中显示的时间与我们最后一次使用该应用的时间并不完全一致。看起来应用更新或接收通知(即使用户没有查看它们)也可能影响时间,然而它对于一般了解用户最后使用的应用来说是有用的:
如果你想知道那一行中哪里可以找到时间,它采用的是被称为 Unix 纪元时间的格式。
理解 Unix 纪元时间
Unix 纪元时间,也称为 Unix 时间或 Posix 时间,是以自 1970 年 1 月 1 日午夜 UTC 以来的秒数(或毫秒数)表示的。10 位数值表示秒数,13 位数值表示毫秒数(至少对于智能手机上常见的时间,因为自 2001 年以来,9 位秒数和 12 位毫秒数值已不再出现)。在我们的示例中,值为1422206858650
;表示自 1970 年 1 月 1 日午夜以来,Google Chrome 上次使用的时间是 14 亿 2 千 2 百 20 万 6 千 8 百 58 秒 650 毫秒!不用担心,我们也不知道这是哪个日期/时间。可以下载许多脚本和工具来将其转换为人类可读的格式;我们喜欢 DCode,这是一个免费的工具,可以在这里找到:www.digital-detective.net/digital-forensic-software/free-tools/
。
在 DCode 中,只需从下拉列表中选择Unix: 毫秒值,在要解码的值字段中输入值,然后点击解码:
可以选择添加偏差字段,将时间转换为所需的时区。
另外,您还可以使用一个非常有用的在线纪元计算器,网址为www.epochconverter.com/
。
使用任一方法,我们可以看到 Google Chrome 实际上是在 2015 年 1 月 25 日 17:27:38.650 UTC 上次使用的。Unix 纪元时间在 Android 设备中经常用于存储日期/时间值,并且在我们的应用分析中会反复出现。
Wi-Fi 分析
Wi-Fi 技术上不是一个应用程序,但它是一个宝贵的数据来源,应该进行检查,所以我们在这里简要讨论一下。Wi-Fi 连接数据位于/data/misc/wifi/wpa_supplicant.conf
中。wpa_supplicant.conf
文件包含用户选择自动连接的接入点列表(当新接入点连接时,默认情况下会设置此选项)。用户通过设备设置忘记的接入点不会显示。如果接入点需要密码,密码也以明文形式保存在文件中。在以下示例中,NETGEAR60
接入点需要密码(ancientshoe601
),而 hhonors
则不需要:
文件中存在的 SSID 并不意味着该设备已连接到该接入点。这些设置保存在用户的 Google 帐户中,并在该帐户设置时添加到设备中。检查者只能得出结论,用户从某个 Android 设备连接了这些接入点,而不一定是正在检查的设备。
联系人/通话分析
联系人和通话记录存储在同一个数据库中。用户无需显式添加联系人,当通过 Gmail 发送电子邮件、在 Google+ 上添加联系人或通过其他许多方式时,联系人可能会自动填充。
包名:com.android.providers.contacts
关注的文件:
-
/files/
:-
photos/
-
profile/
-
-
/databases/
:-
contacts2.db
-
calllog.db
-
files
目录包含用户联系人照片存储在 photos
目录中的照片,以及用户个人资料照片存储在 profile
目录中的照片。
contacts2.db
数据库包含用户 Google 帐户中所有联系人的所有信息:
表格 | 描述 |
---|---|
accounts |
显示设备上有权限访问联系人列表的帐户。至少有一个帐户会显示用户的 Google 帐户电子邮件地址。该列表可能包括已安装的第三方应用程序,这些应用程序有权限访问联系人列表(我们将在 Tango、Viber 和 WhatsApp 部分看到这一点)。 |
contacts |
包含部分联系人信息(更多数据可以在 raw_contacts 表中找到)。name_raw_contact_id 值对应于 raw_contacts 表中的 _id 值。photo_file_id 值对应于在 /files/photos 目录中找到的文件名。times_contacted 和 last_time_contacted 显示该联系人通过设备拨打或接听的次数,以及最后一次通话的时间,时间格式为 Unix 时间戳格式。 |
data |
此表包含每个联系人的所有信息,如电子邮件地址和电话号码。raw_contact_id 列是每个联系人的唯一值,可以与 raw_contact_id 中的 _id 值相关联来识别联系人。请注意,每个联系人可能有多行记录,如相同的 raw_contact_id 值所示。共有 15 个数据列(data1 -data15 ),包含一些关于联系人的信息,但没有明显的规律。同一列可能包含联系人姓名、电子邮件地址、Google+ 个人资料等。data14 列的值与 files/profiles 路径下的图片文件名相关联。data15 列包含联系人的个人资料照片缩略图。 |
deleted_contacts |
包含 contact_id 值和 Unix 时间戳格式的 deleted_contact_timestamp 。然而,无法将其与其他表格关联以识别被删除联系人的姓名。不过,可能可以使用 第六章 中的已删除数据恢复技巧,从 Android 设备恢复已删除数据,来恢复联系人的姓名。contact_id 值对应于 raw_contacts 表中的 contact_id 列。 |
groups |
显示联系人列表中的群组,可以是自动生成的或用户创建的。群组的标题是群组的名称。似乎没有办法识别每个群组中的用户。 |
raw_contacts |
包含联系人列表中每个联系人的所有信息。display_name 显示联系人的姓名(如果有)。要确定联系人的电话号码、电子邮件地址或其他信息,必须将 _id 列的值与数据表中的 raw_contact_id 值匹配。sync3 列显示一个时间戳,但根据我们的测试,这不能假设为联系人添加的时间;我们有一些联系人已经好几年了,但这个月才同步。times_contacted 和 last_time_contacted 列仅适用于电话;发送电子邮件或 SMS 给联系人并不会增加这些值。我们无法识别任何方法来确定联系人是通过手机界面添加的、通过 Google+ 添加为好友的,还是通过其他方式添加的。 |
calllog.db
包含关于来电、去电和未接来电的所有信息:
表格 | 描述 |
---|
| calls
| 包含设备上所有进出通话的信息。number
列显示远程用户的电话号码,以及该通话是拨出还是接听。date
列是通话的日期/时间,存储为 Unix 时间戳格式。duration
列是通话的持续时间(秒)。type
列表示通话类型:
-
收件
-
外发
-
未接来电
name
列显示远程用户的姓名,如果该号码已存储在联系人列表中。geocoded_location
显示电话号码的位置,基于区号(美国号码)或国家代码。|
SMS/MMS 分析
SMS 和 MMS 消息存储在同一数据库中。根据我们的经验,无论使用什么应用程序发送 SMS/MMS(也就是说,通过 Google Hangouts 发送 SMS 将填充此数据库,而不是这里检查的 Hangouts 数据库),此数据库都会被使用,尽管第三方应用程序也可能在其自己的数据库中记录这些数据。
包名:com.android.providers.telephony
感兴趣的文件:
-
/files
-
/databases/
:-
mmssms.db
-
telephony.db
-
files
目录包含作为 MMS 发送的附件,包括发送和接收的文件。
telephony.db
数据库较小,但包含一个潜在有用的信息源:
表格 | 描述 |
---|---|
siminfo |
包含设备中使用过的所有 SIM 卡的历史数据,包括 ICCID、电话号码(如果它存储在 SIM 卡上)和 MCC/MNC,后者可用于识别网络提供商。 |
mmssms.db
数据库包含有关 SMS 和 MMS 消息的所有信息:
表格 | 描述 |
---|---|
part |
包含关于 MMS 附件文件的信息。每条消息至少有两个部分:SMIL 头和附件—可以在 mid 和 ct 列以及附加的文件类型中看到。_data 列提供了在设备上查找文件的路径。 |
pdu |
包含每条彩信的元数据。date 列标识消息发送或接收的时间,采用 Linux 纪元格式。_id 列似乎对应于part 列中的 mid 值;关联这些值可以显示特定图片发送的时间。msg_box 列显示消息的方向(1 = 接收,2 = 发送)。 |
sms |
包含每条短信的元数据(不包括彩信信息)。地址列显示远程用户的电话号码,无论消息是发送还是接收。person 列包含一个可以在contacts2.db 数据库中查找的值,并与data 表中的raw_contact_id 对应。如果是发送的消息,或者远程用户不在联系人列表中,person 列将为空。date 列显示消息发送的时间戳,采用 Linux 纪元格式。type 列显示消息的方向(1 = 接收,2 = 发送)。body 列显示消息内容。seen 列表示消息是否已读(0 = 未读,1 = 已读);所有发送的消息将标记为未读。 |
words , words_content , words_segdir |
似乎包含消息的重复内容;该表的具体目的尚不清楚。 |
用户字典分析
用户字典是检查员获取数据的一个不可思议的来源。每当用户输入一个未被识别的单词并选择保存该单词以避免被自动更正标记时,用户字典就会被填充。有趣的是,我们的测试设备中包含了许多我们从未输入或保存过的单词;这些数据似乎会与用户的 Google 账户同步,并在多个设备之间持久存在。从账户同步的单词按字母顺序添加到数据库的顶部,而手动添加的单词则按添加顺序出现在底部。
包名:com.android.providers.userdictionary
感兴趣的文件:
/databases/user_dict.db
表格 | 描述 |
---|---|
words |
word 列包含添加到字典中的单词。频率列可能应被忽略;无论我们使用该单词多少次,它显示的值始终是(250)。 |
以下是用户字典中的一些示例条目:
Gmail 分析
Gmail 是由 Google 提供的电子邮件服务。在设备第一次设置时,通常会要求提供 Gmail 账户,虽然这不是必须的。
包名:com.google.android.gm
感兴趣的文件:
-
/cache
-
/databases/
:-
mailstore.<username>@gmail.com.db
-
databases/suggestions.db
-
-
/shared_prefs/
:-
MailAppProvider.xml
-
Gmail.xml
-
UnifiedEmail.xml
-
应用程序文件夹中的/cache
目录包含最近的邮件附件文件,无论是已发送还是已接收的。这些附件即使没有被用户明确下载,也会保存在这里。
mailstore.<username>@gmail.com.db
文件包含各种有用的信息。数据库中的有趣表格包括:
表 | 描述 |
---|---|
附件 |
关于附件的信息,包括它们的大小和在设备上的文件路径(上文提到的/cache 目录)。每一行还包含一个messages_conversation 值;该值可以与对话表进行对比,以关联附件和它所在的邮件。filename 列标识文件在设备上的存储路径。 |
对话 |
在旧版本中,可以恢复完整的电子邮件对话。在当前版本中,Google 不再在设备上存储完整的对话,可能假设用户会有数据连接来下载完整对话。现在,只能恢复主题行和一个片段。片段大致是应用通知栏或收件箱屏幕中显示的文本量。fromCompact 列标识发件人和其他收件人。 |
suggestions.db
数据库包含了在应用内搜索的术语。
shared_prefs
目录中的 XML 文件可以确认与应用程序一起使用的账户。Gmail.xml
包含了与我们测试账户关联的另一个账户,但该账户从未在应用中使用。UnifiedEmail.xml
包含了一部分向该账户发送邮件的发件人列表,但没有明确的规律;许多发件人出现在列表中,但远不是所有的,而且它们没有特定的顺序。Gmail.xml
还包含了应用程序上次同步的时间,格式为 Unix 时间戳。
Google Chrome 分析
Google Chrome 是一款网页浏览器,是许多设备的默认浏览器。设备上的 Chrome 数据有些独特,因为它包含的不仅仅是设备上的数据,还包含了用户在所有登录了 Chrome 的设备上的数据。这意味着,用户在台式电脑上浏览的数据很可能会出现在手机数据库中。然而,这也导致了考察者需要处理大量数据,但这也是一个好问题。
包名:com.android.chrome
感兴趣的文件:
-
/app_chrome/Default/
:-
同步数据/SyncData.sqlite3
-
书签
-
Cookies
-
Google Profile Picture.png
-
历史记录
-
登录数据
-
Preferences
-
热门网站
-
Web 数据
-
-
/app_ChromeDocumentActivity/
/app_chrome/Default
文件夹中列出的所有文件,除了那个 PNG 文件、Bookmarks
和Preferences
,都是 SQLite 数据库,尽管它们没有文件扩展名。
SyncData.sqlite3
数据库非常有趣,因为它似乎包含了一份从用户账户在设备上同步到 Google 服务器的数据列表。我们的数据库中,活跃的 Chrome 账户包含超过 2700 条记录,包括浏览历史、自动填充表单信息、密码和书签。例如,我们能够找到其中一位作者在 2012 年搜索的一个术语,见下图:
表格 | 描述 |
---|---|
metas |
数据库中有许多包含时间戳的列,在我们的数据库中,每个条目的时间戳似乎相差仅仅几秒。尚不清楚哪个时间对应于条目添加的确切时间,但所有时间大致与用户账户中活动的时间一致。包含时间戳的列有 mtime 、server_mtime 、ctime 、server_ctime 、base_version 和 server_version 。non_unique_name 和 server_non_unique_name 列显示已同步的内容。例如,我们的一个条目显示:autofill_entry|LNAME|Tindall 。这些列中的其他条目包括访问过的 URL、密码,甚至账户使用过的设备。 |
Bookmarks
文件是一个纯文本文件,包含与账户同步的书签信息。它包括每个书签站点的名称、URL 以及书签添加的日期/时间,时间以我们尚未遇到的格式存储:Webkit 格式。要解码这些值,请参见 解码 Webkit 时间格式 部分。
这是数据存储方法 3:Webkit 时间格式。
Cookies
数据库存储了访问过网站的 cookie 信息(取决于网站和 Chrome 设置),包括网站名称、cookie 保存日期以及最后访问 cookie 的时间,时间以 Webkit 时间格式存储。
Google Profile Picture.PNG
文件是用户的个人资料图片。
History
数据库包含用户的网页历史记录。
表格 | 描述 |
---|---|
keyword_search_terms |
包含在 Chrome 中使用 Google 搜索的术语列表。术语列显示搜索的内容,而 url_id 可以与 URL 表进行关联,以查看搜索的时间。 |
segments |
该表包含一些访问过的 URL,但并非所有的 URL。尚不清楚是什么原因导致数据被输入到这个表中。 |
urls |
包含 Google 帐号在所有设备上的浏览历史记录,而不仅仅是从中提取数据库的设备。我们的历史记录追溯大约 3 个月,包含了 494 条记录,尽管 Google 帐号比这更早,我们在这段时间内肯定访问了超过 494 个页面。目前尚不清楚导致这种差异的具体原因,或者是什么决定了历史记录的截止日期。id 列是每行数据的唯一值。url 和 title 列分别包含访问的 URL 和页面的名称。visit_count 列似乎准确计数了访问该 URL 的次数。typed_count 始终小于或等于 visit_count ,但我们不确定它具体表示什么。对于某些网站,可以通过计算通过书签访问网站而非直接输入 URL 的次数来解释这种差异,但并非所有情况都如此。last_visit_time 是访问该 URL 的最后时间,以 Webkit 时间格式表示。 |
visits |
包含每次访问 urls 表格中 URL 的记录;该表格中每个 URL 的条目数与 url 表格中的 visit_count 列值相对应。url 列值与 url 表格中的 id 列值相关联。每次访问的时间可以在 visit_time 列中找到,同样是 Webkit 时间格式。 |
Login Data
数据库包含保存在 Chrome 中的登录信息,并且会在使用 Google 帐号的所有设备之间同步:
表格 | 描述 |
---|---|
logins |
origin_url 是用户最初访问的网站,action_url 是如果用户被重定向到登录页面的 URL;如果第一个访问页面就是登录页面,那么两个 URL 是相同的。username_value 和 password_value 列显示为该 URL 存储的用户名和密码(明文);我们不会包括数据库的截图!date_created 是首次保存登录信息的日期/时间,以 Webkit 时间格式表示。date_synced 列是登录数据被同步到设备本地的日期/时间,同样采用 Webkit 时间格式。times_used 列显示登录信息在保存后由 Chrome 自动填充的次数(不包括第一次登录,因此某些值可能为 0)。 |
-
Preferences
文件是一个文本文件,包含用户已登录 Chrome 的 Google 帐号。 -
Top Sites
数据库包含最常访问的网站,这些网站在 Chrome 启动时默认显示。 -
Web Data
数据库包含用户为自动填充网站表单而保存的信息。
表格 | 描述 |
---|---|
autofill |
包含网页表单上的字段列表和用户输入的值。name 列显示用户输入的字段名称,value 列显示用户输入的内容。date_created 和 date_last_used 很容易理解,并以 Linux 纪元格式存储。请注意,尽管这可能是非常有价值的信息(例如,我们的数据库中包含了一些没有存储在其他地方的用户名),但也很少有上下文可供参考。无法确定存储这些信息的 URL,并且可能无法确定。 |
autofill_profile_emails |
包含用户保存的用于自动填写网页表单中 email 字段的所有值。 |
autofill_profile_names |
包含用户保存的用于自动填写网页表单中 First、Middle、Last 和 Full Name 字段的所有值。 |
autofill_profile_phonwa |
包含用户保存的用于自动填写网页表单中 Phone Number 字段的所有值。 |
autofill_profiles |
包含用户保存的用于自动填写网页表单中地址信息字段的所有值。 |
/app_ChromeDocumentActivity/
目录包含设备上最近打开的标签页的历史记录文件。可以从这些文件中恢复访问过的网站的 URL。
解码 Webkit 时间格式
这是一个 Webkit 时间值的示例:13066077007826684。
乍一看,它似乎与 Unix 纪元时间非常相似,只是稍微长一些(也许它存储的是纳秒?)。尝试将其解码为纪元时间的检查员将得到一个 2011 年 5 月的日期,这看起来可能很准确,但实际上与正确日期相差了好几年!
Webkit 时间 是 一种纪元时间,它只是基于不同于 Unix 纪元时间的起点。Webkit 纪元时间是自 1601 年 1 月 1 日午夜以来的微秒数。是的,我们说的是 1601 年。一旦知道纪元的起点,将其转换为一个可识别的格式就只是一个数学问题。但,再次强调,我们还是更愿意使用 DCode。
这次在 DCode 中,选择 Decode Format 下拉菜单中的 Google Chrome Value,然后点击 Decode:
我们示例的实际值是 2014 年 11 月 2 日 18:04:33 UTC;这与我们如果以 Unix 纪元时间来解读所得到的值有显著不同!
Google Maps 分析
Maps 是由 Google 提供的地图/导航应用程序。
包名: com.google.android.apps.maps
感兴趣的文件:
-
/cache/http/
-
/databases/
:-
gmm_myplaces.db
-
gmm_storage.db
-
/cache/http
文件夹包含许多文件,扩展名为 .0
和 .1
。.0
文件是对应 .1
文件的网页请求。.1
文件主要是图像文件,可以通过适当更改扩展名来查看;在我们的测试设备上,它们要么是 .jpg
文件,要么是 .png
文件。这些文件主要是用户附近的位置,不一定是用户特意搜索的位置。
这是数据存储方法 4:错误命名的文件扩展名
总是验证无法打开的文件的头部,或使用 EnCase 等自动化工具检测不匹配的头部/文件扩展名。验证文件签名的好资源是 www.garykessler.net/library/file_sigs.html
。
gmm_myplaces.db
数据库包含用户保存的位置。这些位置与用户的 Google 账户同步,因此这些位置未必是通过该应用程序保存的。
gmm_storage.db
包含搜索点击和已导航至的位置:
** 表格** | 描述 |
---|---|
gmm_storage_table |
_key_pri 列似乎标识了位置的类型,bundled 看起来是一个在搜索中出现的点击,而 ArrivedAtPlacemark 标识了实际导航到的位置。 _data 列包含了位置的地址。 |
谷歌即时通讯分析
Hangouts 是 Google 提供的聊天/SMS 应用程序。在 Android 设备上,Hangouts 是默认的 SMS 客户端。
包名:com.google.android.talk
感兴趣的文件:
-
/cache/volleyCache/
-
/databases/babel#.db
(我们的设备上有babel0.db
和babel1.db
) -
/shared_prefs/accounts.xml
cache
目录包含 .0
文件,如在 Google 地图示例中讨论的那样。这些文件包含一个用于获取联系人头像的 URL,以及文件中嵌入的 JPG。访问该 URL 或从文件中切割 JPG 将恢复联系人的图片。
babel#.db
文件包含所有的消息数据。在我们的测试设备上,babel0.db
是空白的,而 babel1.db
包含了活跃账户的所有数据。数据库中有许多值得查看的表格:
表格 | 描述 |
---|---|
conversations |
包含会话数据。每个聊天都有一个唯一的 conversation_id 。 latest_message_timestamp 是最近聊天的时间,采用 Linux epoch 格式。 generated_name 列列出了设备上的所有参与者,减去账户本身。 snippet_text 列是最近消息的内容;与 Gmail 类似,设备上不会存储整个聊天记录。 latest_message_author_full_name 和 latest_message_author_first_name 列标识了 snippet_text 列的作者。 inviter_full_name 和 inviter_first_name 列标识了发起会话的人。 |
dismissed_contacts |
列出了曾经发消息的联系人的姓名列表。这些在应用程序内被标记为 隐藏联系人。 |
messages |
如预期的那样,包含每个对话的详细消息历史记录。文本列包含消息内容,时间戳列是 Linux 时间戳格式的日期/时间。remote_url 列再次是一个 URL,用于检索消息中共享的图像,可以公开访问。author_chat_id 是一个值,可以与参与者表相关联,用来识别每条消息的作者。 |
participants |
包含与之聊天的人的列表。包括全名、个人资料图片 URL 和一个 chat_id 用于在消息表中标识该人。 |
accounts.xml
文件有一个 phone_verification
字段,包含与 Google 账户关联的电话号码,当 Hangouts 配置为发送 SMS 时使用。这可能非常有用,因为通常很难获取设备的电话号码,因为它通常不存储在设备中。
Google Keep 分析
Keep 是由 Google 提供的便签应用。它还可以用于设置提醒,提醒可以在某个特定日期/时间或用户位于指定位置时触发。
包名: com.google.android.keep
相关文件:
-
/databases/keep.db
-
/files/1/image/original
/files/1/image/original
目录包含使用应用程序拍摄的照片。便签和提醒都可以与图像相关联。
Keep.db
包含所有关于便签和提醒的信息。再次提到,有几个重要的表格:
表格 | 描述 |
---|---|
alert |
包含关于基于位置的提醒信息。reminder_id 可以与提醒表中的条目相关联。reminder_detail 表包含为提醒设置的纬度和经度。scheduled_time 是设置提醒的日期/时间,采用 Linux 时间戳格式。 |
blob |
包含 /files 目录中图像的元数据,包括文件名和大小。blob_id 可以与 blob_node 表中的 _id 列相关联。 |
blob_node |
包含 /files 目录中图像的创建时间值,采用 Linux 时间戳格式。 |
list_item |
存储设备上每个便签的数据。文本列包含每个便签的完整内容。list_parent_id 列是每个便签的唯一值;如果多行具有相同的值,则表示它们是在同一便签内作为列表创建的。time_created 和 time_last_updated 列分别是便签的创建时间和最后一次与 Google 服务器同步的时间,采用 Linux 时间戳格式。 |
reminder |
包含应用中设置的每个提醒的数据。如果提醒是基于时间的,julian_date 和 time_of_day 列将被填充。 |
转换 Julian 日期
儒略日类似于 Linux 纪元格式,只是从不同的日期开始。儒略日系统计算的是自公元前 4713 年 1 月 1 日中午以来的天数。美国海军天文台提供了一个优秀的儒略日计算器:aa.usno.navy.mil/data/docs/JulianDate.php
。要从数据库中获取儒略日,只需将两列结合在一起,中间用小数点隔开,例如:
这将对应于儒略日2457042.46800000
。当此值输入到网站时,我们可以得知设置的提醒日期是 2015 年 1 月 19 日,23:13:55.2 UT。如果设置了基于位置的提醒,location_name
、latitude
、longitude
和location_address
字段将会被填充。最后,time_created
和time_last_updated
字段分别表示笔记创建的时间和最后与 Google 服务器同步的时间,以 Linux 纪元时间表示。
数据存储方法 5:儒略日
从 Skype 恢复视频消息
如前所述,视频消息不会保存在设备上。幸运的是,我们可以通过互联网访问它们。第一步是通过查看body_xml
列中的 Messages 表来验证视频消息是否已发送。接下来,记下该消息的convo_id
字段:
我们的视频消息在convo_id
为257
。
然后,在 Chats 表中查找该convo_id
在conv_dbid
列中的记录,并找到dbpath
值。这将是会话备份文件的名称:
要找到备份文件,请查看files/<用户名>/chatsync
目录。每个会话都会有一个文件夹,文件夹的名称是备份名称的前两位数字。我们的备份将位于28
文件夹中。
在十六进制编辑器中打开备份文件,并搜索videomessage
。你应该能找到一个 URL 和一个用于访问视频的代码:
实际访问该 URL 可能需要额外的逮捕令或法律许可,这取决于当地的法律管辖区。由于这些数据不在设备上,且属于私人数据,未经法律指导访问这些数据可能会使视频中的任何证据无效。
Google Plus 分析
Google Plus 是一个基于 Google 的社交网络。它允许分享文本/视频/图片,添加朋友,关注他人并进行消息交流。根据用户的设置,Google Plus 还可能自动上传用户设备上拍摄的所有图片。
包名:com.google.android.apps.plus
感兴趣的文件:
/databases/es0.db
Es0.db
包含了调查员期望从社交媒体账户中找到的所有信息:
表格 | 描述 |
---|---|
all_photos |
包含一个 URL,用于下载用户共享或与用户共享的图像,以及以 Linux 纪元格式显示的创建日期/时间 |
activities |
显示在用户动态流中的数据(即他们的新闻推送)。每个帖子的创建和修改时间再次以 Linux 纪元时间格式存储。标题和评论列将包含帖子的标题以及至少一些评论。永久链接列包含一个可以点击查看帖子的 URL(如果帖子是公开分享的)。如果帖子是私密分享的,仍然可以从嵌入表中恢复其内容。相关表包含由 Google 自动生成的与帖子的相关标签,即使帖子是私密的,也会填充这些标签。 |
activity_contacts |
包含在活动表中发布的人员的姓名列表。 |
all_photos |
包含用户备份到 Google Plus 的所有照片的列表,无论这些照片是否已被分享。image_url 可用于下载用户的任何照片,并且是公开可用的。删除 URL 末尾的 -d 可以在不下载的情况下查看图片。时间戳列是图片被 拍摄 的日期/时间,基于图片的元数据;它不表示图片上传的时间。 |
all_tiles |
包含 all_photos 的一个未知子集,还包括用户共享的图像。 |
circle_contact |
包含用户已添加到其圈子中的人员列表。不包含姓名,但一些 link_person_id 值包含电子邮件地址。link_circle_id 值可以与圈子表关联,以识别每个圈子的名称。然后,link_person_id 可以与联系人表关联,以识别每个用户属于哪个圈子。 |
circles |
包含用户创建的所有圈子,以及每个圈子的成员数量。 |
contacts |
用户圈子中的所有联系人列表。 |
events |
用户被邀请的所有事件的列表,无论是否参加。名称列是事件的标题。creator_gaia_id 可以与联系人表中的 gaia_id 列关联,以识别事件的创建者。start_time 和 end_time 列表示事件的开始时间和结束时间,采用 Linux 纪元格式。event_data 列包含创建者输入的事件描述,以及如果有添加的地点信息。还列出了所有其他被邀请参加事件的用户。 |
squares |
用户加入的群组列表。 |
Facebook 分析
Facebook 是一款社交媒体应用,已在 Google Play 上被下载超过 10 亿次。
包名: com.facebook.katana
感兴趣的文件:
-
/files/video-cache/
-
/cache/images/
-
/databases/
-
bookmarks_db2
-
contacts_db2
-
nearbytiles_db
-
newsfeed_db
-
notifications_db
-
prefs_db
-
threads_db2
-
/files/video-cache
目录包含来自用户新闻推送的视频,但似乎没有办法将这些视频与发布它们的用户关联起来。
/cache/images
目录包含来自用户新闻源的图片,以及联系人个人资料照片。该目录包含多个其他子目录(我们测试的手机上有 65 个),每个子目录可以包含多个 .cnt
文件。.cnt
文件通常是 JPG 文件或其他图像格式。
bookmarks_db2
数据库是显示在用户新闻源侧边的项目列表,如群组和应用程序。许多这些书签是 Facebook 自动生成的,但也可以由用户创建。
表格 | 描述 |
---|---|
bookmarks | 包含数据库中的所有信息。bookmark_name 列是显示给用户的书签名称。bookmark_pic 列包含一个可以公开访问的 URL,用于查看显示给用户的书签图标。bookmark_type 列标识组的类型;我们的测试显示包括 profile 、group 、app 、friend_list 、page 和 interest_list 。最后,bookmark_unread_count 列显示该组中用户未读的消息数量。 |
contacts_db2
数据库,顾名思义,包含所有用户联系人的信息:
表格 | 描述 |
---|---|
contacts |
包含关于用户所有联系人信息。fbid 列是唯一标识符,用于在其他数据库中标识该联系人。first_name 、last_name 和 display_name 列显示联系人的姓名。small_picture_url 、big_picture_url 和 huge_picture_url 包含联系人个人资料照片的公共链接。communication_rank 似乎是一个数字,表示该联系人与用户之间的沟通频率(考虑了消息、评论,可能还有其他因素);较高的数字表示与该联系人的沟通频率较高。added_time_ms 显示联系人作为朋友被添加的时间(以 Linux 纪元格式表示)。bday_day 和 bday_month 列显示联系人的生日日期,但不包括年份。data 列包含数据库中其他所有数据的副本,还包含联系人位置,这是数据库中其他地方找不到的。 |
nearbytiles_db
是一个包含用户附近可能感兴趣的位置的数据库;显然,这个数据库会持续更新,即使用户没有查看这些位置。这个数据库很有趣,因为,虽然它不是精确的位置(我们的大部分测试显示的地点距离我们的位置大约 6-10 英里),但它提供了一个粗略的用户活动区域:
表格 | 描述 |
---|---|
nearby_tiles |
包含用户附近位置的纬度和经度值,以及从 Facebook 服务器获取该位置的时间(以 Linux 纪元格式表示)。 |
newsfeed_db
包含显示在用户新闻源中的数据。根据应用程序的使用情况,它可能是一个非常大的文件:
表格 | 描述 |
---|---|
home_stories |
fetched_at 列显示故事从 Facebook 服务器拉取的时间,通常与用户使用应用程序或查看故事的时间非常接近。story_data 列包含故事,作为数据块存储。当在十六进制或文本编辑器中查看时,可以找到发布故事的用户名。帖子内容也可以以纯文本形式找到,并且通常会以 text 标签作为前缀。下面是一个示例: |
请注意,story_data
列中的这个单元格的实际内容包含超过 10,000 字节的数据,尽管实际消息只有大约 50 字节。
notifications_db
包含发送给用户的通知:
表格 | 描述 |
---|---|
gql_notifications |
seen_state 列显示通知是否已被查看和阅读。更新列包含通知更新的时间(即如果未读则为发送时间,或者为阅读时间),以 Linux 时间戳格式显示。gql_payload 列包含通知的内容以及发送者,类似于 newsfeed_db 中的 story_data 列。消息内容通常会以 text 标记为前缀。少量数据(显示通知文本)可以在 summary_graphql_text_with_entities 和 short_summary_graphql_text_with_entities 列中找到。profile_picture_uri 包含一个公共 URL,用于查看发送者的个人资料图片,而 icon_url 列则有一个链接,用于查看与通知相关的图标。 |
prefs_db
数据库包含应用程序偏好设置:
表格 | 描述 |
---|---|
preferences |
/auth/user_data/fb_username 行显示用户的 Facebook 用户名。/config/gk/last_fetch_time_ms 值是应用程序最后一次与 Facebook 服务器通信的时间戳,但可能不是用户最后一次与应用程序互动的确切时间。/fb_android/last_login_time 显示用户通过应用程序登录的最后时间。数据库中包含许多其他时间戳,当这些时间戳组合在一起时,可以用来构建一个不错的应用使用情况档案。/auth/user_data/fb_me_user 包含关于用户的数据,包括他们的姓名、电子邮件地址和电话号码。 |
threads_db
数据库包含消息信息:
表格 | 描述 |
---|---|
messages |
每条消息在 msg_id 列中都有一个唯一的 ID。文本列包含消息的纯文本。发送者列标识消息发送者的 Facebook ID 和姓名。timestamp_ms 列是消息发送的时间,采用 Linux 时间戳格式。附件列包含一个公共 URL,用于检索附加的图片。坐标列将显示发送者的经纬度,如果他们选择显示位置的话。来源列标识消息是通过网站还是应用程序发送的。 |
Facebook Messenger 分析
Facebook Messenger 是一款独立于主 Facebook 应用程序的消息应用。它在 Play Store 上的下载量超过 5 亿。
包名: com.facebook.orca
感兴趣的文件:
-
/cache/
-
audio/
-
fb_temp/
-
image/
-
-
/sdcard/com.facebook.orca
-
`/files/ rti.mqtt.analytics.xml`
-
/databases/
-
call_log.sqlite
-
contacts_db2
-
prefs_db
-
threads_db2
-
/cache/audio
目录包含通过应用程序发送的音频消息。这些文件的扩展名为 .cnt
,但实际上是 RIFF 文件,可以使用 Windows Media Player、VLC 媒体播放器等程序播放。
/cache/fb_temp
路径包含通过应用程序发送的图片和视频的临时文件。文件将保留多久尚不明确;在我们的测试中,我们发送和接收了共五个文件,且一周后所有五个文件仍然保留在临时文件夹中。
/cache/image
目录包含许多其他目录(我们测试的手机上有 33 个),每个目录可以包含多个 .cnt
文件。应验证每个文件的文件头,因为其中一些是视频文件,另一些是图片。我们找到了几个来自 fb_temp
文件夹的文件,以及一些联系人的头像。
SD 卡上的 fb_temp
文件夹仅包含已发送的图片和视频。
该应用程序还包括一个选项(默认情况下禁用),用于将所有接收到的图片/视频下载到设备的图库中。如果选择此选项,所有接收到的图片/视频将出现在 SD 卡上。
/files/rti.mqtt.analytics.xml
文件包含用户的 Facebook UID。
call_log.sqlite
数据库包含通过应用程序进行的通话记录。person_summary
表包含相关数据:
表格 | 描述 |
---|---|
person_summary |
user_id 列包含远程用户的 Facebook ID;可以通过与 contacts_db2 中的 fbid 列关联来确定该用户的名字。last_call_time 列包含上次通话的时间,采用 Linux 时间戳格式。此表不包含通话方向的信息(发送或接收)。 |
contacts_db2
文件是一个 SQLite 数据库,尽管没有文件扩展名。该数据库中有用的表包括:
表格 | 描述 |
---|---|
contacts |
此表包括用户添加的联系人,以及从用户手机簿中抓取的联系人(如果手机簿联系人使用 Facebook Messenger)。它包含每个联系人的名字和姓氏,以及该联系人的 Facebook ID(如在 call_log.sqlite 表中讨论)。added_time_ms 显示每个用户添加到应用程序的时间。这可以一定程度上揭示联系人是手动添加还是自动添加;在几毫秒内添加的大量联系人很可能是在应用程序安装时自动创建的。small_picture_url 、big_picture_url 和 huge_picture_url 列包含联系人公开的个人资料图片链接。联系人的电话号码可以在数据列中的信息块中找到。需要注意的是,我们不知道此数据库中的某些联系人来源。他们不是我们 Facebook 账户的好友,也不是设备电话簿中的联系人,但是在抓取电话簿时被添加进来。我们最好的猜测是我们电话中的一些联系人具有 Facebook 关联到其他用户的电话号码。 |
favorite_contacts |
favorite_contacts 表显示用户添加为收藏的联系人。它们由 fbid 列标识,可以与联系人表关联。 |
prefs_db
数据库包含有关应用程序和账户的有用元数据:
表格 | 描述 |
---|---|
preferences |
/messenger/first_install_time 值表示应用程序的安装时间,以 Linux 纪元时间为准。/auth/user_data/fb_username 值显示与应用程序关联的用户名。/config/neue/validated_phonenumbe r 值显示与应用程序关联的电话号码。用户的名字和姓氏可以在 /auth/user_data/fb_me_user 值中找到。 |
最后,threads_db2
数据库包含有关消息的数据:
表格 | 描述 |
---|---|
group_clusters |
显示用户创建的文件夹。 |
group_conversations |
包含每个群组聊天的 thread_key 值;这可以与消息表相关联。 |
messages |
thread_key 是为每个聊天会话生成的唯一 ID。文本列包含发送和接收的每条短信的内容。这也通过 You called Facebook User. 、Facebook User called you. 和 You missed a call from Facebook User 这些短语来标识语音电话。发送者列标识每条消息(或每个电话)的发送者。timestamp_ms 列显示每条消息的发送时间,采用 Linux 时间戳格式。附件列将显示每个发送或接收的附件的数据,文件类型也可以在数据中看到。pending_send_media_attachment 显示设备上用于恢复已发送附件的路径。直接找到接收到的附件似乎是不可能的,尽管它们在 /cache/images 目录中被恢复,但没有办法将它们与特定的消息或发送者相关联。 |
Skype 分析
Skype 是一个语音/视频通话应用程序,也是一个由微软拥有的消息应用程序,在 Google Play 上已有超过 1 亿次安装。
包名:com.skype.raider
关注的文件:
-
/cache/skype-4228/DbTemp
-
/sdcard/Android/data/com.skype.raider/cache/
-
/files/
-
shared.xml
-
<username>/thumbnails/
-
<username>/main.db
-
<username>/chatsync
-
/cache/skype-4228/DbTemp
目录包含多个没有扩展名的文件。我们设备中的一个文件(temp-5cu4tRPdDuQ3ckPQG7wQRFgU
)实际上是一个 SQLite 数据库,包含它曾连接过的无线接入点的 SSID 和 MAC 地址。
SD 卡路径将包含在聊天中接收到的任何图片或文件。如果下载了文件,它将保存在 SD 卡根目录下的 Downloads 文件夹中。
shared.xml
文件列出了账户的用户名,以及最后一次连接到 Skype 的 IP 地址:
<username>/thumbnails
目录包含用户的个人资料图片。
main.db
数据库,顾名思义,包含所有应用的使用历史记录。以下是一些重要的表格:
表格 | 描述 |
---|---|
Accounts |
显示设备上使用的账户以及相关联的电子邮件地址。 |
CallMembers |
应用的通话记录。持续时间表是通话的时长,start_timestamp 是通话开始的时间,采用 Linux 时间戳格式;如果通话未接听,这两列都不会被填充。creation_timestamp 是通话的实际开始时间;它会在通话在应用中启动时立即填充,因此即使通话没有接听,仍然会显示在这一列中。ip_address 列显示连接通话时用户的 IP 地址。类型列指示通话是拨出还是接入(1 = 接入,2 = 拨出)。guid 列也显示通话方向,列出每个参与者从左到右,左侧的用户为发起通话的用户。call_db_id 列可以与通话表进行关联,找到有关通话的更多信息。 |
Calls |
与 CallMembers 非常相似,但信息较少。值得注意的是,此表中的 begin_timestamp 列与 CallMembers 中的 creation_timestamp 相同。还有一个 is_incoming 列显示通话的方向:0 表示外呼,1 表示接听。最后需要注意的是,某些通话的时长与 CallMembers 表中的数据不匹配。一个时长比另一个表中显示的多了一秒钟。看起来 CallMembers 表是根据 start_timestamp 计算通话时长,而 Calls 表是根据 begin_timestamp 计算时长。时长差异可能是由于用户接受通话所花费的时间。 |
ChatMembers |
显示每个聊天中的用户。adder 列列出了发起聊天的用户。 |
Chats |
列出了每个独特的聊天会话。时间戳列是对话开始的日期/时间,采用 Linux 时间戳格式。dialog_partner 列显示聊天中的用户,不包括设备上的账号。posters 表显示每个在聊天中发表评论的用户,如果设备上的账号有发表内容,也会包括在内。participants 列与 dialog_partner 列类似,但包括用户的账号。最后,dbpath 列包含存储在 <username>/chatsync 目录中的聊天备份文件的名称。这个信息在本分析中将会变得非常重要。 |
Contacts |
这是一个非常误导的表。在我们的测试中,我们将两个用户添加到联系人列表中,但 Contacts 表却有 233 条记录!is_permanent 列表示该表中列出的用户状态;如果为 1,则表示该用户被作为实际联系人添加到应用中。其他 231 条记录似乎是我们在搜索联系人时出现的名字,但我们并未与这些人进行过沟通或添加为联系人。 |
Conversations |
我们不清楚 Conversations 和 Chats 之间的区别。它们包含了几乎相同的信息,实际上似乎指向相同的聊天会话。 |
| Messages
| 包含每一条来自聊天/对话的单独消息。convo_id
列为每个对话提供唯一的值;任何具有相同 convo_id
值的消息都来自同一对话。author
和 from_dispname
列显示每条消息的作者。时间戳列再次显示消息的日期/时间,采用 Linux 时间戳格式。type
列表示发送的消息类型;以下是我们测试时的值:
-
50: 好友请求
-
51: 请求已接受
-
61: 纯文本消息
-
68: 文件传输
-
30: 通话开始(语音或视频)
-
39: 通话结束(语音或视频)
-
70: 视频消息
body_xml
列包含消息的内容。对于纯文本消息和好友请求,内容就是消息的文字。文件传输显示文件的大小和名称。视频消息则显示它是视频消息,但不提供其他信息。通话记录显示如果通话已接通则显示时长,如果通话未接或被忽略则不显示时长。身份列显示每条消息的发送者,如果是设备上的用户账户发送的消息,可能为空。原因列似乎是用于通话,显示 no_answer
或 busy
来解释为什么通话未接通。
Participants |
与 ChatMembers 类似,显示每个参与聊天/对话的用户。 |
---|---|
SMSes |
我们的测试没有包括 SMS 消息;然而,这张表中的每一列都是自解释的。 |
Transfers |
显示已传输文件的信息,包括文件名、大小和设备上的路径。partner_dispname 列显示开始文件传输的用户。 |
VideoMessages |
显示视频消息的作者和创建时间戳。请注意,视频消息不会存储在设备上;获取它们的方式将在下文的另一个部分介绍。 |
VoiceMails |
我们的测试没有包括语音邮件;然而,这张表中的每一列看起来都是自解释的。 |
Snapchat 分析
Snapchat 是一款图片分享和文本消息服务,下载量超过 1 亿次。它的标志性特点是,用户发送的图片和视频会在发送者设定的时间限制(1-10 秒)后“自毁”。此外,如果用户截取了图片的屏幕截图,发送者会收到通知。文本聊天没有过期计时器。
包名: com.snapchat.android
相关文件:
-
/cache/stories/received/thumbnail/
-
/sdcard/Android/data/com.snapchat.android/cache/my_media/
-
/shared_prefs/com.snapchat.android_preferences.xml
-
/databases/tcspahn.db
/cache/stories/received/thumbnail
包含用户在设备上拍摄的图片的缩略图。/sdcard
路径包含完整尺寸的图片。即使时间限制已过且接收者无法再访问这些图片,它们仍然会保留。这些位置的文件可能没有正确的文件扩展名。
com.snapchat.android_preferences.xml
文件包含用于创建账户的电子邮件地址以及与账户注册的设备的电话号码。
tcspahn.db
数据库包含关于应用程序使用的所有其他信息。
表格 | 描述 |
---|---|
Chat |
列出所有文本聊天。显示发送者、接收者、Linux 时间戳以及消息的文字内容。 |
ContactsOnSnapchat |
显示用户电话簿中也安装了 Snapchat 的所有联系人。isAddedAsFriend 列如果用户已被添加为联系人,则会显示 1。 |
Conversation |
包含每个打开对话的信息。包括发送方和接收方,以及最后发送和接收快照的时间戳(Linux 纪元格式)。 |
Friends |
类似于ContactsOnSnapchat ,但仅包括已添加为朋友的用户。包含每个用户添加另一个用户的时间戳。 |
ReceivedSnaps |
接收到的图片和视频的元数据。一旦图片/视频被查看,它似乎在某个时刻从此表中移除。包含每条消息的时间戳、状态、是否截图以及发送方。 |
SentSnaps |
发送的图片和视频的元数据。一旦图片/视频被查看,它似乎在某个时刻从此表中移除。包含每条消息的时间戳、状态和接收方。 |
Viber 分析
Viber 是一款消息和语音/视频通话应用,下载量超过 1 亿。
包名:com.viber.voip
相关文件:
-
/files/preferences/
-
activated_sim_serial
-
display_name
-
reg_viber_phone_num
-
-
/sdcard/viber/media/
-
/User Photos/
-
/Viber Images/
-
/Viber Videos/
-
-
/databases/
-
viber_data
-
viber_messages
-
/files/preferences
中的文件包含 SIM 卡的 ICCID、用户在应用中显示的名称以及用于注册应用的电话号码。
/sdcard/viber/media
路径中的文件是用户联系人列表中使用 Viber 的人的个人资料照片(无论是否已经在应用中添加为朋友),以及通过该应用发送的所有图片和视频。
viber_data
文件是一个数据库,尽管它没有.db
文件扩展名。它包含有关用户联系人信息:
表格 | 描述 |
---|---|
calls |
这个表没有填充数据,尽管我们从应用中拨打了电话。 |
phonebookcontact |
从法医角度来看,这个表格可能非常有价值。当 Viber 首次打开时,它会抓取用户的电话簿并将找到的所有条目添加到此数据库中。这意味着它可能包含关于用户联系人历史数据;如果用户稍后从电话簿中删除了某个条目,它可能仍然能在这个数据库中恢复。此表格仅包括电话簿中联系人的姓名。 |
phonebookdata |
类似于电话簿联系人,但还包括设备电话簿中联系人的电子邮件地址和电话号码。 |
vibernumbers |
显示设备电话簿中每个联系人使用 Viber 应用的电话号码。actual_photo 中的值对应于/sdcard/viber/media/User/ Photos 目录中的文件名。 |
viber_messages
文件是一个数据库,尽管它没有.db
文件扩展名。它包含关于应用使用的信息:
表格 | 描述 |
---|---|
conversations |
包含每个唯一对话的唯一 ID、接收方和日期。 |
messages |
包含所有对话中的每条单独消息。地址是远程方的电话号码。日期列为 Unix 时间戳格式。类型列对应于消息的方向:1 表示发送消息,0 表示接收消息。如果共享了位置,location_lat 和 location_lng 列将被填充。共享的文件可以附带描述性文字;这些信息在描述列中找到。 |
messages_calls |
这个表格没有被填充,即使我们从应用内进行了通话。 |
participants_info |
包含与用户进行过对话的每个账户的个人资料信息。 |
Tango 分析
Tango 是一款语音/文本/视频消息应用,已在 Play Store 上拥有超过 1 亿次下载。
包名: com.sgiggle.production
这个包名看起来无害,可能会被检查人员误认为是一个游戏。这是每个应用都应该进行分析的原因之一。
感兴趣的文件:
-
/sdcard/Android/data/com.sgiggle.production/files/storage/appdata/
-
TCStorageManagerMediaCache_v2/
-
conv_msg_tab_snapshots/
-
-
/files/
-
tc.db
-
userinfo.xml.db
-
/TCStorageManagerMediaCache_v2
路径在 SD 卡中包含了通过应用发送和接收的图片,以及联系人头像。然而,它也包含了许多从未在应用中查看或使用的图片;这些图片看起来要么是广告图片,要么是可以附加到对话中的表情符号类型的图片。可以通过与 tc.db
关联,找到在对话中使用的具体图片。
conv_msg_tab_snapshots
路径在 SD 卡中包含扩展名为 .dat
的文件。当在十六进制编辑器中查看时,我们能够找到部分明文的对话片段,以及发送和接收的图片路径和 URL。尚不清楚是什么原因导致这些文件的存在,但可能可以从这些文件中恢复在 tc.db
中已删除的内容。
tc.db
数据库是 Tango 用来存储所有消息信息的:
表格 | 描述 |
---|---|
conversations |
每个对话在 conv_id 列中有唯一标识。 |
| messages
| 包含通过应用发送和接收的消息。msg_id
列是每条消息的唯一标识,conv_id
列标识消息来自哪个对话。send_time
列标识消息发送或接收的时间,取决于消息的方向。方向列显示消息的方向:1 = 发送,2 = 接收。类型列标识消息的类型;根据我们的测试,类型如下:
-
0: 明文消息
-
1: 视频消息
-
2: 语音消息
-
3: 图片
-
4: 位置/坐标
-
35: 语音通话
-
36: 尝试过的语音通话(双方均未接听)
-
58: 附带的股票图片,例如在
TCStorageManagerMediaCache_v2
路径下找到的表情符号
最后,负载列包含了消息的内容……可以这么说。这些数据是 Base64 编码的,下面会详细讨论。|
user_info_xml.db
包含有关账户的元数据,例如用户的姓名和电话号码。然而,它的数据完全是 Base64 编码的,就像 tc.db
中的消息一样。
数据存储方法 6:Base64
解码 Tango 消息
Base64 是一种常用于数据传输的编码方案;它不被视为加密,因为它有一个已知的解码方法,并且不需要唯一的密钥来解码数据。Base64 包含可打印的 ASCII 字符,但底层数据是二进制的(这会使我们的输出稍显杂乱!)。来自 tc.db 中消息表的负载列示例如下:
EhZtQzVtUFVQWmgxWnNRUDJ6aE44cy1nGAAiQldlbGNvbWUgdG8gVGFuZ28hIEhlcmUncyBob3cgdG8gY29ubmVjdCwgZ2V0IHNvY2lhbCwgYW5kIGhhdmUgZnVuIYABAKoBOwoFVGFuZ28SABoWbUM1bVBVUFpoMVpzUVAyemhOOHMtZyILCgcKABIBMRoAEgAqADD///////////8BsAHYioX1rym4AYKAgAjAAQHQAQDoAdC40ELIAgTQAgDqAgc4MDgwODg5yAMA2AMA2AXTHw==
注意我们消息末尾的等号;这是一个强烈的指示符,表明数据是 Base64 编码的。需要被编码的输入必须能够被 3 整除,以便 Base64 背后的数学方法能够正常工作。如果输入不能被 3 整除,它会被填充,导致输出中出现等号。
例如,考虑以下表格:
输入字符串 | 字符/字节数 | 输出 |
---|---|---|
Hello, World |
12 |
SGVsbG8sIFdvcmxk |
Hello, World! |
13 |
SGVsbG8sIFdvcmxkIQ== |
Hello, World!! |
14 |
SGVsbG8sIFdvcmxkISE= |
你可以看到,12 字节的输入(可被 3 整除)没有填充,而另外两个输入则有填充,因为它们不能被 3 整除。这一点很重要,因为它表明,虽然等号是 Base64 的强烈指示符,但没有等号并不意味着它就不是 Base64!
现在我们对 Base64 有了一定了解,并且认识到我们的负载列很可能是以 Base64 编码的,我们需要对其进行解码。有一些网站允许用户粘贴编码后的数据,并将其解密(例如:www.base64decode.org),但对于大量数据来说,这种方式不太方便,因为每条消息必须单独输入(而且在大多数情况下,将证据数据上传到互联网上也是不被推荐的)。同样,也可以在基于 Linux 的系统的命令行中解码,但对于大量数据同样不太方便。我们的解决方案是构建一个 Python 脚本,从数据库中提取 Base64 数据,解码后再写入到一个新文件中:
import sqlite3
import base64
conn = sqlite3.connect('tc.db')
c = conn.cursor()
c.execute('SELECT msg_id, payload FROM messages')
message_tuples = c.fetchall()
with open('tcdb_out.txt', 'w') as f:
for message_id, message in message_tuples:
f.write(str(message_id) + '\x09')
f.write(str(base64.b64decode(message)) + '\r\n')
要运行该代码,只需将此代码粘贴到一个新文件中,命名为 tcdb.py
,将脚本与 tc.db
放在同一目录下,然后在命令行中导航到该目录并运行以下命令:
python tcdb.py
脚本将在同一目录下生成名为 tcdb_out.txt
的文件。用文本编辑器打开该文件(或将其导入到 Excel 中作为制表符分隔的文件)将显示 msg_id
值,以便检查员可以将消息与消息表关联,并且解码后的有效载荷显示为明文消息(在数据库中标注为类型 0):
请注意,现在消息内容以明文形式显示,并且前面是会话 ID。输出中还有大量的二进制数据,这很可能是 Tango 使用的元数据或其他信息。如果消息是收到的,用户的姓名也会出现在输出中(这里是 Tango)。
还有其他类型的消息值得查看。这里是视频消息的解码有效载荷条目:
请注意,在视频消息中,我们可以看到两个网址。它们都是公开的,意味着任何拥有链接的人都可以访问它们。以缩略图结尾的 URL 是视频的缩略图,而另一个 URL 将下载完整的视频,格式为 MP4。还显示了 SD 卡路径和图像文件名。
图片和音频消息以非常相似的格式存储,包含查看或下载文件的 URL,以及 SD 卡上的文件路径。
这是一个示例位置消息:
这一次,我们可以看到用户的确切坐标以及地址。同样,SD 卡路径也存在,并将显示该位置的地图视图。与其他消息类型一样,收到的消息也会显示发送者的姓名。
最后,让我们来看一下 userinfo.xml.db
数据库。以下是解码之前它的样子:
我们编写了另一个与第一个非常相似的脚本,用于解析 userinfo.xml.db
数据库:
import sqlite3
import base64
conn = sqlite3.connect('userinfo.xml.db')
c = conn.cursor()
c.execute('SELECT key, value FROM profiles')
key_tuples = c.fetchall()
with open('userinfo_out.txt', 'w') as f:
for key, value in key_tuples:
if value == None:
value = 'Tm9uZQ=='
f.write(str(base64.b64decode(key)) + '\x09')
f.write(str(base64.b64decode(value)) + '\r\n')
唯一的不同之处在于文件名、表名和数值发生了变化,并且这一次数据库中的两列都进行了 base64 编码。再次提醒,可以通过将其放在与 userinfo.xml.db
相同的位置并运行以下命令来执行它:
python userinfo.py
这是结果文件中相关部分的输出,显示了用户用于注册帐户的个人数据:
在输出的进一步部分,还有一个列表,列出了所有使用 Tango 的用户联系人,包括联系人的姓名和电话号码。
WhatsApp 分析
WhatsApp 是一款流行的聊天/视频消息服务,在 Google Play 上已有超过 5 亿次下载。
包名: com.whatsapp
感兴趣的文件:
-
/files/
-
Avatars/
-
me
-
me.jpeg
-
-
/shared_prefs/
-
RegisterPhone.xml
-
`VerifySMS.xml`
-
-
/databases/
-
msgstore.db
-
wa.db
-
-
/sdcard/WhatsApp/
-
Media/
-
Databases/
-
/files/avatars
目录包含使用该应用程序的联系人头像的缩略图,而 me.jpg
是用户头像的全尺寸版本。该 me
文件包含与账户关联的电话号码。
与账户关联的电话号码也可以在 /shared_prefs/RegisterPhone.xml
中恢复。/shared_prefs/VerifySMS.xml
文件显示账户验证的时间(当然是 Unix 纪元格式),指示用户首次开始使用该应用的时间。
msgstore.db
数据库,顾名思义,包含消息数据:
表格 | 描述 |
---|---|
chat_list |
key_remote_jid 列显示用户与之沟通过的每个账户;表中的值是远程用户的电话号码。例如,如果值是 13218675309@s.whatsapp.net ,那么远程用户的号码就是 1-321-867-5309 。 |
group_participants |
包含群聊的元数据。 |
messages |
显示所有消息数据。再次强调,key_remote_jid 字段标识远程发送者。key_from_me 值表示消息的方向(0=接收,1=发送)。数据列包含消息文本,时间戳是发送或接收的时间,采用 Linux 纪元格式。对于附件,media_mime_type 标识文件格式;media_size 和 media_name 列应该不言而喻。如果附件有标题,文本将显示在 media_caption 列中。如果附件是位置,纬度和经度列将相应填充。thumb_image 列包含大量无用数据,但也包含设备上附件的路径。raw_data 列包含图片和视频的缩略图。 |
wa.db
数据库用于存储联系人信息:
表格 | 描述 |
---|---|
wa_contacts |
和其他应用一样,WhatsApp 会抓取并存储用户的整个电话簿,并将信息存储在自己的数据库中。它包含联系人的姓名和电话号码,以及该联系人是否是 WhatsApp 用户的状态。 |
SD 卡是 WhatsApp 数据的宝藏。/sdcard/WhatsApp/Media
文件夹包含每种类型媒体的文件夹(音频、通话、图片、视频和语音笔记),并将该类型的所有附件存储在该文件夹中。发送的媒体存储在一个名为 Sent 的目录中。接收的媒体则直接存储在文件夹的根目录下。
Databases
目录是一个更大的信息源。WhatsApp 每晚都会备份 msgstore.db
,并将备份存储在这里。这使得检查人员能够查看可能已被删除的历史数据;如果我今天删除了一条聊天记录,但你查看昨天的备份,你将能够访问我删除的数据。该应用程序甚至贴心地将日期包含在文件名中,例如:msgstore-2018-12-12.1.db.crypt12
。唯一的问题是这些备份是加密的!
解密 WhatsApp 备份
幸运的是,现有工具可以用来解密备份。它可以在此找到,并附有详细的说明:andreas-mausch.de/whatsapp-viewer/
。WhatsApp Viewer 可以用来解密不同版本的加密 WhatsApp 数据库。在此示例中,我们将解密其最新版本.crypt12
:
-
转到文件 | 解密 .crypt12….
-
选择加密的数据库文件和密钥文件(可以在
/files
目录中找到):
- 点击“解密…”按钮并选择解密后的数据库文件位置。
数据存储方式 7:加密文件
Kik 分析
Kik 是一个即时通讯应用,已在 Play 商店下载超过 1 亿次。
包名:kik.android
感兴趣的文件:
-
/cache/
-
chatPicsBig/
-
contentpics/
-
profPics/
-
-
/files/staging/thumbs
-
/shared_prefs/KikPreferences.xml
-
/sdcard/Kik/
-
/databases/kikDatabase.db
/cache
中的chatPicsBig
和contentpics
目录包含在应用中发送和接收的图像。contentpics
中的文件包含看似嵌入在图像之前的Kik
元数据;JPG 文件必须从这些文件中提取出来。在我们的测试中,contentpics
中的所有文件也存储在chatPicsBig
中,尽管随着应用使用的增加,情况可能会发生变化。用户的个人资料图片位于/profPics
目录中。
数据存储方式 8:基本隐写术;一个文件存储在一个更大的文件中。
/files/staging/thumbs
目录包含发送和接收图像的缩略图;我们的测试发现该位置的图像与/cache
目录中的图像相同,但同样地,随着应用使用的增加,情况可能会有所不同。
/shared_prefs
中的KikPreferences.xml
文件显示了用户在应用中使用的用户名和电子邮件地址。有趣的是,它还包含用户密码的未加盐 SHA1 哈希值。
/sdcard/Kik
目录包含在应用中发送和接收的全尺寸图像。文件名可以与kikDatabase.db messagesTable
中的数据进行关联,以识别包含图像的消息。
kikDatabase.db
数据库包含来自应用的所有消息数据:
表格 | 描述 |
---|---|
KIKContentTable |
该表格包含已发送和接收图像的元数据。每条消息都分配有一个唯一的content_id 值,该值与sdcard/Kik 目录中的文件名相对应。每张图像的预览和图标值对应于/files/staging/thumbs 中的文件名。每张图像还包含一个file-url 值;这是一个公共 URL,可以用来查看该文件。 |
KIKcontactsTable |
该表显示了每个联系人对应的user_name 和display_name 。in_roster 值似乎是为用户明确添加的联系人设置的(如果值为1 );in_roster 值为 0 的联系人似乎是自动添加的。jid 列是每个联系人的唯一值。 |
messagesTable |
该表包含了通过应用发送和接收的所有消息数据。body 列显示了消息中发送的文本数据。partner_jid 值可以与KIKcontactTable 中的jid 列关联,识别远程用户。was_me 列用于表示消息的方向(0 = 发送,1 = 接收)。read_state 列显示消息是否已读(500 = 已读,400 = 未读)。时间戳仍然以 Linux 纪元格式表示。content_id 列填充了消息附件,可以与KIKContentTable 关联以获取更多信息。 |
微信分析
微信是一款在 Play 商店下载超过 1 亿次的消息应用。
包名:com.tencent.mm
请注意,这些路径中有些包含星号(*)。这表示一个唯一的字符串,每个账户都会不同。我们的设备在星号位置使用了7f804fdbf79ba9e34e5359fc5df7f1eb
。
关注的文件:
-
/files/host/*.getdns2
-
/shared_prefs/
-
com.tencent.mm_preferences.xml
-
system_config_prefs.xml
-
-
/sdcard/tencent/MicroMsg/
-
diskcache/
-
WeChat/
-
-
/sdcard/tencent/MicroMsg/*/
-
image2/
-
video/
-
voice2/
-
-
/MicroMsg/
-
CompatibleInfo.cfg
-
*/EnMicroMsg.db
-
在/files/host
中找到的*.getdns2
文件可以作为文本文件或十六进制编辑器打开。文件中有一个名为[clientip]
的部分,显示了用户连接的 IP 地址以及连接时间(以 Linux 纪元格式表示)。我们的设备包含了三个这样的文件,显示了三次不同的连接,但随着应用使用量的增加,可能会生成超过三个这样的文件。
/shared_prefs
中的com.tencent.mm_preferences.xml
文件记录了设备的电话号码,在login_user_name
字段中。system_config_prefs.xml
文件包含了用户设备上个人资料图片的路径,以及稍后需要的default_uin
值。
SD 卡包含了大量的微信数据。/tencent/MicroMsg/diskcache
目录中包含了一张从未在应用中使用过的图片;我们认为它是在附加另一张图片时放入的,因为微信会加载设备图库中的许多图片。/WeChat
目录位于/sdcard/tencent/MicroMsg
中,包含了从设备发送的图片。
/sdcard/tencent/MicroMsg/*
中的/video
、/voice
和/voice2
文件夹包含了它们所说的内容:通过应用发送的视频和语音文件。
微信的一个独特之处在于,它并不使用应用程序目录结构中的/databases
目录;MicroMsg
目录充当其等效物。CompatibleInfo.cfg
包含设备的 IMEI,稍后会用到。
/MicroMsg
目录中的*
文件夹包含EnMicroMsg.db
数据库。只有一个问题:该数据库是使用 SQLCipher 加密的!SQLCipher 是一个开源的 SQLite 扩展,能够加密整个数据库。幸运的是,与其他使用加密的应用一样,解密该文件的密钥存储在设备上。
数据存储方法 9:SQLCipher,完整的数据库加密
解密微信的 EnMicroMsg.db
幸运的是,Forensic Focus 网站有一篇非常好的文章,正是讲如何完成这项操作:articles.forensicfocus.com/2014/10/01/decrypt-wechat-enmicromsgdb-database/
。
他们甚至提供了一个 Python 脚本来帮我们完成这项工作:gist.github.com/fauzimd/8cb0ca85ecaa923df828/download#
。
要运行 Python 脚本,只需将EnMicroMsg.db
文件和system_config_prefs.xml
文件放在与脚本相同的目录下,然后在命令行中输入以下内容:
python fmd_wechatdecipher.py
脚本接下来会提示你输入设备的 IMEI。这可以在/MicroMsg/CompatibleInfo.cfg
文件中找到,或者在设备上某个地方打印出来(如电池后面、SIM 卡托上,或设备背面刻印的位置),或者通过在键盘上输入*#06#
来获取。
脚本应能正常运行,并在目录中生成一个名为EnMicroMsg-decrypted.db
的文件。
现在我们可以检查EnMicroMsg-decrypted.db
了:
表格 | 描述 |
---|---|
ImgInfo2 |
包含发送和接收图像的路径信息。bigImgPath 列包含图像的文件名;可以在 SD 卡上搜索该文件名来找到图像。或者,图像会存储在/sdcard/tencent/MicroMsg/*/image2 目录下的文件夹中,文件夹名称与文件名相对应。例如,3b9edb119e04869ecd7d1b21a10aa59f.jpg 文件可以在/3b/9e 路径下的image2 目录中找到。文件夹按文件名的前两个字节、然后是接下来的两个字节进行划分。thumbImgPath 列包含图像缩略图的名称。 |
message |
包含应用程序的所有消息信息。isSend 列表示消息的方向(0 = 接收,1 = 发送)。createTime 列是消息的时间戳,采用 Linux 纪元格式。talker 列包含远程用户的唯一 ID,可以与rcontact 表相关联来识别远程用户。content 列显示作为文本发送的消息数据,视频通话则标识为voip_content_voice 。imgPath 包含图片缩略图的路径,可以与ImgInfo2 表相关联,以定位完整大小的图片。它还包括音频文件的文件名,可以在/sdcard/tencent/MicroMsg/*/voice2 目录中搜索或找到。 |
rcontact |
包含联系人列表,并包括许多应用程序默认添加的联系人。用户名可以与消息表中的 talker 列相关联。昵称列显示用户的名称。类型列是一个指示联系人是手动添加还是自动添加的标志(1 = 设备用户,3 = 用户添加,33 = 应用程序添加)。例外情况是weixin 用户,该用户是自动添加的,但类型值为 3。 |
userinfo |
该表包含用户信息,包括姓名和电话号码。 |
总结
本章深入研究了特定的安卓应用程序,以及它们如何/在哪里存储数据。我们研究了 19 个特定的应用程序,发现了 9 种不同的数据存储和混淆方法。知道应用程序以多种方式存储数据应该能帮助检查员更好地理解他们正在检查的数据,并希望在找不到他们期望应用程序有的数据时,促使他们更加仔细地寻找。检查员必须能够适应不断变化的应用程序分析世界;由于应用程序不断更新,检查员必须能够更新自己的方法和能力,以跟上步伐。
下一章将介绍几款免费的/开源的和商业的工具,用于镜像和分析安卓设备。
第八章:Android 取证工具概述
本章概述了免费/开源和商业的 Android 取证工具,并将展示如何使用这些工具处理常见的调查场景。在本章结束时,读者应熟悉以下工具:
-
Autopsy
-
Belkasoft 证据中心
-
Magnet AXIOM
Autopsy
Autopsy 是一个免费且开源的分析工具,最初由 Brian Carrier 开发。Autopsy 作为底层基于 Linux 的 SleuthKit 工具集的图形用户界面开始,但自版本 3 起,它已成为一款独立的 Windows 工具。Autopsy 可以从www.sleuthkit.org/autopsy/
下载。
Autopsy 并不用于进行移动设备的获取,但可以分析大多数常见的 Android 文件系统(如 YAFFS 和 EXT)。在这个例子中,我们将加载通过dd
从三星 Galaxy J7 获取的完整物理镜像。
在 Autopsy 中创建案件
打开 Autopsy 后,用户将被提示创建新案件、打开最近的案件或打开案件:
我们将创建一个新案件。请按照以下步骤操作:
- 填写完案件名称字段后,下一步按钮将变为可用:
- 可选的案件编号和检查员信息可以输入:
- 选择“完成”后,将显示选择要添加的数据源类型的屏幕。选择虚拟机文件的磁盘镜像选项:
- 点击“下一步”并使用浏览按钮选择要加载的镜像文件:
- 点击“下一步”按钮,进入配置导入模块向导:
导入模块是 Autopsy 内置的工具,可以在案件启动时运行,或者在之后的任何时间运行。以下是该版本 Autopsy 中的默认模块:
-
最近活动:提取最近的用户活动,如网页浏览、最近使用的文档和已安装的程序。
-
哈希查找:使用提供的哈希数据库识别已知和显著的文件,如标准 NSRL 数据库。允许我们导入自定义哈希数据库。
-
文件类型识别:根据二进制签名匹配文件类型。
-
嵌入式文件提取器:提取嵌入式文件(ZIP, RAR, DOCX, XLSX)。自动提取这些文件类型并将其内容放入目录树中。
-
退出解析器:导入 JPEG 文件并检索其 EXIF 元数据。
-
关键词搜索:使用关键词和正则表达式在列表中进行文件索引和定期搜索。允许加载自定义关键词/列表。
-
电子邮件解析器:此模块检测并解析 Mbox 和 PST/OST 文件,并在黑板中填充电子邮件证据。
-
扩展名不匹配检测器:标记具有非标准扩展名的文件,基于其文件类型。
-
E01 验证器:验证 E01 文件的完整性。
-
加密探测器:查找具有指定最小熵的文件。
-
有趣文件标识符:根据有趣项目规则集识别有趣的项目。
-
PhotoRec 切割器:使用 PhotoRec 从数据源中切割未分配的空间。
-
关联引擎:将属性保存到中央存储库以供后续分析。
-
虚拟机提取器:提取虚拟机文件并将其添加到案件中。
-
Android 分析器:提取 Android 系统和第三方应用程序数据。
请注意,许多这些模块在 Android 设备上是不需要的(例如 E01 验证器和电子邮件解析器)。仅选择有用的模块可以加快数据导入速度。还要注意,点击模块可能会显示更多选项。
- 点击 下一步 将加载数据源并开始导入过程。遇到的任何错误都将被记录:
- 选择“完成”将带领检查员进入主屏幕,以便分析已导入的案件:
在 Autopsy 中分析数据
即使案件仍在加载中,数据导入模块正在运行(如上图右下角的进度条所示),检查员也可以开始分析案件。通过扩展左上角的图像文件,可以显示 Autopsy 识别的分区/卷:
Autopsy 识别了我们设备上的 28 个分区。为了找到数据分区(因为我们知道大部分感兴趣的数据都存储在那里),我们可以简单地展开已分配的分区,直到找到看起来像数据分区的那个:
在我们的图像中,第 27 卷是数据分区。我们可以看到它有一个 app
目录(存储 APK 文件的地方)、一个 data
目录(存储应用程序数据的地方)以及一个 media
目录(SD 卡的符号链接位置)。
展开 data
目录将显示我们应该从第七章 Android 应用程序的法医分析中记住的信息:
立刻,我们可以看到 com.android.providers.telephony
和 userdictionary
。如何分析这些应用程序的内容,请参阅第七章,Android 应用程序的法医分析;这就是如何使用 Autopsy 访问相关文件。例如,展开 com.android.providers.telephony
将显示用于分析 SMS 和 MMS 数据的 mmssms.db
文件:
“应用程序”标签让检查员在内置查看器中查看 SQLite 数据库:
现在,让我们来看看 Autopsy 的其他功能。在屏幕左侧展开“视图”部分将显示一些使用的获取模块的结果:
文件类型视图展示了由文件类型识别模块识别的文件。最近文件显示了来自最近活动模块的结果;在这种情况下,设备似乎已经六天没有使用,然后在最后一天被使用。查看这里识别的文件可以显示用户在该时间段内的活动。请注意红色的 X,它表示这些文件中的一些已被删除,但被 Autopsy 恢复了:
在我们的案例中,我们可以看到downloads.db
和EmailProvider.db
数据库已被修改。分析这些文件会显示一封带附件的电子邮件被接收,附件随后被下载到设备上。
最后,视图部分识别了已删除的文件(这些文件在移动设备上非常常见,因磨损均衡而被删除),以及大文件(这些文件有助于快速找到图像/视频,或识别隐写术)。
结果部分将显示来自Android 分析器和关键字搜索模块的输出:
在提取内容下看到的 Android 分析结果大多符合预期。值得注意的是,联系人(1)部分只指向 contacts.db 文件,并没有实际解析其中的数据。例如,通话记录显示了从contacts2.db
提取的数据,如第七章中所述,安卓应用的取证分析:
检测到扩展名不匹配的结果还显示了我们在第七章中发现的数据,安卓应用的取证分析。有几个应用程序被描述为具有.cnt
文件,而这些文件实际上是 JPEG 图像,这些文件被 Autopsy 正确识别:
双击任何一个文件将带用户到文件在文件系统中找到的位置。
关键字命中部分正确地找到了许多电子邮件地址和电话号码,但其中许多是在应用程序文件中找到的(即应用程序开发者的联系信息)以及其他并非由用户实际存储的地方(这在移动和计算机取证工具中非常常见)。
Autopsy 还有许多更高级的功能,这里没有涵盖;要了解更多,基础技术提供了一个 Autopsy 培训课程:www.autopsy.com/training/
。
Belkasoft 证据中心
Belkasoft Evidence Center 是一个商业数字取证产品,允许检查员从不同来源获取、处理和分析数据,包括移动设备,如 Android 智能手机和平板电脑。
该产品的试用版可以从belkasoft.com/get
下载。
在 Belkasoft Evidence Center 中创建案件
要开始在 BEC 中创建新案件,请执行以下步骤:
-
点击新建案件按钮,填写以下字段:
-
案件名称:案件名称或编号。
-
根文件夹:存储所有案件数据的文件夹。
-
案件文件夹:当前案件数据存储的文件夹。
-
调查员:检查员的姓名。
-
时区:显示时间戳时使用的时区(推荐使用 UTC)。
-
描述:案件概述:
-
- 创建并打开按钮将带你进入下一个窗口,即添加数据源窗口:
Belkasoft 提供了带有产品的测试镜像,因此我们可以使用一个 Android 备份进行演示。当然,也可以使用自己的镜像,包括逻辑镜像和物理镜像。如果你没有镜像,但想获取一个,可以在获取与分析部分选择移动设备选项:
- 由于我们决定使用提供的 Android 备份,因此可以直接点击下一步并选择要从中提取的工件:
一个好的策略是只选择与 Android 相关的工件,但有时选择更多的工件可能会带来更好的结果,所以如果你有足够的时间,可以选择所有类型的工件来处理镜像。
由于我们处理的是逻辑镜像,因此雕刻选项不可用。使用物理镜像时,该选项可用,因此检查员可以使用数据雕刻来恢复和提取更多数据。
- 点击完成按钮将初始化镜像处理过程。如果案件只有一个镜像,请在最后一个窗口点击否按钮:
在 Belkasoft Evidence Center 中分析数据
BEC 的不同功能分布在多个标签页中。我们先来看一些,首先是案件浏览器:
这里显示的是处理后提取的工件数量,在我们的案例中是 210 个。实际数据可以在右侧窗格查看。有多种视图选项:你可以查看项目的属性,或者以常规形式或十六进制形式查看它。BEC 还拥有一个强大的SQLite 浏览器,支持从预写日志(WAL)中提取数据,并从空闲列表和未分配空间中恢复已删除记录。
另一个有用的标签是时间线:
这对于 Android 恶意软件调查特别有用。你可以轻松找到恶意应用安装前发生的事情,例如,用户收到一条带有该应用链接的可疑短信,点击后用网页浏览器下载了该应用。当然,这也可以用于常规案件,例如,如果你需要了解用户在特定时间段内使用手机时做了什么。
最后,如果需要,你可以执行手动文件系统分析。在下一张截图中,你可以看到一个包含应用数据的文件夹内容:
如果你想使用关键词进行数据搜索,搜索结果标签也会非常有用,因为它是存放关键词搜索命中的地方。要在工件中进行搜索,你可以按Ctrl + F,点击主工具栏上的搜索图标,或者选择编辑主菜单中的搜索...选项。进行搜索时,你可以使用单个单词或短语、关键词列表、正则表达式,或者预定义的搜索,比如adult sites
。
Magnet AXIOM
Magnet AXIOM 是另一款强大的商业数字取证产品,能够获取、处理和分析移动设备,包括运行 Android 操作系统的设备。
本产品的试用版可以从www.magnetforensics.com/try-magnet-axiom-free-30-days/
下载。
在 Magnet AXIOM 中创建案件
要在 Magnet AXIOM 中创建案件,请执行以下步骤:
- 启动 AXIOM 进程并点击创建新案件按钮:
- 第一个窗口是案件详情;在这里,我们需要填写一些字段,如案件编号、类型、案件文件路径和已获取的数据:
- 证据来源窗口允许检查员选择数据源或直接从设备获取镜像:
- 为了演示,我们将使用三星智能手机的实物图片,因此请选择ANDROID选项:
- 由于我们决定使用一个预制的镜像,选择加载证据选项:
如果你想使用 Magnet AXIOM 创建一个镜像并进行处理,你可以选择获取证据选项。
- 由于我们使用的是镜像,在下一步中选择镜像选项:
现在我们可以看到,我们的证据源已添加到案件中:
让我们继续进行并配置处理细节:
-
添加关键词以进行搜索:你可以在处理开始之前添加关键词搜索词,甚至可以添加列表,这样你就能在 AXIOM Examine 的关键词过滤器下找到相关内容。
-
MAGNET.AI 聊天分类:AXIOM 使用内置类别对聊天记录进行分类,因此它可以通过机器学习自动从数千条消息中提取有用的证据。
-
搜索存档和手机备份:此选项对于计算机取证特别有用;如果 AXIOM 找到存档或手机备份,它会处理并将其数据添加到案件中。
-
计算哈希值:你可以导入哈希集以排除已知的好文件:
-
分类图片和视频:允许检查员使用来自 Project VIC 和 CAID 的已知媒体文件哈希集或 JSON 文件。
-
将 CPS 数据添加到搜索中:允许检查员导入并使用 儿童保护系统 (CPS) 网站的数据。
-
查找更多证据:允许检查员使用动态应用查找器查找当前不受产品支持的应用数据:
- 选择检查员希望提取的证据。由于我们的源是 Android 镜像,我们选择了所有移动设备证据:
当然,如果需要,证据列表是可以定制的:
现在我们准备开始图像处理:
AXIOM 检查窗口将自动打开,因此你可以在处理阶段开始分析。AXIOM 处理窗口仍然很有用,你可以监控处理进度。
在 Magnet AXIOM 中分析数据
案例仪表盘标签将为你提供 AXIOM 处理从数据源中提取的证据概览——在我们的案例中,共提取了42,156个证据:
案例仪表盘标签
要更详细地查看提取的数据,让我们进入 证据 查看器,你可以从下拉菜单中选择它(点击 案例仪表盘):
所以我们有相当多的证据,例如 230 个移动设备证据。它们是什么?让我们学习一下:
如你所见,AXIOM 提取了关于用户账户、通话记录、Wi-Fi 配置文件、Google Play 搜索记录和已安装应用的信息。
如果你更喜欢手动分析,可以使用 文件系统 查看器。你可以在以下截图中看到包含应用数据的文件夹:
这个查看器拥有进行手动分析所需的一切,包括 SQLite 浏览器和十六进制查看器。
总结
本章概述了几款可供 Android 法医检查员使用的免费和商业工具。当然,市场上还有更多商业工具,但我们选择了 Belkasoft Evidence Center 和 Magnet AXIOM,因为它们都有适用于每个人的试用版。
当然,解决一个案例并不总是需要复杂的工具,有时候你只需要一个好的 SQLite 浏览器,甚至是一个十六进制查看器。
下一章将向你介绍 Android 恶意软件,并带你了解一些识别其的方法。
第九章:识别安卓恶意软件
识别恶意软件是许多安卓取证检查中的典型任务。本章将首先介绍最常见的安卓恶意软件类型概述,然后带你了解使用不同方法识别安卓设备中的恶意软件的过程。
本章将涵盖以下主题:
-
安卓恶意软件简介
-
安卓恶意软件概述
-
识别安卓恶意软件
安卓恶意软件简介
如今,恶意程序在任何操作系统上都很常见,移动设备也不例外。即使是像运行 iOS 的设备、iPhone 和 iPad 这样的安全设备,也可能会感染恶意软件。一个很好的例子是Pegasus间谍软件,它在 2016 年被用于攻击阿拉伯人权捍卫者 Ahmed Mansoor。它能够越狱目标设备并植入间谍软件,从而使攻击者能够读取受害者的消息、追踪电话、收集密码、定位手机,并从不同的应用程序收集信息。
如果我们谈论安卓系统,情况更为严重。从不受信任的来源安装应用程序更容易,这使得安卓成为受恶意软件影响最严重的移动平台。更重要的是,安全研究人员经常在 Google Play 商店发现大量恶意软件样本!一个很好的例子是Android Grabos运动,它是在 2017 年底/2018 年初由 McAfee 发现的。这个运动将不需要的应用推送给毫无防备的用户——这通常被称为按下载付费骗局。安全研究人员发现并从 Google Play 中移除了 144 个应用程序。但在它们被移除之前,全球约有 1750 万台智能手机设备已经下载了这些应用。
现在让我们进一步了解最常见的安卓恶意软件类型。
安卓恶意软件概述
如你所知,不同类型的恶意软件有不同的目标,因此它们的功能也各不相同。一些恶意程序会监视受害者并试图窃取应用数据,例如短信和电子邮件,而另一些则仅仅是向用户显示不需要的广告。本节将向你介绍最常见的安卓恶意软件类型。
银行恶意软件
银行恶意软件是安卓平台上最常见的恶意软件之一。它可以伪装成假冒银行应用程序来窃取用户输入的银行信息,或者作为一个第三方应用从真实的银行应用中窃取信息。此外,银行木马通常可以拦截银行交易,并执行典型的间谍软件行为,例如发送、删除和拦截短信,以及键盘记录。一些银行木马甚至具有更高级的功能。一个很好的例子是MysteryBot——它还可以从受感染设备发送垃圾邮件,并具备勒索软件功能。
间谍软件
间谍软件监视、记录并将目标设备的重要信息发送到攻击者的服务器。这些信息可能包括短信消息、录音电话、截屏、按键记录、电子邮件或可能对攻击者感兴趣的任何其他应用程序数据。一个有趣的例子是 BusyGasper,由卡巴斯基实验室专家于 2018 年初发现。它不仅具有收集来自 WhatsApp、Viber 和 Facebook 等流行消息应用程序的信息的常见间谍软件功能,还具有设备传感器监听器,包括运动检测器。
广告软件
广告软件是另一种在 Android 设备上非常常见的恶意或不需要的应用程序类型。它相对容易检测,因为受害者会在其设备屏幕上接收持续的弹出窗口和广告。这些不受欢迎的程序并不总是无害的,因为弹出窗口可能导致下载另一种恶意软件,包括已提到的间谍软件和银行木马。
勒索软件
当然,勒索软件的主要目标是桌面 Windows 计算机和服务器,但它也存在于移动平台上,尤其是 Android。通常,它只锁定设备屏幕并附上勒索信息,但有时也会加密用户的数据。一个很好的例子是 2017 年针对中国 Android 用户的 WannaLocker 勒索软件,它使用 AES 加密用户的文件,除了其路径名以 .
开头和包含 DCIM
、download
、miad
、android
和 com
的文件。
加密货币挖掘恶意软件
加密货币现在非常流行,因此这种类型的恶意程序甚至适用于 Android 等移动平台。此类应用程序的目标是使用受害者设备的计算能力来挖掘加密货币,例如 Monero。有时,这种类型的恶意软件甚至会使智能手机硬件处于风险之中。例如,具有加密货币挖掘功能的木马 Loapi 会让受害者的手机工作得非常辛苦,以至于其电池在不到 48 小时内膨胀!
下一节将指导您识别 Android 设备上的恶意应用程序。
Android 恶意软件识别
本节将指导您如何使用防病毒扫描器、VirusTotal 和 YARA 规则在取证镜像中识别 Android 恶意软件的过程。
使用防病毒扫描器在 Android 设备上识别恶意软件
使用防病毒扫描器是查找已知恶意软件的典型方法,因此这是选择低 hanging fruit 的推荐第一步。有许多防病毒扫描器,其中许多都有免费版本,移动取证检查员可以使用这些版本完成这些任务。其中大多数是基于 Windows 的,因此第一步是挂载先前创建的物理镜像,以便操作系统和防病毒扫描器可以访问它。
如你所知,大多数 Android 设备使用 EXT4 作为文件系统,尤其是从取证角度来看最有趣的分区——userdata 分区。默认情况下,Windows 不支持这种文件系统,因此我们需要一个第三方工具来挂载它,更重要的是,必须以只读模式进行挂载,因为我们不希望防病毒扫描器删除我们将要检查的镜像中的任何内容。
当然,取证检查员有这样的工具可以使用。它叫做Linux 文件系统 for Windows,其试用版可以在此下载:www.paragon-drivers.com/en/lfswin/
。安装后,你就可以开始挂载 userdata 分区了。你需要 FTK Imager,但应该已经安装了它,因为我们在前面的章节中使用过它。以下是在 Windows 主机上挂载 ext4 分区的两步简单操作:
- 打开 FTK Imager,点击文件|映像挂载...
AccessData FTK Imager
- 选择镜像文件。在我们的例子中,它是一个 Android 9 userdata 分区的物理镜像。选择物理与逻辑作为挂载类型,选择块设备 / 只读作为挂载方式,然后点击挂载按钮:
使用 FTK Imager 挂载 EXT4 镜像
就这样!现在文件系统作为逻辑磁盘E:
在我们的 Windows 10 主机上可用了:
Windows 资源管理器中挂载的文件系统的一部分
现在可以使用防病毒扫描器轻松扫描它。通常,用户安装的应用程序可以在/data/app
目录下找到,因此,开始我们的恶意软件检测时扫描这个文件夹可能是一个非常好的主意。对于本例,我们将使用 ESET NOD32 防病毒软件(www.eset.com/int/home/antivirus/
)。从取证的角度来看,它有一个非常有趣的选项——扫描不清除。这使得检查人员能够找到恶意软件,但不会删除或隔离它。要选择此选项,右键点击你选择的文件夹,然后进入高级选项。在我们的例子中,扫描只用了几秒钟,结果显示出了两个恶意对象:
防病毒扫描日志
如你所见,有时候,尤其是如果你知道在哪里查找,使用防病毒引擎可以非常快速、轻松地找到 Android 恶意软件。当然,你使用的软件可能没有包含相应的签名,可能会漏掉恶意应用程序,因此强烈建议使用多个引擎进行扫描。
使用 VirusTotal 识别 Android 恶意软件
VirusTotal 是一个免费的服务,可以用来分析可疑的文件和 URL 是否包含恶意软件。如你所见,Android 应用程序的文件扩展名为 .apk
,所以如果你发现一个可疑文件,你可能会想把它上传到 VirusTotal,检查它是否真的是恶意的。为什么这比使用杀毒软件扫描更好?因为它会使用至少 55 个杀毒引擎扫描你的文件!更重要的是,你可能不希望将真实案例中的文件上传到互联网上,但这不是问题,因为你可以通过文件的哈希值 MD5、SHA1 或 SHA256 来查找已经上传的文件。此服务可以在这里使用:www.virustotal.com
。
我们已经在 Android 9 镜像中发现了两个恶意文件,因此让我们将其中一个文件上传到 VirusTotal,看看它是如何被其他杀毒引擎检测到的。使用你选择的网页浏览器访问 VirusTotal,然后点击“选择文件”按钮:
VirusTotal 界面
如果文件的哈希值已经在数据库中,你将立即被重定向到包含结果的页面;如果没有,系统将需要一些时间来扫描该文件。在我们的例子中,文件的哈希值已立即找到,我们看到了结果:
VirusTotal 扫描结果
如你所见,我们的恶意软件样本已经被 56 个杀毒引擎中的 29 个检测到——表现还不错。但如果我们不想上传我们的样本呢?如前所述,你可以使用哈希值在 VirusTotal 上查找恶意文件。
若要获取可疑文件的哈希值,你可以使用 Eric Zimmerman 提供的免费工具 Hasher,该工具可在 ericzimmerman.github.io
上下载。接下来请按照以下步骤操作:
-
启动工具,进入工具 - 选项,选择哈希算法。在我们的案例中,我们选择了 MD5 和 SHA256。
-
要选择你想要哈希的文件,进入文件 - 选择文件,或者按 Alt + 1。你将在主窗口看到结果:
哈希值结果
要复制哈希值,点击相应字段并按 Alt + C。现在你可以前往 VirusTotal,点击搜索标签,并粘贴哈希值:
使用哈希值在 VirusTotal 上搜索
由于我们使用的是已经由 VirusTotal 扫描过的文件的 SHA256 哈希值,我们将被重定向到相同的页面。但即使我们没有上传文件,由于该文件已经被第三方上传,我们也能获得结果。
有时候,你需要扫描一大堆文件,逐个上传可能会很麻烦。为了自动上传一堆文件,你可以使用 VirusTotal Uploader,该工具可以在这里下载:support.virustotal.com/hc/en-us/articles/115002179065-Desktop-Apps
。
要上传一个文件或多个文件,请单击“选择文件”并上传:
VirusTotal 上传工具界面
为了演示目的,让我们上传我们已经识别的第二个恶意文件。它的哈希值也被找到了,所以工具立即打开了包含扫描结果的浏览器选项卡:
VirusTotal 扫描结果
这个文件的检测结果更好 —— 60 个引擎中有 34 个。但如果文件没有被任何防病毒引擎检测到,因为没有对应的签名,法医检查员该怎么办呢?使用 YARA 编写您自己的规则吧!您将在接下来的章节中学习如何做到这一点。
使用 YARA 规则进行 Android 恶意软件识别
根据官方文档(可在yara.readthedocs.io/en/v3.8.1/
找到),YARA 是一个旨在帮助恶意软件研究人员(当然也包括计算机和移动设备的法医检查员)识别和分类恶意软件样本的工具。
借助 YARA 的帮助,检查员可以基于文本或二进制模式编写规则。这里是这样一个规则的示例:
rule test_rule
{
meta:
description = "Test YARA rule"
author = "Oleg Skulkin"
strings:
$string = "teststring"
condition:
$string
}
此规则将检测包含teststring
字符串的任何文件。让我们仔细看看规则的主要部分:
-
meta
:此部分包含规则的元数据,例如它确切地检测到什么以及谁编写了它。它甚至可能不包含在规则中。 -
strings
:这些是您的恶意软件样本必须包含的字符串,以便进行检测。您可以使用多个字符串或甚至二进制模式。字符串可以区分大小写,也可以是 ASCII 格式或宽字符形式(两个字节用于编码一个字符),或者两者兼有。 -
condition
:这部分包含一个布尔表达式,告诉我们在什么情况下文件满足规则。它可以是在strings
部分定义的所有字符串,也可以是其中有限数量的字符串。
让我们编写一个 YARA 规则来检测我们在前几节已经识别的恶意软件。首先,我们必须找到唯一的字符串。为了能够做到这一点,让我们使用 Eric Zimmerman 的另一个法庭工具 bstrings:ericzimmerman.github.io/
。
这是一个命令行工具,因此您必须从 Windows 命令提示符中运行它。使用-f
开关指定要从中提取字符串的文件:
使用 bstrings 从 APK 文件中提取字符串
从一开始就出现了一个有趣的字符串 —— com.example.horsenjnj
。但我们如何确定它是否是唯一的呢?一个好主意是在 Google 或其他可用的搜索引擎中搜索这个字符串:
谷歌搜索结果
正如您所见,只有一个搜索结果,这使我们找到的字符串变得独特。而且,如果我们点击链接,它将带我们到我们在前一部分已经看过的 VirusTotal 页面。
如果我们滚动字符串的输出,我们会发现更多有趣的字符串,例如 res/xml/shit.xml
—这个名称并不是应用程序资源中的常见 XML 文件名称。
让我们用我们发现的两个字符串编写一个 YARA 规则来检测我们的恶意软件样本。如您从前面的章节中记得,大多数杀毒引擎将其检测为 Android Banker,所以我们将我们的规则命名为 android_banker
。同样可以在描述中写出—检测 Android Banker;我们会将其添加到 meta
部分。我们有两个字符串供规则使用。由于我们不知道它们的编码方式,我们可以在它们后面添加 ascii wide
。最后一部分—条件(将被规则检测到的文件)必须包含这两个字符串,因此我们将使用 all of them
作为条件。
这是我们最终得到的结果:
rule android_banker
{
meta:
description = "Detects Android Banker"
author = "Oleg Skulkin"
strings:
$s1 = "com.example.horsenjnj" ascii wide
$s2 = "res/xml/shit.xml" ascii wide
condition:
all of them
}
要使用它,您必须将其保存为一个以.yar
扩展名结尾的文件。现在,您需要的只是一个能够使用 YARA 规则的扫描器。您可以在这里获得: github.com/virustotal/yara/releases/
。
扫描器是另一个命令行工具。使用 -r
开关递归扫描您选择的目录:
使用 YARA 规则扫描恶意软件
如您从前面的截图中看到的,我们的恶意软件样本已成功被 YARA 扫描器识别。
当然,您可以创建更复杂的规则,官方的 YARA 文档是一个非常好的参考资源。您可以在这里找到它:yara.readthedocs.io/en/v3.8.1/
。
总结
本章向您展示了如何使用杀毒扫描器、VirusTotal 和 YARA 规则,在 Android 智能手机和平板电脑的取证镜像中识别恶意软件,以及如何编写您自己的规则。
最后一章将向您介绍 Android 恶意软件分析技术,包括恶意应用程序的动态和静态分析基础。
第十章:Android 恶意软件分析
在本章中,我们将对在上一章中识别的恶意 Android 应用进行动态和静态分析。我们将涵盖以下主题:
-
使用在线沙箱进行恶意 Android 应用的动态分析
-
恶意 Android 应用的静态分析:
-
解包 Android 应用
-
Manifest 文件解码与分析
-
Android 应用反编译
-
查看和分析反编译代码
-
恶意 Android 应用的动态分析
分析恶意 Android 应用的最简单方法是将其运行在受控环境中。你已经知道如何运行模拟器并通过 ADB 安装应用程序,因此你可以在干净的虚拟系统中安装一个可疑应用程序,并查看运行后留下的任何痕迹。例如,你可以找到恶意应用程序收集的数据的 SQLite 数据库,或其配置文件。
使用在线沙箱进行动态分析
更简单且高效的方法是使用预构建的沙箱进行恶意软件分析。其中一个沙箱是Joe Sandbox。它支持自动化的动态分析,涵盖多种应用类型,包括 Windows、macOS、Linux、iOS,当然还有 Android。你可以注册一个免费账户,每月启用 10 次免费的分析。Android 应用的沙箱可以在这里访问:www.joesandbox.com/#android
。
只需要几个简单的步骤即可在沙箱中运行应用程序:
-
首先,使用选择文件...按钮选择你要分析的文件。
-
调整运行时间;你可以在沙箱中运行应用程序 30 到 500 秒。
-
接受条款和条件,并点击分析按钮。
一旦分析完成,你将收到一封带有分析结果链接的电子邮件。在我们的案例中,它是www.joesandbox.com/analysis/67297
。
让我们浏览 HTML 报告并讨论其最重要的部分。
Joe Sandbox 有自己基于自动化分析结果的检测机制。在我们的案例中,样本得到了 72 分(满分 100),并被分类为恶意:
它还使用杀毒引擎和 VirusTotal 扫描上传的样本。根据报告,我们的样本被 Avira 检测为ANDROID/Spy.Banker.YD.G****en,并且 51% 的杀毒引擎在 VirusTotal 上也进行了检测,截图如下:
根据下一部分,我们的样本尝试提升其权限,通过运行 su
命令请求 root 权限,然后尝试添加新的设备管理员:
我们来看一下网络部分。看起来我们的示例尝试从www.poog.co.kr
下载一个新的 APK 文件new.apk
,但由于文件不可用,下载失败:
另一个有趣的部分是电子银行欺诈。我们的样本包含与银行相关的包名字符串;它们可能用于检测设备上安装的银行应用。此外,它还能够为其他应用添加覆盖层,并具有列出当前运行应用程序的权限:
接下来的部分显示分析的应用请求了在后台进行电话拨打、发送短信和写入短信存储的权限。此外,它还能够使用 SmsManager 发送短信并结束来电;这些行为是银行木马的典型特征:
系统摘要部分向我们展示了样本请求的潜在危险权限列表:
让我们仔细看一下它们:
-
CALL_PHONE
:允许应用发起电话拨打 -
GET_TASKS
:允许应用收集关于当前运行应用程序的信息 -
INTERNET
:允许应用打开网络套接字 -
READ_CONTACTS
:允许应用读取联系人数据 -
READ_PHONE_STATE
:允许应用以只读模式访问电话状态,包括电话号码和蜂窝网络信息 -
READ_SMS
:允许应用读取短信 -
RECEIVE_SMS
:允许应用接收短信 -
SEND_SMS
:允许应用发送短信 -
SYSTEM_ALERT_WINDOW
:允许应用创建在所有其他应用上方显示的窗口 -
WAKE_LOCK
:允许应用防止处理器进入睡眠状态或防止屏幕变暗 -
WRITE_CONTACTS
:允许应用写入联系人数据 -
WRITE_EXTERNAL_STORAGE
:允许应用写入外部存储,例如 SD 卡 -
WRITE_SETTINGS
:允许应用读取或写入系统设置 -
WRITE_SMS
:允许应用写入存储在手机或 SIM 卡上的短信,或删除它们
我们已经知道我们的样本尝试下载一个 APK 文件。如果我们查看持久性和安装行为部分,我们会发现它不仅能够下载应用程序,还能安装它们:
为了在重启后生存,样本请求了在手机重启后执行代码的权限(RECEIVE_BOOT_COMPLETED
),创建了一个新的唤醒锁来保持设备处于开启状态,并能够启动一个服务以实现自启动功能:
让我们深入了解钩子和其他隐藏及保护技术部分。该样本能够中止广播事件;它帮助恶意应用隐藏电话事件,如接收到的短信:
另一个有趣的信息是,我们的样本请求了终止后台进程的权限:
Language, Device and Operating System Detection部分显示样本收集了有关 SIM 提供商国家代码、服务提供商名称、移动国家代码、移动网络代码、WiFi MAC 地址、语音邮件号码、操作系统版本以及唯一设备 ID 的信息,如国际移动设备身份识别码(IMEI)、移动设备识别码(MEID)和电子序列号(ESN):
以下截图显示了样本收集的唯一设备 ID:
下一部分显示应用程序监控外拨电话,能够创建短信数据,并检查是否安装了 SIM 卡:
更重要的是,它监控来电并读取来电号码,解析短信(正文和来电号码),并查询已安装的应用程序和包列表:
最后,如果我们查看Antivirus Detection部分的URLs子部分,我们可以看到我们的样本试图下载的 APK 文件被 Avira URL Cloud 检测为恶意:
你可能已经注意到在之前的截图中有更多的 URLs;这些可能是恶意软件的命令与控制服务器。
总结一下,让我们汇总从Joe Sandbox动态分析中得到的信息:
-
基于病毒检测和我们发现的伪装物品,我们分析的这款恶意软件是一个银行木马。
-
它能够从
www.poog.co.kr
下载其他恶意软件。 -
它收集有关银行相关应用程序的信息。
-
它能够为其他应用程序添加覆盖层。
-
它能够监控进出电话,读取和写入短信,并拦截它们。
-
它能够终止其他应用程序的进程。
-
它能够收集运行设备的信息。
-
它请求在手机重启后执行代码,以实现持久性。
-
它可能使用
http://rtrjkrykki.iego.net/appHome/
或http://192.151.226.138:80/appHome/
作为命令与控制服务器。
接下来的部分将带你了解执行 Android 恶意应用静态分析所需的步骤。
恶意 Android 应用程序的静态分析
为了对之前识别的恶意 Android 应用程序进行动态分析,我们在 Joe Sandbox 的帮助下将其运行在受控环境中。与动态分析相比,静态分析允许检查员在不实际运行恶意软件的情况下理解其行为。让我们从解包开始,进行我们的恶意软件样本的静态分析。
解包 Android 应用程序
要查看 APK 文件的内容,你可以使用任何压缩工具。一个好的例子是 7-Zip,这是一个免费的开源压缩工具,可以在这里下载:www.7-zip.org/download.html
。
要解压 APK 文件,右键点击它,选择 7-Zip,然后选择 打开压缩包:
APK 文件内容
现在你可以浏览 APK 文件的内容并导出其部分内容进行进一步分析。在下一节中,我们将重点关注 Android 清单文件:AndroidManifest.xml
。
Manifest 文件解码与分析
Manifest 文件描述了应用程序的基本信息,供 Android 构建工具、Android 操作系统和 Google Play 使用。如果你在文本编辑器中打开这样的文件,你会看到大部分数据被编码,无法正常查看。
如果我们想分析其内容,我们需要使用 Android 二进制 XML 解码器。一个这样的解码器是 axmldec
,可以在这里下载:github.com/ytsutano/axmldec/releases
。
要解码提取的 manifest 文件,请在命令提示符下运行 axmldec
,并使用以下参数:
axmldec.exe -i AndroidManifest.xml -o manifest_decoded.xml
输出文件可以通过你选择的文本编辑器轻松查看。该文件包含大量有用的信息。例如,我们可以获取包名:
<manifest android:versionCode="1" android:versionName="1.0" package="com.example.horsenjnj">
此外,我们还可以获取有关主活动的信息。主活动是用户启动应用时第一个出现的屏幕。每个活动可以启动另一个活动以执行不同的操作。在我们的例子中,主活动是 com.cc.MainActinn
:
<activity android:label="type1/2131034112" android:name="com.cc.MainActinn" android:excludeFromRecents="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
还有另一个活动 – com.cc.WebInterfaceActivity
:
<activity android:theme="type1/16973835" android:name="com.cc.WebInterfaceActivity" android:screenOrientation="1"/>
这个活动有若干 广播接收器。广播接收器允许应用程序接收系统或其他应用程序广播的 意图。意图是由意图对象定义的消息,描述了要执行的操作。当一个应用程序向系统发出意图时,系统会根据 manifest 文件中的意图过滤器声明,定位一个能够处理该意图的应用组件。
让我们从 com.cc.MyAdminReceiver
开始,它用于获取设备管理员权限:
<receiver android:label="type1/2131034112" android:name="com.cc.MyAdminReceiver" android:permission="android.permission.BIND_DEVICE_ADMIN" android:description="type1/2131034112">
<meta-data android:name="android.app.device_admin" android:resource="type1/2130968576"/>
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED"/>
</intent-filter>
</receiver>
下一个广播接收器是 com.cc.BootRt
:
<receiver android:name="com.cc.BootRt" android:enabled="true" android:exported="true">
<intent-filter android:priority="2147483647">
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.ACTION_SHUTDOWN"/>
<action android:name="android.intent.action.USER_PRESENT"/>
</intent-filter>
</receiver>
如你所见,它接收以下信息:
-
设备是否完成了启动过程
-
设备是否正在关机
-
设备唤醒后是否有用户在场
另一个广播接收器是 com.cc.A123
:
<receiver android:name="com.cc.A123">
<intent-filter android:priority="2147483647">
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.PHONE_STATE"/>
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
<action android:name="android.intent.action.TIMEZONE_CHANGED"/>
<action android:name="android.intent.action.TIME_SET"/>
<action android:name="android.intent.action.TIME_TICK"/>
<action android:name="android.intent.action.UID_REMOVED"/>
<action android:name="android.intent.action.UMS_CONNECTED"/>
<action android:name="android.intent.action.UMS_DISCONNECTED"/>
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_CHANGED"/>
<action android:name="android.intent.action.PACKAGE_DATA_CLEARED"/>
<action android:name="android.intent.action.PACKAGE_FIRST_LAUNCH"/>
<action android:name="android.intent.action.PACKAGE_FULLY_REMOVED"/>
<action android:name="android.intent.action.PACKAGE_INSTALL"/>
<action android:name="android.intent.action.PACKAGE_NEEDS_VERIFICATION"/>
<action android:name="android.intent.action.PACKAGE_REPLACED"/>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<action android:name="android.intent.action.PACKAGE_RESTARTED"/>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
<action android:name="android.intent.action.MEDIA_UNMOUNTED"/>
<action android:name="android.intent.action.MEDIA_UNMOUNTABLE"/>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<action android:name="android.intent.action.MANAGE_PACKAGE_STORAGE"/>
<action android:name="android.intent.action.MEDIA_BAD_REMOVAL"/>
<action android:name="android.intent.action.MEDIA_BUTTON"/>
<action android:name="android.intent.action.MEDIA_CHECKING"/>
<action android:name="android.intent.action.MEDIA_EJECT"/>
<action android:name="android.intent.action.MEDIA_MOUNTED"/>
<action android:name="android.intent.action.MEDIA_NOFS"/>
<action android:name="android.intent.action.MEDIA_REMOVED"/>
<action android:name="android.intent.action.MEDIA_SCANNER_FINISHED"/>
<action android:name="android.intent.action.MEDIA_SCANNER_SCAN_FILE"/>
<action android:name="android.intent.action.MEDIA_SCANNER_STARTED"/>
<action android:name="android.intent.action.MEDIA_SHARED"/>
<action android:name="android.intent.action.LOCALE_CHANGED"/>
<action android:name="android.intent.action.INPUT_METHOD_CHANGED"/>
<action android:name="android.intent.action.HEADSET_PLUG"/>
<action android:name="android.intent.action.GTALK_DISCONNECTED"/>
<action android:name="android.intent.action.GTALK_CONNECTED"/>
<action android:name="android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE"/>
<action android:name="android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE"/>
<action android:name="android.intent.action.DOCK_EVENT"/>
<action android:name="android.intent.action.DEVICE_STORAGE_OK"/>
<action android:name="android.intent.action.DEVICE_STORAGE_LOW"/>
<action android:name="android.intent.action.DATE_CHANGED"/>
<action android:name="android.intent.action.CLOSE_SYSTEM_DIALOGS"/>
<action android:name="android.intent.action.CAMERA_BUTTON"/>
<action android:name="android.intent.action.BATTERY_OKAY"/>
<action android:name="android.intent.action.BATTERY_LOW"/>
<action android:name="android.intent.action.BATTERY_CHANGED"/>
<action android:name="android.intent.action.AIRPLANE_MODE"/>
<action android:name="android.intent.action.PROVIDER_CHANGED"/>
<action android:name="android.intent.action.ACTION_SHUTDOWN"/>
<action android:name="android.intent.action.USER_PRESENT"/>
<action android:name="android.intent.action.WALLPAPER_CHANGED"/>
<action android:name="android.net.wifi.WIFI_STATE_CHANGED"/>
<action android:name="com.noshufou.android.su.REQUEST"/>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
<category android:name="android.intent.category.HOME"/>
</intent-filter>
</receiver>
它接收以下信息/执行以下操作:
-
如果设备完成了启动过程,手机状态
-
如果开始了一个新的外拨电话
-
是否连接了电源
-
是否断开了电源
-
如果时区发生变化
-
如果时间已设置
-
如果时间已更改
-
如果用户 ID 已被删除
-
如果设备已进入 USB 大容量存储模式
-
如果设备已退出 USB 大容量存储模式
-
如果已安装新的应用包
-
如果现有的应用包已被更改
-
如果用户已清除包的数据
-
如果应用程序首次启动
-
如果应用程序已从设备中完全移除
-
如果应用程序已下载并安装
-
如果需要验证包
-
如果安装了应用包的新版本
-
如果应用程序已完全或部分卸载
-
如果用户重新启动了一个包
-
如果现有的应用程序被新版本安装并覆盖
-
如果外部媒体存在但无法挂载
-
如果由于内存不足,需要启动包管理
-
如果外部媒体从 SD 卡槽中移除,但挂载点未被卸载
-
如果按下了媒体按钮
-
如果外部媒体存在并正在进行磁盘检查
-
如果用户表示希望移除外部存储媒体
-
如果外部媒体存在并已挂载
-
如果外部媒体存在,但使用了不兼容的文件系统或是空白的
-
如果外部媒体已被移除
-
如果媒体扫描器已完成扫描目录
-
请求媒体扫描器扫描一个文件并将其添加到媒体数据库
-
如果媒体扫描器已开始扫描目录
-
如果外部媒体因通过 USB 大容量存储共享而被卸载
-
如果当前设备的区域设置已更改
-
如果输入法已更改
-
如果插入或拔出了有线耳机
-
如果 GTalk 连接已断开
-
如果 GTalk 连接已建立
-
如果一组包的资源当前不可用,因为存储它们的媒体不可用
-
如果一组包的资源当前可用
-
如果设备的物理对接状态发生变化
-
如果设备上不再存在存储空间不足的情况
-
如果设备存储空间不足
-
如果日期发生变化
-
如果用户操作要求显示临时系统对话框以进行关闭
-
如果按下了相机按钮
-
如果电池在低电后已恢复正常
-
如果设备处于低电状态
-
充电状态、电池电量级别及其他电池信息
-
如果用户已将手机切换到飞行模式或退出飞行模式
-
如果服务提供商的数据发生变化,例如未读电子邮件数量发生变化
-
如果设备正在关机
-
如果设备唤醒后用户存在
-
如果当前系统的壁纸已更改
-
如果 Wi-Fi 已启用、禁用、正在启用、正在禁用或状态未知
-
调用
su
二进制文件以获取 root 权限 -
如果网络连接发生变化
-
如果设备接收到新的基于文本的短信
此外,我们在恶意应用程序的清单文件中有关于三个服务的信息,com.cc.service.Int
、com.cc.service.Ir
和com.cc.service.Hearttttt
:
<service android:name="com.cc.service.Int" android:persistent="true" android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</service>
<service android:name="com.cc.service.Ir" android:persistent="true" android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</service>
<service android:name="com.cc.service.Hearttttt" android:persistent="true" android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</service>
与活动不同,服务没有可视的用户界面。如果你查看它们的意图过滤器,你会注意到每个服务在设备完成启动过程后都会接收到一个广播信号,因此它可以在后台自动启动。
清单文件的最后部分包含应用程序使用的权限:
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
<uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS"/>
<uses-permission android:name="android.permission.GET_TASKS"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
我们已经在动态分析部分讨论过权限问题,因此这里不再重复。现在,让我们深入研究并开始进行代码反编译。
安卓应用程序反编译
在这一步中,我们需要从 APK 文件中获取另一个文件:classes.dex
。为了将.dex
(Dalvik 执行文件)转换为.class
文件并打包到.jar
容器中,我们需要进行反编译。我们可以使用dex2jar
来完成这个任务,工具下载地址:github.com/pxb1988/dex2jar
。
要反编译classes.dex
,请在命令提示符中运行d2j-dex2jar.bat
,并使用以下参数:
d2j-dex2jar.bat classes.dex -o classes.jar
就是这里。现在,我们有一个classes.jar
文件,里面包含了classes.dex
中的所有 Java 类。我们将在下一部分查看和分析这个.jar
文件。
查看和分析反编译的代码
现在我们可以查看和分析我们在之前步骤中解压和反编译的数据。我们可以使用 JD-GUI 来进行这个操作。JD-GUI 是一个免费的工具,能够显示.class
文件的 Java 源代码。你可以在这里下载这个工具:jd.benow.ca/
。
这是 JD-GUI 显示的classes.jar
内容:
classes.jar
的内容
我们已经知道了很多关于银行木马的信息,现在让我们通过代码分析来学习一些新的东西。通过动态分析,我们识别出了两个可疑的 URL,rtrjkrykki.iego.net/appHome/
和192.151.226.138:80/appHome/
。很可能这两个是同一个服务器,所以我们可以尝试在代码中使用 JD-GUI 查找至少一个 URL:
使用 JD-GUI 搜索 URL
好的,现在我们知道 URL 位于ConstantDatas.class
中。让我们看一下:
ConstantDatas.class
内容的一部分
如果我们搜索BANKURL
,我们会发现它在MainActinn.class
中被使用:
MainActinn.class
内容的一部分
看看这一行:"ConstantDatas.URL = ConstantDatas.BANKURL;"。现在让我们搜索ConstantDatas.URL
。我们会在Hearttttt.class
中找到一个很好的匹配:
Hearttttt.class
内容的一部分
在这里,你可以看到应用程序收集关于设备的信息,包括安装的操作系统、已安装的银行应用程序、移动国家代码和移动网络代码、唯一的用户订阅 ID 等,并将这些数据以 JSON 格式发送到192.151.226.138:80/appHome/servlet/OnLine
。
如你所见,通过静态代码分析,你可以获得大量的附加信息;有时这相对简单,有时则不然,因为恶意软件样本可能会高度混淆。
为了以更高的成功率进行代码分析,我们强烈建议你开始学习 Android 编程。请参考深入阅读部分提供的书籍。
总结
本章介绍了恶意 Android 应用程序的动态和静态分析。你已经学习了如何使用在线沙箱进行动态分析,如何解包 Android 应用程序,分析其清单文件,并反编译其代码。最后,你已经了解了反编译代码分析的概念。
深入阅读
请参阅以下参考资料:
-
应用开发者文档:
developer.android.com/docs/
-
John Horton,《Android 编程入门(第二版)》:
www.packtpub.com/application-development/android-programming-beginners-second-edition