将非 ASCII 字符写入 tty 上程序的标准输入(通过 ssh)
Write non-ASCII characters to stdin of a progam on a tty (over ssh)
我正在通过一些二进制挑战通过 SSH 连接到远程服务器。
有一次它要求我输入文本。我知道它正在使用 fgets()
来读取 stdin
,并且我可以溢出它被复制到的位置并覆盖附近的变量。
问题是我不知道如何输入我需要的地址值,\x84
和 \x04
等。如果我能够使用 bash 我会 echo -ne "\x84"
或使用 C 十六进制数组,但我不能在这里做那种事情。
我试过使用十六进制到 ASCII 转换器并复制二进制字符,还使用 expect 脚本发送二进制值,但两者都有相同的问题。 x84 添加了一个额外的字符,而 x04 根本不会写入。
知道在 Unix tty 上通过 ssh 将无法用 ASCII 字符表示的值可靠地写入内存的最佳方法吗?
您可以通过在键盘上键入控制字符来输入 0x00
到 0x1f
范围内的字符。按住Control键,同时在此ASCII Chart第三列输入一个字符,得到第一列对应的代码。
一些控制字符对终端驱动程序有特殊意义(例如 Ctl-c 终止进程),你可以通过在 Ctl 前面按字面输入它们-v.
你可以通过输入Ctl-vDelete得到0x7f
(这是向后删除字符,可能被标记为 Backspace,而不是可能位于单独键盘中的向前删除)。
我不确定是否有任何简单的方法可以在上面输入字符。根据终端仿真器中的设置,您可以通过在键入相应的 ASCII 字符时按住 Alt 键来设置高位。例如。 Alt-A 将发送 0xc1
(0x80 | 0x41
).
对于高字符,你大概可以copy/paste。
例如echo -ne "\x84" | xclip -i
然后在你的终端模拟器中单击鼠标中键,如果你的桌面也是 运行ning Linux。 (也可能不是,见下文)。或者 echo ... | ssh user@host
可以工作。
ssh -T
或任何其他终端仿真器中的等效项也可能是 "Disable pseudo-terminal allocation" 的一个选项,因此远程端的程序将其 stdin
是来自sshd,而不是伪终端,我认为。我认为这会禁用 ^s
和 ^v
之类的特殊内容。
相反,echo foo | ssh -tt
将强制它在远程端请求 tty,即使您正在将内容传输到 ssh。
确保 SSH 上的二进制数据通过 TTY 层并到达接收程序的 stdin
的一种侵入性较小的方法是在每个字节之前加上控制 -v
(十六进制0x16).
正如 Barmar 指出的那样,这是下一个字符(stty -a
输出中的lnext
)。您可以在负载的 每个 字节之前使用它;它甚至在普通字符之前就被接收器中的 TTY 层剥离了。
# LANG=C sed to replace every byte with ^V byte
# using bash $'' to put a literal control-V on sed's command line
echo "hello" | LANG=C sed $'s/./\x16&/g' | hd
16 68 16 65 16 6c 16 6c 16 6f 0a |.h.e.l.l.o.|
您可以通过输入 hexdump -C
(又名 hd
)在本地测试所有这些。只需 运行 在终端中输入或粘贴一些内容,然后按 control-D 直到它退出。
$ echo -ne "\x01\xff\x99" | LANG=C sed $'s/./\x16&/g' | hd
00000000 16 01 16 ff 16 99 |......|
00000006
# yup, correct bytes from sed
$ echo -ne "\x01\xff\x99" | LANG=C sed $'s/./\x16&/g' | xclip -i
$ LANG=C hd
^A�� (middle click, return, control-d)
00000000 01 ef bf bd ef bf bd 0a |........|
# nope, that munged my data :/
$ xclip -o | hd
00000000 16 01 16 ff 16 99 |......|
所以 X 选择本身是正确的,但是它在我粘贴时被 Konsole 弄脏了,或者在从 Konsole 到 hexdump
的途中被 TTY 层弄脏了?后者似乎不太可能。应该是粘贴的问题。 Konsole 的 "encoding" 设置为 UTF-8。它似乎没有纯 ASCII 设置。
也许可以尝试使用 LANG=C xterm
之类的东西,或者只是将 expect
脚本正确地发送到 ssh
,而不是转义码。
fgets
当然不处理转义序列,比 strcpy
处理得更多。通常 C 函数不会;但在 C 中,编译器 在编译时处理 字符串文字 中的转义序列。
我正在通过一些二进制挑战通过 SSH 连接到远程服务器。
有一次它要求我输入文本。我知道它正在使用 fgets()
来读取 stdin
,并且我可以溢出它被复制到的位置并覆盖附近的变量。
问题是我不知道如何输入我需要的地址值,\x84
和 \x04
等。如果我能够使用 bash 我会 echo -ne "\x84"
或使用 C 十六进制数组,但我不能在这里做那种事情。
我试过使用十六进制到 ASCII 转换器并复制二进制字符,还使用 expect 脚本发送二进制值,但两者都有相同的问题。 x84 添加了一个额外的字符,而 x04 根本不会写入。
知道在 Unix tty 上通过 ssh 将无法用 ASCII 字符表示的值可靠地写入内存的最佳方法吗?
您可以通过在键盘上键入控制字符来输入 0x00
到 0x1f
范围内的字符。按住Control键,同时在此ASCII Chart第三列输入一个字符,得到第一列对应的代码。
一些控制字符对终端驱动程序有特殊意义(例如 Ctl-c 终止进程),你可以通过在 Ctl 前面按字面输入它们-v.
你可以通过输入Ctl-vDelete得到0x7f
(这是向后删除字符,可能被标记为 Backspace,而不是可能位于单独键盘中的向前删除)。
我不确定是否有任何简单的方法可以在上面输入字符。根据终端仿真器中的设置,您可以通过在键入相应的 ASCII 字符时按住 Alt 键来设置高位。例如。 Alt-A 将发送 0xc1
(0x80 | 0x41
).
对于高字符,你大概可以copy/paste。
例如echo -ne "\x84" | xclip -i
然后在你的终端模拟器中单击鼠标中键,如果你的桌面也是 运行ning Linux。 (也可能不是,见下文)。或者 echo ... | ssh user@host
可以工作。
ssh -T
或任何其他终端仿真器中的等效项也可能是 "Disable pseudo-terminal allocation" 的一个选项,因此远程端的程序将其 stdin
是来自sshd,而不是伪终端,我认为。我认为这会禁用 ^s
和 ^v
之类的特殊内容。
相反,echo foo | ssh -tt
将强制它在远程端请求 tty,即使您正在将内容传输到 ssh。
确保 SSH 上的二进制数据通过 TTY 层并到达接收程序的 stdin
的一种侵入性较小的方法是在每个字节之前加上控制 -v
(十六进制0x16).
正如 Barmar 指出的那样,这是下一个字符(stty -a
输出中的lnext
)。您可以在负载的 每个 字节之前使用它;它甚至在普通字符之前就被接收器中的 TTY 层剥离了。
# LANG=C sed to replace every byte with ^V byte
# using bash $'' to put a literal control-V on sed's command line
echo "hello" | LANG=C sed $'s/./\x16&/g' | hd
16 68 16 65 16 6c 16 6c 16 6f 0a |.h.e.l.l.o.|
您可以通过输入 hexdump -C
(又名 hd
)在本地测试所有这些。只需 运行 在终端中输入或粘贴一些内容,然后按 control-D 直到它退出。
$ echo -ne "\x01\xff\x99" | LANG=C sed $'s/./\x16&/g' | hd
00000000 16 01 16 ff 16 99 |......|
00000006
# yup, correct bytes from sed
$ echo -ne "\x01\xff\x99" | LANG=C sed $'s/./\x16&/g' | xclip -i
$ LANG=C hd
^A�� (middle click, return, control-d)
00000000 01 ef bf bd ef bf bd 0a |........|
# nope, that munged my data :/
$ xclip -o | hd
00000000 16 01 16 ff 16 99 |......|
所以 X 选择本身是正确的,但是它在我粘贴时被 Konsole 弄脏了,或者在从 Konsole 到 hexdump
的途中被 TTY 层弄脏了?后者似乎不太可能。应该是粘贴的问题。 Konsole 的 "encoding" 设置为 UTF-8。它似乎没有纯 ASCII 设置。
也许可以尝试使用 LANG=C xterm
之类的东西,或者只是将 expect
脚本正确地发送到 ssh
,而不是转义码。
fgets
当然不处理转义序列,比 strcpy
处理得更多。通常 C 函数不会;但在 C 中,编译器 在编译时处理 字符串文字 中的转义序列。