GKLBB

当你经历了暴风雨,你也就成为了暴风雨

导航

应用安全 --- apk加固 之 全内存取证

核心原理

许多安卓应用,尤其是那些经过“加固”保护的,会动态地加载或解密关键的 DEX 文件。这些 DEX 文件在应用运行时必然存在于进程的内存空间中。通过转储整个进程的内存镜像,我们可以像“大海捞针”一样,从中扫描、提取并重组出完整的 DEX 文件。gcore 和 dd 是两种不同的内存转储工具。


方法一:使用 gcore 转储 (需要 Root)

gcore 是 NDK 调试工具链的一部分,它可以直接附加到进程并生成一个 core dump 文件(ELF 格式),其中包含了进程的完整内存布局。

操作步骤:

  1. 准备工作 (PC端)

    • 下载并配置好 Android NDK。

    • 从 NDK 的 prebuilt/[架构]/bin 目录中找到 gcore 工具,或者使用 ndk-build 编译一个。

    • 确保你的安卓设备已 Root(如 Magisk)。

    • 将 gcore 推送到设备的 /data/local/tmp 目录,并赋予可执行权限。

    bash
     
    adb push /path/to/your/gcore /data/local/tmp/
    adb shell chmod +x /data/local/tmp/gcore
  2. 获取目标进程的 PID

    • 在设备上运行你想要分析的目标应用。

    • 通过 adb shell 进入设备 shell,然后使用 ps 或 pidof 命令找到应用的进程 ID (PID)。

    bash
     
    adb shell
    su
    pidof com.example.targetapp
    # 或者
    ps -A | grep "com.example.targetapp"
  3. 使用 gcore 转储内存

    • 假设目标 PID 是 1234,运行 gcore 命令。这可能会花费几秒钟到几分钟,取决于应用的内存占用大小。

    bash
     
    /data/local/tmp/gcore -o /sdcard/dump 1234
    • 执行成功后,你会在 /sdcard/ 目录下找到名为 dump.<pid>(如 dump.1234)的文件。

  4. 将 Core Dump 文件拉取到电脑进行分析

    bash
     
    adb pull /sdcard/dump.1234 .
  5. 从 Core Dump 中提取 Dex (Carving)

    • 现在你有了一个 ELF 格式的内存镜像。你可以使用多种工具从其中扫描 Dex 文件:

      • DexExtractor (需编译): 专门用于此目的的工具。

      • LIEF (Python库): 一个强大的二进制文件解析和修改库,可以解析 ELF 并从其段和节中扫描 Dex 文件。

      • 自定义脚本: 使用 hexdumpxxdgrep 或编写 Python 脚本搜索 Dex 文件魔数 64 65 78 0a 30 33 35 00 (dex.035)。

    • 使用 LIEF 的示例思路:

      python
       
      import lief
      dump = lief.parse("dump.1234")
      for segment in dump.segments:
          content = segment.content # 这是一个字节数组
          # 在 content 中搜索 dex 魔数,并将找到的区域提取到文件

方法二:使用 dd 转储 (需要 Root)

dd 是 Linux 系统的“瑞士军刀”,可以直接读取设备文件。在 Linux/Android 中,每个进程的内存都映射在 /proc/[pid]/mem 这个虚拟文件中。我们可以用 dd 来读取它。

操作步骤:

  1. 获取目标进程的 PID (同方法一步骤 2)

  2. 确定内存映射范围

    • 为了更高效地转储,我们通常只转储应用堆等可能包含 Dex 的区域,而不是整个 4GB 的虚拟地址空间。查看 /proc/[pid]/maps 文件来了解内存布局。

    bash
     
    adb shell
    su
    cat /proc/1234/maps > /sdcard/1234.maps
    • 拉取 maps 文件到电脑分析:

    bash
     
    adb pull /sdcard/1234.maps .
    • 分析 maps 文件,寻找具有可读可执行 (r-xp) 权限的大内存块,这很可能是加载 Dex 或代码的地方。也关注 [anon:libc_malloc] 这样的堆区域。

  3. 使用 dd 转储特定内存区域

    • 假设我们从 maps 文件中发现一个区域:73a00000-73a8000 r-xp ...

    • 计算大小:0x73a80000 - 0x73a00000 = 0x80000 (524,288 bytes)

    • 使用 dd 转储这个区域:

    bash
     
    adb shell
    su
    dd if=/proc/1234/mem of=/sdcard/mem_dump_73a00000.bin bs=1 skip=$((0x73a00000)) count=524288
    • 注意:直接 dump 整个 /proc/pid/mem 非常困难,因为地址空间中存在大量未映射的“空洞”,dd 会遇到 I/O 错误而停止。因此分区域转储是更可行的方案。

  4. 从转储的 bin 文件中提取 Dex

    • 现在你得到的是原始的内存块。你可以直接在这些 .bin 文件上使用 carving 工具。

    • 使用 DexExtractor (假设你已编译好):

      bash
       
      ./DexExtractor mem_dump_73a00000.bin
    • 它会扫描文件,寻找 Dex 头,并尝试修复 checksum 和 signature,然后输出可被 d2j-dex2jar 或 jadx 反编译的 Dex 文件。


方法三:使用集成化工具 (推荐)

手动操作上述步骤非常繁琐。社区有一些强大的集成工具可以自动化整个过程:

  1. Fridump (基于 Frida)

    • 这是一个用 Python 编写的工具,利用 Frida 的 API 来转储进程内存。

    • 优点: 不需要 gcore 或 dd,只需设备上运行 Frida-server 即可。可以转储整个地址空间并自动绕过一些空洞问题。

    • 使用方法:

      bash
       
      # 在电脑上运行
      fridump -U -s com.example.targetapp -o output_dir/
    • 它会在 output_dir 生成很多内存块文件和一个 maps 文件,然后你可以用 carving 工具分析 output_dir

  2. DexDump (基于 Frida)

    • 同样是基于 Frida 的著名工具,它更智能:它不仅转储内存,还会主动遍历内存中的类加载器,寻找 DexFile 对象,并直接从内存中导出完整的 Dex 文件,成功率非常高。

    • 使用方法:

      bash
       
      frida -U -l dexdump.js -f com.example.targetapp --no-pause
    • 执行后,它通常会将导出的 Dex 文件保存到设备的 /sdcard 目录。

总结与注意事项

特性gcoreddFridump/DexDump
易用性 中等 复杂 简单
可靠性 高 (生成标准ELF) 高 (原始数据)
完整性 完整进程镜像 需手动分块转储 完整或智能导出
需求 Root, NDK工具 Root 只需Frida (通常需Root)
输出 ELF core dump 原始内存块 内存块或直接得到Dex

重要提示:

  • Root 权限:几乎所有方法都需要 Root 权限。在没有 Root 的设备上,几乎无法完成此操作。

  • 对抗加固:高强度的加固方案会混淆 Dex 结构、阻止调试器附加(反制 gcore)、或抹去 Dex 头信息,这会增加 Carving 的难度。可能需要更高级的逆向技术来绕过。

  • 合法性:请在获得授权的情况下对应用进行内存取证,切勿用于非法用途。

posted on 2025-09-03 07:30  GKLBB  阅读(51)  评论(0)    收藏  举报