Android 内存执行ELF研究
2022-11-22
| 2022-12-3
0  |  阅读时长 0 分钟
type
status
date
slug
summary
tags
category
icon
password
Property
Dec 3, 2022 02:50 AM

初遇

在Linux系统中,我们可以通过 memfd_create 和 execve 实现内存运行ELF,但是在 Android 中,却遇到了这样的问题
通过 这篇文章 了解到可以通过 LD_DEBUG 环境变量开启 linker 日志,执行
`LD_DEBUG=1 /data/local/tmp/memexec`
并通过 logcat 抓到了如下日志
看起来是命名空间的问题,我们的 payload 的命名空间为 default,但是为什么会这样呢,明明 memexec 是 unrestricted。

相知

通过 Google 搜索 android linker namespace 看到官方文档 链接器命名空间 ,在 /linkerconfig/ld.config.txt 文件中配置了相关信息
首先我们要知道这个文件可不可以写,查看 mount 信息发现该文件所在的不是只读文件系统,所以可以直接修改
以下使用 /data/adb/magisk/busybox vi /linkerconfig/ld.config.txt 编辑文件

原来命名空间是根据路径来的,于是编辑该文件,在最前面手动加上一行
然后重新执行,问题依旧。

难道是没有路径分割符的问题,于是在代码中给文件名加上一个 /
编译并重新执行,还是一样的报错。

尝试重新编辑,把它设置成根目录
这次报错多了一行
看样子是没办法通过单纯的改配置文件完成了,于是前往阅读linker的源码

相识

由于aospxref服务最近不太稳定,我在看的时候刚好打不开,使用了android官方的源码在线浏览工具,然而这个玩意并不好用
众所周知,linker 的源码在 bionic/linker 目录下。
通过字符串 “Using config section” 定位到 linker_config.cpp 的 parse_config_file 函数,在阅读代码后,我们上面的尝试为什么会失败,就已经有了答案。

为什么设置 /memfd: 目录不行

因为它不是一个真实存在的目录,在代码中通过 access 函数判断改路径不存在,所以不行

为什么设置根目录不行

因为代码中删除了末尾所有的/ 符号,传入根目录之后字符串变成了空字符串,于是抛出了那个Warning

相杀

修改无非两个思路:
  1. 静态替换 linker
  1. 动态 hook
虽然有 magisk,替换 system 分区下文件变得方便了起来,但是替换 linker 依然是一件麻烦事,动态 Hook 对于解决这个问题来说,我觉得更加方便。由于目标代码位置的特殊性,现有 inline hook, plt hook 轮子都不能取得比 linker 更早的执行时机。
也许是我孤陋寡闻,如果有请务必告诉我
最终我选择的方案是先 fork 生成一个子进程,对子进程进行 ptrace,修改逻辑后再 detach 掉。
对于逻辑的修改,主要有两步:
  1. /linkerconfig/ld.config.txt 添加 "dir.unrestricted = /memfd:/\n”
  1. 让 access 这个目录返回 0

第一步

直接编辑该文件添加上述行即可

第二步

  • Android
  • ARM64 内核研究 (一)CMake去除__FILE__宏
    • Giscus
    目录