我想知道什么程序调用特定的可执行文件,包括该可执行文件何时通过 shebang 行用作解释器。
这与问题不完全相同知道什么程序访问特定文件。例如,auditctl -w /usr/bin/myprogram
告诉我程序正在由……本身执行,因为审计事件是在成功execve
调用后生成的。
一种选择是用包装程序替换可执行文件,如下所示……
#!/bin/sh
logger "$0: executed by uid=$(id -u) ruid=$(id -ur) cmd=$(ps -o args= -p $PPID)"
exec "$0.real" "$@"
但这需要移动实际文件,这是破坏性的(该文件不能是只读的,它与包管理器所做的修改发生冲突等)。如果程序用作脚本的解释器,则它不起作用,因为 shebang 不嵌套。 (在这种情况下,auditctl -w /usr/bin/interpreter
确实给出了有用的结果,但我想要一个适用于这两种情况的解决方案。)如果是 bash,它也不适用于 setuid 程序,/bin/sh
因为 bash 会删除权限。
如何监视特定可执行文件的执行,包括将该可执行文件用作 shebang 解释器,特别是记录有关调用进程的有用信息(不仅是 PPID,而且至少是进程名称或父可执行文件路径,理想情况下还包括调用进程)用户和参数)?最好不要用包装器替换文件。特定于 Linux 的解决方案就可以了。
答案1
这可能很麻烦,但如果它是动态链接的可执行文件,您可以设置一个全局预加载,/etc/ld.so.preload
只有在检测到您处于正确的可执行文件中时才会触发日志记录挂钩。
就像是:
#define _XOPEN_SOURCE
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define TARGET "/some_executable"
__attribute__((constructor))
static void
logger(int argc, char** argv){
/*catch own argv right here and parent's later from /proc */
static char buf[sizeof(TARGET)];
readlink("/proc/self/exe", buf, sizeof(buf)-1);
if ( 0==strcmp(TARGET, buf)){
/* ... */
syslog(/*...*/);
}
}
这种方法的明显缺点是它会稍微延迟系统上每个动态链接的可执行文件的执行,但我的测量表明延迟非常小(<1ms,其中 fork+exec 的成本约为 2ms)。
至于删除权限问题,您可能有一个小的 setuid-root 二进制文件,它将无条件读取并回显其祖父母 proc 文件(status
最有可能的是该文件),可能当且仅当其父级是您想要记录其父级的可执行文件时。然后,您可以在日志记录挂钩中生成 setuid 可执行文件,以获取有关可执行文件父级(setuid 帮助程序的祖父)的信息。
答案2
您可以使用扇通知用于侦听对给定文件系统中的文件进行的所有打开操作的 API。该信息以事件结构流的形式提供,其中包括提供正在打开的文件名的文件描述符以及请求者的进程 ID。
您的程序可以选择允许或拒绝打开,这意味着它可以在/proc
允许其继续之前查找 pid 以查找执行打开的命令和用户,而不会出现竞争条件。
手册页粉丝通知(7)提供了一个完整的 C 程序来获取事件并对打开的请求进行调解,因此您只需插入一些额外的行即可从/proc
.请注意,您将获得整个安装点中所有文件的事件,因此请在专门安装的小型文件系统上测试您的代码。
该fatrace
命令显示了如何在简单的测试中获取其中一些信息。例如,复制/bin/bash
到/tmp/bash
,然后编写一个小~/test2
脚本
#!/tmp/bash
pwd
fatrace
并仅在文件系统上运行/tmp
(假设它是单独的 tmpfs 挂载),方法是使用选项-c
侦听当前目录文件系统并-f O
侦听打开情况:
cd /tmp
sudo fatrace -c -f O
现在当你跑步时
sh -c 'echo $$; ~/test2'
expect -c 'spawn /home/meuh/test2'
~/test2
你应该看到已记录
sh(7360): RO /tmp/bash
expect(7414): RO /tmp/bash
bash(7590): RO /tmp/bash