netcat联机帮助页指示,如果没有-c和-e选项,可以使用以下命令通过nc提供shell。
$ rm -f /tmp/f; mkfifo /tmp/f
$ cat /tmp/f | /bin/sh -i 2>&1 | nc -l 127.0.0.1 1234 > /tmp/f
现在,根据我的理解,来自fifos的读取和写入都是阻塞操作。例如,如果我运行
$ mkfifo foo
$ cat foo
bash会阻塞,因为没有任何内容写入foo。来自nc联机帮助页的示例中的管道如何不阻塞?我认为我误解了管道的执行方式。
答案 0 :(得分:7)
管道中的所有命令同时运行,而不是顺序运行。因此cat /tmp/f
确实会阻止,但/bin/sh
和nc
仍将在此时启动。当客户端连接到端口并发送命令时,nc
将写入FIFO,这将允许cat
取消阻止。
答案 1 :(得分:3)
bash中的管道字符不是esle,然后将第一个命令的输出流连接到第二个命令的输入流。 echo "123" | cat
基本上与cat < <(echo 123)
相同(后者只会启动一个子shell,而第一个为每个命令启动一个,但这里可以忽略 - 加上,它是一个基础,不起作用sh
)。
$ mkfifo foo
$ cat foo
确实会阻止 - 但不会冻结。当任何其他程序向foo
写入任何内容时,cat将显示它。
你在netcat调用中做什么实际上是创建一个cicrle:写入FIFO的任何内容都将由cat
显示,并且cat
连接到sh
发送到后者。然后sh
将执行代码(因为sh只执行写入其输入流的任何内容)并将输出发送到nc
。 nc
会将其发送给客户。
客户端发送给nc
的任何内容都将写入FIFO - 我们的圈子已完成。
你犯的错误(我认为)是假设管道的第二个进程只读取数据一次,而不是连续读取,因此必须等待第一个进程结束。事实并非如此,因为管道中的每个进程都是在一个shubshell中启动的,所以它们都是相互依赖的。
您还应该能够更改管道中所有命令的顺序。只要第一个从FIFO读取并且最后一个写入它(完成圆圈),它就应该有效。