本来只是想记录一下 reverse shell 的一些东西,结果越学越觉得什么都不懂,索性深入研究了一下从底层讲一讲 pwnable 中的 fd tricks,预计共分三篇完成。

第一篇主要区分一些设备上容易混淆的概念,和 fd 关系并不大,但是很有意思。参考了很多,链接都放在最后了。

(这篇 post 基本是搬运了参考链接- -感谢大佬们的无私分享)

什么是 CLI

Command-line Interface 即命令行界面,通俗的说就是黑客电影中满屏都是字符的界面,与 GUI(图形用户界面,Graphical User Interface)相对。CLI 具有高效率等优点,因此即使是图形化较完善的操作系统(如 Windows)中,也保留了 cmd.exe 和 powershell 等命令行的程序

什么是终端

在计算机领域,终端 (Terminal) 指的是一种将用户的输入传给计算机,并显示计算结果的机器,但要充分理解终端的话,需要我们回溯历史。

历史上的终端

在计算机刚诞生的时代,巨大的计算机往往放置在一个单独的房间里,程序员在其他的房间里通过某些设备与计算机进行交互,这些设备就称为终端(Terminal),也叫终端机。

早期的终端一般是一种叫做电传打字机(Teletype)的设备,原因很简单,*nix 系统作为一个多用户的系统,需要每个用户都有一个终端,而价格低廉的 Teletype 就成了最好的选择(为什么不用键盘和显示器?因为那个时代还没有独立的键盘和显示器)。

这样,第一代程序员将这些打字机接到主机上,就实现了 *nix 的多用户交互,电传打字机也就成了第一个 Terminal 。

什么是控制台

上边说到,历史上的终端是一种连接到计算机上方便用户输入输出的外设,但有一个终端与众不同,它是计算机的一个组成部分,与主机一体,这个特殊的终端就叫控制台(Console)

控制台,顾名思义是用来管理计算机的,只能给系统管理员用,具有比普通终端更大的权限,一台计算机一般只有一个控制台,但可以有很多个终端(如下图中左边的即为 console,右边的为 terminal)

但需要注意的是,随着 PC 的普及,Console 与 Terminal 的概念已经逐渐模糊。当我们在管理系统时,他们是控制台;当做一般的工作时,他们是终端。我们既是一般用户,有事系统管理员

因此,现在的 Console 和 Terminal 基本可以看作是同义词

什么是终端模拟器

随着硬件的发展,我们现在已经很少见到专门的终端设备了,取而代之的是键盘(输入)和显示器(输出)。

没了终端设备,为了与操作系统交互,就需要一个程序来处理键盘和显示器的动作,模拟传统终端的行为,这种程序就是终端模拟器(Terminal Emulator)(下图是我正在使用的 terminal emulator: deepin-terminal)

Terminal Emulator 的工作流程如下:

  1. 捕获键盘输入
  2. 将输入的信号经过处理后传递给其他程序(程序会认为这是从一个真正的终端设备输入的)
  3. 获得程序的输出结果
  4. 调用图形接口,将输出结果渲染到显示器

终端模拟器的种类有很多,举几个常见的例子:

  • Linux: gnome-terminal, Konsole;
  • macOS: Terminal.app, iTerm2;
  • Windows: Win32 控制台

同样,随着历史发展,现在当人们一般直接直接将终端模拟器称作终端

终端窗口与虚拟控制台

大部分终端模拟器都是在图形用户界面(GUI)中运行的,叫做终端窗口(Terminal Window),如上图中的 deepin-terminal。

但有一些终端模拟器比较特殊,如在 *nix 系统下,使用快捷键 Ctrl + Alt + F1...F6 等快捷键可以切换到虚拟控制台(Virtual Console),快捷键 Ctrl + Alt + F7 切换回 GUI,虽然 Virtual Console 不运行在 GUI 中,但他们实质上也是一种终端模拟器(下图为正在现实系统启动信息的 Virtual Console)。

Terminal Window 与 Virtual Console 的区别是 Virutal Console 是直接由操作系统内核(OS kernel)提供的,因此当图形界面 down 了时,往往还可以到 virtual console 抢救,因为他们是由 kernel 直接提供的,只要系统不出问题一般都还是可以用的

那么,什么是 TTY ?

先给结论,tty 就是终端的统称。

从上边的历史我们知道电传打字机(Teletype)是最早的终端,tty 即为 Teletype 的缩写。由于 *nix 是多用户的操作系统,所以一台计算机会有多个终端连接。在早期,为了支持这些连接的电传打字机,开发者设计了名为 tty 的子系统(因为所有终端都是 tty,因此这个子系统也被命名为了 tty)。

同时因为 *nix 系统的哲学之一 —— Everything is a file,具体的硬件设备也被抽象为了 /dev/tty? 等文件

上边说的 ctrl + alt + F1-6 等 virtual console 分别对应了图中的 /dev/tty1-6

虽然现在终端设备已经不再限制于 teletype,但 tty 这个名称还是被保留了下来,所以在现代,tty 就可以理解成终端设备,终端设备即为 tty 。

后来,在 tty 子系统中衍生出了 pty,ptmx,pts 等概念,这些概念留到第三篇

什么是 shell

先看这张图,shell 位于最外层,像一层壳(shell)一样供用户与 kernel 沟通,让 kernel 完成用户交于的任务

实际上 shell 知识提供了用户操作系统的入口,一般是通过 shell 去调用其他的应用程序来达成目的。

如我们运行 cat test 时,shell 会运行 cat 这个程序,cat 再去调用内核提供的 open,read,write 等系统调用,虽然 shell 并没有直接与内核进行交互,但广义上我们可以认为 shell 提供了用户与内核交互的界面

shell 可以分为命令行 shell 和图形 shell 两类。命令行 shell 提供 CLI 界面,图形 shell 提供 GUI 界面(如 windows 的 explorer.exe,接受用户的指令,与内核完成交互)

常用的命令行 shell 有:

  • *nix:
    • sh(Bourne shell),最经典的 shell
    • bash(Bourne-Again shell),绝大多数 linux 发行版的默认 shell
    • zsh,fish 等专注于用户友好体验的 shell
  • Windows 下的 cmd.exe 与 powershell

shell 与终端的分工

总结一下:

  • 终端从用户接受输入(通过键盘,鼠标等输入设备),把输入交给 shell,然后把 shell 返回的结果通过显示器等方法展示给用户。
  • shell 从终端接受用户的输入,解析后交给操作系统内核进行处理,并把结果返回给终端

References:

https://superuser.com/questions/144666/what-is-the-difference-between-shell-console-and-terminal

https://www.zhihu.com/question/65280843

https://blessing.studio/the-difference-between-cli-terminal-shell-tty/

https://stackoverflow.com/questions/21014344/terminal-or-console-or-shell-or-command-prompt

https://zh.wikipedia.org/wiki/終端

https://en.wikipedia.org/wiki/Terminal_emulator