将非ASCII字符写入tty上的程序员的stdin(通过ssh)

时间:2017-09-20 18:36:23

标签: c terminal binary reverse-engineering tty

我已经通过一些二进制挑战SSH到远程服务器。

有一次它要求我输入文字。我知道它正在使用fgets()来读取stdin,并且我可以溢出它被复制到的地方并覆盖附近的变量。

问题是我不知道如何输入我需要的地址值,\x84\x04等。如果我能够使用bash,我会echo -ne "\x84"或使用C十六进制数组,但我不能在这里做那种事情。

我尝试过使用十六进制到ASCII转换器并复制二进制字符,并使用expect脚本发送二进制值,但两者都有相同的问题。 x84添加了额外的字符,x04根本不会写入。

任何想法都是可靠地将值写入内存的最佳方法,这些内容在Unix tty上的ssh上无法用ASCII字符表示?

2 个答案:

答案 0 :(得分:3)

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

某些控制字符对终端驱动程序具有特殊含义(例如 Ctl-c 以终止进程),您可以通过在 Ctl-v 之前进行字面输入。

您可以通过键入 Ctl-v 删除来获取0x7f(这是后退删除字符,可能标记为 Backspace ,而不是可能在单独的键盘中的前向删除)。

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

答案 1 :(得分:3)

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

e.g。 echo -ne "\x84" | xclip -i然后在终端模拟器中单击鼠标中键,如果您的桌面也在运行Linux。 (或者可能不是,见下文)。或echo ... | ssh user@host可行。

ssh -T或任何其他终端仿真器中的等效项也可能是“禁用伪终端分配”的选项,因此远程端的程序将其stdin作为管道来自我想是sshd,而不是伪终端。我认为这会禁用^s^v等特殊内容。

相反,echo foo | ssh -tt将迫使它在远程端请求tty,即使你正在将东西输入ssh。

通过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中,编译器在编译时处理字符串文字中的转义序列。