如何在自己的 tty 中运行程序?

如何在自己的 tty 中运行程序?

我正在搞乱 TIOCSTI,它将数据推入终端的输入缓冲区。我希望能够在数据到达 shell 或将其重定向到文件之前捕获该数据。

为了更好地说明我正在尝试做的事情:

gcc -x c -o pusher.bin - <<PUSHER
#include <unistd.h>
#include <sys/ioctl.h>
#include <termios.h>

int main() {
  char *c = "echo 'Catch me if you can'\n";
  while(*c) ioctl(0, TIOCSTI, c++);
}
PUSHER
./pusher.bin

如果在我的终端中运行,./pusher.bin将注入echo 'Catch me if you can'\n我的 tty,我的 shell 将立即执行。如果我运行setsid ./pusher.bin, echo 不会被注入到我的终端中,但我也无法捕获它。

我想./pusher.bin用一些东西来包装,这样我就可以检查如果裸机运行的话,推送器会在我的 tty 输入缓冲区中注入什么内容。

澄清:我知道注入的输入在到达我的 shell 的标准输入后可以被捕获。这种方法虽然可以有效捕获注入的输入,但也可以捕获正常的用户输入。此外,如果 stdin 关闭或进程未附加到 tty,则此方法将不起作用。仅这些缺点就使得捕获 stdin 作为通用解决方案不可行。

答案1

这似乎script是解决方案,正如 AB 提到的,-e您甚至可以获得程序的返回代码。cat -vet更明确地显示回车符^M和换行符$

$ script -q -e out -c ./pusher.bin >/dev/null; echo $?
0
$ cat -vet out
Script started on Mon Dec 21 10:54:40 2020$
echo 'Catch me if you can'^M$

答案2

注入后您需要阅读终端。例如,对于一行:

$ ./pusher.bin;read a
$ echo "Intercepted: $a"

或者一般来说:

$ ./pusher.bin;cat

您可能必须注入 EOF 才能cat结束。

如果你想看看,另一种选择只是注入的字符:

$ stty -echo;./pusher.bin;cat;stty echo

您将无法捕获这些注入的字符串并将它们与正常输入区分开来

答案3

我想出了这个实用但有缺陷的解决方案:

RESULT="$(bash -c 'ID="s$(head -c 8 /dev/urandom | base64 | sed "s/[^0-9a-zA-Z]//g")"; F="$(mktemp)";  screen -d -m -S "$ID" bash -c "./escape.bin; cat >/$F"; sleep 1s; screen -S "$ID" -X quit; cat <$F; rm "$F"')"

分解重要的部分:

# Generate a unique session name for screen
ID="s$(head -c 8 /dev/urandom | base64 | sed "s/[^0-9a-zA-Z]//g")";

# Get a temporary file
F="$(mktemp)";  

# Run pusher in a detached (`-d -m`) screen session 
# with its own tty and read back the tty's buffer 
# using cat and write it to the temporary file
screen -d -m -S "$ID" bash -c "./pusher.bin; cat >/$F"; 

# Sleep for one second for pusher to finish (I'm a 
# aware that I can poll screen using `-list`, but 
# exec fails for some reason, help here would be 
# appreciated)
sleep 1s; 

# Kill screen session manually (again, `exec`ing 
# fails for some reason )
screen -S "$ID" -X quit; 

# Print the contents of F to stdout so that it can 
# be captured by the outermost `$(...)`
cat <$F; 

# Removes the temporary file
rm "$F"'

这种方法对于我的用例来说足够可靠,但它存在明显的问题:

  1. 的退出状态pusher.bin丢失。
  2. 不等待pusher.bin退出,但假设 1 秒后完成。
  3. 使用屏幕会话(一种共享且面向用户的资源)来获取 tty。
  4. 不会尽早取消临时文件的链接,如果出现任何问题,这可能会导致留下临时文件。

其中一些很容易修复,而另一些则更复杂。

相关内容