在 mac 上记录 `open` 系统调用
recording `open` syscalls on mac
我想知道在 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 可以跟踪系统调用,但我不确定这是否是一个安全的选择。
您所做的称为库注入,Apple 正在努力从他们的系统中删除此功能。
由于他们的努力,在启用 SIP 的情况下,您可以只对未加固(或加固但有几个特定例外)的应用程序执行 DYLD_INSERT 魔法,我想这些应用程序是您建造和酿造船只。
Apple 二进制文件,其中之一是 touch,通常以其他方式加固或保护。
这里没有太多选择:
- 禁用 SIP 并注入你想要的东西
- 部分禁用 SIP,您可能会实现一些目标(dtrace 可能会有所帮助)
- 编写一个内核扩展进行注入,并以某种方式从 Apple 获得 kext 签名——它可以在启用 SIP 的情况下工作。
所有这些选项都是针对 Intel-based macs,对于 m1 可能更难。
关于安全性:关闭 machine 并从外部数据源(Internet,USB-drives 等)禁用 SIP,进行研究,然后重新启用 SIP 并连接 mac 再次走向世界。
最近版本的 macOS 基本上不再支持通用库注入。
但是您确实可以像您怀疑的那样使用 dtrace
执行此操作,特别是 dtruss
脚本。不幸的是,macOS 附带的这个脚本版本相当陈旧,所以我建议使用 my updated version of dtruss
¹,因为这可以让你追踪所有 sub-processes,如果你追踪 shell 脚本。它还避免了必须 运行 您尝试使用 sudo
跟踪的命令,这可能会使它的行为有所不同。
这个命令…
path/to/dtruss -d -e -f -t open touch /tmp/testingtesting
…链接版本应该可以正常工作。命令行解释:
-d
和 -e
显示调用时间。 (可选)
-f
启用“跟随”模式以跟踪生成的 sub-processes - 这对于 touch
命令来说并不是很有趣,但您可能需要它来跟踪一个bash 脚本。
-t open
限制对 open
系统调用的跟踪。 (将其关闭以跟踪 all 系统调用。注意:这可能会产生大量输出。)
使用原版 dtruss
,您可以退回到:
sudo dtruss -d -e -t open touch /tmp/testingtesting
- 但请注意,在这种情况下,touch
将作为 root 用户 运行,并且不支持跟踪 sub-processes。
sudo dtruss -d -e -t open -n touch
,然后在另一个终端中 运行 touch /tmp/testingtesting
。这避免了 运行ning touch
作为 root,但它会跟踪 all 个名为 touch
. 的进程
当使用 dtruss
的原始版本时,跟踪系统调用的输出也可能不太清楚,因为更新版本在格式化系统调用参数(尤其是字符串)方面做得更好。 (对于 open()
具体而言,the updated version prints the 'mode' argument for created file permisions as octal,这通常是您想要的。)
是的,您需要禁用 SIP 的 dtrace 部分才能使 dtrace 的所有功能正常工作,这可能会带来一个小的安全风险,但我还没有听说过任何试图利用的恶意软件这个。
脚注:
¹ 我不是要 self-promote 我的代码。我根本不知道更好的解决方案 - 我遇到了与提问者非常相似的问题,并且 built-in 工具不够好,所以我修复了它。
我想知道在 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 可以跟踪系统调用,但我不确定这是否是一个安全的选择。
您所做的称为库注入,Apple 正在努力从他们的系统中删除此功能。
由于他们的努力,在启用 SIP 的情况下,您可以只对未加固(或加固但有几个特定例外)的应用程序执行 DYLD_INSERT 魔法,我想这些应用程序是您建造和酿造船只。 Apple 二进制文件,其中之一是 touch,通常以其他方式加固或保护。
这里没有太多选择:
- 禁用 SIP 并注入你想要的东西
- 部分禁用 SIP,您可能会实现一些目标(dtrace 可能会有所帮助)
- 编写一个内核扩展进行注入,并以某种方式从 Apple 获得 kext 签名——它可以在启用 SIP 的情况下工作。
所有这些选项都是针对 Intel-based macs,对于 m1 可能更难。
关于安全性:关闭 machine 并从外部数据源(Internet,USB-drives 等)禁用 SIP,进行研究,然后重新启用 SIP 并连接 mac 再次走向世界。
最近版本的 macOS 基本上不再支持通用库注入。
但是您确实可以像您怀疑的那样使用 dtrace
执行此操作,特别是 dtruss
脚本。不幸的是,macOS 附带的这个脚本版本相当陈旧,所以我建议使用 my updated version of dtruss
¹,因为这可以让你追踪所有 sub-processes,如果你追踪 shell 脚本。它还避免了必须 运行 您尝试使用 sudo
跟踪的命令,这可能会使它的行为有所不同。
这个命令…
path/to/dtruss -d -e -f -t open touch /tmp/testingtesting
…链接版本应该可以正常工作。命令行解释:
-d
和-e
显示调用时间。 (可选)-f
启用“跟随”模式以跟踪生成的 sub-processes - 这对于touch
命令来说并不是很有趣,但您可能需要它来跟踪一个bash 脚本。-t open
限制对open
系统调用的跟踪。 (将其关闭以跟踪 all 系统调用。注意:这可能会产生大量输出。)
使用原版 dtruss
,您可以退回到:
sudo dtruss -d -e -t open touch /tmp/testingtesting
- 但请注意,在这种情况下,touch
将作为 root 用户 运行,并且不支持跟踪 sub-processes。sudo dtruss -d -e -t open -n touch
,然后在另一个终端中 运行touch /tmp/testingtesting
。这避免了 运行ningtouch
作为 root,但它会跟踪 all 个名为touch
. 的进程
当使用 dtruss
的原始版本时,跟踪系统调用的输出也可能不太清楚,因为更新版本在格式化系统调用参数(尤其是字符串)方面做得更好。 (对于 open()
具体而言,the updated version prints the 'mode' argument for created file permisions as octal,这通常是您想要的。)
是的,您需要禁用 SIP 的 dtrace 部分才能使 dtrace 的所有功能正常工作,这可能会带来一个小的安全风险,但我还没有听说过任何试图利用的恶意软件这个。
脚注:
¹ 我不是要 self-promote 我的代码。我根本不知道更好的解决方案 - 我遇到了与提问者非常相似的问题,并且 built-in 工具不够好,所以我修复了它。