安卓安全秘籍(一)

原文:zh.annas-archive.org/md5/BE954DA99BB76B6D22AFE08F5BDE9A0C

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

安卓系统迅速成为了最受欢迎的移动操作系统之一,不仅受到用户的喜爱,各种开发公司和开发者也同样青睐。当然,这也使其成为了恶意对手的热门攻击目标。

自 2005 年以来,安卓系统一直在公共领域广为人知,其功能和复杂性都实现了巨大的增长。如今的移动智能手机通常包含了关于用户的高度敏感信息,以及访问他们的电子邮件、短信和社交、专业网络服务的权限。与任何软件一样,这种能力和复杂性的提升也带来了安全风险的提升;软件越强大、越复杂,管理起来就越困难,适应这个充满挑战的世界也就越困难。

这尤其适用于移动智能手机上的软件。这些充满个人和敏感信息的热点提出了一个有趣的安全背景,在其中解决问题。从某种角度看,移动智能手机的安全背景很难与网络上的服务器或“云”中的服务器相提并论,因为它们本质上是不移动的。它们不容易被移动或盗取;我们可以实施软件和物理安全措施,以防止未经授权的访问。我们还可以持续监控它们,并自主快速响应安全事件。然而,对于我们装在口袋、手提包里,以及遗忘在出租车上的设备来说,游戏规则就大不相同了!

安卓用户和开发者需要不断关注他们的移动安全风险,正因为这种需求,移动安全与风险评估专家和安全工程师的需求量很大。本书旨在为初露头角的安卓安全评估专家平滑学习曲线,同时作为经验丰富的安卓安全专业人士解决常见安卓安全问题的工具。

本书涵盖内容

第一章,安卓开发工具,介绍了我们如何设置并运行开发者用来在安卓平台上开发安卓应用和本地级别组件的工具。这一章也作为对那些对安卓还不太熟悉,并想了解设置常见开发环境和工具需要些什么的人的介绍。

第二章,应用安全参与,向我们介绍了安卓操作系统提供的,专门用于保护应用程序的组件。本章涵盖了手动检查以及使用一些与保护应用程序及其与操作系统的交互相关的安全工具和服务。

第三章,Android Security Assessment Tools,介绍了安卓安全专家用于评估应用程序给用户带来的技术风险的流行以及新兴的安全工具和框架。在这里,你将学习如何设置、运行并扩展后续章节中将使用的黑客攻击和逆向工程工具。

第四章,利用应用程序,涵盖了针对安卓应用程序的案例利用技术。本章内容涵盖了所有类型的安卓应用程序组件,并详细介绍了如何从源代码和跨应用程序的语境中检查它们的安全风险。它还介绍了第三章中介绍的工具的更高级用法,即安卓安全评估工具。

第五章,保护应用程序,被设计为与第四章,利用应用程序完全相反。这一章不是纯粹讨论应用程序的缺陷,而是讲述应用程序的修复方法。它引导读者了解开发者可以使用的实用技术,以保护应用程序免受第四章中详细描述的某些攻击。

第六章,逆向工程应用程序,帮助读者学习如何破解应用程序,并教授他们安卓逆向工程师用于检查和分析应用程序的技术。你将详细了解 Dex 文件格式,以及如何将 Dex 字节码解释为有用的表示,使逆向工程更加容易。该章节还涵盖了逆向工程师在应用程序和本地组件在安卓操作系统上运行时,可以使用的新的动态分析方法。

第七章,安全网络,帮助读者深入了解应用程序开发人员可以遵循的实用方法,以保护数据在网络中传输时的安全。使用这些技术,你将能够为安全套接字层(SSL)通信添加更强的验证。

第八章, 原生利用与分析,致力于涵盖专注于 Android 平台的本地环境的安全评估和测试技术。读者将学会寻找可用于 root 手机和提升 Android 系统权限的安全漏洞,以及对本地服务执行低级别攻击,包括内存破坏和竞争条件利用。

第九章, 加密和开发设备管理策略,重点介绍如何正确使用加密技术,避免一些常见的反模式,以保持应用程序中的数据安全。它推荐了几个健壮且节省时间的第三方库,以快速且安全地增强应用程序的安全性。最后,我们将介绍如何使用 Android 设备管理 API 来实现和执行企业安全策略。

阅读本书所需的条件

尽管这本书对软件有一些要求,但书中的许多演练在开始使用它们来参与讨论的主题之前,都会讨论下载和安装所需的软件。

以下是开始演练前你可能需要安装的软件列表:

  • Android 软件开发工具包(SDK)

  • Android 原生开发工具包(NDK)

  • GNU C/C++编译器(GCC)

  • GNU 调试器(GDB)

  • Python,最好是 2.7 版本,但 3.0 版本应该也可以正常工作

  • Virtual box

  • Ettercap(适用于 Windows 或 Linux/Unix 系统)

  • Dex2Jar

  • Objdump

  • Radamsa

  • JD-GUI

  • Java 开发工具包(JDK)

  • drozer,一个 Android 安全评估框架

  • OpenSSL命令行工具

  • keytool命令行工具

本书的目标读者

本书有的章节致力于利用 Android 应用程序,有的章节专注于加强它们的安全性,旨在展示硬币的两面,即攻击者和防御者。

安全研究人员、分析师和渗透测试人员将享受有关如何利用 Android 应用的具体细节。对于渴望了解更多安全知识的应用程序开发人员,他们将获得如何保护应用程序免受攻击的实际建议。

约定

在这本书中,你会发现多种文本样式,用于区分不同类型的信息。以下是一些样式示例及其含义的解释。

文本中的代码字、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 处理程序将如下所示:“您必须使用–t开关指定上一步选择的系统映像 ID。”

代码块设置如下:

from drozer import android
from drozer.modules import common, Module
class AttackSurface(Module,common.Filters, common.PackageManager):

当我们希望引起您对代码块中某个特定部分的注意时,相关的行或项目会以粗体显示,如下所示:

from drozer import android
from drozer.modules import common, Module
class AttackSurface(Module,common.Filters, common.PackageManager):

任何命令行输入或输出都会按照以下方式编写:

sudo aptitude update //If you have aptitude installed

新术语重要词汇会用粗体显示。你在屏幕上、菜单中或对话框里看到的单词,例如,会在文本中像这样出现:“接受许可后,你可以通过点击安装来收集你的文档和 API”。

注意

警告或重要提示会像这样出现在一个框里。

提示

提示和技巧会像这样出现。

读者反馈

我们非常欢迎读者的反馈。告诉我们你对这本书的看法——你喜欢或可能不喜欢的地方。读者的反馈对我们来说非常重要,它帮助我们开发出对你真正有用的书籍。

如果要给我们发送一般性反馈,只需将电子邮件发送至<feedback@packtpub.com>,并在邮件的主题中提及书名。

如果你有一个有专业知识的主题,并且有兴趣撰写或参与书籍编写,请查看我们在www.packtpub.com/authors的作者指南。

客户支持

既然你现在拥有了 Packt 的一本书,我们有很多方法可以帮助你最大限度地利用你的购买。

下载示例代码

你可以从你在www.packtpub.com的账户下载你所购买的所有 Packt 书籍的示例代码文件。如果你在其他地方购买了这本书,可以访问www.packtpub.com/support注册,我们会直接将文件通过电子邮件发送给你。

勘误

尽管我们已经尽力确保内容的准确性,但错误仍然会发生。如果你在我们的书中发现了一个错误——可能是文本或代码中的错误——如果你能报告给我们,我们将不胜感激。这样做,你可以避免其他读者的困扰,并帮助我们改进本书的后续版本。如果你发现任何勘误,请通过访问www.packtpub.com/submit-errata报告,选择你的书,点击勘误提交表单链接,并输入你的勘误详情。一旦你的勘误被验证,你的提交将被接受,勘误将在我们网站的相应位置上传,或者添加到现有勘误列表中。任何现有的勘误可以通过在www.packtpub.com/support选择你的标题来查看。

侵犯版权

互联网上版权材料的侵犯是所有媒体面临的持续问题。在 Packt,我们非常重视保护我们的版权和许可。如果你在互联网上发现我们作品的任何非法副本,无论何种形式,请立即提供位置地址或网站名称,以便我们可以寻求补救。

如果发现任何疑似盗版材料,请通过<copyright@packtpub.com>联系我们,并提供相关链接。

我们感谢您帮助保护我们的作者,以及我们向您提供有价值内容的能力。

咨询问题

如果您在阅读本书的任何方面遇到问题,可以通过<questions@packtpub.com>联系我们,我们将尽力解决。

第一章:Android 开发工具

在本章中,我们将介绍以下内容:

  • 安装 Android 开发工具(ADT)

  • 安装 Java 开发工具包(JDK)

  • 更新 API 源

  • ADT 的替代安装方法

  • 安装本地开发工具包(NDK)

  • 模拟 Android

  • 创建 Android 虚拟设备(AVDs)

  • 使用 Android 调试桥(ADB)与 AVD 进行交互

  • 在 AVD 上复制文件

  • 通过 ADB 在 AVD 上安装应用程序

引言

曾经有位非常聪明的人说过,“你应该亲近你的朋友,但更要亲近你的敌人”。作为一名安全专业人士意味着要关注开发者正在做什么,已经做了什么,以及可能做什么。因为他们的决定极大地影响着安全环境;毕竟,如果没有人编写糟糕的软件,没有人会去利用它!

鉴于这本书面向任何对分析、黑客或开发 Android 平台感兴趣的人,了解你的敌人的概念同样适用于你!Android 开发者需要跟上 Android 黑客的活动,以希望在他们给用户带来负面影响之前捕捉到安全漏洞。反之,Android 黑客也需要跟上 Android 开发者的步伐。

接下来的章节将指导你获取最新和最棒的开发及黑客工具,并让你直接与 Android 安全架构进行交互,既包括破解应用程序也包括保护它们。

本章重点介绍如何安装并运行Android 开发工具ADT),并讨论如何解决安装问题以及保持工具更新。如果你认为自己已经非常熟悉 Android 开发环境和工具链,可以自由跳过这一章。

不再赘述,让我们直接讨论如何获取并安装最新的 Android 开发工具。

安装 Android 开发工具(ADT)

考虑到已经有许多版本的 Android 框架部署在移动平台上,以及支持它的各种不同手机,Android 开发者需要能够访问到 Android 平台上许多设备和操作系统特定的应用程序编程接口(APIs)。

我们不仅仅讨论 Android API,还包括手机特定的 API。每个手机制造商都希望通过提供专有的 API 和服务来吸引开发者,例如 HTC OpenSense APIs。ADT 统一了这些 API 的访问方式;提供了所有必要的工具来调试、开发和部署你的 Android 应用;并且让你轻松下载并保持更新。

如何操作…

以下步骤将指导你完成下载 ADT 并让它们运行起来的过程:

  1. 你需要访问developer.android.com,并导航到 ADT 下载页面,或者直接访问developer.android.com/sdk/index.html#download。你应该能看到如下截图所示的页面:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  2. 到达那里后,点击下载 SDK,应出现以下屏幕:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  3. 当然,在下载之前,你需要接受许可协议,并选择适当的 CPU 类型。如果你不确定如何检查 CPU 类型,可以选择注册大小。

    在 Windows 上,你需要完成以下步骤:

    1. 点击开始

    2. 我的电脑上右键点击。

    3. 选择属性

    4. 应弹出包含计算机系统特定信息的窗口。你寻找的信息应在系统部分,标记为系统类型

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    在 Ubuntu、Debian 或基于 Unix 的发行版上检查系统类型,执行以下步骤:

    1. Ctrl + Alt + T 打开终端,或者直接通过图形界面启动它。

    2. 执行以下命令:

       uname -a
      
      
    3. 或者,你可以使用 lscpu,它应该会显示类似于以下截图的内容:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  4. 当你对许可协议感到满意,并选择了正确的系统类型后,在 ADT 下载页面上点击下载。下载 ZIP 文件后,在 Windows 上应该看起来像以下截图:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在基于 Linux 或 Unix 的发行版上,该归档文件具有相同的结构。

安装 Java 开发工具包(JDK)

Android 使用定制的 Java 运行时版本来支持其应用程序。这意味着,在我们可以使用 Eclipse 开发 Android 应用程序之前,实际上需要安装 Java 运行时和开发工具。这些工具包含在Java 开发工具包JDK)中。

如何操作…

在 Windows 上安装 JDK 的步骤如下:

  1. 从 Oracle 的下载页面获取 JDK 的副本,www.oracle.com/technetwork/java/javase/downloads/index.html。点击DOWNLOAD。以下截图显示了下载页面:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  2. 确保选择适合你的系统类型的适当版本;查看前面的演练以了解如何检查系统类型。以下截图突出了 Oracle Java JDK 支持的 Windows 系统类型:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  3. 下载 JDK 后,运行jdk-[版本]-[平台版本].exe文件。例如,您可能有一个名为jdk-7u21-windows-i586.exe的 EXE 文件。现在您需要做的就是按照提示操作,直到所有设置安装完成。一旦启动安装向导,它看起来应该像下面的截图:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一旦安装向导完成其工作,您应该在C:\Program Files\Java\jdk[版本]下看到全新安装的 JDK 和 JRE,并且现在应该能够启动 Eclipse。

还有更多…

