【问题标题】:recording `open` syscalls on mac在 Mac 上录制“打开”系统调用
【发布时间】:2022-02-08 04:32:26
【问题描述】:

我想知道在 bash 脚本中对 open(2) 进行了哪些调用。

我编写了以下拦截系统调用的程序:

#include <fcntl.h>
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>

#define DYLD_INTERPOSE(_replacment,_replacee) \
__attribute__((used)) static struct{ const void* replacment; const void* replacee; } _interpose_##_replacee \
__attribute__ ((section ("__DATA,__interpose"))) = { (const void*)(unsigned long)&_replacment, (const void*)(unsigned long)&_replacee };

static
int
my_open(const char *filename, int oflag, mode_t mode)
{
    printf("$jason$ open: %s\n", filename);
    return open(filename, oflag, mode);
}
DYLD_INTERPOSE(my_open, open)

然后我使用:

clang -dynamiclib libfile.c -o libfile.dylib
export DYLD_INSERT_LIBRARIES=libfile.dylib
touch /tmp/testingtesting

它不起作用。

我用我编译的程序试了一下,效果很好。我用 brew 编译的程序试了一下,效果很好。我阅读了touch.c 的源代码。它调用open(2)

然后我禁用了 SIP,它运行良好。因此,我得出结论认为是 SIP 导致了问题。不过我不想禁用 SIP。

我该怎么办?我正在考虑只允许 dtrace:csrutil enable --without dtrace。因为我认为 dtrace 可以跟踪系统调用,但我不确定这是否是一个安全的选择。

【问题讨论】:

    标签: c bash macos system-calls dtrace


    【解决方案1】:

    您所做的称为库注入,Apple 努力从他们的系统中删除此功能。

    由于他们的努力,启用 SIP 后,您只能对未经过强化(或经过几个特定例外强化)的应用程序执行 DYLD_INSERT 魔法,我想这些应用程序是您构建和 brew 发布的应用程序。 Apple 二进制文件(其中之一是触控)通常以其他方式强化或保护。

    这里没有太多选择:

    1. 禁用 SIP 并注入您想要的内容
    2. 部分禁用 SIP,您可能会实现一些目标(dtrace 可能会有所帮助)
    3. 编写一个内核扩展进行注入并以某种方式从 Apple 获取 kext 签名 - 它可以在启用 SIP 的情况下工作。

    所有这些选项都适用于基于 Intel 的 mac,对于 m1 可能更难。

    关于安全性:将禁用 SIP 的机器与外部数据源(互联网、USB 驱动器等)断开,进行研究,然后重新启用 SIP 并再次将 mac 连接到世界。

    【讨论】:

      【解决方案2】:

      最新版本的 macOS 基本上不再支持通用库注入。

      但是,您确实可以使用dtrace 来执行此操作,特别是dtruss 脚本。不幸的是,macOS 附带的这个脚本版本相当陈旧,所以我建议使用my updated version of dtruss¹,因为这可以让您跟踪所有子进程,如果您正在跟踪 shell 脚本,这非常重要。它还避免了必须使用 sudo 运行您尝试跟踪的命令,这可能会使其行为不同。

      这个命令……

      path/to/dtruss -d -e -f -t open touch /tmp/testingtesting

      ...应该可以在链接版本中正常工作。命令行解释:

      • -d-e 显示通话时间。 (可选)
      • -f 启用“follow”模式以跟踪生成的子进程 - 这对于 touch 命令来说并不是很有趣,但您可能需要它来跟踪 bash 脚本。
      • -t open 限制跟踪到 open 系统调用。 (将其关闭以跟踪 所有 系统调用。注意:这可能会产生大量输出。)

      使用dtruss 的库存版本,您可以回退到:

      • sudo dtruss -d -e -t open touch /tmp/testingtesting - 但请注意,touch 在这种情况下将以 root 用户身份运行,并且不支持跟踪子进程。
      • sudo dtruss -d -e -t open -n touch,然后在另一个终端中运行touch /tmp/testingtesting。这避免了以 root 身份运行 touch,但它会跟踪名为 touch所有进程。

      使用dtruss 的原始版本时,跟踪的系统调用的输出可能也不太清楚,因为更新的版本在格式化系统调用参数方面做得更好,尤其是字符串。 (对于open(),特别是the updated version prints the 'mode' argument for created file permisions as octal,这通常是你想要的。)

      是的,您需要禁用 SIP 的 dtrace 部分才能使 dtrace 的所有功能正常工作,这可能会带来一个小的安全风险,但我还没有听说任何恶意软件试图利用它。

      脚注:

      ¹我并不是想自我推销我的代码。我根本不知道更好的解决方案 - 我遇到了与提问者非常相似的问题,并且内置工具不够好,所以我修复了它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-19
        • 2011-05-12
        • 2018-06-06
        • 1970-01-01
        相关资源
        最近更新 更多