在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表示?

+1

你的问题很混乱。您是问如何在终端上输入控制字符,或者C程序如何将它读入内存? – Barmar

+0

如果你使用二进制数据,你不应该使用'fgets()'和朋友。这是为了读取文本数据。 –

+0

对不起,我现在正在使用我的手机。可能是前者。如果我写AAAA,我会在内存中获得x41x41x41x41等。如果我写\ x84它会写x78x38x34等。我在编写十六进制值时遇到了困难,因为fgets将所有内容解释为ascii,而且似乎不允许使用转义序列。 – GhostSparkles

对于高字符,您可能可以复制/粘贴。

例如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指出的那样,这是字面上的下一个字符(lnextstty -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编译器编译器处理字符串文字中的转义序列。

+1

'前面的每个字节都带有control-v(十六进制0x16)',对我来说非常合适。我使用pexpect脚本来发送十六进制。 对Barmar的回答很好的延伸。 Upvoted两个。 '它被接收器中的TTY层剥离,甚至在普通人物的非常有趣的信息之前,谢谢! – GhostSparkles

通过在键盘上输入控制字符,可以编写0x000x1f范围内的字符。按住控制键,同时在此ASCII Chart的第三列中键入一个字符以获取第一列中的相应代码。

一些控制字符具有特殊意义的终端驱动器(例如CTL -C杀死进程),则可以通过用CTL-V前述手动键入它们。

而且你可以通过键入CTL-V删除得到0x7f(这是落后删除字符,这可能是labeld Backspace键,而不是向前删除,可能是在一个单独的键盘)。

我不确定是否有任何简单的方法来输入上面的字符。根据终端仿真器中的设置,您可以通过在输入相应的ASCII字符时按住键来保持高位设置。例如。 Alt-A将发送0xc10x80 | 0x41)。

+0

如果您可以克服终端中的任何UTF-8假设,您也可以复制/粘贴高位设置的数据。 ' –