在 Ubuntu Linux 上安装 Java 运行时和开发工具相对简单。考虑到 Ubuntu 有一个成熟的包和仓库管理器,您只需要通过终端窗口执行几个简单的命令来利用它。您需要执行以下步骤:

  1. 打开一个终端,可以通过您的 Unity、KDE 或 Gnome 桌面搜索终端应用程序,或者按Ctrl + Alt + T

  2. 在安装之前,您可能需要更新您的软件包列表,除非您几分钟前已经做过。您可以通过执行以下任一命令来完成此操作:

    sudo aptitude update   //If you have aptitude installed 
    
    

    或者:

    sudo apt-get update
    
    

    您应该会看到您的终端打印出从您的仓库执行的所有下载,如下面的截图所示:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  3. 完成后,执行以下命令:

    sudo apt-get install openjdk-[version]-jdk apt-get 
    
    

    如果您已正确添加到sudoers文件,您需要输入密码。或者,如果您有 root 用户的密码,可以通过执行以下命令借用 root 权限来完成此操作:

    su root
    
    

    下面的截图显示了这一点:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一旦您的 JDK 安装正确,您应该能够启动 Eclipse 并开始进行 Android 开发。当您启动 Eclipse 时,您应该会看到以下截图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

成功安装后,您的 Eclipse 安装中的工具栏应该看起来类似于下面截图中的样子:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

更新 API 源

SDK 管理器和相关工具与 ADT 包捆绑在一起;它们提供了对最新和最稳定的 API、Android 模拟器镜像以及各种调试和应用程序测试工具的访问。以下演练将指导您如何更新您的 API 和其他与 Android 开发相关的资源。

如何操作…

更新 ADT 的 API 如下操作:

  1. 导航到 SDK 管理器。如果您从 Windows 进行所有操作,您应该在ADT-bundle文件夹的根目录中找到名为SDK Manager.exe的文件。Ubuntu 用户可以在[ADT-bundle 路径]/sdk/tools/android找到它。

  2. 您需要做的就是启动 SDK 管理器。它应该启动并开始检索可用的 API 和文档包的新列表。外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  3. 你需要确保选择了 工具 软件包;当然,你也可以选择其他附加软件包。一个好的建议是下载最后两个版本。Android 向后兼容性很好,所以你不必太担心较旧的 API 和文档,除非你正在使用它们来支持非常旧的 Android 设备。

  4. 你需要表明你接受许可协议。你可以为每个正在安装的对象这样做,或者点击 全部接受

  5. 接受完许可协议后,你可以通过点击 安装 来收集你的文档和 API,如下截图所示:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

ADT 的替代安装方法

如果前面介绍安装 Eclipse 和 ADT 插件的方法由于某些原因不奏效,你可以选择走老路,下载你自己的 Eclipse 副本并手动通过 Eclipse 安装 ADT 插件。

如何操作…

下载并安装 ADT 的步骤如下:

  1. www.eclipse.org/downloads/ 下载 Eclipse—Helios 或更高版本。请确保选择适合你操作系统的版本。你应该会看到一个类似以下截图的页面:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  2. 从 Android 网站 developer.android.com/sdk/installing/installing-adt.html 下载适合你平台版本的 ADT 套件。以下截图显示该网站页面的部分内容:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  3. 确保你已经安装了 Java JDK。

  4. 如果你的 JDK 安装没有问题,运行在第 1 步下载的 Eclipse 安装程序。

  5. 一旦 Eclipse 安装完毕并准备就绪,就可以安装你的 ADT 插件了。

  6. 打开 Eclipse 并点击菜单栏中的 帮助 按钮。外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  7. 点击 安装新软件…

  8. 将会弹出 可用软件 对话框。你需要点击 添加…外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  9. 将会显示 添加仓库 对话框。你需要点击 归档… 按钮。

  10. 应该会弹出一个文件浏览器。此时,你需要导航到在前面的步骤中下载的 ADT ZIP 文件。外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  11. 找到 ADT 文件后,点击 打开

  12. 然后点击 确定

  13. 将会显示 .zip 压缩文件中的可用软件包。点击 全选 然后点击 下一步外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  14. 现在你需要接受许可协议;当然,你有权不接受。阅读它总是一个好主意。如果你满意,选择 我接受许可协议的条款 选项,然后点击 完成外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  15. 软件安装现在开始。你可能会收到一个警告,指出内容未签名,无法验证真实性。点击确定外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  16. 重启 Eclipse。

Android SDK、设备模拟器和支持 Eclipse 的功能现在应该已经准备就绪。查看你的 Eclipse 工具栏,它应该有一些新图标。

安装本地开发工具包(NDK)

如果你想在 Android 设备上进行任何低级利用或开发,你需要确保自己能够在 Android 平台上进行较低级别的应用程序编写。低级别指的是使用诸如 C/C++等语言进行开发,这些语言使用的编译器是为了适应嵌入式平台及其各种细节而构建的。

Java 和本地/低级编程语言之间有什么区别?这个话题本身就足以写成一本书。但仅就表面层次的差异来说,Java 代码是在虚拟机中运行的,之前会进行编译和静态分析——即源代码在运行前会被检查。对于 Android Java,这个虚拟机被称为 Dalvik——稍后会详细介绍。Android 的本地开发组件按照其源代码的精确描述,在随 Android 设备附带的类 Linux 嵌入式操作系统上运行。除了编译器扩展和优化之外,没有额外的解释和检查层次,使本地代码得以运行。

Android 团队提供的工具链和文档,使得 Android 开发者能够轻松地进行本地开发,这些工具和文档统称为本地开发工具包NDK)。NDK 包含了 Android 开发者编译其 C/C++代码所需的所有工具,并支持 ARM、MIPS 和 x86 嵌入式平台。它还包括一些帮助本地开发者分析和调试本地应用程序的工具。本教程将介绍如何在你的机器上安装并运行 NDK。

在开始之前,你需要查看developer.android.com/tools/sdk/ndk/index.html#Reqs上的系统要求列表,以确保你的机器可以顺利运行。

如何操作…

在你的机器上获取 NDK 就像下载它并确保它能运行一样简单。我们可以使用以下步骤:

  1. 下载 NDK 非常简单。前往developer.android.com/tools/sdk/ndk/index.html获取最新版本,并确保选择适合你系统类型的适当版本。外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  2. 将 NDK 解压到方便的位置。

模拟 Android

Android SDK 带有一个相当不错的工具,名为模拟器,它允许你模拟 Android 设备。该模拟器包含一些最受欢迎的手机,并允许你创建自己的模拟手机。使用这个工具,你可以刷新新内核,摆弄平台,当然,还可以调试应用程序和测试你的 Android 恶意软件和应用漏洞。在整本书中,我们将大量使用这个工具,所以,重要的是你要了解 Android 模拟器。

模拟器使用起来非常直观。当你想要启动一个设备时,你需要做的就是从 SDK 文件夹或直接从 Eclipse 打开Android 虚拟设备AVD)工具。然后,你可以设置一个新的设备,为其配备自己的内存卡、CPU 和屏幕大小以及其他自定义功能,或者你可以从列表中选择一个预配置的设备。在本节中,我将详细介绍这些内容。

只是一个简短的免责声明:以下屏幕截图是在 Windows 7 机器上拍摄的,但 AVD 管理器和设备模拟器在 Windows 和 Linux 平台上工作完全相同,所以 Linux 用户也将能够跟随操作指南。

如何操作…

要在 Eclipse 中模拟一个设备,请按照以下步骤操作:

  1. 点击工具栏上的 AVD 管理器图标。外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  2. AVD 会弹出。你可以选择一个预配置的特色设备,或者根据你自己的标准设置一个设备。对于这个指南,让我们坚持配置我们自己的设备。

  3. 点击新建…外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  4. 创建新的 Android 虚拟设备 (AVD) 对话框应该会弹出。你需要为新的虚拟设备填写一些指标并为其命名。这里你可以输入任何你感觉合适的内容,因为这个指南只是为了让你模拟你的第一个设备。

  5. 完成后,点击确定。新的设备应该会出现在 AVD 对话框中。

  6. 点击你刚刚创建的设备,然后点击启动…外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这一点上,AVD 会提示你选择屏幕尺寸选项;默认值还不错。完成后点击启动,几秒钟后你的新 AVD 将开始启动。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

创建 Android 虚拟设备 (AVD)

你们中的一些人可能出于某些原因更喜欢从命令行界面使用 AVD。也许你有一些很棒的脚本,你想编写它们来设置一些出色的 AVD。本指南详细介绍了如何创建 AVD 并直接从命令行启动它们。

如何操作…

在创建你自己的 AVD 之前,你需要为它指定一些属性;最重要的一个是将要使用的系统镜像。为此,执行以下步骤:

  1. 你可以使用以下命令找到可供你使用的系统镜像列表:

    [path-to-sdk-install]/tools/android list targets
    
    

    或者在 Windows 终端中使用以下命令:

    C:\[path-to-sdk-install]\tools\android list targets
    
    

    例如,在命令提示符中输入以下内容:

    C:\Users\kmakan\Documents\adt-bundle-windows-x86-20130219\sdk\tools\android list targets
    
    

    这个命令将列出你系统上可用的系统镜像。如果你想要更多,需要通过 SDK 管理器安装它们。在这份列表中你需要找的信息是目标 ID,因为下一步你需要它们来识别系统镜像。

  2. 使用以下命令创建 AVD:

    [path-to-sdk-install]/tools/android create avd –n [name of your new AVD] –t [system image target id]
    
    

    你需要为新创建的 AVD 决定一个名称,通过–n开关来指定。你需要在上一步骤中选择系统镜像 ID,使用–t开关来指定。如果一切顺利,你应该刚刚创建了一台全新的虚拟机。

  3. 你可以使用以下命令启动全新的 AVD:

    [path-to-sdk-install]/tools/emulator –avd [avd name]
    
    

    在这里,[avd name]是你在上一步中决定的 AVD 名称。如果一切顺利,你新创建的 AVD 应该会立即启动。

还有更多…

你可能想要了解更多关于命令的信息。关于模拟器,它能够模拟具有不同配置的设备。

模拟内存卡或外部存储

当你创建虚拟设备时,可以使用–c选项指定它也模拟一些外部存储,如下面的命令所示:

android create –avd –n [avd name] –t [image id] –c [size][K|M]

例如,请看以下命令:

android create –avd –n virtdroid –t 1 –c 128

显然,你需要提供新模拟内存卡的大小。你还需要指定单位,通过指定K表示千字节或M表示兆字节。

分区大小

另一件你可能想要做的事情是指定希望分配给内部存储分区的空间大小。你可以通过使用-partition-size开关来实现,如下面的命令所示,当你调用模拟器时指定:

emulator –avd [name] –partition-size [size in MBs]

你还需要为分区提供大小。默认情况下,测量单位是兆字节(MB)。

另请参阅

在模拟器方面,还有许多其他选项可以利用。如果你有兴趣了解更多,请查看以下链接提供的文档:

使用 Android 调试桥(ADB)与 AVD 交互

与模拟的 Android 设备交互是开发者和 Android 安全工程师/审计师最重要的技能之一。Android 调试桥ADB)提供了与 Android 设备本地级别组件交互所需的功能。它允许开发者和安全工程师读取文件系统的内容,并与包管理器、应用程序管理器、内核驱动接口和初始化脚本等进行交互,仅举几例。

如何操作…

使用 ADB 与虚拟设备交互的方法如下:

  1. 你需要首先启动一个 AVD,或者,如果你愿意,只需通过 USB 将你的 Android 设备连接到任何安装了 SDK 的机器上。你可以使用以下命令启动 AVD:

    emulator –avd [name]
    
    
  2. 我们可以使用以下命令列出所有连接的 Android 设备(针对 Windows 机器):

    C;\\[path-to-sdk-install]\platform-tools\adb devices
    
    

    或者,如果你使用的是 Linux 机器,使用以下命令:

    [path-to-sdk-install]/platform-tools/adb devices
    
    

    这个命令会给你列出连接的设备列表,基本上就是你可以通过 ADB 连接的所有设备。你需要留意列表中的设备名称。当你使用 ADB 启动与它们的连接时,你需要识别这些设备。

  3. 你可以使用以下命令向你的 Android 设备启动 shell 连接:

    /sdk/platform-tools/abd shell –s [specific device]
    
    

    或者,如果你恰好知道你想连接的 Android 设备是唯一的模拟设备,你可以使用以下命令:

    /sdk/platform-tools/adb shell –e
    
    

    或者,如果设备是唯一通过 USB 连接的设备,你可以使用以下命令:

    /sdk/platform-tools/adb shell –d
    
    

    开关 –d-e-p 同样适用于其他 ADB 命令,不仅仅是 shell。如果这操作顺利,你应该会看到类似以下命令的提示字符串——用于标识正在使用的命令 shell 的字符串:

    root@android$
    
    

现在你应该拥有一个功能齐全的 shell,其中包含一些传统的 Unix/Linux 命令和工具。在你的指尖尝试搜索文件系统,了解所有内容的位置。

还有更多…

既然你已经连接了一个设备,你需要了解一些关于导航 Android 文件系统和使用命令的知识。以下是一个帮助你开始的小列表:

  • ls {path}: 这将列出指定路径目录的内容

  • cat {file}: 这将在屏幕上打印文本文件的内容

  • cd {path}: 这将改变当前工作目录到指定路径的目录

  • cd ../: 这将改变当前工作目录到刚好高一级的目录

  • pwd: 这将打印当前工作目录

  • id: 这将检查你的用户 ID

另请参阅

在 AVD 上复制文件

在你即将进行的 Android 平台冒险中,你可能会想要在某些时刻从 Android 设备(无论它们是不是模拟器)上复制东西。复制文件相当简单。你需要的是以下内容:

  • 你希望连接的设备

  • 你想要复制到/从设备上复制的文件

  • 你想要放置这个文件的位置

如何操作…

要使用 ADB 访问你 Android 设备上的文件,你需要执行以下操作:

  1. 实际上这个过程相当简单。你需要从命令行界面执行以下命令:

    adb {options} pull [path to copy from] [local path to copy to]
    
    
  2. 要将文件复制到 AVD 上,你可以使用以下命令:

    adb {options} push [local path to copy from] [path to copy to on avd]
    
    

通过 ADB 向 AVD 安装应用程序

