我正在调查一些事情。我有一个/bin/sh
(dash
在本例中)进程,它运行输入到 shell 的STDIN
.其他东西会启动(守护进程)这个进程,我想知道这个进程的作用以及该脚本是什么样的。
例如,如果您将以下内容提交到 shell 中
echo 'echo ONE; sleep 99; sleep 666; echo TWO' | /bin/sh
在任何时间点的进程列表中,您只能看到当前正在执行的命令(例如sleep 99
),而看不到整个脚本。
如何恢复整个脚本的内容?
PS 这个问题的重点不是找到一种方法来告诉谁/什么启动了脚本或者为什么我需要它等等。
答案1
在 Linux 上,您可以使用bpftrace
报告sh
从 stdin 读取的进程:
#! /usr/bin/env bpftrace
tracepoint:syscalls:sys_enter_read /comm == "sh"/ {
/*
* Upon read(2) syscall entry, record whether the read() is on fd 0 (stdin)
* and if yes, where the read goes on a per-task basis
*/
@from_stdin[tid] = (args->fd == 0);
if (@from_stdin[tid]) {
@addr[tid] = args->buf;
}
}
tracepoint:syscalls:sys_exit_read /
comm == "sh" &&
@from_stdin[tid] &&
args->ret > 0
/ {
printf(
"sh process %d read %d bytes from stdin: \"%r\"\n",
tid,
args->ret,
buf(@addr[tid], args->ret)
);
}
然后运行将显示在该脚本echo 'echo foo | cat' | sh
的输出中:bpftrace
$ sudo ./that-bpftrace-script
./that-script:13:16-18: WARNING: Addrspace mismatch
comm == "sh" &&
~~
Attaching 2 probes...
sh process 83359 read 15 bytes from stdin: "echo foo | cat\x0a"
(我不知道什么地址空间不匹配警告是关于但似乎无害;你可以将其抑制连接 2 个探头...和-q --no-warning
)。
答案2
您可以尝试劫持外壳,但这充满了潜在的复杂性,最重要的是,也许我根本没有对此进行过很好的测试。
- 将外壳从 移动
/bin/sh
到/bin/sh.bin
- 创建一个名为的脚本
/bin/sh
来捕获标准输入到一个文件,然后调用/bin/sh.bin
运行它 - 请记住确保脚本可执行并且它使用
/bin/sh.bin
该脚本可能看起来像这样
#!/bin/sh.bin
# If it looks interactive run the real shell directly
[ -t 0 ] && exec /bin/sh.bin "$@"
# Otherwise grab stdin and then execute it
tee /tmp/sh_stdin.$$ | /bin/sh.bin "$@"
确保您在某个根窗口中打开了不同的 shell。例如,sudo bash
并且在确认脚本黑客工作正常之前不要关闭该会话和您已恢复更改。