在tty上写非ASCII字符到程序的stdin(通过ssh)
我用一些二进制挑战SSHd到远程服务器。在tty上写非ASCII字符到程序的stdin(通过ssh)
有一次,它要求我输入文字。我知道它使用fgets()
来读取stdin
,并且我可以溢出它被复制到并覆盖附近变量的位置。
的问题是我不知道如何键入我所需要的地址值,\x84
和\x04
等。如果我能够使用bash我会echo -ne "\x84"
或使用C六角阵列,但我不能做那种这里的东西。
我试过使用十六进制ASCII转换器和复制二进制字符,也使用期望脚本发送二进制值,但都有同样的问题。 x84增加了一个额外的字符,x04根本不会写入。
任何想法最好的方法来可靠地写入值的内存,不能用Unix上的tty上的ASCII字符通过ssh表示?
对于高字符,您可能可以复制/粘贴。
例如echo -ne "\x84" | xclip -i
然后在您的终端模拟器中单击,如果您的桌面也在运行Linux。 (或可能不是,见)。或者echo ... | ssh [email protected]
可以工作。
ssh -T
或其他任何终端仿真程序中的等价物也可能是“禁用伪终端分配”的选项,因此远程端的程序将使其stdin
成为sshd的管道而不是伪 - 终端,我想。这可能会导致像^s
和^v
这样的东西变得很特殊,我想。
相反,echo foo | ssh -tt
会强制它在远程端请求一个tty,即使你将东西输入到ssh中。
A-侵入较少的方法以确保二进制数据通过SSH获取通过TTY层和接收程序的stdin
是每字节与一个控制v
(十六进制0x16)之前。
正如Barmar指出的那样,这是字面上的下一个字符(lnext
在stty -a
输出)。您可以在之前每字节使用它;它甚至在普通字符之前被接收器中的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
)测试这个本地所有。只需在终端中运行它,然后键入或粘贴一些内容,然后控制-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的“编码”设置是UTF-8。它似乎没有简单的ASCII设置。
也许试试LANG=C xterm
什么的,或者只是脚本expect
正确发送实际二进制数据到ssh
,而不是转义码。
当然不处理转义序列的fgets
,任何超过strcpy
会。通常C函数不会;但在C编译器编译器处理字符串文字中的转义序列。
'前面的每个字节都带有control-v(十六进制0x16)',对我来说非常合适。我使用pexpect脚本来发送十六进制。 对Barmar的回答很好的延伸。 Upvoted两个。 '它被接收器中的TTY层剥离,甚至在普通人物的非常有趣的信息之前,谢谢! – GhostSparkles
通过在键盘上输入控制字符,可以编写0x00
至0x1f
范围内的字符。按住控制键,同时在此ASCII Chart的第三列中键入一个字符以获取第一列中的相应代码。
一些控制字符具有特殊意义的终端驱动器(例如CTL -C杀死进程),则可以通过用CTL-V前述手动键入它们。
而且你可以通过键入CTL-V删除得到0x7f
(这是落后删除字符,这可能是labeld Backspace键,而不是向前删除,可能是在一个单独的键盘)。
我不确定是否有任何简单的方法来输入上面的字符。根据终端仿真器中的设置,您可以通过在输入相应的ASCII字符时按住键来保持高位设置。例如。 Alt-A将发送0xc1
(0x80 | 0x41
)。
如果您可以克服终端中的任何UTF-8假设,您也可以复制/粘贴高位设置的数据。 ' –
你的问题很混乱。您是问如何在终端上输入控制字符,或者C程序如何将它读入内存? – Barmar
如果你使用二进制数据,你不应该使用'fgets()'和朋友。这是为了读取文本数据。 –
对不起,我现在正在使用我的手机。可能是前者。如果我写AAAA,我会在内存中获得x41x41x41x41等。如果我写\ x84它会写x78x38x34等。我在编写十六进制值时遇到了困难,因为fgets将所有内容解释为ascii,而且似乎不允许使用转义序列。 – GhostSparkles