有时你可能需要将本地文件系统上的应用安装包APKs)安装到你自己拥有的模拟器或设备上。通常基于 Android 的安全工具在 Play 商店中无法获取——因为它们可能会让不守规矩的用户面临过多风险,或者被恶意软件滥用——需要手动安装。此外,你可能还需要开发和 Android 原生二进制文件来演示和验证漏洞利用。

如何操作…

使用 ADB 安装 APK 可以通过以下方式完成:

  1. 你需要知道 APK 在你本地机器上的具体位置,找到后,你可以像下面这个命令一样,用path来替换它:

    adb {options} install [path to apk]
    
    
  2. 你还可以使用针对特定设备的命令来缩小你想安装的目标设备。你可以使用以下命令:

    adb {-e | -d | -p } install [path to apk]
    
    

第二章:与应用程序安全互动

在本章中,我们将涵盖以下内容:

  • 检查应用程序证书和签名

  • 签名 Android 应用程序

  • 验证应用程序签名

  • 检查 AndroidManifest.xml 文件

  • 通过 ADB 与活动管理器交互

  • 通过 ADB 提取应用程序资源

引言

在本章中,我们将通过直接与它们互动,了解一些 Android 安全架构组件的实际应用,特别是那些专注于保护应用程序的部分。“在你亲自动手之前,你永远不会真正理解任何事。” 这正是本章试图激发的理念;实际动手拆卸一些安全机制,剖析它们,真正了解它们的作用。

我们在这里只介绍最基本的内容,这些技巧和窍门能让你在需要逆向工程应用程序或对 Android 应用程序进行彻底的手动安全评估时,或者你只是纯粹对应用程序安全感兴趣并想了解更多时,获取所需的信息。

检查应用程序证书和签名

应用证书是开发者用来声明他们对发布到应用市场的应用程序的信任。这是通过声明他们的身份并将其与他们的应用程序以加密方式相关联来完成的。应用签名确保没有应用程序可以通过提供一种简单有效的机制来冒充另一个应用程序,从而确定并强制执行 Android 应用程序的完整性。所有应用程序在安装前必须使用证书进行签名,这是一个要求。

Android 应用程序签名是对 JAR 签名的重新利用。它通过对应用程序内容应用加密哈希函数来工作。我们很快将看到 APK 文件中确切哪些内容被哈希。然后,这些哈希值与声明开发者身份的证书一起分发,将其与开发者的公钥以及实际上他的私钥相关联,因为它们在语义上是相关的。证书通常使用开发者的私钥进行加密,这意味着它是一个自签名证书。没有可信赖的第三方来证明开发者实际上拥有给定的公钥。这个过程产生了一个签名,并且应该与这个公钥一起分发或发布。

一个应用程序的签名是唯一的,找到应用程序的证书和签名是一项关键技能。你可能在设备上寻找恶意软件签名,或者你可能想要列出共享给定公钥的所有应用程序。

准备工作

在开始之前,你需要在你的机器上安装以下软件:

  • Java JDK:这可以在 Unix/Linux 发行版或 Microsoft Windows 系统上安装,如前一章所示

  • Android SDK:如前一章所示,可以在你的 Linux Debian 或 Microsoft Windows 系统上安装。

  • WinZip(针对 Windows):可以在www.winzip.com下载;如果你运行的是 Windows 7,则不需要显式安装 WinZip

  • 解压(针对 Debian/Ubuntu Linux 系统):可以通过在终端输入以下命令进行安装:

    sudo apt-get install unzip
    
    

假设我们还没有一个明确想要查看证书的应用程序,并且你想要完全复制这里所展示的内容,从模拟器中提取一个应用会方便得多。此食谱还详细介绍了如何设置模拟器以执行此操作。

按照这里的方式进行模拟器设置,确保你可以访问完全相同的程序和模拟系统,最终,拥有相同的证书,这样容易检查你是否走在正确的轨道上。在模拟 Android 设备之前,需要确保 Android SDK 工具已更新,包括最新的 API 级别和模拟器镜像。如果你不确定如何升级你的 Android SDK,请参考上一章。

因此,首先让我们通过执行以下步骤来启动一个Android Virtual DeviceAVD):

  1. 打开命令行界面并执行以下命令:

    [path-to-your-sdk-install]/android create avd –n [your avd name]  –t [system image target]
    
    

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    如果你使用的是 Windows 机器,请输入:

    C:\[path-to-your-sdk-install]\android create avd –n [your avd name] –t [system image target]
    
    
  2. 如果一切顺利,你应该刚刚创建了一个 AVD。现在可以执行以下命令来启动它:

    [path-to-your-sdk-install]/emulator –avd [your avd name] –no-boot-anim
    
    

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  3. 你应该会立即看到一个模拟器弹出。给它一点时间启动。一旦完全启动,你可以看到锁屏,这意味着你可以启动 ADB,为我们提取一些 APK 文件。你可以通过输入以下命令来提取 APK 文件:

    adb pull /system/app/Contacts.apk
    
    

    以下截图为实际操作示例:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    如果你需要其他示例,可以查看system/app/目录的内容,找到联系人应用或其他应用,如下面的截图所示:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    你应该刚刚将联系人应用复制到你的本地设备上。如果这部分内容让你感到困惑,请参考上一章;它涵盖了如何创建模拟器以及如何从模拟器复制设备。

如何操作…

你应该在硬盘上有一个你想要检查的 APK 文件的本地副本。我们现在可以开始检查应用程序的证书。要查看应用程序的公钥证书和签名,首先需要解压 APK 文件。如果你知道如何解压归档文件,这非常简单,因为 APK 文件实际上是被重命名的 ZIP 归档文件。你可以通过执行以下步骤来解压归档文件:

  1. 如果你使用的是 Windows 机器,你可能需要确保已安装 WinZip。你需要做的就是使用 WinZip 打开 APK 文件,它应该像其他任何 ZIP 存档一样打开。在 Linux Debian 机器上,你需要将此文件复制到一个带有 ZIP 扩展名的文件中,以便 WinZip 可以为我们愉快地解压:

    cp Contacts.apk Contacts.zip
    
    
  2. 将存档解压到容易记住的地方;你可以通过执行以下命令来完成:

    unzip Contacts.zip
    
    

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    解压存档后,你的目录应该如下截图所示:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  3. 定位名为META-INF的文件夹。这个文件夹包含签名文件和实际的CERT.RSA文件,这是自签名的公钥证书;你可以使用随 Java JDK 捆绑的 keytool 来查看它,你应该在尝试此配方之前安装 Java JDK。使用以下命令打印证书:

    keytool –printcert –file META-INF/CERT.RSA
    
    

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    现在你面前的是声明公钥持有者的证书。

  4. 要查看与应用程序内容相关的实际签名,请定位到META-INF文件夹下的名为CERT.SF的文件。你可以在 Windows 上通过记事本或其他可用的文本编辑器打开它来查看,或者在 Unix/Linux 机器上执行以下命令:

    cat [path-to-unzipped-apk]/META-INF/CERT.SF
    
    

    现在你面前应该有签名文件。它包含了应用程序中包含的资源文件的加密哈希;以下截图为例:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    jarsigner工具尝试验证应用程序内容时,会使用此文件;它会计算CERT.SF文件中列出的资源的加密哈希,并将其与每个资源的摘要进行比较。在之前的截图中,哈希—SHA-1 Digests—已经进行了 base64 编码。

工作原理…

META-INF文件夹是一个非常重要的资源,因为它有助于建立应用程序的完整性。由于该文件夹中的内容在应用程序内容的加密安全中扮演着重要角色,因此有必要讨论该文件夹的结构以及其中应该包含什么内容以及原因。

META-INF文件夹内,你应该至少能找到以下内容:

  • MANIFEST.MF:此文件声明资源,与CERT.SF文件非常相似。

  • CERT.RSA:这是前面讨论过的公钥证书。

  • CERT.SF:此文件包含了应用程序中所有在应用程序签名中已计算的资源。它被添加以适应 JAR 特定的加密签名。

  • CERT.RSA:这是一个 X.509 v3 证书;其中的信息由 keytool 以下列方式结构化:

    • 所有者:此字段用于声明公钥持有者,其中包含有关与此个人相关的国家和组织的一些基本信息。

    • 颁发者:此字段用于声明将公钥与声明持有者关联的 X.509 证书的颁发者。这里提到的人或组织是有效为密钥持有者担保的人。他们是确立证书中列出的公钥真实性的人。

    • 序列号:这是用于标识已颁发证书的识别码。

    • 有效期限:此字段指定了证书及其相关属性可以被颁发者验证的期限。

    • 证书指纹:此字段保存了证书的摘要和。它用于验证证书是否被篡改。

数字签名是通过使用受信任第三方的私钥加密证书来计算的。在大多数 Android 应用程序中,“受信任的第三方”是开发者。这意味着此签名是通过使用他/她自己的私钥(通常与公钥关联的私钥)加密证书生成的。这种数字签名用法在功能上可能是正确的——它利用了数字签名机制的功能——但它不如依赖像证书颁发机构(CA)这样的受信任第三方那样健壮。毕竟,任何人都可以通过用自己的密钥签署来说他们开发了 Twitter 应用,但没有人可以说他们拥有 VeriSign 或赛门铁克的私钥!

如果证书是自签名的,开发者在填写与证书相关的信息时可以发挥其创造性。Android 包管理器并不努力验证证书的颁发者、所有者或任何其他证书详细信息的有效性或是否是实际存在的实体。例如,“所有者”无需明确提及关于开发者的任何有效个人信息,或者“颁发者”可以是完全虚构的组织或个人。尽管这样做是可能的,但强烈建议不要这样做,因为它使得应用程序非常难以被信任;毕竟,移动应用程序经常被存储和使用在非常私人的设备上,而那些得知公钥证书虚构细节的人可能不再信任这样的应用程序。

生成可信任应用程序证书的最佳方式是通过合格证书颁发机构(CA),你可以生成自己的公钥和私钥对之后,请求签署公钥证书,或者请求 CA 生成带有公钥证书的公私钥对,因为他们通常会验证证书中发布的信息。像赛门铁克等 CA 和安全供应商经常提供一系列服务以方便生成可信任的公钥证书,其中一些服务专门用于支持 Android 应用程序开发。

本教程的下一部分包含了一些关于公钥证书的有用链接,供您查看。

还有更多内容…

你也可以在 Linux 的命令行工具中使用 OpenSSL 库执行以下步骤来查看完整的公钥证书:

  1. 确保你已经安装了 OpenSSL;如果没有,你可以使用以下命令安装 OpenSSL:

    apt-get install openssl
    
    
  2. 安装完成后,如果你处于解压后的APK目录的根目录下,可以使用以下命令查看证书:

    openssl pcks7 –inform DER –in META-INF/CERT.RSA –noout –print_certs –text
    
    

    你应该在终端屏幕上看到类似以下截图的内容:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    上一个截图的后半部分如下:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    前一个截图的证书最后一部分是颁发证书的 CA 的实际数字签名。

另请参阅

签名 Android 应用

所有 Android 应用在安装到 Android 设备之前都必须进行签名。Eclipse 和其他 IDE 几乎可以为你处理应用签名的所有工作;但为了让你真正理解应用签名是如何工作的,你应该尝试使用 Java JDK 和 Android SDK 中的工具亲自签一个应用。

首先,关于应用签名的一些背景知识。Android 应用签名只是 JAR 签名的重新利用。多年来,它一直被用来验证 Java 类文件存档的真实性。Android 的 APK 文件与 JAR 文件并不完全相同,并且比 JAR 文件包含更多的元数据和资源;因此,Android 团队需要对 JAR 签名进行调整以适应 APK 文件的结构。他们通过确保 Android 应用中包含的额外内容成为签名和验证过程的一部分来实现这一点。

所以,在不过多透露关于应用签名的情况下,让我们获取一个 APK 文件并进行签名。在后续的演练中,我们将尝试在我们签署后的应用安装在 Android 设备上,作为一个简单的方式来验证我们确实正确地签了名。

准备工作

在开始之前,你需要安装以下内容:

  • Java JDK:这包含了所有必要的签名和验证工具

  • APK 文件:这是一个待签名的 APK 示例

  • WinZip:这是 Windows 机器上必需的操作

  • 解压:这是 Ubuntu 机器上必需的操作

考虑到你可能使用的是一个已经签名的 APK 文件,你首先需要从 APK 文件中删除证书和签名文件。为此,你需要执行以下步骤:

  1. 解压 APK 文件。重新解包 APK 文件是浪费时间的;所以,如果你在这一步需要帮助,请参考检查应用程序证书和签名的菜谱。

  2. 解压 APK 文件后,你需要删除META-INF文件夹。Windows 用户可以直接打开解压后的APK文件夹,使用图形用户界面删除META-INF文件夹。在 Unix/Linux 系统上,可以通过执行以下命令从命令行界面完成:

    rm –r [path-to-unzipped-apk]/META-INF
    
    

    现在你应该准备好签署应用程序了。

如何操作…

