Android 内核历险记:深入了解编译、定制和应用程序分析

admin 2025年4月21日00:18:03评论1 views字数 4919阅读16分23秒阅读模式
Android 内核历险记:深入了解编译、定制和应用程序分析

本文是系列文章的第一篇,旨在分享我的 Android 内核探索经历、个人笔记和见解。我将主要关注如何修改内核,以便更深入地分析系统上运行的应用程序。需要注意的是,距离我上次接触 Android 内核——上次是在我那台老旧的三星 Galaxy 手机上编译并运行模块——已经过去很久了。不出所料,从那以后,很多事情发生了变化,在撰写后续文章的过程中,这将是一个重新发现和学习的过程。如果我犯了任何错误,或者您有任何建议,请随时联系我们。事不宜迟,让我们一起踏上这段旅程吧!

鉴于 Android 应用的 RASP(运行时应用程序自我保护)解决方案日益复杂,将精力集中在系统更深层(例如 Android 内核)上,已成为一种更有效的安全分析战略方法。专注于内核,无需绕过在应用层实施的保护措施,因为 RASP 解决方案专门设计用于保护更高层级,但并不涵盖内核。此外,了解 Android 内核的内部工作原理可以显著提升漏洞研究人员的工作效率,为 Android 操作系统中的漏洞提供宝贵的见解。
根据 Android 的文档 ,Android 内核由 Linux 内核和 Android 特定的补丁组成,形成了所谓的 Android 通用内核 (ACK) 。从内核版本 5.4 开始,ACK 被称为 GKI(通用内核映像) 内核。GKI 是 Google 认证的启动映像,其中包含从 ACK 源代码树构建的内核,旨在写入 Android 设备的启动分区。GKI 是 Google 项目的一部分,旨在通过将 Google 维护的内核的通用核心功能与构建供应商内核模块的特定于供应商的内核构建配置分开来解决内核碎片化问题。下图说明了 Android 的架构,显示所有内容都在 Linux 内核之上运行。

Android 内核历险记:深入了解编译、定制和应用程序分析

在 Android 文档https://source.android.com/docs/core/architecture/kernel/android-common,您还可以找到每个 Android 版本支持的内核列表,分为启动内核和功能内核 。启动内核是特定 Android 版本设备发布的有效内核,而功能内核则确保特定版本功能的实现,防止这些功能被反向移植到早期的内核版本。

Android 内核历险记:深入了解编译、定制和应用程序分析

我们测试的内核版本是 android13–5.15 。Android 内核分支的组织方式反映了 Android 版本和对应的内核版本,格式为 ANDROID_RELEASE-KERNEL_VERSION ,其中 ANDROID_RELEASE 代表 Android 版本, KERNEL_VERSION 代表内核版本。例如,android13–5.15 内核对应的是 Android 13 的内核版本 5.15。我们使用以下命令下载 Android 内核。

