返回介绍

10.1 命令分析和使用

发布于 2024-10-10 22:32:17 字数 6508 浏览 0 评论 0 收藏 0

以前想看一个应用的沙盒数据(/data/data/xxx/目录内容),一般都是选择 root 之后去查看对应的数据库、XML 等数据。但是如果没有 root 了也想看这些数据,怎么办呢?Android 中提供了一个命令,那就是 run-as,不过这个命令有一个缺陷,就是只有 debug 模式应用才能被查看。

命令的用法很简单:run-as[packagename]。其中 packagename 就是想查看的应用的包名,运行命令之后,就直接进入指定应用的目录:/data/data/packagename/。

现在稍微了解了 Android 中有这个命令可以查看 debug 应用的沙盒数据,但直接运行会遇到问题,运行结果如下所示:

为什么这个命令会报错呢?遇到这个情况有两种方式解决:一种是网上查资料,一种是自己去看源代码。为了问题解决的高效性,就去看源码吧。Android 中的命令一般都在/system/bin 和/system/xbin 目录下,这些命令的源码都是放在 Android 源码目录/system/core/下,如图 10-1 所示。

图 10-1 run-as 命令源码的位置

run-as 的源码如图 10-2 所示。

图 10-2 run-as 源码分析(一)

看到这里,原来 run-as 命令运行是有很多限制的。下面分别介绍。

第一个限制:运行的 uid 限制

运行命令的用户 id 只能是 shell 和 root 用户。下面可以验证一下,使用 system 的 uid 运行命令:

这里用于测试的设备已经 root 了。看到使用 su 可以随意设定 uid,这里将 uid 变成了 system,再运行 run-as 发现报错了,符合预期吧?

第二个限制:应用的安装必须合法

这里再仔细看看 get_package_info 这个函数的源码,它位于 run-as.c 同目录下的 package.c,如图 10-3 所示。

这里通过 map_file 函数来获取 PACKAGES_LIST_FILE 文件的 buffer 内容,再来看一下 PACKAGES_LIST_FILE 的定义:

图 10-3 run-as 源码分析(二)

导出这个文件,查看内容:

这个文件记录所有安装应用的信息:包名,用户 id(uid),是否为 debug 模式,对应的数据目录,是否是 release 版,组 id(gid)。这里发现 demo.systemapi 应用是 debug 模式的。一般正式 App 都是非 debug 模式。

通过读取这些信息就可以构造出一个 PackageInfo 了,如图 10-4 所示。

图 10-4 run-as 源码分析(三)

注意,这里看到了 packages.list 文件是存储安装包的简略信息,和它同一目录下还有一个重要文件 packages.xml,可以导出来看看,如下所示:

这里记录了安装应用的详细信息,还有一个重要信息就是应用的安装来源,有些 App 可以做到这点就是通过这个信息来获取的,还有签名信息、权限等。

当然可以使用 Android 中的 dumpsys packageinfo 命令来查看指定应用的详细信息,如下所示:

第三个限制:应用的 uid 必须合法

对于查看的应用的 uid 也是有相应限制的,如下所示:

这里 AID_APP 的定义在 Android 源码目录\system\core\include\private\android_filesystem_config.h 下。

定义了一些 uid 信息,例如:

·AID_ROOT 对应的是 root 用户,uid=0。

·AID_SYSTEM 对应的是 system 用户,uid=1000。

·AID_SHELL 对应的是 shell 用户,uid=2000。

可以看到,root 用户的权限>system 用户的权限>shell 用户的权限>第三方应用的权限。

不过这里所说的权限只是针对一些情况,不是全部。Android 中有些 API 会做 uid 限制,即使用反射机制也是访问失败的,比如,一个 API 限制只能 uid=1000 的用户即 system 用户才能调用,那么这时你是 root 用户也是没办法的,不过可以使用 su 进行降权。

这三个用户的 id 最好记住,算是常识,如下代码有详细定义:

再往下看,第三方应用 uid 的定义如下所示:

这里的 AID_APP 是 10000,安装的应用的 uid 都是从 10000 开始的,所以 uid 都是大于 10000 的,代码中做了一层 uid 的合法性判断限制。

注意:一般查看应用的 uid 时,得到最后的整数+10000 就是应用的 uid,比如 demo.systemapi 的 uid 就是:10000+100=10100。

如下代码可以获取到应用的 uid:

这可以验证,查看上面提到的 packages.list 文件中的信息,如下所示:

第四个限制:应用是否为 debug 模式

之前说过,run-as 有一个最大的限制就是查看应用的数据时,应用必须是 debug 模式的,所以在开发程序的时候千万要保证一点,就是 debug 包不能外泄,不然数据就等于外泄了。

言归正传,源码看得差不多了,看一下问题,在运行 run-as 的时候遇到的问题如下所示:

问题就出在如下代码上:

再看 get_package_info 函数:

再看 map_file 函数:

终于找到原因了,原来是/data/system/packages.list 文件的读取权限是 AID_SYSTEM,查看一下如下代码:

问题找到了,尝试使用 su 升级权限再查看一下,如下所示:

可惜的是,这样明显是不行的,原因很简单,run-as 有限制,本身这个命令只能是 root 和 shell 用户才可以访问。这里也可以看到,shell 用户也不比 system 用户权限低,所以要视情况而定来看 root、system、shell 这三个用户的权限范围。

那么再使用 root 用户去尝试一下,如下所示:

这是可以的,因为 run-as 的权限验证通过了。

从上面的几个限制可以看到,首先 root 的 uid 限制可以放行,然后是 debug 模式可以放行,packages.list 文件的访问权限是 system,但是这对于 root 用户来说没有限制,因为在文件的读取权限上 root 可以操作任何文件,demo.systemapi 的 uid 可以放行。

注意:这里运行完 run-as 命令之后,进入/data/data/demo.systemapi 目录下,看到变成了 sh 命令,#变成$了,这其实是 run-as 在启动一个 shell 程序,可以查看 run-as 的源码:

到这里就分析完了为什么运行 run-as 命令失败,失败的原因也找到了,解决的办法也有了,但是还是需要 root,这貌似和开始说的有点出入,因为本身 run-as 命令就是可以在非 root 设备上查看 debug 模式下应用的沙盒数据,那现在 root 了,还有什么意义呢?其实不是的,run-as 命令很特殊。找到一个没有 root 的设备,然后运行 run-as 命令,结果如下所示:

也是可以运行成功的,而且这个设备没有 root。但是在上面已经 root 的设备上运行 run-as 却报错,为什么呢?下面就开始本章的主要内容,即为何没有 root,run-as 命令还能运行成功,进入指定的应用目录下。

是这样的:开始的时候为了讲解 run-as 源码和一些前提知识,做了一件事,就是修改了 run-as 命令的权限,如下所示:

查看 run-as 命令的本来权限是:

然后修改了它的权限 chmod 0755 run-as,变成

这个操作是为了开始本章内容。

下面把 run-as 权限改回原来的值,然后再运行 run-as,如下所示:

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文