通过执行以下步骤可以为你的 Android 应用程序签名:

  1. 你首先需要为自己设置一个密钥库,因为它将保存你用来签署应用程序的私钥。如果你已经有了一个密钥库,可以跳过这一步。在 Windows 和 Unix/Linux 发行版上生成全新的密钥库,你需要执行以下命令:

    keytool –genkey –v -keystore [nameofkeystore] –alias [your_keyalias] –keyalg RSA –keysize 2048 –validity [numberofdays]
    
    
  2. 输入这个命令后,keytool 将帮助你为你的密钥库设置密码;你应该确保输入一些你真正能记住的东西!另外,如果你打算将这个密钥库用于实际用途,请确保将其保存在一个非常安全的地方!

  3. 在为你的密钥库设置好密码后,keytool 将开始提示你输入用于构建证书的信息;请密切关注所请求的信息,并尽可能诚实回答——尽管以下截图并未展示这一点:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    现在你应该已经设置了一个全新的密钥库,其中安全地保存了你的新私钥、公钥和自签名证书,并为你提供加密保护。

  4. 你现在可以使用这个全新的密钥库来签署应用程序,通过执行以下命令即可完成:

    jarsigner –verbose –sigalg MD5withRSA –digestalg SHA1 –keystore [name of your keystore] [your .apk file] [your key alias]
    
    
  5. 系统将提示你输入密钥库的密码。一旦你正确输入,jarsigner将开始原地签署应用程序。这意味着它将修改你提供的 APK 文件,通过添加带有所有证书和签名相关细节的META-INF文件夹。外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    就是这样。签署应用程序就是如此简单。我也无意中展示了如何重新签署应用程序,即替换原本与应用程序一起分发的签名。

工作原理…

首先,让我们看看提供给 keytool 的选项:

  • -genkey:这个选项告诉 keytool 你想要生成一些密钥。

  • -v:这个选项启用详细输出;然而,这个命令是可选的。

  • -keystore:这个选项用于定位你希望用来存储生成的密钥的密钥库。

  • -alias:这个选项是为你生成的密钥对的别名。

  • -keyalg:这个选项说明了用于生成密钥的加密算法;你可以选择使用 RSA 或 DSA。

  • -keysize:此选项指定你将要生成的密钥的实际位数。

  • -validity:此选项提到生成的密钥将有效的天数;Android 官方推荐使用超过 10,000 天的值。

Keytool 实际上对公钥和私钥的操作是将公钥包装在一个 X.509 v3 证书内进行存储。此证书用于声明公钥持有者的身份,并且可以用来确认提到的公钥属于声明的持有者。这需要像 CA 这样的可信第三方的参与,但 Android 并不要求以这种方式确认公钥。关于这些证书如何被使用和构建的更多信息,请参考 检查应用程序证书和签名 的食谱。

jarsigner 的选项将在以下命令后详细描述:

jarsigner –verbose –sigalg MD5withRSA –digestalg SHA1 –keystore [nameof your keystore] [your .apk file] [your key alias]

以下部分解释了前述命令的属性:

  • -verbose:用于启用详细输出。

  • -sigalg:用于提供签名过程中将要使用的算法。

  • -digestalg:用于提供将计算 .apk 文件中每个资源的签名的算法。

  • -keystore:用于指定你想要使用的密钥库。

  • [你的 .apk 文件]:这是你打算签名的 .apk 文件。

  • [你的密钥别名]:这是你与密钥/证书对关联的别名。

参见

验证应用程序签名

在前面的食谱中,我们讲解了应用程序是如何签名的以及如何生成密钥以安全地签名它们。这个食谱将详细说明如何验证应用程序签名。能够手动完成这一操作非常重要,因为它不仅让你了解验证实际是如何工作的,而且也是深入了解加密应用程序安全性的门户。

准备开始

要执行此食谱,你需要以下内容:

  • JDK

  • 一个待验证的已签名应用程序样本

这就是你需要的一切。让我们开始吧!

如何操作…

要验证应用程序签名,你需要执行以下步骤:

  1. Java JDK 有一个名为 jarsigner 的工具,它能够处理所有繁重的工作;你需要做的就是执行以下命令:

    jarsigner –verify –verbose [path-to-your-apk]
    
    
  2. 现在你需要做的是在屏幕上寻找jar 已验证的字样;这表示应用程序签名已经经过验证。

检查 AndroidManifest.xml 文件

应用程序清单可能是对 Android 应用程序安全专家来说最重要的信息来源。它包含了有关应用程序权限以及构成应用程序的各个组件的所有信息,并且向我们详细介绍了这些组件将如何被允许与平台上的其他应用程序交互。我将使用这个食谱作为讨论应用程序清单、其结构以及示例清单中每个组件含义的好借口。

准备工作

在开始之前,你需要安装以下软件:

  • Windows 上的 WinZip

  • Java JDK

  • 一个便捷的文本编辑器;通常 Vi/Vim 可以胜任,但 Emacs、Notepad++和 Notepad 也都很好用;在这里我们不需要花哨的东西。

  • Android SDK(这里并不意外!)

你可能还需要获取一个名为apktool的工具;它使得解码AndroidManifest.xml文件变得非常简单。实际上,它所做的只是重新格式化另一个 Android SDK 工具的输出。设置它非常简单,你只需要执行以下步骤:

  1. 下载工具;你可以在android-apktool.googlecode.com/files/apktool1.5.2.tar.bz2找到它。

    如果你已经安装了 Android SDK,你可以将刚刚下载的 apktool 解压到 SDK 文件夹中的platforms-tools目录下,具体来说:

    C:\\[path to your sdk]\sdk\platform-tools\
    
    

    或者对于 Linux 机器:

    /[path to your sdk]/sdk/platform-tools/
    
    

    请确保你获取了apktool.jar文件和 apktool 脚本,与其他文件放在同一目录下;不要将其放在自己的子文件夹中!

  2. 如果你不想下载 Android SDK,还有一些依赖项需要你下载。它们可以在code.google.com/p/android-apktool/downloads/list下载。

    特别是,如果你使用的是 Windows 电脑,你应该在android-apktool.googlecode.com/files/apktool-install-windows-r05-ibot.tar.bz2获取 apktool。

    如果你在使用 Linux Debian 系统,你应该在这个地址获取相应的工具android-apktool.googlecode.com/files/apktool-install-linux-r05-ibot.tar.bz2

    你还需要确保所有下载的文件都在同一个目录下。

  3. 你应该能够启动它,并且可以通过以下方式测试它:

    在 Windows 上:

    C:\[path-to-apktool]\apktool -help
    
    

    在 Debian Linux 上:

    /[path-to-apk-too]/apktool -help
    
    

    如果你完成了所有这些步骤,你就可以进入下一步,也就是实际剖析一个AndroidManifest.xml文件。

如何操作…

要获取给定应用程序包的AndroidManifest.xml文件副本,你需要执行以下步骤:

  1. 你需要做的就是将 apktool 指向你的 APK 文件。我们将使用之前食谱中从模拟器中提取的Contacts.apk应用程序。在命令提示符中输入以下内容,并确保你的工作目录——你当前所在的终端/命令提示符目录——是提取 apktool 的目录。

    在 Debian Linux 上:

    /[path-to-apktool]/apktool d -f –s [apk file] decoded-data/
    
    

    在 Windows 上:

    C:\[path-to-apktool]/apktool d –f –s [apk file] decoded-data/
    
    

    例如,如果你使用的是Contacts.apk应用程序,并且你想将所有解码的文件保存到一个名为decoded的文件夹中,你可以在 Linux 机器上输入以下命令:

    ~/adt-bundle-linux-x86_64/sdk/platform-tools/apktool d –f –s Contacts.apk decoded
    
    

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  2. 现在你可以查看应用程序清单了。它应该在你上一步选择提取的文件夹中,在一个名为AndroidManifest.xml的文件里。要查看它,只需拿出你最喜欢的文本编辑器——Linux 用户,你的操作系统几乎捆绑了一百万个文本编辑工具——并将其指向AndroidManifest.xml文件。

    在 Linux 上:

    vi [path-to-your-decoded-data]/AndroidManifest.xml
    
    

    或者,你也可以通过执行以下命令在终端屏幕上显示清单:

    cat [path-to-your-decoded-data]/AndroidManifest.xml
    
    

    在 Windows 上:

    C:\Windows\System32\notepad.exe [path-to-decoded-data]\AndroidManifest.xml
    
    
  3. 你可以在终端屏幕上看到清单——如果你使用的是 Linux 机器——或者记事本会自动弹出并打开清单。你们中的一些人可能不理解屏幕上的这些乱码是什么,或者这些信息有多宝贵,因此下一个食谱将包含对应用程序清单结构所有重要部分的解释:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    所以,你可能正盯着AndroidManifest.xml文件中的乱码信息。它的意义以及为什么这一切都很重要,在接下来的演练食谱中会有说明。它提供了关于某些元素及其属性如何工作的良好背景。我只涵盖了与安全和应用程序安全评估最相关的元素背景。

工作原理…

为了帮助你理解应用程序清单,我将在这里向你展示清单的结构,并解释最重要部分的意义。如果你想了解更多关于 Android 清单语言的信息,你应该查看本食谱的另请参阅部分。

清单的结构如下:

<?xml version="1.0" encoding="utf-8"?>

<manifest>

  <uses-permission /> <permission /> <permission-tree /> <permission-group /> <instrumentation /> <uses-sdk /> <uses-configuration /> <uses-feature /> <supports-screens /> <compatible-screens /> <supports-gl-texture />
  <application>
    <activity>
      <intent-filter>
        <action />
        <category />
        <data />
      </intent-filter>
      <meta-data />
    </activity>
    <activity-alias>
      <intent-filter> . . . </intent-filter>
      <meta-data />
    </activity-alias>
    <service>
      <intent-filter> . . . </intent-filter>
      <meta-data/>
    </service>
    <receiver>
      <intent-filter> . . . </intent-filter>
      <meta-data />
    </receiver>

    <provider>
      <grant-uri-permission />
      <meta-data />
      <path-permission />
    </provider>
    <uses-library />
  </application>
</manifest>

提示

下载示例代码

你可以从你在www.packtpub.com的账户下载你购买的所有 Packt 图书的示例代码文件。如果你在其他地方购买了这本书,可以访问www.packtpub.com/support注册,我们会直接将文件通过电子邮件发送给你。

这究竟意味着什么呢?首先,第一行更多是关于文件类型和 Android 清单,几乎与它的作用和目的无关。从.xml扩展名你可能已经看出,它是一个可扩展标记语言XML)文件。这意味着 Android 清单是用 XML 语言编写的。XML 基本上是用于创建任何你希望的语言的格式;一些资料坦率地将其描述为定义标记语言的的语言。XML 旨在成为一组描述几乎所有事情的规则!

所以,当你看到以下代码时,你就知道紧随其后的行是一个使用 UTF-8 编码的 XML 版本 1 的 XML 文件:

<?xml version="1.0" encoding="utf-8"?>

接下来谈谈 Android 特有的部分:

<manifest>

此元素是应用程序清单中条目的开始标签;它标志着开始,被称为 XML 文档的根元素。下一个标签声明应用程序需要给定权限:

<uses-permission android:name="string"/>

这通常是在你安装应用程序时根据权限类型显示的字符串。android:name属性指定了权限的名称;例如,如果你的应用程序需要使用设备的摄像头服务,它的清单中应该有以下代码:

<uses-permission android:name="android.permission.CAMERA">

下一个元素类型如下:

<permission android:description="string resource" android:icon="drawable resource" android:label="string resource" android:name="string" android:permissionGroup="string" android:protectionLevel=["normal" | "dangerous" | "signature" | "signatureOrSystem"] />

此元素用于定义权限;例如,当开发者认为其他应用程序要与特定应用程序组件交互时,需要特殊的唯一权限。这个元素相当有趣;让我们看看它的属性:

  • android:description:此属性用于定义当用户被提示授予权限时作为权限描述显示的字符串。

  • android:icon:此属性用于定义当用户被提示授予权限时显示的描述性图标。

  • android:label:此属性用作当用户被提示授予权限时权限的名称,例如,网络访问和读取短信。

  • android:name:此属性是权限的实际名称。这是在应用程序的清单中查找的字符串,以确定它是否具有此权限,例如android.permission.Camera

  • android:protectionLevel:此属性用于指示与此权限相关的风险级别。这些级别被分类如下:

    • "dangerous":此级别通常分配给任何允许应用访问敏感用户数据或操作系统配置数据的权限。这用于保护任何可能被用于危害用户的函数或数据的访问。

    • "normal":此级别用于指示任何授予访问不带来固有风险的数据或服务的权限。

    • "signature":当权限需要自主授予与定义该权限的应用具有相同证书的任何应用时,会设置此级别,即AndroidManifest.xml中带有相关<permission>标签的应用。

    • "signatureOrSystem":当权限需要自主授予与定义该权限的应用具有相同证书的任何应用时,会设置此级别。

你应该密切关注protectionLevel属性中使用的值,尤其是那些需要专业进行应用评估的人。尝试思考开发者决定的保护级别是否恰当。你需要能够确保与此权限相关的风险能够明确地指示给用户。

protectionLevel的另一个关键属性在于它决定了在应用安装前向用户显示哪些权限。用户总是会被提示授予危险保护级别的权限,而普通权限只有在用户明确请求时才会显示。另一方面,signaturesignatureOrSystem权限在应用安装前不会显示给用户。这意味着如果应用在signaturesignatureOrSystem保护级别下被授予了风险权限,用户将对此一无所知。在检查应用清单时请考虑这一点,因为它将帮助确定应用如何向用户传达风险。接下来是下一个元素类型!

<application>

此元素用于定义一个应用的开始。关于安全,此元素的重要之处在于其属性以及它们如何影响在此元素内定义的组件。为了简洁起见,这里省略了属性定义;你需要参考在developer.android.com/guide/topics/manifest/application-element.html可获取的官方文档以获取更多详细信息。

此元素的一个重要属性是,某些属性仅为元素内部定义的组件的相应属性设置默认值;这意味着其组件将能够覆盖它们。这些可覆盖属性中的一个显著元素是称为permission的属性,它声明了其他应用与之交互所需的权限。这意味着如果一个应用设置了一个给定的权限,而它的一个组件设置了不同的权限作为其属性,那么组件的权限将优先考虑。如果组件用普通权限覆盖了危险权限,这可能会带来相当大的风险。

