有安全的猫吗?

有安全的猫吗?

我有时会从curl 或本地文件系统中获取二进制文件。在大多数情况下,损坏的端子可以用以下方法修复重置。在其他情况下,特别是如果二进制文件很大,终端将卡住几分钟打印输出,如下所示:

2c1

又名

c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;
2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;
2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;
2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;

关于这个场景我有三个问题;

  1. 2c1 是什么意思?为什么终端会打印这个?
  2. 您是否见过cat在交互式会话中实际防范这种不良行为的情况?
  3. 您对如何对这样的猫进行编程有什么建议(在 cee 或 golang 中)

我最初的本能是将 cat 包装在一个函数中来检测这一点,但我很快意识到这是相当困难的,而且会有很多边缘情况。

function cat() {
    # warn user if
    #   - argument 1 is a large  executable 
    #   - argument 1 to the previous command in the a pipe-chain looks like a large binary
    # abort if
    #   - session is interactive and we are able to detect 2c1 garbage
}

一个实用的解决方案可能是在查看“不安全”输入时始终使用 less (使用 LESSPIPE),但这个问题与寻呼机无关。我知道管子越来越少了。我每天都积极使用它们。也许少+少管是这个问题的解决方案,less 的作者在大约 20-30 年前实现了同样的问题

然而,cat 与“寻呼机”的不同之处不止一种......主要是 cat 是非交互式的。这对我来说意义重大。

关于 less+lesspipe 的建议实际上非常好(恕我直言),但我更关心控制字符的本质、特殊的转义序列以及不同的终端如何处理这些输入。

我对控制字符的技术细节以及终端或 shell 如何解释“垃圾”和控制字符更感兴趣。我不是在问“你将如何解决这个问题”。我问“为什么终端要这样处理二进制文件”。

答案1

我会使用less它来警告二进制文件,并且在某些系统上可以处理各种类型(例如在 CentOS 7 上,我可以less file.rpm查看 RPM 中的文件)。我相信这就是所谓的“lesspipe”。

另外,下次发生这种情况时,您可以尝试reset恢复tput reset正常。它们将转义序列发送到终端,告诉它重置为默认的正常状态,并执行相当于将stty sanetty 设备文件的设置更改为正常默认值的操作(尽管转储二进制文件不应影响这些设置)。reset还可以修复 tty 设备文件的终端或终端仿真器窗口大小的概念(如 所报告的tty size)以及支持查询它的终端。

答案2

没有人提到“字符串”。尽管字符串与 cat 并不完全相同,但它确实只打印连续文本数据中的文本字符串,以便在终端中查看更安全。它通常与 binutils 软件包一起提供。这是一个方便的程序,可以快速确保您不会从打印数据中获得任何二进制输出,并且如果您只想查看连续的非二进制数据,它也很有用。请注意,默认情况下,它仅打印包含 4 个或更多 ASCII 字符的连续文本部分。这可以使用 -n 选项进行调整。

答案3

您可以通过串行线路或伪 tty 设备(模拟串行线路)与终端或终端仿真器进行交互。

尽管内核中有一个软件模块位于中间作为一种适应层并进行一些转换(稍后简要讨论),但您通常:

  • 通过该串行线向终端发送字节流,终端将其解释为在屏幕上呈现的字形或更改其行为的特殊指令
  • 作为回报,终端通过串行线路上的另一条线向计算机发送字节流,以告诉计算机您键入的内容或响应它收到的一些控制查询。

例如,终端可以配置为 ISO8859-1(又名 latin1 终端),这意味着当它收到 0x53 0x74 0xe9 0x70 0x68 0x61 0x6e 0x65时,它会将其解释S为在当前光标在屏幕上的位置。相反,当用户输入 时,终端发送 0x53 字节。téphaneS

0 到 0x1f 范围内的字节值被解释为控制人物。也就是说,它们并不表示为字形,而是具有特殊含义。

例如:

  • 0x7 (BEL) 生成音频或视频警报
  • 0x8 (BS) 光标向左移动
  • 0xa (LF) 光标下移
  • 0xd (CR) 移动光标到屏幕第一列
  • 0x9 (TAB) 将光标移动到下一个制表

该范围内只有 32 个控制字符,大多数终端都有更多功能或控制它们的方式。因此,除了这些之外,您还可以发送超过字节来控制你的终端。对于大多数终端和大多数序列,第一个字节是 0x1b (ESC),后跟一个或多个字节。

例如,虽然有控制字符可以将光标向左或向下移动,如上所示,但没有控制字符可以将其向右或向上移动(最初,在电传打字机中,向右将用“空格”完成,但在CRT 终端会擦除光标下的内容,并且您不会使用电传打字机,因为这可能会造成卡纸),因此必须为这些终端引入转义序列,在大多数终端上分别为 0x1b 0x5b 0x43 和 0x1b 0x5b 0x41 (顺便说一句,这也是许多终端在按下RightUp对于具有此类键的终端时发送的字节序列)。