mkdir android-kernel && cd android-kernelrepo init -u https://android.googlesource.com/kernel/manifest -b common-android13-5.15repo sync -c -j4
在 android-kernel 目录中,我们可以看到一个名为 WORKSPACE 的文件。这表明我们正在处理一个 Bazel 项目。Bazel 是由 Google 开发的一款免费开源软件工具,旨在自动化软件构建和测试流程。包含 WORKSPACE 文件的目录被视为工作区的根目录,工作区是一个目录树,其中包含我们尝试构建的软件的源代码文件。Bazel 的安装说明可在此链接中找到。
在开始编译内核之前,需要强调的是,我们将使用 Cuttlefish 来测试内核。Goldfish(Android Studio 中使用的模拟器)和 Cuttlefish 的主要区别在于它们的用途以及它们模拟 Android 环境的方式。Goldfish 针对应用程序测试进行了优化,但并不适合测试操作系统,因为它无法准确复制真实硬件,并且存在局限性,尤其是在启动过程中。另一方面,Cuttlefish 是一个虚拟平台,旨在更忠实地模拟真实硬件,使其成为测试 Android 操作系统和内核的理想选择,因为它可以更准确、更典型地模拟物理设备的行为。您可以通过此链接找到 Cuttlefish 的安装说明。
Android 内核构建文件使用名为 Kleaf 的框架,该框架与 Bazel 一起负责构建 Android 内核及其他相关组件,例如启动映像、内核模块等。虽然我并非 Kleaf 或 Bazel 方面的专家,但本文将重点讲解一些关键代码片段,帮助您了解如何构建和修改 Android 内核。
还记得我提到过,GKI 将内核拆分成两个部分:一个由 Google 维护的内核映像,以及一个由供应商实现的、针对 SoC 和主板的模块。Google 维护的内核映像文件存储在公共目录中,而 SoC 和主板专用模块的文件存储在公共模块目录中。这两个内核将分别进行编译,我们接下来会看到。
从 common/BUILD.bazel 文件开始分析后,我们发现了 Define_common_kernels 宏-https://android.googlesource.com/kernel/build/+/146474a1d1666759345578580470c1ab4553c0ca/kleaf/common_kernels.bzl,该宏负责定义 Android 内核的通用构建目标。对于 x86_64 内核(我们将使用该架构构建内核),使用的配置文件是 build.config.gki.x86_64 。
load("//build/kernel/kleaf:common_kernels.bzl""define_common_kernels""define_db845c")
配置文件 build.config.gki.x86_64 使用了三个额外的配置文件: build.config.common 、 build.config.x86_64 和 build.config.gki 。我无法详细介绍所有这些文件,但有一点需要注意:在 build.config.gki 文件中,您将遇到 check_defconfig 命令的执行。如果您打算修改默认内核配置(我们稍后会做),请务必注释掉此行。否则,在配置文件中检测到更改后,内核构建将失败。
###POST_DEFCONFIG_CMDS="check_defconfig"
分析 common-modules/virtual-device/Build.bazel 文件后,我们发现了几个内核构建目标。由于我们将构建支持虚拟 x86_64 设备的内核,因此我们将重点关注以下几行:
kernel_build(    name = "virtual_device_x86_64",    srcs = [":virtual_device_x86_64_common_sources"],    outs = [],    base_kernel = "//common:kernel_x86_64",    build_config = "build.config.virtual_device.x86_64",    module_outs = _virt_common_modules + [# keep sorted"test_meminit.ko","test_stackinit.ko",    ],)
从脚本的这一部分可以看出,内核配置将位于文件 build.config.virtual_device.x86_64 中。build.config.virtual_device.x86_64 文件的内容表明,内核构建中使用的配置之一存储在 common/arch/x86/configs/gki_defconfig 文件中。利用此信息,我们可以修改其内容以在内核中添加其他功能。为了测试这一点,我们将添加对 ftrace 的支持,该功能在默认内核配置中未启用。
PRE_DEFCONFIG_CMDS="KCONFIG_CONFIG=${ROOT_DIR}/${KERNEL_DIR}/arch/x86/configs/${DEFCONFIG}${ROOT_DIR}/${KERNEL_DIR}/scripts/kconfig/merge_config.sh -m -r ${ROOT_DIR}/${KERNEL_DIR}/arch/x86/configs/gki_defconfig ${ROOT_DIR}/common-modules/virtual-device/virtual_device.fragment"
ftrace 是一个直接集成到 Linux 内核的跟踪和分析框架。它允许通过静态探针(在内核编译期间添加)和动态探针(在运行时注入)来观察和记录内核的函数执行流程。使用这些探针,ftrace 可以捕获与进程调度、中断、系统调用、函数延迟、I/O 设备交互,甚至内核中执行的特定函数相关的事件。要在内核中启用 ftrace,必须在内核配置文件 gki_defconfig 中添加以下几行。
CONFIG_FUNCTION_TRACER=yCONFIG_FUNCTION_GRAPH_TRACER=yCONFIG_STACK_TRACER=yCONFIG_DYNAMIC_FTRACE=y
接下来,在 android-kernel 目录中,我们将执行以下命令来编译两个内核以及启动 Cuttlefish 所需的模块。
tools/bazel build //common:kernel_x86_64_disttools/bazel run //common-modules/virtual-device:virtual_device_x86_64_dist
编译完成后,我们可以验证 bzImage 和 initramfs.img 等文件是否已复制到 out/android13-5.15/dist 目录。我们将使用这些文件在 Cuttlefish 上测试内核。

Android 内核历险记:深入了解编译、定制和应用程序分析

Cuttlefish 配置正确后,我们可以使用以下命令测试新编译的内核。相关参数可以根据需要进行调整。

HOME=${PWD} ./bin/launch_cvd -daemon -memory_mb 27000 -data_policy always_create -blank_data_image_mb 30000 -cpus 1 --kernel_path=/home/thiago/android-kernel/out/android13-5.15/dist/bzImage -initramfs_path=/home/thiago/android-kernel/out/android13-5.15/dist/initramfs.img
下图显示了 Cuttlefish 中运行我们内核的虚拟设备,其中 ftrace 正常工作。

Android 内核历险记:深入了解编译、定制和应用程序分析

结论

总而言之,本文概述了编译和修改 Android 内核,以及如何在 Cuttlefish 中执行测试以验证其功能的关键步骤。这为在虚拟化环境中定制 Android 内核奠定了基础。在接下来的文章中,我们将探讨高级内核调试技术,并演示如何定制内核以收集有关系统上运行的应用程序的详细信息。

参考

https://2net.co.uk/blog/cuttlefish-android12.html?source=post_page-----d20af6f2080a---------------------------------------

https://source.android.com/docs/setup/build/building-kernels?source=post_page-----d20af6f2080a---------------------------------------

https://source.android.com/docs/core/tests/debug/ftrace?source=post_page-----d20af6f2080a---------------------------------------

原文始发于微信公众号(Ots安全):Android 内核历险记:深入了解编译、定制和应用程序分析

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年4月21日00:18:03
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Android 内核历险记:深入了解编译、定制和应用程序分析https://cn-sec.com/archives/3978678.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息