其他属性不能被它们的组件覆盖。这取决于属性中设定的值,并应用于每一个单独的组件。组件包括以下属性:

  • debuggable:此属性指定给定的组件或组件组是否可调试。

  • enabled:此属性指定安卓应用框架是否能够启动或运行此元素定义的组件;默认为true。只有当设置为false时,它才会覆盖所有组件的值。

  • description:这个属性仅是一个用于描述应用的字符串。

  • allowClearUserData:此属性是一个标志,用于确定用户是否可以清除与 app 关联的数据;默认情况下,它被设置为true,在一些平台上非系统应用不能将其设置为其他值。

以下元素是应用程序组件的定义,允许开发者为它们决定某些属性:

<activity
  android:exported=["true" | "false"]
  android:name="string"
  android:permission="string"
  android:enabled=["true" | "false"]
  android:permission="string"
...other attributes have been omitted
>
`android:exported`: This attribute is used to decide whether the components of other applications will be able to interact with this element. All application components—services, broadcast receivers, and content providers—have this attribute in common.

What's interesting here is the default behavior of this attribute, if it is not explicitly set for this element. Whether or not it will be "`exported`" partly depends on whether intent filters are defined for the activity or not. If intent filters are defined and the value is not set, the Android system assumes that the component intends to respond to interaction from external application components and will allow them to interact with it, given that the initiator of the interaction has the necessary permissions to do so. If no intent filters are defined and the attribute value is not set, the Android application framework will only allow explicit intents to be resolved against the component.

There is another caveat. Because of the way in which older Android API levels work, there are attributes that can override the default value; for applications that set either `android:minSdkVersion` or `android:targetSdkVersion` to 16 or lower, the default value is `true`. For applications that set `android:minSdkVersion` or `android:targetSdkVersion` as equal to or higher than 17, the default value is `false`.

This is very valuable information because it will help us determine an application's attack surface—it determines how potentially malicious applications will interact with its components—and quite literally determine the difference between a good security assessment and an ineffective one.

`android:name`: This attribute specifies the class file that contains the Java code for the component; I've added it here because you will need to know this value should you want to launch explicit intents aimed at a given component. All component types have this attribute in common.`android:permission`: This attribute is used to specify the permission required to interact with the component.`android:enabled`: This attribute is used to indicate whether the system is allowed to start/instantiate the component:

<service android:enabled=[“true” | “false”] android:exported=[“true” | “false”] android:icon=“drawable resource” android:isolatedProcess=[“true” | “false”] android:label=“string resource” android:name=“string” android:permission=“string”>


It is used to define the attributes of a service; some XML attributes are unique to services, namely:

*   `android:isolatedProcess`: This attribute indicates if the service will run in an isolated process with no permissions.

    ```

        <receiver android:enabled=["true" | "false"] android:exported=["true" | "false"] android:icon="drawable resource" android:label="string resource" android:name="string" android:permission="string" android:process="string" ></receiver>

    ```kt

    This element declares the broadcast receiver component:

    ```

        <provider android:authorities="list" android:enabled=["true" | "false"] android:exported=["true" | "false"] android:grantUriPermissions=["true" | "false"] android:icon="drawable resource" android:initOrder="integer" android:label="string resource" android:multiprocess=["true" | "false"] android:name="string" android:permission="string" android:process="string" android:readPermission="string" android:syncable=["true" | "false"] android:writePermission="string" ></provider>

    ```kt

    It defines the components of the content provider type. Seeing that the content providers are basically database-like components, they would need to be able to define the controls for accessing their data structures and content. The following attributes help them to do just that:

*   `android:writePermission`: This attribute specifies the name of the permission components from other applications that this content provider is in charge of. It is a must-have in order to change or augment data structures.
*   `android:readPermission`: This attribute specifies the name of the permission components from other applications that this content provider is in charge of. It is a must-have in order to read from or query the data structures.
*   `android:authorities`: This attribute specifies a list of names identifying the URI authorities. Usually, these are the Java classes that implement the provider: 

    ```

        <intent-filter android:icon="drawable resource" android:label="string resource" android:priority="integer" ></intent-filter>

    ```kt

另请参阅

通过 ADB 与活动管理器交互

对于任何初露头角的安卓安全专家来说,了解安卓调试桥ADB)是非常重要的。ADB 允许你直接与本地服务和资源进行交互,例如包管理器、活动管理器以及其他各种对安卓系统操作至关重要的守护进程,这些都被安卓系统所使用。本指南将提供如何通过演示一些你可以执行的命令与活动管理器交互的详细信息。

准备就绪

在开始之前,你需要准备以下物品:

  • 安卓 SDK 工具

  • 可以是虚拟设备,查看检查 AndroidManifest.xml 文件的菜谱以了解如何创建和启动一个,或者是物理的安卓设备

如何操作…

要使用应用程序管理器启动活动,你需要执行以下步骤:

  1. 使用以下命令在你的安卓设备上打开一个 shell:

    adb shell
    
    
  2. 找到一个要启动的活动;你可以通过使用包管理器搜索设备上已安装的活动列表来实现这一点。

    pm list packages
    
    

    大量的包列表应该开始从你的屏幕上倾泻而下;其中任何一个都可以作为一个很好的示例:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  3. 选择你想要启动的活动后,执行以下命令:

    am start [package name]
    
    

还有更多…

除了启动活动之外,你还可以通过使用 start 命令接受的意图参数,指定要发送到活动的意图,如下所示:

am start <INTENT> < --user UID | current >

<INTENT> 参数可以由允许你详细描述一个意图的几个参数组成。

  • -a [动作]:此参数指定要指定的动作的字符串标签。它有助于详细说明被发送意图的预期目的或“动作”。

  • -d [数据 URI]:此参数指定要附加到意图的数据 URI。它指向处理意图的应用程序要使用的数据。

  • -t [MIME 类型]:此参数指定意图中包含的数据的 MIME 类型。

  • -c [类别]:此参数指定意图的类别。

  • -n [组件]:此参数指定了意图指定的包的目标组件。它用于精确调整意图的目标。

  • -f [标志]:此参数指定意图标志。它用于描述应如何尊重意图,并允许你控制尊重意图的应用程序的一定数量的行为。

  • -e [额外键] [字符串值]:此参数添加与给定键关联的字符串值。某些意图定义允许你向应用程序传递字符串值的字典。当意图被尊重时,将访问这些字符串值。

  • -e [额外键] [字符串值]:此参数的功能与 -e 相同。

  • -ez [额外键] [布尔值]:此参数将布尔值与名称关联。

  • -ei [额外键] [整数值]:此参数将整数值与名称关联。

  • -el [额外键] [长整数值]:此参数将长数字值与名称关联。

  • -ef [额外键] [浮点数值]:此参数将浮点数值与名称关联。

  • -eu [额外键] [URI 值]:此参数将 URI 与名称关联。

  • -ecn [额外键] [组件名称]:此参数将组件名称(将被转换为 ComponentName 对象)与名称关联。

  • -eia [额外键] [整数值, 整数值,...]:此参数允许你将整数数组与名称关联。

  • -efa [额外键] [浮点值, 浮点值,...]:此参数与-eia相同,不同之处在于在这种情况下,您可以将一系列浮点数值与一个名称关联。

并非所有意图参数都是必须的。要让此命令逻辑上合理,只需要意图目标组件或动作值;这些规则适用于所有针对应用程序的意图。

可选的--user参数允许您指定应用程序应以哪个用户身份运行。如果没有为活动提供此参数,它将以 ADB 用户的身份运行。

您还可以将标志与意图关联。要获取完整选项列表,请参考意图规范 - Android 开发者部分中的标记链接。

使用此命令的工作方式类似于以下命令:

am start –n com.android.MyPackage/com.android.MyPackageLaunchMeActivity –e MyInput HelloWorld –a android.intent.MyPackageIntentAction –c android.intent.category.MyPackageIntentCategory

您也可以使用活动管理器启动服务;您可以通过使用startservice命令来完成此操作:

am startservice <package name>/<component name> <INTENT>

使用此命令的工作方式如下:

am startservice com.android.app/com.android.app.service.ServiceComponent
you can also specify

活动管理器支持的另一个功能是停止服务和进程。当应用程序占用所有系统资源并减慢系统速度时,这非常有用。以下是使用活动管理器杀死进程的方法:

kill < --user UID | current > <package>

与之前的命令一样,UID参数是可选的。在这里,此参数允许您将kill命令限制为以给定用户身份运行的包。如果未指定,ADB 将尝试杀死与给定包关联的所有用户的运行进程。

有关 Android 活动管理器支持的其他命令,请参见Android 调试桥 - Android 开发者部分中的标记链接。

另请参阅

通过 ADB 提取应用程序资源

以下指南将展示如何对您的 Android 应用程序进行一些侦查。具体来说,找出它们用来存储重要信息的数据结构类型以及它们存储的信息类型,例如,高分、密码、联系人和电子邮件。除了允许您将高分设置为负数,这还是一种有效的方法,可以允许您从后端影响应用程序行为。它还让您了解应用程序如何保护用户数据,例如,数据是否加密?如何加密?应用程序是否保护用户数据的完整性?在进行逆向工程和评估应用程序安全性时,这也是一项非常有用的技能。

准备工作

不幸的是,对于这一点,您需要一个“已 root”的手机或模拟器,因为您已经拥有模拟设备上的 root 权限。

如果你想要访问其他应用程序的资源,你需要获得 root 权限。如果你想研究市场上应用程序的行为,使用 ADB 将它们从你的设备上拉下来并在虚拟设备上安装没有任何阻碍。

你还需要安装 Android SDK。

如何操作…