现在,终端支持的转义序列包括:

  • 更改文本或背景颜色以及其他图形渲染属性
  • 更改字符集。例如,latin1 中没有希腊字符,并且终端(从 Unicode 出现之前至今)支持切换到不同的字符集以显示其他语言的字母或方框图字符。
  • 设置制表位的位置
  • 可以从终端查询信息,例如光标位置、颜色、窗口标题、大小...
  • 会影响输入的处理方式。例如,某些终端支持输入一种模式,例如,在按Shift+A时,它不会发送 0x41 (ASCII A) 字符,而是发送一系列字节,用于对有关修饰符(shift、alt、ctrl ...)和键码的信息进行编码。
  • 一些 X11 终端模拟器可以识别转义序列来更改字体、窗口大小、显示 JPEG 图像、将屏幕内容发送到打印机...

在文本文件中,通常只有代表图形字符的字节(如果是 UTF-8 或其他多字节字符集,则为字节序列)。唯一的控制您在文本文件中找到的字符是 NL(0xa,又名 LF)和 TAB(0x9)。

当您这样做时cat file.txtcat只需读取 的内容file.txt并将其写入其标准输出。如果 stdout 是一个串行或伪 tty 设备文件(例如 ) /dev/ttyS0/dev/pts/0并且将终端行规则推送到其上,就像您从终端仿真器中的交互式 shell 运行该命令一样,则行规则会转换这些 NL到 CR+NL(尽管 NLNL 可能被翻译为 CRNLNL),因此终端在收到 CRNL 后会将光标移动到开头,然后向下移动。

因此,如果文件中的文本以终端的字符集进行编码,则文件内容中的文本将显示在终端屏幕上。

现在,可执行文件或其他随机二进制文件中的字节并不旨在表示字符,它们可以具有任何值,包括 0 到 31 范围内的值,因此当发送到终端时,终端将按照其指示执行操作并将它们解释为控制字符,这可能会使其执行上面列出的任何操作以及更多操作,并使其完全无法使用。

为了防止这种情况,首先不要将这些文件发送到终端,因为这没有意义,或者如果您不知道文件是否可能是文本文件(或打算由用户逐字查看的文件)带有转义序列的终端故意的无论是否由终端解释,您都可以使用一个工具来删除控制字符(至少是除 TAB 和 NL 之外的所有字符)或为它们提供可视化图形表示。

这就是许多实现所支持的-v和选项所做的事情。其中,除了 NL 和 TAB 之外的所有字符都转换为字节 0 到 31 和 0x7f、字节 0x80 到 0x9f 和 0xff 以及字节 0xa0 到 0xfe 的某种表示法,这些是非 ASCII 字符的常见视觉表示。并且仅适用于 TAB(更改为)。-tcat-v^XM-^XM-X-t^I

或者您可以使用寻呼机,例如lessvim,它view默认执行此操作(至少只要您不使用-r/ -Rraw 选项)并且更聪明一点,因为它们不会转换非 ASCII 字符意味着在您的语言环境中具有图形表示,并通过使用着色或突出模式更清楚地显示哪些字节已被转换。

或者,您可以使用专用于预览非文本文件的工具,例如hexdump -Cxxd

另请参阅which 命令以更明确的方式执行类似于和 is standard (与 相反)l的操作:sedcat -vtecat -vte

sed -n l < a-file

答案4

  • 是的,年轻学徒。
$ cargo search bat 
bat = "0.23.0"            # A cat(1) clone with wings.
  • 但是师傅,什么是货物?
$ cargo --help |any install rust 
Rust's package manager
      --list                List installed commands
      --explain <CODE>      Run `rustc --explain CODE`
    install     Install a Rust binary. Default location is $HOME/.cargo/bin
    uninstall   Uninstall a Rust binary
$ cargo install bat
(...)

掌握:如果您尝试使用bat二进制文件,就会发生这种情况。

$ bat `which bat`
[bat warning]: Binary content from file '/home/jaroslav/.cargo/bin/bat'
will not be printed to the terminal (but will be present if the output
of 'bat' is piped). You can use 'bat -A' to show the binary file contents.
  • 学徒:大师,击球有什么缺点吗?
  • 掌握:是的,它在处理大文件时可能会很慢,但这部分是因为它突出显示了结构化语法。这些东西可以被禁用,例如 --style=plain --color=never
  • 学徒:那么,主人,cat 输出到终端的奇怪字符呢?
  • 掌握:发生这种情况是因为终端会很乐意接受并解释任何看起来像 ANSI 转义码(内部终端命令)的内容,并尝试执行该命令所说的操作(如果该命令已实现)。有关简短介绍,请查看此Ansi 颜色转义序列列表

以下是重现此行为的方法:

$ echo -ne "\u1B\u5B\u63" | xxd
00000000: 1b5b 63                                  .[c

$ echo -ne "\u1B\u5B\u63" 
^[[?1;2c

$ 1;2c

相关内容