在 Android 设备上列出文件可以通过以下方式完成:

  1. 使用以下命令在你的 Android 设备上启动 shell:

    adb shell [options]
    
    
  2. 导航到/data/data/目录:

    cd /data/data/
    
    

    该目录应类似于以下截图:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    如果你列出文件权限、创建、修改和其他元数据,它应该看起来像以下截图:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    注意数据目录的所有者和组,这是列表从左数第一和第二个列。这里所有者是实际的应用程序。默认情况下,Linux 将每个应用程序作为其自己的 Linux 用户运行,这本质上是应用程序沙箱操作的方式。当一个应用程序被赋予对它本质上无法访问的资源的权限时,Linux 会将它放入相关的用户组。

  3. 如果你希望一次性查看所有应用程序资源和元数据,请执行以下命令:

    ls –alR */
    
    

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    但是,通常情况下,除非你将输出重定向到文件,否则你不会希望屏幕被大量的目录列表淹没。你可能只想显示数据库:

    ls –alR */databases/
    
    

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    或者,也许只显示每个应用程序在/files/目录中保存的文件或其他内容:

    ls –alR */files/
    
    

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    或者,你可以通过指定扩展名来搜索特定类型的文件,以下是一些例子:

    ls –al */*/*.xml
    ls –al */*/*.png
    ls –al */*/*.mp3
    
    
  4. 找到你要找的文件后,你需要使用古老的adb pull命令将它们复制到你的机器上:

    adb pull /data/data/[package-name]/[filepath] 
    
    

还有更多…

我们在这里真正做的只是列出不同的文件类型。其中一种是 sqlite3 数据库,你可能在一些目录中看到的 DB 文件。我敢肯定你很想知道如何打开它们并看看里面有什么。以下是操作方法。

在开始之前,你需要确保已安装 sqlite3,它随 Android SDK 一起提供。

  1. 使用以下命令将 DB 文件提取到你的机器上的位置:

    adb pull /data/data/[package-name]/databases/[database-filename] 
    
    
  2. 使用 sqlite3 加载.db文件:

    sqlite3 [database-filename]
    
    

    如果你需要一个示例,请查看以下截图:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在本章中,我们介绍了一些保护应用程序的机制,一些涉及应用程序间通信、应用程序权限以及加密签名和文件系统相关保护的基本保护措施。

你应该从这儿带走的是执行安全机制所需的一些技巧和窍门。这使你能够独立于执行这些机制的 Android 设备来评估这些机制的有效性,并且还能让你直接与它们交互,希望这能帮助你更好地理解它们。

第三章:Android 安全评估工具

在本章中,我们将介绍以下内容:

  • 安装和设置 Santoku

  • 设置 drozer

  • 运行 drozer 会话

  • 枚举已安装的软件包

  • 枚举活动

  • 枚举内容提供者

  • 枚举服务

  • 枚举广播接收器

  • 确定应用程序攻击面

  • 启动活动

  • 编写一个 drozer 模块——一个设备枚举模块

  • 编写一个应用程序证书枚举器

引言

我们已经介绍了所有 Android 开发基础,并介绍了所有 Android 开发工具。现在是我们开始深入了解 Android 黑客和安全评估工具的时候了。

本章介绍了一个名为drozer的利用和 Android 安全评估框架——正式名称为Mercury——由 MWR Labs 的一些人开发。同时本章还介绍了一个基于 Debian 的 Linux 发行版,名为Santoku,它基本上就像是移动安全评估的 BackTrack 或 Kali Linux。这里我们将介绍如何设置它并使其运行。

在我们开始设置 drozer 并编写一些示例脚本之前,对于你来说非常重要的一件事是要了解一些关于 drozer 的运作方式以及它是如何在 Android 安全评估游戏中解决一些问题的。

drozer 分为两部分:一部分是在你的本地机器上运行的“控制台”,另一部分是安装在目标 Android 设备上的“服务器”。当使用控制台与 Android 设备交互时,你实际上是在将 Java 代码注入到 drozer 代理中,该代理在实际设备上执行。

为什么要这样设计呢?在 drozer 出现之前,编写以应用程序漏洞为目标的利用意味着为了利用特定的漏洞,你需要编译一个 Android 应用,将其部署到目标手机上,并检查是否有效。如果无效,你需要重新进行整个流程!这种做法非常繁琐,会使得 Android 安全评估变得像一件苦差事。drozer 通过代理 drozer 代理传递命令到设备,使得部署和测试利用变得简单,这意味着你永远不需要接触 Android 开发环境或多次重新编译利用应用。

drozer 被称为框架,因为它允许你通过编写自己的模块或插件来扩展其功能,并适应你的需求。它本质上是最接近移动安全评估的 Metasploit。

标准 drozer 框架的另一个效果是,它本质上是一个 Android 应用程序——其中的一部分——没有权限,这意味着你在 Android 设备上成功执行的任何利用将自动变得非常可移植,并且成功所需的权限级别非常低。目的是展示一个“无权限”应用程序在利用 Android 设备及其上托管的应用程序时可以多么有效。

关于 drozer 的基本背景知识就介绍到这里。至于本章的其余部分,你可能需要一些 Python 编程语言的基础知识,因为 drozer 的模块是用 Python 开发的。如果你了解 Java 反射,或者知道如何开发一些 Android 应用,也会有所帮助。如果你从未认真开发过东西,或者通常不使用 Python 编程,不要担心——我会确保详细解释所有的 Python 代码。

那么不再犹豫,让我们开始吧!

安装和设置 Santoku

viaForensics 的开发者们开发了一个基于 Ubuntu 的非常酷的发行版,其中包含移动安全评估工具,名为 Santoku。以下指南将展示如何设置你自己的安装。我首先做这个是因为你可能想要在你的 Santoku 操作系统安装中安装并运行 drozer。

准备就绪

首先,我们将进行一些下载。从santoku-linux.com/download获取最新 Santoku 映像的副本。

如何操作…

下载最新版本的 Santoku 后,你可以按照以下步骤开始设置:

  1. 首先,你可以使用 Ubuntu 启动盘创建器或 Windows 的通用 USB 安装程序将 Santoku 映像写入 USB 存储棒,可从www.pendrivelinux.com/downloads/Universal-USB-Installer/Universal-USB-Installer-1.9.4.7.exe获取。

  2. 将你下载的 Santoku 映像写入 USB 磁盘。

  3. 使用通用 USB 安装程序,执行以下步骤:

    1. 启动通用 USB 安装程序,在步骤 1中选择尝试未列出的 Linux ISO外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    2. 点击浏览,选择你 Santoku ISO 的路径,如前一个截图所示。

    3. 步骤 3中,选择你希望写入映像的 USB 闪存盘。

    4. 点击创建,然后放松休息,同时你的安装磁盘映像正在准备中。

  4. 在插入 USB 设备的情况下重启你的主机;打开启动菜单并选择从 USB 磁盘启动。

  5. 一旦从 USB 启动盘启动,你应该会看到以下屏幕:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  6. 在启动屏幕上,选择install – 直接启动安装程序

  7. 安装应该从以下截图所示的屏幕开始:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  8. 按照安装向导的提示操作,直到开始安装。这个过程非常容易理解,对于之前安装过 Ubuntu 的人来说应该很熟悉。

    安装完成后,你应该会看到一个全新的 Santoku 桌面,如下截图所示:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

还有更多…

如果你打算在虚拟机上安装,你需要获取 VirtualBox 的副本。对于 Windows 和 Unix/Linux 用户,可以在www.virtualbox.org/wiki/Downloads找到。

下载并安装 VirtualBox 后,你需要通过以下步骤创建一个新的虚拟机:

  1. 点击 VirtualBox 窗口左上角的新建按钮。

  2. 创建虚拟机对话框应该会弹出。在名称字段中输入Santuko,或者你也可以根据喜好为新的虚拟机命名。

  3. 类型下拉菜单中选择Linux

  4. 版本下拉菜单中选择Ubuntu并点击下一步外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  5. 此时会出现内存大小对话框;默认设置为512。这个设置是足够的;但是,如果你的宿主机有足够的内存,你可以更慷慨一点。确定内存大小后,点击下一步

  6. 硬盘设置对话框会出现;选择现在创建虚拟硬盘选项并点击下一步

  7. 你将看到硬盘文件类型对话框;选择VDI(VirtualBox 磁盘映像)选项并点击下一步

  8. 物理硬盘上的存储对话框应该会出现;选择动态分配选项;因为你会很可能在这个虚拟机的硬盘上安装和下载许多应用程序和工具。点击下一步

  9. 文件位置和大小对话框应该会出现。你可以接受这里的默认设置;8 吉字节足以存储所有初始操作系统数据及工具。如果你需要更多空间,可以配置虚拟机占用更多的存储空间;一切由你决定。选择合适的大小后,点击下一步

  10. 你的虚拟机现在应该设置好了;你需要为其配置一个可启动的实时 CD。为此,点击设置

  11. 设置对话框出现后,点击设置对话框左侧面板中的存储

  12. 控制器: IDE部分下,点击控制器: IDE部分标签旁边的第一个按钮添加 CD/DVD 设备外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  13. 会弹出一个VirtualBox 问题对话框;在这个对话框上,点击选择磁盘。你应该会看到一个文件对话框。

  14. 导航到并选择你已下载的 Santoku 映像。

  15. 你现在可以启动新的 Santoku 虚拟机并开始安装。外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

设置 drozer

安装并设置 drozer 是相当简单的;设置过程适用于 Windows 7 和 Unix/Linux 类型的系统。

如何操作…

在开始编写一些 drozer 脚本并了解利用和枚举模块之前,你需要获取适合你系统的 drozer 安装程序。以下是操作方法:

  1. 访问 www.mwrinfosecurity.com/products/drozer/community-edition/ 获取 drozer 框架的副本;当然,这里我将讨论社区版。如果你愿意花钱购买非免费版本,请访问 products.mwrinfosecurity.com/drozer/buy外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    Windows 用户应点击 drozer (Windows 安装程序) 选项;它应该会立即开始下载 drozer-installer-[version].zip 文件。

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    Unix/Linux 用户根据你的发行版或操作系统类型,选择 drozer (Debian/Ubuntu Archive) 文件或 drozer (RPM) 包 文件。

  2. 下载与你的系统兼容的 drozer 版本后,根据你的系统,你需要执行以下操作:

    对于 Windows 用户:

    1. 你需要将 drozer-installer-[version].zip 文件解压到你能轻松记住的位置/路径中。外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    2. 安装向导设置好后,你需要做的就是按照提示操作,注意配置对话框,并确保记下 drozer 将安装在系统上的位置;你需要经常访问此路径以使用 drozer。安装开始后,你应该会看到以下对话框出现:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    3. 安装完成后,你应该已经将 drozer 安装到你指定的路径中。默认情况下,这被配置在 C 驱动的根目录下,如下截图所示:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

      对于 Unix/Linux 用户:

      drozer 框架以与你的系统相关的包文件格式提供,因此对于 Debian 用户是 DEB 文件,对于 Red Hat 用户是 RPM 文件。你只需使用包管理器打开此文件,其余的它会处理。Debian 用户可以使用以下命令来安装 drozer:

      dpkg –I drozer-[version].deb
      
      
  3. 安装完 drozer 后,你应该尝试运行它。如何运行部分取决于你的操作系统。

    对于 Windows 用户:

    1. 打开命令提示符并转到你安装 drozer 的路径。如前所述,默认情况下这是 C:\drozer 路径。

    2. 通过执行以下命令调用 drozer:

       C:\drozer\drozer
      
      

      你应该看到类似于以下截图的输出:

      外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    3. 作为诊断测试,尝试调用 drozer 控制台。如果出现问题,它会在告诉你设备(这里未连接)不可用或拒绝连接之前,通知你错误。执行以下命令:

       C:\drozer\drozer console
      
      

      除非你已经足够聪明地解决了错误,否则你应该看到与以下屏幕截图相似的输出:

      外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

      这个错误意味着 drozer 无法找到你的 Java 安装。

  4. 假设你已经安装了 Java,你可以将 drozer 添加到你的系统 PATH 变量中。

    在 Windows 上增强你的 PATH 变量非常直接;你可以通过执行以下步骤开始:

    1. 打开 我的电脑

    2. 点击 系统属性

    3. 在屏幕的 控制面板 部分下,点击 高级系统设置外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    4. 应该会弹出 用户访问控制 提示。如果你有管理员权限,只需点击 确定 或输入管理员密码。

    5. 系统属性 对话框中,点击标记为 环境变量… 的按钮。外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    6. 一旦弹出 环境变量 对话框,在标记为 系统变量 的部分,向下滚动到名为 Path 的变量并点击 编辑…外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    7. 应该会弹出一个对话框,允许你编辑 PATH 变量。在变量值的末尾添加以下字符串:

             ;C:\Program Files\Java\jre7
      

对于 Unix/Linux 用户:

  1. 你可以通过从你的终端窗口执行以下命令来调用 drozer:

    drozer
    
    
  2. 如果一切正常,你应该看到与 Windows 版 drozer 完全相同的输出。

  3. 如果 Java 尚未添加到你的 PATH 变量中,执行以下命令以添加它:

    PATH=$PATH:`which java
    
    

    为了使这个持久化,将之前的命令行添加到你的 /home/[user]/.bashrc 文件的末尾。

还有更多…

在 drozer 能够启动并运行之前,你需要在 Android 设备上安装 drozer 代理。这很简单;以下是操作方法:

  1. 假设设备通过 USB 连接到你的主机,你可以按照以下方式安装 drozer.apk 文件:

    adb install drozer.apk
    
    
  2. 为了使这个工作,你需要确保目标 Android 设备已启用 未知来源USB 调试

    启动 drozer 后,你应该看到以下内容:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  3. 为了使从命令行界面使用 drozer 控制台更加方便,你也可以将 drozer 本身添加到你的系统 PATH 变量中。

    对于 Windows 用户:

    1. 按照前一个菜谱描述的方式访问 环境变量 对话框。

    2. 将以下字符串添加到你的 PATH 变量中:

             ;C:\drozer\drozer
      
      

    如果你是一个 Unix/Linux 用户,从你的终端执行以下命令:

    PATH=$PATH:`which drozer`
    
    

    为了使这个持久化,将之前的命令行添加到你的 /home/[user]/.bashrc 文件的末尾。

如果 DEB 文件安装失败,还有另一种相对无痛的方法来安装 drozer。要在不使用 DEB 包的情况下安装 drozer,请执行以下步骤:

  1. 首先,通过执行以下命令获取 Python 开发头文件和软件包的副本:

    apt-get install python-dev
    
    
  2. 通过执行以下命令获取 Python 安装工具的副本:

    apt-get install python-setuptools
    
    
  3. 为你的 Debian 系统安装 32 位支持库:

    apt-get install ia32-libs-i386
    
    
  4. 安装 Python 依赖项;第一个是 protobuf,你可以通过执行以下命令来安装:

    easy_install –allow-hosts pypi.python.org protobuf==2.4.1
    
    
  5. 安装 protobuf 之后,你需要为 Python 安装 twisted,可以通过执行以下命令来完成:

    easy_install twisted==10.2.0
    
    
  6. 接下来你需要做的是获取一份可在 www.mwrinfosecurity.com/system/assets/571/original/drozer-2.3.2.tar.gz 下载的 drozer 独立架构包。

  7. 下载后,将其解压到你选择的某个目录中。解压后,它应该包含一个名为 drozer-[version]-py2.7.egg 的文件。然后你可以通过执行以下命令来安装这个 EGG:

    easy_install drozer-[version]-py2.7.egg
    
    

    就这样——drozer 应该已经准备好大显身手了!

运行 drozer 会话

既然已经设置好 drozer 并准备就绪,你就可以在示例 Android 设备上运行一些 drozer 会话了——最好是已经安装了 drozer 代理的设备。

以下教程将带你了解设置 drozer 会话的基础知识以及如何通过 drozer 控制台快速运行一些简单的模块。

如何操作…

在继续本教程之前,你需要在你的机器上安装 drozer 控制台,在目标设备上安装 drozer 代理。如果这些都准备好了,你可以通过执行以下步骤来开始你的 drozer 控制台会话:

  1. 使用 ADB,设置一些端口转发,前提是你连接了某种设备:

    adb forward tcp:31415 tcp:31415
    
    
  2. 您需要确保已启动 drozer 嵌入式服务器。你需要通过设备上的应用程序界面来启动它。只需在设备上找到 drozer 代理;它应该会出现在其他应用程序中,但由于你可能刚刚安装了它,你可能会看到一条关于它的通知,并且可以从通知菜单中启动它。

  3. 点击通过 drozer 代理用户界面标记为 嵌入式服务器 的按钮。你应该会看到如下截图所示的屏幕:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  4. 将标记为 禁用 的按钮向右拖动。现在它应该显示 启用,并且用户界面中 服务器详情 部分下的 启用 标签应该已激活,如下截图所示:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  5. 然后,你可以通过执行以下命令来连接 drozer 控制台:

    drozer console connect
    
    

    然后 drozer 应该进入控制台模式,允许你开始执行命令和模块。

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

枚举已安装的包

drozer 代理已经设置好了,你也成功启动了 drozer 控制台;你可以开始运行一些 drozer 模块,真正与设备的安全性进行交互。

以下教程详细介绍了如何使用 drozer 框架执行诸如枚举已安装的包并根据包名进行过滤等新任务。

如何操作…

当你搭建并运行了你的 drozer 框架后,你可能想要开始在 Android 设备上摸索和尝试。你可能想要做的一件有用的事情是列出设备上安装的所有包。你可以通过从你的 drozer 控制台触发以下命令来实现这一点:

dz> run app.package.list

你应该会在屏幕上看到类似以下内容开始出现:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

它是如何工作的…

让我们来看看 drozer 的源代码,确切地了解它是如何与包管理器 API 接口来获取所有这些有用信息的。我将解释大部分模块背后的代码,以便你了解 drozer 是如何工作的,并在本章的后面指导你自己编写一个 drozer 模块!毕竟,框架的意义就在于——构建你自己的模块和插件。

非 Python 用户/开发者请注意!你可能需要一些 Python 背景知识才能阅读这段源代码;尽管如此,考虑到 Python 的语义性,即使你从未编写过 Python 代码,你也应该能很容易地跟上。drozer 设计的一个额外好处是,它们基本上镜像了 Android Java API,使得模块开发对 Android 开发者来说很容易上手。所以,总之,你暂时还不需要去拿本 Python 的书来读。如果你之前写过 Android 应用,这将非常容易理解。无论如何,废话少说——让我们来看一些代码!

注意

以下代码可以在github.com/mwrlabs/drozer/blob/master/src/drozer/modules/app/package.py(第 99-121 行)找到。

def add_arguments(self, parser):
  parser.add_argument("-a", "--package", default=None, help="the identifier of the package to inspect")
  parser.add_argument("-d", "--defines-permission", default=None, help="filter by the permissions a package defines")
  parser.add_argument("-f", "--filter", default=None, help="keyword filter conditions")
  parser.add_argument("-g", "--gid", default=None, help="filter packages by GID")
  parser.add_argument("-p", "--permission", default=None, help="permission filter conditions")
  parser.add_argument("-u", "--uid", default=None, help="filter packages by UID")

def execute(self, arguments):
  if arguments.package == None:
    for package in self.packageManager().getPackages(common.PackageManager.GET_PERMISSIONS | common.PackageManager.GET_CONFIGURATIONS | common.PackageManager.GET_GIDS | common.PackageManager.GET_SHARED_LIBRARY_FILES):
      self.__get_package(arguments, package)
  else:
    package = self.packageManager().getPackageInfo(arguments.package, common.PackageManager.GET_PERMISSIONS | common.PackageManager.GET_CONFIGURATIONS | common.PackageManager.GET_GIDS | 
            common.PackageManager.GET_SHARED_LIBRARY_FILES)

      self.__get_package(arguments, package)

def get_completion_suggestions(self, action, text, **kwargs):
  if action.dest == "permission":
    return android.permissions

def __get_package(self, arguments, package):
  application = package.applicationInfo

execute()方法在你从控制台触发app.activity.info模块时会被调用。它实际上是模块执行实际工作的入口点。

我们看到对包管理器的调用,self.packageManager().getPackages(…);这返回一个包含每个包对象及其权限、配置、GID 和共享库的列表。脚本在每个包对象上调用self.__get_package()来将其输出到 drozer 控制台。当通过命令行参数提供特定包时,也会执行相同的操作。

如果你想要获取这段代码的副本,可以从 drozer 的官方 GitHub 仓库获取,如果你足够用心去 Google,找到它是非常容易的。为了让大家更方便,我在本食谱的另请参阅部分提供了一个代码仓库的 URL。

还有更多…

dz> run app.package.list命令是对 Android 包管理器的一个封装;因此,你能做的很酷的一件事就是基于应用名称进行筛选,如下所示:

dz> run app.package.list –f [application name]

在这里,[application name]是你想要检查的应用程序或包的名称。以下是一个例子:

dz> run app.package.list –f facebook

drozer 中的另一个用于提取信息的枚举类型模块是app.package.info,它会获取关于一个包的以下信息:

  • 权限

  • 配置

  • 群组 ID

  • 共享库

你可以通过从你的 drozer 控制台发出以下命令来使用这个模块:

dz> run app.package.info --help

以这种方式使用时,它将提取关于你 Android 设备上所有软件包的相关信息。

自然地,你可能希望将此信息缩小到特定的软件包:

dz> run app.package.info –-package [package name]

你也可以使用以下开关的简写方式:

dz> run app.package.info –a [package name]

这是一个示例:

dz> run app.package.info –a com.android.browser

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

之前截图中显示输出的快速解释如下:

  • 应用程序标签:应用程序显示的名称

  • 进程名称:此应用程序运行的进程名称

  • 版本:安装的应用程序版本

  • 数据目录:将用于存储与该应用程序特别关联的用户数据和应用程序的目录的完整路径

  • APK 路径:设备上实际 Android 应用程序包文件的路径

  • UID:与应用程序关联的用户 ID;它在 Android 系统上执行的所有操作都将使用与此用户 ID 关联的访问权限,除非它让其他应用程序和进程代表它执行操作

  • GID:与该应用程序用户 ID 关联的系统群组 ID;通常,这些 ID 基于授予应用程序的特殊权限数量与之关联

  • 共享库:此应用程序使用的共享库的完整路径

  • 共享用户 ID:此应用程序允许使用的共享用户 ID

  • 使用权限:授予此应用程序的权限列表

另一个例子,如果你有一个 Nexus 设备,可以按照以下方式针对 Google 服务框架运行:

dz> run app.package.info –a com.google.android.gsf

之前的命令应该会产生如下截图所示的输出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

你还可以使用app.package.info模块做另一件很酷的事情,那就是基于权限查找软件包。你可以通过执行以下命令来完成:

dz> run app.package.info –p [permission label]

一个例子如下:

dz> run app.package.info –p android.permission.INTERNET

这为什么这么酷?好吧,你可能想知道所有具有一组危险权限的应用程序。我的意思是,你知道你的应用程序中有多少个具有INTERNET权限或其他危险权限的吗?不知道吧?正是如此!

另请参阅

枚举活动

drozer 还提供了一个有用的模块,用于枚举目标 Android 设备上可用的活动组件信息。以下食谱演示了此模块的使用。

如何操作…

你可能有时候想要找出设备上安装并导出的活动。drozer 框架使这变得相当简单,以下是操作方法:

从你的 drozer 控制台执行以下命令:

dz> run app.activity.info

此命令将列出设备上导出的所有活动。

还有更多…

你可能想要获取有关设备上活动的更多信息;例如,列出所有具有特定名称或名称中包含特定字符串的应用程序,如"browser"或"facebook",这些应用程序具有什么权限,甚至搜索未导出的活动。以下是操作方法:

通过执行以下命令,根据名称搜索活动:

dz> run app.activity.info –-filter [activity name]

这将列出名称中带有[activity name]的所有活动。例如:

dz> run app.activity.info –-filter facebook

与所有 Unix 风格或 Linux 风格的命令一样,这个命令也有一个快捷方式:

dz> run app.activity.info –f facebook

上一个命令应该会产生如下截图所示的输出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

你还可以指定要检查活动的包。

按照以下方式在给定包中搜索活动:

dz> run app.activity.info –-package [package name]

你也可以使用此命令的快捷方式:

dz> run app.activity.info –a [package name]

这是一个例子:

dz> run app.activity.info –a com.android.phone

上一个命令应该会产生如下截图所示的输出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

另请参阅

枚举内容提供者

与枚举活动和包类似,drozer 也提供了一些模块来列出所有内容提供者及其一些信息。以下食谱将介绍如何使用app.provider.info模块进行操作。

如何操作…

让我们开始枚举内容提供者。

  1. 从你的 drozer 终端执行以下命令:

    dz> run app.provider.info
    
    
  2. 这将返回有关内容提供者的以下信息:

    • 权限 - 实现其 SQLite 前端的类名称

    • 读取权限

    • 写入权限

    • 授予 URI 权限

    • 路径

它是如何工作的…

让我们看看app.provider.info模块的代码。

注意

以下代码在github.com/mwrlabs/drozer/blob/766329cacde6dbf1ba05ca5dee36b882041f1b01/src/drozer/modules/app/provider.py

def execute(self, arguments):
  if arguments.package == None:
    for package in self.packageManager().getPackages      (common.PackageManager.GET_PROVIDERS |         common.PackageManager.GET_URI_PERMISSION_PATTERNS):
      self.__get_providers(arguments, package)
  else:
    package = self.packageManager().getPackageInfo(arguments.package, common.PackageManager.GET_PROVIDERS | common.PackageManager.GET_URI_PERMISSION_PATTERNS)

    self.__get_providers(arguments, package)

def get_completion_suggestions(self, action, text, **kwargs):
  if action.dest == "permission":
    return ["null"] + android.permissions

def __get_providers(self, arguments, package):
  providers = self.match_filter(package.providers, 'authority', arguments.filter)

  if arguments.permission != None:
    r_providers = self.match_filter(providers, 'readPermission',       arguments.permission)
    w_providers = self.match_filter(providers, 'writePermission',       arguments.permission)

代码中第一个值得注意的部分是脚本调用包管理器的地方。它看起来像这样:

self.packageManager().getPackages(common.PackageManager.GET_PROVIDERS | common.PackageManager.GET_URI_PERMISSION_PATTERNS)

脚本通过调用 Android 包管理器获取一个包列表,并抛出一些标志以确保获取到带有授权 URI 权限模式的提供者。接下来我们看到,一旦包管理器收集了关于内容提供者的详细信息,脚本就会调用一个名为 __get_provider() 的函数,该函数提取有关提供者读取和写入权限的信息(如果有的话)。通过 match_filters() 调用进行一些简单的字符串匹配,__get_provider() 函数基本上在定义内容提供者权限的部分查找某个字符串值。这个字符串值由 readPermission 标记,表示从内容提供者读取所需的权限,或者由 writePermission 标记,出人意料的是,它表示写入内容提供者所需的权限。在此之后,它会在将提供者对象打印到控制台之前重置该对象。

还有更多…

与 drozer 中的其他 .info 模块类似,你可以通过以下方式添加过滤器信息:

  • 基于包名称搜索:

    dz> run app.provider.info –a [package name]
    
    

    或者:

    dz> run app.provider.info –-package [package name]
    
    
  • 基于权限搜索:

    dz> run app.provider.info –p [Permission label]
    
    

    或者:

    dz> run app.provider.info –-permission [permission label]
    
    

另请参阅

枚举服务

你可能还想了解设备上安装了哪些服务。drozer 有一个名为 app.service.info 的模块,可以提取有关服务的有用信息。

如何操作…

从你的 drozer 控制台执行以下命令:

dz> run app.service.info –-package [package name]

不带参数运行此命令将列出目标设备上安装的所有服务。运行时它看起来会像以下截图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

你还可以使用以下过滤器来缩小搜索范围:

  • 基于权限搜索:

    dz> run app.service.info –p [permission label]
    dz> run app.service.info –-permission [permission label]
    
    
  • 基于服务名称搜索:

    dz> run app.service.info –f [Filter string]
    dz> run app.service.info. –filter [filter string]
    
    
  • 你还可以选择列出未导出的服务,例如以下:

    dz> run app.service.info –u
    dz> run app.service.info –-unexported
    
    
  • 最后,如果你想了解其他开关和选项的信息,可以随时运行 –help 选项,如下所示:

    dz> run app.service.info –-help
    
    

    之前的命令应该会产生如下截图所示的输出:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

它是如何工作的…

app.service.info 模块通过 API 调用包管理器,其工作方式与其他 .info.list 类型的 drozer 模块类似。以下是来自 drozer/master/src/drozer/modules/service.py 的包管理器调用:

def execute(self,arguments):
  if arguments.package == None:
    for package in self.packageManager().getPackageInfo      (common.PackageManager.GET_SERVICES |         common.PackageManager.GET_PERMISSIONS):
      self.__get_servcies(arguments, package)
  else:
    package = self.packageManager().getPackageInfo(arguments.package, common.PackageManager.GET_SERVICES | common.PackageManager.GET_PERMISSIONS)
    self.__get_services(arguments,package)

脚本会检查是否将特定包作为参数传递,这是 execute 方法中的第一段代码:

if arguments.package == None:

如果没有定义参数或包名,脚本会获取一个包列表,并通过调用self.__get_services()方法来遍历它们,这个方法通过字符串匹配从self.packageManager().getPackageInfo(arguments.package,common.PackageManager.GET_SERVICES | common.PackageManager.GET_PERMISSIONS)调用返回的数据来确定一些包属性;例如,在寻找具有特定权限的服务时,它会执行以下操作:

services = self.match_filter(services, "permission", arguments.permission)

这是为了提取具有所需权限的服务列表。

参见

枚举广播接收器

广播接收器通常包含有关应用程序攻击面的有用信息,并可能为攻击者提供执行任意代码到传播信息等多种机会;因此,在针对应用程序的安全评估中不能忽略它们。drozer 的开发者深知这一点,并提供了模块来帮助获取有关广播接收器的信息。

下面的指南详细介绍了app.broadcast.info模块的不同调用选项,以此演示其功能。

如何操作…

广播接收器的枚举是通过以下命令执行的:

dz> run app.broadcast.info

前一个命令的输出应类似于以下截图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个app.broadcast.info模块具有其他.info模块所有的酷功能,以及一些特定的广播接收器选项。

你可以指定一个特定的包,从中提取接收器的信息;以下命令是一个示例:

dz> run app.broadcast.info –a [package]

下面的命令是另一个示例:

dz> run app.broadcast.info –-package [package]

你也可以基于它们的名称搜索和列出广播接收器;例如:

dz> run app.broadcast.info –f [filter]

或者使用更长的形式:

dz> run app.broadcast.info –-filter [filter]

另一个选项是选择包含未导出的接收器:

dz> run app.broadcast.info –u
dz> run app.broadcast.info –-unexported

最后,你可以选择是否在请求的信息中包含意图过滤器;例如:

dz> run app.broadcast.info –i

或者:

dz> run app.broadcast.info –-show-intent-filters

参见

确定应用程序的攻击面

在您的应用程序安全评估过程中,您可能想要了解给定应用程序的攻击面是什么。drozer 有一个非常整洁的模块可以帮助您确定这一点。就这个模块而言,应用程序的攻击面仅是指导出组件的数量。

如何操作…

从您的 drozer 控制台执行以下命令:

dz> app.package.attacksurface [package name]

此命令将列出由包管理器 API 确定的给定包的所有导出活动。

例如,您可以尝试针对一个示例包按以下方式运行它:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

它的工作原理…

让我们看看 app.package.attacksurface 模块的代码。我认为这可能是最有趣的模块之一,通过阅读其代码应该能激发您如何以应用程序的形式编写自动化测试工具的想法。当您想要进行大规模的自动化应用程序扫描时,它绝对会派上用场!

来自 drozer-master/src/mrw/droidhg/modules/package.py 的代码如下:

from drozer import android
from drozer.modules import common, Module
class AttackSurface(Module,common.Filters, common.PackageManager):

def execute(self,arguments):
  If arguments.package != None:
    Package = self.packageManger().getPackageInfo(arguments.package, common.PackageManager.GET_ACTIVITIES | common.PackageManager.GET_RECEIVERS | common.PackageManager.GET_PROVIDERS | common.PackageManager.GET_SERVICES)
    application = package.applicationInfo
    activities = self.match_filter(package.activities, 'exported',True)
    receivers = self.match_filter(package.receivers, 'exported', True)
    providers = self.match_filter(package.proviers, 'exported', True)
    services = self.match_filter(package.services, 'exported', True)
    self.stdout.write("Attack Surface:\n")
    self.stdout.write(" %d activities exported\n" % len(activities))
    self.stdout.write(" %d broadcast receivers exported\n" % len(receivers))
    self.stdout.write(" %d content providers exported\n" % len(providers))
    self.stdout.write(" %d services exported\n" % len(services))
    if (application.flags & application.FLAG_DEBUGGABLE) != 0:
      self.stdout.write("is debuggable\n")
    if package.sharedUserId != None:
      self.stdout.write("Shared UID (%s)\n" % package.sharedUserId)
  else:
  self.stdout.write("Package Not Found\n")

这里的代码很多,但这个模块的好处在于它遵循与包管理器接口的相同风格。该模块从包管理器获取关于服务、活动、广播接收器和内容提供者的信息,并尝试确定它们是否根据包管理器导出。确定了哪些组件是导出的,它只是枚举它们,并在屏幕上打印导出组件的数量。该模块所做的就是尝试确定应用程序是否可调试以及是否使用共享用户 ID,这对于攻击面来说是非常有价值的信息。我将在下一章解释为什么。

另请参阅

启动活动

活动是促进用户交互的应用程序组件。在应用程序安全评估期间,了解哪些应用程序可以在没有权限的情况下启动可能很有用,以防它们中的任何一个提供了对敏感数据的访问或如果在不正确的上下文中启动导致应用程序崩溃。除了通过 drozer 控制台与活动互动的明显好处之外,它还是一个很好的响应式介绍,可以与应用程序组件互动,因为您实际上可以从终端看到您的 Android 设备对您的命令做出响应。所以,不再赘述,让我们开始一些活动吧!

如何操作…

你需要选择一个要启动的活动,但由于你无法本质上知道可启动活动在哪里或者它们叫什么,我认为我应该在教程中包含查找可启动活动的过程。

  1. 使用 app.activity.info 模块查找一些活动:

    dz> run app.activity.info –-package [package name]
    
    

    在下一步中,你需要选择一个包和一个活动。习惯于多次运行这个命令;如果你打算进行 Android 渗透测试,你会经常使用它。

  2. 找到你要找的活动后,你可以向它发送一些启动意图,并在你的 Android 设备屏幕上看到它弹出。以下是操作方法:

    dz> run app.activity.start –-action [intent action]-category [intent category]-component [package name] [component name]
    
    

    在这里,[intent action] 是目标活动设置的意图过滤器的动作属性,[intent category] 是目标活动设置的意图过滤器的类别属性,你可以从第一步的命令中获得。

这是一个你可以尝试的例子:

dz> run app.activity.start –-action android.intent.action.MAIN –-category android.intent.category.LAUNCHER –-component com.android.browser com.android.browser.BrowserActivity

它的工作原理…

让我们查看 drozer 的源代码,确切地了解它是如何启动某些活动的。

注意

以下代码可以在github.com/mwrlabs/drozer/blob/master/src/drozer/modules/app/activity.py(第 166-174 行)找到。

.... #some code has been omitted for brevity
def execute(self,arguments)
  intent = android.Intent.fromParser(arguments)

  if len(intent.flags) == 0:
    intent.flags.append('ACTIVITY_NEW_TASK')

  if intent.isValid():
    self.getContext().startActivity(intent.buildIn(self))
  else:
    self.stderr.write('invlaid intent: one of action or component must be set')
...#some code has been omitted for brevity

我们可以看到,drozer 通过参数解析器获取用户提供的参数后,将这些参数打包成一个意图;在检查意图是否有效后,它发送这个意图。这与来自 Android 应用的意图工作方式相同。

还有更多…

你可以使用 app.activity.forintent 模块查找要启动的活动。

这个便捷的模块允许你根据给定的意图动作和类别搜索活动;以下是操作方法:

dz> run app.activity.forintent –-action [intent action] –category [intent category]

这是一个例子:

dz> run app.activity.forintent –-action android.intent.action.VIEW –-category android.intent.category.DEFAULT

另请参阅

编写一个 drozer 模块——设备枚举模块

本教程通过演示构成 drozer 模块开发的实际步骤,解释了如何实际开发 drozer 模块。以下设备信息枚举器获取有关部分硬件和操作系统版本的信息。

如何操作…

让我们开始编写一个 drozer 设备枚举模块:

  1. 打开文本编辑器并输入以下代码:

    from drozer.modules import Module
    class Info(Module):
      name = "Get Device info"
      description = "A module that returns information about the device and hardware features"
      examples = "run ex.device.info"
      date = "10-11-13"
      author = "Keith Makan"
      license = "GNU GPL"
      path = ["ex","device"]
      def execute(self,arguments):
        build = self.new("android.os.Build")
        self.stdout.write("Getting device info...\n")
        self.stdout.write("[*] BOARD : %s\n" % (build.BOARD))
        self.stdout.write("[*] BOOTLOADER : %s\n" % (build.BOOTLOADER))
        self.stdout.write("[*] BRAND : %s\n" % (build.BRAND))
        self.stdout.write("[*] CPU_ABI : %s\n" % (build.CPU_ABI))
        self.stdout.write("[*] CPU_ABI2 : %s\n" % (build.CPU_ABI2))
        self.stdout.write("[*] DEVICE : %s\n" % (build.DEVICE))
        self.stdout.write("[*] DISPLAY : %s\n" % (build.DISPLAY))
        self.stdout.write("[*] FINGERPRINT : %s\n" % (build.FINGERPRINT))
        self.stdout.write("[*] HARDWARE : %s\n" % (build.HARDWARE))
        self.stdout.write("[*] MANUFACTURER : %s\n" % (build.MANUFACTURER))
        self.stdout.write("[*] MODEL : %s\n" % (build.MODEL))
        self.stdout.write("[*] TAGS : %s\n" % (build.TAGS))
    
  2. 将该文件保存为 ex.device.info

  3. 创建一个目录来保存你未来所有的 drozer 模块,并将 ex.device.info 文件保存在其中。

  4. 启动 drozer 控制台并执行以下命令:

    dz> module repository create [path-to-your-module-dir]/repo
    
    
  5. 然后执行以下命令:

    dz> module install [path-to-your-module-dir]/ex.device.info
    
    
  6. 如果没有语法错误或故障,drozer 应该已经安装了你的新模块。现在你可以使用以下命令执行它:

    dz> run ex.device.info
    
    

    之前命令的输出应该类似于以下截图中的输出:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

接下来的几个食谱都是关于编写一些有用的模块来扩展你的 drozer 框架;在每一个中,我将演示一些你会在本书后面发现有用的关键模块开发技能。

它是如何工作的…

为了开始这个解释,我想讨论一下你刚刚为你新的 drozer 模块编写的代码,以及它是如何设法提取关于你设备的信息的。

首先,我想谈谈 drozer 模块的结构。你编写的每个模块都将从以下这行开始:

import drozer.modules import Module
class Info(Module)

第一行本质上是包含了一些来自modules库的代码,并让 drozer 模块能够访问到它们操作所需的所有魔法方法和属性。第二行称为类声明的头部,并标记了 Python 中对象定义的开始。你可能注意到了头部中的(Module)部分;这就是Info类如何采用Module类的属性,从语义上讲,这类似于 Java 中的继承。

接下来的几行如下:

name = ""
description = ""

license = ""

这些只是 drozer 用来将一些元数据关联到模块,并使文档标准化、易于执行的一些变量——这里没有技术性的内容。继续:

def execute(self, arguments):

这段特定的代码称为函数头,并标记了 Python 函数定义的开始。这个函数的特殊之处在于,它是执行模块所有繁重工作的方法,类似于 Java 类中的Main方法。让我们谈谈execute方法期望传递的参数:

  • self:这是正在定义的类的实例。它被解析到类中的每个函数,以便它们可以访问类实例。

  • arguments:这是从控制台传给 drozer 模块的分析后的参数字典。

最后,我们有以下这段代码:

build = self.new("android.os.Build")

好吧,除了解引用self对象和使用一个名为new的魔法方法之外,我们看到一个字符串值android.os.Build作为参数传递。这个字符串是 Android Java API 中的一个 Java 类的名称,而new方法使用了一种称为 Java 反射的东西来实例化持有我们想要打印到屏幕上所有信息的Build类。

代码的其余部分看起来像下面这样:

self.stdout.write("[*] BOARD : %s\n" % (build.BOARD))

上面的代码只是简单地打印出设备信息。

另请参阅

编写一个应用程序证书枚举器

在这个教程中,我将向你展示如何编写一个证书枚举器,它所做的不过是提取应用程序证书作为十六进制摘要并在屏幕上输出。我之所以包含这部分内容,首先是因为它演示了如何与包管理器接口并获取本节其他模块无法获取的信息。其次,当你寻找使用相同公钥签名的所有应用程序时,它可能有助于你获取应用程序签名。这很有用,因为开发者和恶意软件作者通常会用同一把钥匙为他们的多数应用程序签名。它还将允许你识别可能共享资源并自主互相授权权限的应用程序;这一过程将在下一节详细讨论。

如何操作…

  1. 打开你喜欢的文本编辑器并输入以下代码:

    from drozer.modules import Module, common
    from drozer import android
    import M2Crypto
    import subprocess
    from OpenSSL import crypto
    class Info(Module,common.Filters,common.PackageManager):
      name = "Print the Signer certificate for an application"
      description = "this module allows you to print the signer x509 certificate for a given applicaiton"
      examples = "run ex.cert.info -p com.android.browser"
      author = "Keith Makan"
      date = "11-11-2013"
      license = "GNU GPL"
      path = ["ex","cert"]
      def add_arguments(self, parse):
        parse.add_argument("-p","--package",default=None,help="The Package Name")
      def execute(self,arguments):
        pm = self.packageManager()
        if arguments.package == None:
          for info in pm.getPackages(common.PackageManager.GET_SIGNATURES):
            self.stdout.write("[*] certificate info for {%s}\n" % (info.packageName))
            self.__print_certs(info)
        elif arguments.package != None:
          self.stdout.write("[*] certificate info for {%s}\n" % (arguments.package))
          info = pm.getPackageInfo(arguments.package,common.PackageManager.GET_SIGNATURES)
          self.__print_certs(info)
        else:
          self.stdout.write("[!] cannot process arguments : '%s'\n" % (repr(arguments)))
      def __print_certs(self,info):
        sigs = info.signatures[0].toCharsString()
        sigs = sigs + '\n'
        temp_cert = open("/tmp/cert.crt","w")
        end = 2
        #converting to DER file
        for start in range(0,len(sigs)-2,2):
          temp_cert.write(chr(int(sigs[start:end],16)))
          end +=2
        temp_cert.flush()
        temp_pem = open("/tmp/cert.pem","w")
        temp_pem.flush()
        temp_pem.close()
        certtext = subprocess.check_output(["openssl","x509","-inform","DER","-in","/tmp/cert.crt","-outform","PEM","-out","/tmp/cert.pem","-text"])
        temp_pem = open("/tmp/cert.pem","r")
        pem_cert_string = temp_pem.read()
        temp_pem.close()
        x509cert = crypto.load_certificate(crypto.FILETYPE_PEM,pem_cert_string)
        m2crypto_crt = M2Crypto.X509.load_cert_string(pem_cert_string,1)
        self.stdout.write("[*] Version : %s\n" % (x509cert.get_version()))
        self.stdout.write("[*] Issuer : %s\n" % (self._print_x509Name(x509cert.get_issuer())))
        self.stdout.write("[*] Subject : %s\n" % (self._print_x509Name(x509cert.get_subject())))
        self.stdout.write("[*] Algorithm : %s\n" % 
          (x509cert.get_signature_algorithm()))
        self.stdout.write("[*] NotBefore : %s\n" % (x509cert.get_notBefore()))
        self.stdout.write("[*] NotAfter : %s\n" % (x509cert.get_notAfter()))
        self.stdout.write("[*] Key Length : %s\n" % (x509cert.get_pubkey().bits()))
        self.stdout.write("[*] Public Key : \n%s\n" % (self._print_key(m2crypto_crt)))
        self.stdout.write("\n")
        #self.stdout.write("\n%s\n" % (certtext))
      def _print_x509Name(self,xname):
        return ''.join(["%s=%s " % (i[0],i[1]) for i in xname.get_components()])
      def _print_key(self,m2cert):
        return m2cert.get_pubkey().get_rsa().as_pem()
    
  2. 将其保存到你的模块仓库中;如果你还没有仓库,只需在你的机器上创建一个文件,用来保存你所有的模块。你可以通过从你的 drozer 控制台执行以下命令来安装模块:

    dz> module install [path to your module code]
    
    

    当这一切准备就绪,你可以使用以下命令运行该模块:

    run external.cert.info –p com.google.android.gsf
    
    

    你的屏幕上应该会显示类似以下截图的内容:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值