【笔记】CSE 365 - Fall 2024之Linux Luminarium(pwn.college)

news/2024/10/20 23:04:43

【笔记】CSE 365 - Fall 2024之Linux Luminarium(pwn.college)

Hello Hackers

本模块将教你与命令行交互的基础知识!命令行允许您执行命令。当您启动终端时,它将执行命令行 “shell”,如下所示:

hacker@dojo:~$

这称为 “prompt”,它会提示您输入命令。让我们来看看这里发生了什么:

提示中的hacker是当前用户的用户名。在 pwn.college网站的虚拟机DOJO环境中,默认用户就是“hacker”。

在上面的示例中,提示符的 dojo 部分是 shell 所在的机器的主机名(例如,如果您是每天处理许多机器的系统管理员,则此提醒可能很有用)。在上面的例子中,主机名是 dojo,但在 pwn.college 中,它将从你正在尝试的挑战的名称派生出来。

我们可以看看自己的虚拟机,你可以看到自己的主机名接在你的用户名后边

image-20241019191138269

我们稍后会介绍 ~ 的含义 :-)

提示符末尾的 $ 表示hacker不是管理用户。在 pwn.college 的后面的模块中,当你学会使用漏洞利用程序成为管理用户时,你会看到这里会通过回显 # 而不是 $ 来表示你的权限,然后你就会知道你成功了!

Intro to Commands 命令介绍

在这个挑战中,您将调用您的第一个命令!当您键入命令并按 Enter 键时,将调用该命令,如下所示:

hacker@dojo:~$ whoami
hacker
hacker@dojo:~$

这里,用户执行了 whoami 命令,该命令只是将用户名 (hacker) 打印到终端。当命令终止时,shell 将再次显示提示符,为下一个命令做好准备。

在这一关中,调用 hello 命令以获取flag!请记住:Linux 中的命令区分大小写:helloHELLO 不同。

查看解析
hello

我们直接输入"hello"即可调用"hello"命令

Intro to Argument 参数介绍

让我们尝试更复杂的方法:带有参数的命令,这就是我们所说的传递给命令的附加数据。当您键入一行文本并按 Enter 键时,shell 实际上会将您的输入解析为命令及其参数

第一个单词是命令,后面的单词是参数。示例如下:

hacker@dojo:~$ echo Hello
Hello
hacker@dojo:~$

在本例中,命令是 echo,参数是 Helloecho 是一个简单的命令,它将其所有参数都“回显”到终端上,就像您在上面的会话中看到的那样。

让我们看看具有多个参数的 echo

hacker@dojo:~$ echo Hello Hackers!
Hello Hackers!
hacker@dojo:~$

在本例中,命令是 echo,而 HelloHackers!echo 的两个参数。很简单对吧!

在此挑战中,要获取flag,您必须运行带有一个 hackers 参数的hello命令(不是 echo 命令)。现在就试试吧!

查看解析
hello hackers
我们在"hello"命令后接上"hackers"参数即可

Pondering Paths 思考路径

The Root 根

文件系统从 / 开始。在此之下,还有一大堆其他目录、配置文件、程序,最重要的是,还有flag。在这个关卡中,我们在 / 目录中添加了一个名为 pwn 的程序,它将为你提供flag。在这一关中,您需要做的就是调用此程序!

您可以通过在命令行上提供程序的路径来调用程序。在本例中,您将提供从 / 开始的确切路径,因此路径将为 /pwn。这种以根目录开头的路径样式称为 “绝对路径”。

开始挑战,启动一个终端,使用其绝对路径调用 pwn 程序,然后得到其中的flag!祝你好运!

我们可以观察自己虚拟机的文件结构,可以看出linux系统一切皆文件的理念

查看解析
/pwn
通过在"pwn"程序前加上"/"调用处于根目录的"pwn"程序

Program and absolute paths 程序的路径和绝对路径

让我们探索一条新的稍微复杂的路径!除了上一级之外,pwn.college 中的 很多关卡的挑战 都在 challenge 目录中,而 challenge 目录又在根目录 (/) 中。因此,目录的访问路径是 /challenge

此关卡中挑战的程序名称为 run,它位于 /challenge 目录中。因此,run 的程序路径是 /challenge/run

此挑战要求您通过调用程序的绝对路径来执行它。您需要执行 challenge 目录中的 run 文件,进而执行 / 目录中的运行文件。如果您正确调用了请求,它将为您提供flag。祝你好运!

查看解析
/challenge/run
通过输入"run"程序的绝对路径调用"run"程序

Position thy self 定位自己

Linux 文件系统有大量的目录和大量的文件。您可以使用 cdchange directory) 命令并将路径作为参数传递给命令,如下所示:

hacker@dojo:~$ cd /some/new/directory
hacker@dojo:/some/new/directory$ cd /some/new/directory

这会影响进程的 “当前工作目录” (在本例中为 bash shell) 。每个进程都有一个当前挂起的目录。其原因将在稍后的模块中阐明。

顺便说一句,现在你可以思考终端中的 ~ 是什么了!这一块显示的是 shell 所在的当前路径。

此挑战将要求您从特定路径执行 /challenge/run 程序(它会告诉您)。在重新运行挑战程序之前,您需要 cd 到该目录。祝你好运!

Bash shell是一种命令行界面和脚本语言,广泛用于Unix和Linux系统。它提供了用户与操作系统交互的方式,可以执行命令、运行脚本以及自动化任务

查看解析
/challenge/run
`回显路径`
cd `回显路径`
/challenge/run
通过"cd `回显路径`"跳转到指定路径执行程序

Position elsewhere 定位其他位置

与上一个挑战一样

Position yet elsewhere 再定位其他位置

与上一个挑战一样,重复题型加深记忆

implicit relative paths, from / 隐式相对路径,从/目录开始

现在,您已经熟悉了引用绝对路径和更改目录的概念。如果你到哪都输入绝对路径调用程序,那么你在哪个目录中真的无关紧要,你可能在前面的三个挑战中发现了这一点。

但是,当前工作目录对于相对路径确实很重要。

  • 相对路径是任何不以根开头的路径(即,它不以 / 开头)。
  • 相对路径英文是 current working directorycwd) 。
  • cwd 是显示当前所在的目录的提示符。

这意味着如何指定特定文件取决于终端提示符所在的位置

想象一下,我们想访问位于 /tmp/a/b/my_file 的某个文件

  • 如果我的 cwd/,那么文件的相对路径是 tmp/a/b/my_file
  • 如果我的 cwd/tmp,则文件的相对路径是 a/b/my_file
  • 如果我的 cwd/tmp/a/b/c,则文件的相对路径是 ../my_file.. 用于引用父目录。

父目录即上层目录

让我们在这里试试吧!您需要使用相对路径运行 /challenge/run,同时具有当前工作目录 /。在这一关中,我给你一个提示。您的相对路径需要以字母 c 开头

查看解析
cd /
challenge/run
为了使相对路径以字母c开头,我们在根目录下调用程序

explicit relative paths, from / 显式相对路径,从/目录开始

之前,你的相对路径是 “naked”:它直接指定了从当前目录进入到的下层目录。在这个关卡中,我们将探索更明确的相对路径。

在大多数操作系统(包括 Linux)中,每个目录都有两个隐式条目,您可以在 paths中引用它们:...

第一个.用于直接引用同一个目录,因此以下绝对路径彼此相同:

  • /challenge
  • /challenge/.
  • /challenge/./././././././././
  • /./././challenge/././

以下相对路径也彼此相同:

  • challenge
  • ./challenge
  • ./././challenge
  • challenge/.

当然,如果你现在的工作目录是 /,那么上面的相对路径相当于上面的绝对路径

做好准备,此挑战需要您在相对路径中使用 .

查看解析
cd /
./challenge/run
为了在相对路径中使用"."开头,我们在根目录下使用"./"调用程序

implicit relative 隐式相对路径

在这个关卡中,我们将练习使用 .更多地引用路径。此挑战需要您从 /challenge 目录运行它。在这里,事情变得有点棘手。

当您提供裸路径时,Linux 明确避免自动查找当前目录。请考虑以下事项:

hacker@dojo:~$ cd /challenge
hacker@dojo:/challenge$ run

不会调用 /challenge/run。这实际上是一种安全措施:如果 Linux 每次进入裸路径时都会在当前目录中搜索程序,你可能会不小心在当前目录中执行恰好与核心系统实用程序同名的程序!因此,上述命令将产生以下错误:

bash: run: command not found

我们稍后将探讨此概念背后的机制,但在此挑战中,将学习如何在此场景中显式使用相对路径来启动 run。执行此操作的方法是告诉 Linux 您明确希望在当前目录中执行一个程序,就像上一关一样。现在就试一试吧!

“裸路径”(naked path)指的是不包含任何目录结构或文件扩展名的路径,仅包含文件名。例如,文件名“example”就是一个裸路径,而“/home/user/example.txt”则不是。

查看解析
cd /challenge
./run
这一关旨在告诉我们在路径下直接输入程序名称不能调用程序,linux的安全机制阻止了

显式相对路径:明确指定了当前目录的相对位置,通常以当前工作目录作为起点。例如,如果当前工作目录是 /home/user,则文件 document.txt 的显式相对路径是 ./document.txt,或者直接用 document.txt 表示。

隐式相对路径:不直接指出当前工作目录,而是依赖于上下文或系统默认的路径。例如,直接使用 document.txt 就是一种隐式相对路径,系统会自动将其解析为当前工作目录下的文件。

home sweet home

每个用户都有一个主目录,通常在文件系统中的 /home 下。在 dojo虚拟机 中,您是 hacker 用户,您的主目录是 /home/hacker。主目录通常是用户存储大多数个人文件的位置。当您浏览 pwn.college 时,您将在主目录存储大部分文件。

通常,您的 shell 会话将以您的主目录作为当前工作目录开始。请考虑初始提示:

hacker@dojo:~$

此提示中的 ~ 是当前工作目录,其中 ~/home/hacker 的简写。Bash 提供并使用这种简写,因为同样,您的大部分时间将花在主目录中。因此,每当 bash 以与 path 一致的方式看到 ~ 作为参数的开头时,它就会将其扩展到您的主目录。考虑:

hacker@dojo:~$ echo LOOK: ~
LOOK: /home/hacker
hacker@dojo:~$ cd /
hacker@dojo:/$ cd ~
hacker@dojo:~$ cd ~/asdf
hacker@dojo:~/asdf$ cd ~/asdf
hacker@dojo:~/asdf$ cd ~
hacker@dojo:~$ cd /home/hacker/asdf
hacker@dojo:~/asdf$

请注意,~ 的扩展是绝对路径,并且只有前导 ~ 被扩展。这意味着,例如,~/~ 将扩展为 /home/hacker/~,而不是 /home/hacker/home/hacker

有趣的事实:cd 将使用你的主目录作为默认目标(就是当你使用cd命令不传入任何参数时默认会跳转到主目录):

hacker@dojo:~$ cd /tmp
hacker@dojo:/tmp$ cd
hacker@dojo:~$

现在轮到您玩了!在此挑战中,/challenge/run 会将flag的副本写入您在命令行上的参数指定的文件,并具有以下条件:

  1. 您的参数必须是绝对路径。
  2. 该路径必须位于您的主目录中。
  3. 在扩展之前,您的参数必须为三个字符或更少。
查看解析
/challenge/run ~/a
按照题目提示"run"程序能够将flag的副本写入参数指定的文件,我们使用"~"代替绝对路径"/home/hacker"

Comprehending Commands 理解命令

cat: not the pet, but the command cat:不是宠物而是命令

最关键的 Linux 命令之一是 catcat 最常用于读出文件,如下所示:

hacker@dojo:~$ cat /challenge/DESCRIPTION.md
One of the most critical Linux commands is `cat`.
`cat` is most often used for reading out files, like so:

如果提供了多个参数,cat 将 concatenate(连接)多个文件。例如:

hacker@dojo:~$ cat myfile
This is my file!
hacker@dojo:~$ cat yourfile
This is your file!
hacker@dojo:~$ cat myfile yourfile
This is my file!
This is your file!
hacker@dojo:~$ cat myfile yourfile myfile
This is my file!
This is your file!
This is my file!

最后,如果你根本没有给出任何参数,cat 将从终端 input (输入)中读取并输出它。我们将在后面的挑战中探讨这一点......

在这个挑战中,我会将flag复制到你的主目录(你的 shell 开始的地方)的flag文件中。使用cat去读吧!

查看解析
cat flag
使用"cat"命令读取当前目录下的"flag"文件

catting absolute paths 使用绝对路径cat读取文件

在上一个关卡中,您执行了 cat flag 以从您的主目录中读取flag!当然,你可以将 cat 的参数指定为绝对路径:

hacker@dojo:~$ cat /challenge/DESCRIPTION.md
In the last level, you did `cat flag` to read the flag out of your home directory!
You can, of course, specify `cat`'s arguments as absolute paths:
...

在此挑战中,我不会将其复制到您的主目录,但会使其可读。你可以在它的绝对路径 /flag 中使用 cat 来读取它。

有趣的事实:/flag 在 pwn.college 的虚拟机中一直存在 ,但与本次挑战不同的是,您通常无法直接访问该文件。

查看解析
cat /flag
使用"cat"命令读取根目录下的"flag"文件

more catting practice 更多cat读取练习

你可以指定各种路径作为命令的参数,我们将使用 cat 进行更多练习。在这个关卡中,我将把flag放在某个疯狂的目录中,我不允许你用 cd 来改变目录,所以别想着用 cat flag。您必须通过绝对路径检索flag,无论它位于何处。

查看解析
cat "flag的绝对路径"
"flag的绝对路径"在打开终端的那一刻给出

grepping for a needle in a haystack 大海捞针

有时,您可能会发现cat的文件太大。幸运的是,我们有 grep 命令来搜索我们需要的内容!我们将在这次挑战中学习。

grep 的方法有很多种,我们将在以下示例中学习:

hacker@dojo:~$ grep SEARCH_STRING /path/to/file

像这样调用,grep 将在文件中搜索包含 SEARCH_STRING 的文本行,并将它们打印到控制台。

在这次挑战中,我在 /challenge/data.txt 文件中放入了 10 万行文本。使用 grep 寻找flag!

提示: flag总是以 pwn.college 开头。

查看解析
grep pwn.college /challenge/data.txt
使用"grep"命令搜索包含“pwn.college”的文本行

listing files 列出文件

到目前为止,我们已经告诉您要与哪些文件进行交互。但是目录里面可以有很多文件(和其他目录),我们不会总告诉你它们的名字。您需要学习使用 ls 命令来 list 它们的内容!

ls 将列出提供给它的所有目录中的文件,如果未提供参数,则列出当前目录中的文件。观察以下示例:

hacker@dojo:~$ ls /challenge
run
hacker@dojo:~$ ls
Desktop    Downloads  Pictures  Templates
Documents  Music      Public    Videos
hacker@dojo:~$ ls /home/hacker
Desktop    Downloads  Pictures  Templates
Documents  Music      Public    Videos
hacker@dojo:~$

在这个挑战中,我们用一些随机名称命名了 /challenge/run!列出 /challenge 中的文件以查找它。

查看解析
ls /challenge
`run程序的新名字`
/challenge/`run程序的新名字`
使用"ls"命令查看"/challenge"目录下的“run”程序的名称并运行

touching files 创建文件

当然,您也可以创建文件!有几种方法可以做到这一点,但我们在这里看一个简单的命令。您可以通过使用 touch 命令触摸来创建新的空白文件:

hacker@dojo:~$ cd /tmp
hacker@dojo:/tmp$ ls
hacker@dojo:/tmp$ touch pwnfile
hacker@dojo:/tmp$ ls
pwnfile
hacker@dojo:/tmp$

就这么简单!在这个关卡中,请创建两个文件:/tmp/pwn/tmp/college,然后运行 /challenge/run 来获取你的flag!

查看解析
touch /tmp/pwn
touch /tmp/college
/challenge/run
使用"touch"命令创建文件

removing files 删除文件

文件就在你身边。就像糖果包装纸一样,它们最终会太多。在这个关卡中,我们将学习清理它们!

在 Linux 中,使用 rm 命令可以删除文件,如下所示:

hacker@dojo:~$ touch PWN
hacker@dojo:~$ touch COLLEGE
hacker@dojo:~$ ls
COLLEGE     PWN
hacker@dojo:~$ rm PWN
hacker@dojo:~$ ls
COLLEGE
hacker@dojo:~$

让我们练习一下。此挑战在您的主目录中创建了一个 delete_me 文件!删除它,然后运行 /challenge/check,这将确保您已删除它,然后为您提供flag!

查看解析
rm delete_me
/challenge/check
使用"rm"命令删除文件

hidden files 隐藏文件

有趣的是,ls 默认情况下不会列出所有文件。Linux 有一个约定,默认情况下,以 .开头的文件不会显示在 ls 和其他一些上下文中。要使用 ls 查看它们,您需要使用 -a flag调用 ls,如下所示:

hacker@dojo:~$ touch pwn
hacker@dojo:~$ touch .college
hacker@dojo:~$ ls
pwn
hacker@dojo:~$ ls -a
.college	pwn
hacker@dojo:~$

现在,轮到你了!找到那个flag,它隐藏在 / 中是一个带点的文件。

查看解析
ls -a /
使用"ls -a"命令查看根目录的隐藏文件

An Epic Filesystem Quest 史诗级的文件系统任务

凭借您对 cdlscat 的了解,我们已经准备好玩一个小游戏了!

我们将从 / 开始。如下所示:

hacker@dojo:~$ cd /
hacker@dojo:/$ ls
bin   challenge  etc   home  lib32  libx32  mnt  proc  run   srv  tmp  var
boot  dev        flag  lib   lib64  media   opt  root  sbin  sys  usr

内容真是太多了!总有一天,你会对它们非常熟悉,但你可能已经认出了flag文件和challenge关卡挑战目录。

在这次挑战中,我隐藏了flag!在这里,您将使用 lscat 来跟踪我的线索并找到它!以下是它的工作原理:

  1. 你的第一个线索在 / 中。向那边走。
  2. ls 环顾四周。将会有一个名为 HINT 或 CLUE 或类似名称的文件!
  3. cat那个文件来读线索!
  4. 根据线索所说的内容,前往下一个目录(或者不要!
  5. 循线索到flag!

祝你好运!

查看解析
灵活运用"cd""ls""cat"三条指令即可< /challenge/read_me

making directories 创建目录

我们可以创建文件。目录可以创建吗?你可以使用mkdir命令来创建目录,然后你就可以把文件贴进去了!

这里给出实例:

hacker@dojo:~$ cd /tmp
hacker@dojo:/tmp$ ls
hacker@dojo:/tmp$ ls
hacker@dojo:/tmp$ mkdir my_directory
hacker@dojo:/tmp$ ls
my_directory
hacker@dojo:/tmp$ cd my_directory
hacker@dojo:/tmp/my_directory$ touch my_file
hacker@dojo:/tmp/my_directory$ ls
my_file
hacker@dojo:/tmp/my_directory$ ls /tmp/my_directory/my_file
/tmp/my_directory/my_file
hacker@dojo:/tmp/my_directory$

现在创建一个 /tmp/pwn 目录并在其中创建名为college的文件!然后运行 /challenge/run,它将检查您的答案并为您提供flag!

查看解析
mkdir /tmp/pwn
touch /tmp/pwn/college
/challenge/run

finding files 查找文件

现在我们知道如何列出、读取和创建文件了。但是我们如何查找它们呢?我们使用 find 命令!

find 命令采用描述搜索条件和搜索位置的可选参数。如果未指定搜索条件,则 find 将匹配每个文件。如果未指定搜索位置,则 find 将使用当前工作目录 (.)。例如:

hacker@dojo:~$ mkdir my_directory
hacker@dojo:~$ mkdir my_directory/my_subdirectory
hacker@dojo:~$ touch my_directory/my_file
hacker@dojo:~$ touch my_directory/my_subdirectory/my_subfile
hacker@dojo:~$ find
.
./my_directory
./my_directory/my_subdirectory
./my_directory/my_subdirectory/my_subfile
./my_directory/my_file
hacker@dojo:~$

指定搜索位置时:

hacker@dojo:~$ find my_directory/my_subdirectory
my_directory/my_subdirectory
my_directory/my_subdirectory/my_subfile
hacker@dojo:~$

当然,我们可以指定标准!例如,在这里我们使用-name参数按名称进行筛选:

hacker@dojo:~$ find -name my_subfile
./my_directory/my_subdirectory/my_subfile
hacker@dojo:~$ find -name my_subdirectory
./my_directory/my_subdirectory
hacker@dojo:~$

如果你愿意,你可以在整个文件系统中搜索!

hacker@dojo:~$ find / -name hacker
/home/hacker
hacker@dojo:~$

现在轮到你了。我已将flag隐藏在文件系统上的随机目录中。它仍然被称为 flag。快去找吧!

几个笔记:首先,文件系统上还有其他名为 flag 的文件。如果您尝试的第一个没有实际的flag,请不要惊慌。其次,文件系统中有很多地方是普通用户无法访问的。这些将导致 find 生成错误,但您可以忽略这些错误;我们不会把flag藏在那里!最后,find可能需要一段时间;请耐心等待!

查看解析
find / -name flag
使用"find"命令查找整个文件系统中名为"flag"的文件

linking flag 链接文件

如果您使用 Linux(或计算机)进行任何合理的时间来执行任何实际工作,您最终可能会遇到以下情况:您希望两个程序访问相同的数据,但程序希望该数据位于两个不同的位置。 幸运的是,Linux 为这个困境提供了一个解决方案:链接

链接有两种类型:链接和(也称为符号)链接。 我们将通过一个比喻来区分两者:

链接是指您使用多个地址来称呼您的公寓,这些地址都直接指向同一个地方(例如,岭南1栋南雅1栋是同一栋楼)。

链接是指您移动公寓并修改快递地址,快递公司自动将您的快递从旧地方转发到新地方。

在文件系统中,从概念上讲,文件是该文件内容所在的地址。 硬链接是一个备用地址,它索引该数据---对硬链接的访问和对原始文件的访问是完全相同的,因为它们会立即产生必要的数据。 而软/符号链接则包含原始文件名。 当您访问符号链接时,Linux 将意识到它是一个符号链接,读取原始文件名,然后(通常)自动访问该文件。 在大多数情况下,这两种情况都会导致访问原始数据,但机制不同。

硬链接对大多数人来说听起来更简单(例如,我在上面的一句话中解释了它,而软链接则有两句),但它们有各种缺点和实现问题,这使得软/符号链接成为迄今为止更流行的选择。

在这个挑战中,我们将学习符号链接(也就是软链接)。 符号链接是使用带有 -s 参数的 ln 命令创建的,如下所示:

hacker@dojo:~$ cat /tmp/myfile
This is my file!
hacker@dojo:~$ ln -s /tmp/myfile /home/hacker/ourfile
hacker@dojo:~$ cat ~/ourfile
This is my file!
hacker@dojo:~$

你可以看到,访问符号链接会导致获取原始文件内容! 此外,您还可以查看 ln -s 的用法。 请注意,原始文件路径位于命令中的链接路径之前

可以通过几种方法识别符号链接。 例如,file 命令(它接受文件名并告诉你它是什么类型的文件)将识别符号链接:

hacker@dojo:~$ file /tmp/myfile
/tmp/myfile: ASCII text
hacker@dojo:~$ file ~/ourfile
/home/hacker/ourfile: symbolic link to /tmp/myfile
hacker@dojo:~$

好了,现在你试试吧! 在这个关卡中,flag一如既往地在 /flag 中,但 /challenge/catflag 程序将读取 /home/hacker/not-the-flag文件。 使用符号链接,并欺骗它给你flag!

文件A -----> 数据块X

硬链接1 ---> 数据块X
硬链接2 ---> 数据块X

软链接1 -----> 文件A

查看解析
ln -s /flag /home/hacker/not-the-flag 
/challenge/catflag
使用"ln -s"命令将"/flag"与"/home/hacker/not-the-flag"进行软链接,这样当"/challenge/catflag"程序读取"/home/hacker/not-the-flag"文件时会被链接读取到"/flag"文件

Digesting Documentation 摘要文档

Learning From Documentation 从文档中学习

我们使用文档只是想要弄清楚如何使用所有这些程序,其中一个具体的例子就是弄清楚在命令行上指定什么参数。本模块将主要深入研究这个概念,作为了解如何一般使用这些程序的代理。在本模块的其余部分中,您将了解向环境寻求程序帮助的各种方法,但首先,我们将深入了解阅读文档的概念。

程序的正确使用在很大程度上取决于对它们的参数的正确规范。回想一下基本命令模块的隐藏文件查询中指令 ls -a-a

-a 是一个参数,它告诉 ls 列出隐藏文件和非隐藏文件。因为我们想要列出隐藏的文件,所以在我们的场景中使用 ls-a 参数是正确的使用它的方法。

此挑战的程序是 /challenge/challenge,您需要正确调用它才能为您提供flag。让我们假设这是它的文档:

Welcome to the documentation for `/challenge/challenge`! To properly run this program, you will need to pass it the argument of `--giveflag`. Good luck!
欢迎使用 /challenge/challenge 的文档!要正确运行此程序,您需要向其传递 --giveflag 的参数。祝你好运!

有了这些知识,就去获取这题的flag吧!

查看解析
/challenge/challenge --giveflag
我们通过题目给出的提示文档得知我们需要给"challenge"程序传入"--giveflag"的参数

Learning Complex Usage 学习复杂用法

虽然使用大多数命令很简单,但某些命令的使用可能会变得相当复杂。例如,像 sedawk 这样的命令的参数(我们现在先不讨论这些)是用深奥的编程语言编写的整个程序!在 cdawk 之间的某些地方是将参数转换为其参数的命令......

这听起来很疯狂,但您已经在 基本命令 中的 find 关卡遇到过这种情况。find 有一个 -name 参数,而 -name 参数本身需要一个参数,指定要搜索的名称。许多其他命令都是类似的。

以下是 /challenge/challenge 的本层级文档:

Welcome to the documentation for /challenge/challenge! This program allows you to print arbitrary files to the terminal, when given the --printfile argument. The argument to the --printfile argument is the path of the flag to read. For example, /challenge/challenge --printfile /challenge/DESCRIPTION.md will print out the description of the level!

欢迎使用 /challenge/challenge 的文档!当给定 --printfile 参数时,该程序允许您将任意文件打印到终端。--printfile 参数的参数是要读取的flag的路径。例如, /challenge/challenge --printfile /challenge/DESCRIPTION.md 将打印出关卡的描述!

有了这个文档,就去获取flag吧!

查看解析
/challenge/challenge --printfile /flag
按照文档指示使用"challenge"程序读取"/flag"

Reading Manuals 阅读手册

此关卡介绍了 man 命令。manmanual 的缩写,它将显示(如果可用的话)您作为参数传递的命令的手册。例如,假设我们想了解 yes 命令(是的yes是一个真正的命令,不信你试试):

hacker@dojo:~$ man yes

这将显示 yes 的手册页,如下所示:

YES(1)                           User Commands                          YES(1)NAMEyes - output a string repeatedly until killedSYNOPSISyes [STRING]...yes OPTIONDESCRIPTIONRepeatedly output a line with all specified STRING(s), or 'y'.--help display this help and exit--versionoutput version information and exitAUTHORWritten by David MacKenzie.REPORTING BUGSGNU coreutils online help: <https://www.gnu.org/software/coreutils/>Report any translation bugs to <https://translationproject.org/team/>COPYRIGHTCopyright  ©  2020  Free Software Foundation, Inc.  License GPLv3+: GNUGPL version 3 or later <https://gnu.org/licenses/gpl.html>.This is free software: you are free  to  change  and  redistribute  it.There is NO WARRANTY, to the extent permitted by law.SEE ALSOFull documentation <https://www.gnu.org/software/coreutils/yes>or available locally via: info '(coreutils) yes invocation'GNU coreutils 8.32               February 2022                          YES(1)

重要的部分包括:

NAME(1)                           CATEGORY                          NAME(1)NAMEThis gives the name (and short description) of the command orconcept discussed by the page.SYNOPSISThis gives a short usage synopsis. These synopses have a standardformat. Typically, each line is a different valid invocation of thecommand, and the lines can be read as:COMMAND [OPTIONAL_ARGUMENT] SINGLE_MANDATORY_ARGUMENTCOMMAND [OPTIONAL_ARGUMENT] MULTIPLE_ARGUMENTS...DESCRIPTIONDetails of the command or concept, with detailed descriptionsof the various options.SEE ALSOOther man pages or online resources that might be useful.COLLECTION                        DATE                          NAME(1)

您可以使用箭头键和 PgUp/PgDn 在手册页中滚动。阅读完手册页后,可以按 q 退出。

手册页存储在集中式数据库中。如果您好奇,这个数据库位于 /usr/share/man 目录中,但您永远不需要直接与它交互:您只需使用 man 命令查询它。man 命令的参数不是文件路径,而只是条目本身的名称(例如,您运行 man yes 来查找 yes 手册页,而不是 man /usr/bin/yes,这将是 yes 程序的实际路径,但会导致 man 显示垃圾)。

此关卡的挑战有一个秘密选项,当您使用它时,将导致挑战打印flag。您必须通过 challenge 的手册页来了解此选项

查看解析
man /challenge/challenge
我们通过"man"命令查看challenge"程序的使用手册

Searching Manuals 搜索手册

您可以使用箭头键(和 PgUp/PgDn)滚动手册页,并使用 / 进行搜索。搜索后,您可以按 n 转到下一个结果,按 N 转到上一个结果。你可以使用 ?来向后搜索!

通过阅读 challenge 的使用手册找到为您提供flag的选项

查看解析
man /challenge/challenge
我们通过"man"命令查看"challenge"程序的使用手册

Searching For Manuals 搜索“搜索”的使用手册

这个关卡很棘手:它通过随机化其名称来隐藏挑战的手册页。幸运的是,所有的手册页都收集在一个可搜索的数据库中,因此您将能够搜索手册页数据库以找到隐藏的挑战手册页!要了解如何搜索正确的手册页,请通过执行以下操作阅读手册页:man man

提示 1:man man 教你 man 命令本身的高级用法,你必须利用这些知识来弄清楚如何搜索隐藏的 manpage,它会告诉你如何使用 /challenge/challenge

提示 2:虽然手册页是随机命名的,但您实际上仍然使用 /challenge/challenge 来获取flag!

查看解析
man -K /challenge/challenge
我们通过"man -K"命令搜索手册页中包含“/challenge/challenge”这个字符串的所有条目(因为权限问题难以直接读取"challenge"程序的使用手册)

Helpful Programs 有帮助的程序

有些程序没有手册页,但如果使用特殊参数调用,可能会告诉您如何运行它们。通常,此参数是 --help,但通常可以是 -h,或者在极少数情况下是 -?help 或其他深奥的值,如 /?(尽管后者在 Windows 上更常见)。

在这个关卡中,你将练习使用 --help 阅读程序的文档。试试看!

查看解析
/challenge/challenge --help

Help for Builtins 内置软件的帮助功能

某些命令(不是带有手册页和帮助选项的程序)内置在 shell 本身中。这些称为 builtin。内置函数的调用方式与命令类似,但 shell 在内部处理它们,而不是启动其他程序。你可以通过运行内置帮助来获取 shell 内置函数的列表,如下所示:

hacker@dojo:~$ help

您可以通过将特定帮助传递给内置 help 来获得该帮助。让我们看看我们之前已经使用过的 builtin,cd

hacker@dojo:~$ help cd
cd: cd [-L|[-P [-e]] [-@]] [dir]Change the shell working directory.Change the current directory to DIR.  The default DIR is the value of theHOME shell variable.
...

这有一些好信息!在这个挑战中,我们将练习使用 help 来查找内置函数的帮助。此挑战的 challenge 命令是内置的 shell,而不是程序。和以前一样,你需要查找它的帮助以找出要传递给它的 secret 值!

查看解析
help challenge

File Globbing 文件通配

Matching with * 与*匹配

我们将学习的第一个通配符是 *。当它在任何参数中遇到 * 字符时,shell 会将其视为 “通配符” 并尝试用任何与模式匹配的文件替换该参数。展示一个示例比解释更容易:

hacker@dojo:~$ touch file_a
hacker@dojo:~$ touch file_b
hacker@dojo:~$ touch file_c
hacker@dojo:~$ ls
file_a	file_b	file_c
hacker@dojo:~$ echo Look: file_*
Look: file_a file_b file_c

当然,尽管在这种情况下,glob 导致了多个参数,但它也可以简单地只匹配一个。例如:

hacker@dojo:~$ touch file_a
hacker@dojo:~$ ls
file_a
hacker@dojo:~$ echo Look: file_*
Look: file_a

当匹配到零个文件时,默认情况下,shell 会保持 glob 不变:

hacker@dojo:~$ touch file_a
hacker@dojo:~$ ls
file_a
hacker@dojo:~$ echo Look: nope_*
Look: nope_*

* 匹配文件名中除 / 或前导 . 字符之外的任何部分(也就是说不能像这样匹配:*flag->/flag*flag->.flag)。例如:

hacker@dojo:~$ echo ONE: /ho*/*ck*
ONE: /home/hacker
hacker@dojo:~$ echo TWO: /*/hacker
TWO: /home/hacker
hacker@dojo:~$ echo THREE: ../*
THREE: ../hacker

现在,自己练习吧!从你的主目录开始,将你的目录改为 /challenge,请使用通配符将你传递给 cd 的参数在四个字符以内!达成条件后,运行 /challenge/run 以获取flag!

查看解析
cd /ch*
./run
我们使用通配符"*"将"/ch*"匹配为"/challenge"(以"ch"开头的文件是独一无二的"challenge",不能是其他的)

Matching with ? 与?匹配

接下来,让我们了解 ?。当它在任何参数中遇到 ?字符时,shell 会将其视为单字符通配符。这与 * 类似,但只匹配一个字符。例如:

hacker@dojo:~$ touch file_a
hacker@dojo:~$ touch file_b
hacker@dojo:~$ touch file_cc
hacker@dojo:~$ ls
file_a	file_b	file_cc
hacker@dojo:~$ echo Look: file_?
Look: file_a file_b
hacker@dojo:~$ echo Look: file_??
Look: file_cc

现在,自己练习吧!从您的主目录开始,将您的目录更改为 /challenge,但在 cd 的参数中使用 ?字符来替代 cl!达成条件后,运行 /challenge/run 以获取flag!

查看解析
cd /?ha??enge
./run
我们使用通配符"?"将"/?ha??enge"匹配为"/challenge"

Matching with [] 与[]匹配

接下来,我们将介绍 []。方括号实质上是 ?的有限形式,因为 [] 不是匹配任何字符,而是在方括号内指定的某些潜在字符子集的通配符。例如,[pwn] 将匹配字符 pwn。例如:

hacker@dojo:~$ touch file_a
hacker@dojo:~$ touch file_b
hacker@dojo:~$ touch file_c
hacker@dojo:~$ ls
file_a	file_b	file_c
hacker@dojo:~$ echo Look: file_[ab]
Look: file_a file_b

在这里试试吧!我们在 /challenge/files 中放置了一堆文件。将工作目录更改为 /challenge/files,并使用一个参数运行 /challenge/run,使用[]file_bfile_afile_sfile_h 作为参数输入!

查看解析
cd /challenge/files
../run file_[bash]
我们使用通配符"[]"将"file_[bash]"匹配为`file_b`、`file_a`、`file_s`、`file_h`四个文件

Matching paths with [] 使用[]匹配路径

通配是基于路径发生的,因此你可以使用通配参数扩展整个路径。例如:

hacker@dojo:~$ touch file_a
hacker@dojo:~$ touch file_b
hacker@dojo:~$ touch file_c
hacker@dojo:~$ ls
file_a	file_b	file_c
hacker@dojo:~$ echo Look: /home/hacker/file_[ab]
Look: /home/hacker/file_a /home/hacker/file_b

现在轮到你了。我们再次在 /challenge/files 中放置了一堆文件。从您的主目录开始,使用单个参数运行 /challenge/run,该参数将 file_bfile_afile_sfile_h 文件的绝对路径括起来!

查看解析
/challenge/run /challenge/files/file_[bash]
我们使用通配符"[]"将"file_[bash]"匹配为`file_b`、`file_a`、`file_s`、`file_h`四个文件

Mixing globs 混合globs

现在,让我们把前面的关卡放在一起吧!我们在 /challenge/files 中放置了一些 Happy 但名称不同的文件。去 cd 那里,使用你学到的 globing,编写一个简短的(6 个字符或更少)的 glob,它将匹配 “challing”、“academical” 和 “pwning” 文件!

查看解析
cd /challenge/files
../run  [cap]*
我们使用通配符"[]"和"*"将"[cap]*"匹配为`challing`、`academical`、`pwning`四个文件

Exclusionary globbing 排他性通配

有时,您想过滤掉 glob 中的文件!幸运的是,[] 可以帮助你做到这一点。如果括号中的第一个字符是 或着^^用于较新版本的 bash 中),则 glob 将反转,并且该括号实例匹配列出的字符。例如:

hacker@dojo:~$ touch file_a
hacker@dojo:~$ touch file_b
hacker@dojo:~$ touch file_c
hacker@dojo:~$ ls
file_a	file_b	file_c
hacker@dojo:~$ echo Look: file_[!ab]
Look: file_c
hacker@dojo:~$ echo Look: file_[^ab]
Look: file_c
hacker@dojo:~$ echo Look: file_[ab]
Look: file_a file_b

有了这些知识,就转到 /challenge/files 并对所有不以 pwn 开头的文件运行 /challenge/run

注意:字符不是 [] glob 的第一个字符时,它在 bash 中具有不同的特殊含义,因此如果事情不再有意义,请记住这一点!^ 没有这个问题,但也不兼容旧的 shell

查看解析
cd /challenge/files
../run  [!pwn]*
我们使用通配符"[!]"和"*"将"[!pwn]*"匹配为开头不为`p`、`w`、`n`的文件

Practicing Piping 练习管道

Redirecting output 重定向输出

首先,让我们看看将 stdout 重定向到文件。您可以使用 > 字符完成此操作,如下所示:

hacker@dojo:~$ echo hi > asdf

这会将 echo hi 的输出(即 hi)重定向到文件 asdf。然后,你可以使用 cat 等程序输出此文件:

hacker@dojo:~$ cat asdf
hi

在此挑战中,您必须使用此输入重定向将单词 PWN(全部大写)写入文件名 COLLEGE(全部大写)

查看解析
echo PWN > COLLEGE
我们使用"echo"将"PWN"作为输出流,并使用">"将输出流写入"COLLEGE"文件中

stdout 是标准输出流(Standard Output)的缩写,我们将它视为终端的输出回显即可

Redirecting more output 重定向更多输出

除了重定向 echo 的输出之外,您当然还可以重定向任何命令的输出(比如printcat)。在这个关卡中,/challenge/run 将再次给你一个flag,但前提是你将其输出重定向到文件 myflag中。当然,您的flag最终会重定向出现在 myflag 文件中!

你会注意到尽管你重定向了 stdout ,/challenge/run 仍然会有输出打印到你的终端。那是因为它通过标准错误(stderr)来传达其指令和反馈,并且只在stdout上打印flag!

stderr 是标准错误流(Standard Error)的缩写,用于输出错误消息或诊断信息。

查看解析
/challenge/run > myflag
cat myflag
我们使用">"将"/challenge/run"输出流写入"COLLEGE"文件中

image-20241020163401388

Appending output 附加输出

输出重定向的一个常见用例是保存一些命令结果以供以后分析。通常,您希望汇总执行此操作:运行一堆命令,保存其输出,并在以后 grep 完成它。在这种情况下,您可能希望所有输出都继续附加到同一个文件,但 > 每次都会创建一个新的输出文件,并删除旧内容。

您可以使用 >> 而不是 >附加模式下重定向输入,如下所示:

hacker@dojo:~$ echo pwn > outfile
hacker@dojo:~$ echo college >> outfile
hacker@dojo:~$ cat outfile
pwn
college
hacker@dojo:$

练习一下,运行challenge/run时,将输出以附加模式重定向到文件/home/hacker/the-flag。这种做法将把flag的前半部分写入文件,如果将标准输出重定向到文件,则将后半部分写入标准输出。如果您以追加模式正确地重定向,则后半部分将追加到第一部分,但如果您以截断模式(>)重定向,则后半部分将覆盖第一部分,并且您将无法获得flag!(此时请重启靶机

现在开始吧!

查看解析
/challenge/run >> the-flag
cat the-flag
我们使用">>"将"/challenge/run"输出流附加写入"the-flag"文件中

Redirecting errors 重定向错误

就像标准输出一样,您也可以重定向命令的错误通道。在这里,我们将学习文件描述符编号。文件描述符(FD)是Linux中描述通信通道的数字。你已经在使用它们了,尽管你没有意识到。我们已经熟悉了三个:

  • FD 0: Standard Input 标准输入
  • FD 1: Standard Output 标准输出
  • FD 2: Standard Error 标准误差

当您重定向进程通信时,您可以通过 FD 编号来执行此操作,尽管某些 FD 编号是隐式的。例如,没有数字的 > 表示 1>,这会重定向 FD 1(标准输出)。因此,以下两个命令是等效的:

hacker@dojo:~$ echo hi > asdf
hacker@dojo:~$ echo hi 1> asdf

从这一点开始,重定向错误非常容易。如果你有一个命令可能通过标准错误(比如 /challenge/run)生成数据,你可以这样做:

hacker@dojo:~$ /challenge/run 2> errors.log

这会将标准错误 (FD 2) 重定向到 errors.log 文件。此外,您可以同时重定向多个文件描述符!例如:

hacker@dojo:~$ some_command > output.log 2> errors.log

该命令会将输出重定向到 output.log 并将错误重定向到 errors.log

让我们把它付诸实践吧!在这个挑战中,你需要像之前的关卡一样,首先将 /challenge/run 的输出重定向到 myflag

然后将 “errors”(即标准错误输出)重定向到 instructions。您会注意到不会将任何内容打印到终端,因为您已经重定向了所有内容!当您成功完成此操作时,您可以在instructions中找到说明/反馈,并在 myflag 中找到flag!

查看解析
/challenge/run > myflag 2> instructions
cat instructions
cat myflag
我们使用"2>"将标准错误输出流写入"instructions"文件中

Redirecting input 重定向输入

就像您可以重定向程序的输出一样,您也可以将输入重定向到程序!这是使用 < 完成的,如下所示:

hacker@dojo:~$ echo yo > message
hacker@dojo:~$ cat message
yo
hacker@dojo:~$ rev < message
oy

您可以使用输入重定向在许多不同的程序中做有趣的事情!在这个关卡中,我们将练习使用 /challenge/run,这将需要您将 PWN 文件重定向到它,并让 PWN 文件包含值 COLLEGE!要将该值写入 PWN 文件,请回想一下之前对 echo 的输出重定向的挑战!

查看解析
echo PWN > COLLEGE
/challenge/run < PWN
我们使用"<"将文件"PWN"作为输入流

Grepping stored results 对存储结果进行grep

您知道如何运行命令,如何重定向其输出(例如 >),以及如何搜索结果文件(例如 grep)。让我们把这个放在一起吧!

在这个更复杂的关卡时,我们希望您:

  1. /challenge/run 的输出重定向到 /tmp/data.txt
  2. 这将产生 10 万行文本,其中之一是 /tmp/data.txt 中的flag。
  3. 使用grep得到flag!
查看解析
/challenge/run > /tmp/data.txt
grep pwn.college /tmp/data.txt

Grepping live output grep实时输出

事实证明,您可以 “省去中间人”,避免将结果存储到文件中的需要,就像您在上一关中所做的那样。您可以使用 |(管道符)运算符来使用它。管道左侧命令的标准输出将连接到管道右侧的命令的标准输入端(通过管道连接到该管道)。例如:

hacker@dojo:~$ echo no-no | grep yes
hacker@dojo:~$ echo yes-yes | grep yes
yes-yes
hacker@dojo:~$ echo yes-yes | grep no
hacker@dojo:~$ echo no-no | grep no
no-no

现在自己试试吧!/challenge/run 将输出 10 万行文本,包括flag。用 Grep 找出flag!

查看解析
/challenge/run | grep pwn.college

image-20241020183031498

Grepping errors grep错误

您知道如何将错误输出重定向到文件,并且知道如何通过管道将输出传输到另一个程序。但是,如果您想直接 grep 错误输出怎么办?

> 运算符将给定的文件描述符重定向到文件,并且您使用了 2> 重定向 fd 2,这是标准错误。管道符 | 仅将标准输出重定向到另一个程序,并且不存在管道符的 2|形式!它只能重定向标准输出(FD 1)。

shell 有一个 >& 运算符,它将一个文件描述符重定向到另一个文件描述符。这意味着我们可以有一个两步过程来grep修复错误:首先,我们将标准错误重定向到标准输出(2>&1),然后将现在组合的stderr和stdout作为正常管道(|)!

现在就试试吧!与上一关一样,此关卡将用输出为难您,但这次是标准错误输出。解决它并找到flag!

查看解析
/challenge/run 2>&1 | grep pwn.college

image-20241020184751573

Duplicating piped data with tee 使用tee复制管道数据

当您将数据从一个命令传递到另一个命令时,您当然不会再在屏幕上看到它。这并不总是需要的:例如,您可能希望查看数据在命令之间流动时的数据,以调试意外结果(例如,“为什么第二个命令不起作用???”)。

幸运的是,有一个解决方案!tee 命令以管道中的“T 型分离器”命名,它将流经管道的数据复制到命令行上提供的任意数量的文件中。例如:

hacker@dojo:~$ echo hi | tee pwn college
hi
hacker@dojo:~$ cat pwn
hi
hacker@dojo:~$ cat college
hi
hacker@dojo:~$

如您所见,通过向 tee 提供两个文件,我们最终得到了三个管道传入数据的副本:一个到 stdout,一个到 pwn 文件,一个到 college 文件。您可以想象如何使用它来调试事情变得混乱:

hacker@dojo:~$ command_1 | command_2
Command 2 failed!
hacker@dojo:~$ command_1 | tee cmd1_output | command_2
Command 2 failed!
hacker@dojo:~$ cat cmd1_output
Command 1 failed: must pass --succeed!
hacker@dojo:~$ command_1 --succeed | command_2
Commands succeeded!

image-20241020190021882

现在,你试试吧!在这关中 /challenge/pwn 必须通过管道传输到 /challenge/college,但你需要拦截数据才能看到 pwn 需要你做什么!

查看解析
/challenge/pwn | tee output | /challenge/college
cat output
通过使用"tee"将"pwn"程序的输出流复制到"output"

Writing to multiple programs 写入多个程序

好的,现在我们明白了我们可以用 tee 将数据复制到两个文件:

hacker@dojo:~$ echo HACK | tee THE > PLANET
hacker@dojo:~$ cat THE
HACK
hacker@dojo:~$ cat PLANET
HACK
hacker@dojo:~$

您已经使用 tee 将数据复制到文件和命令中:

hacker@dojo:~$ echo HACK | tee THE | cat
HACK
hacker@dojo:~$ cat THE
HACK
hacker@dojo:~$

但是复制到两个命令呢? 正如 tee 在其手册页中所说,它被设计为写入文件和标准输出:

TEE(1)                           User Commands                          TEE(1)NAMEtee - read from standard input and write to standard output and files

Luckily, Linux follows the philosophy that "everything is a file". This is, the system strives to provide file-like access to most resources, including the input and output of running programs! The shell follows this philosophy, allowing you to, for example, use any utility that takes file arguments on the command line (such as tee) and hook it up to the input or output side of a program!
幸运的是,Linux 遵循“一切都是文件”的理念。 也就是说,系统努力提供对大多数资源的类似文件的访问,包括正在运行的程序的输入和输出! shell 遵循这一理念,例如,允许您使用任何在命令行上获取文件参数的实用程序(例如 tee)并将其挂接到程序的输入端或输出端!

这是使用所谓的 进程替换 完成的。 如果你写一个 >(rev) 的参数,bash 将运行 rev 命令(rev这个命令从标准输入中读取数据,逆序,并将其写入标准输出!),但将其输入挂接到它将创建的临时文件。 当然,这不是一个真正的文件,它是所谓的命名管道,因为它有一个文件名:

hacker@dojo:~$ echo >(rev)
/dev/fd/63
hacker@dojo:~$

/dev/fd/63 从何而来? bash>(rev) 替换为与 rev 的输入挂钩的命名管道文件的路径! 当命令正在运行时,写入此文件会将数据通过管道传输到命令的标准输入。 通常,这是使用将输出文件作为参数的命令(如 tee)完成的:

hacker@dojo:~$ echo HACK | rev
KCAH
hacker@dojo:~$ echo HACK | tee >(rev)
HACK
KCAH

在上面,发生了以下事件序列:

  1. bash 启动了 rev 命令,将命名管道(可能是 /dev/fd/63,我们可以使用命令echo >(rev)看看命名管道)挂接到 rev 的标准输入
  2. bash 启动了 tee 命令,将管道挂接到其标准输入,并将 tee 的第一个参数替换为 /dev/fd/63tee 甚至从未看到过参数 >(rev);Shell 在推出 tee之前替换了
  3. bash 使用 echo 内置函数将 HACK 打印到 tee 的标准输入中
  4. tee 读取 HACK,将其写入标准输出,然后将其写入 /dev/fd/63(连接到 rev 的 stdin管道)
  5. rev 从其标准输入中读取 HACK,将其反转,并将 KCAH 写入标准输出

image-20241020195346858

个人理解是将输出流写入文件是直接使用>,而使用>()是将输出流导到下一个程序输入流的管道中

stdin 是标准输入流(Standard Input)的缩写,通常用于程序接收输入数据。

现在轮到你了! 在这个挑战中,我们有 /challenge/hack/challenge/the/challenge/planet。 运行 /challenge/hack 命令,并将其输出复制为 /challenge/the/challenge/planet 命令的输入!


补充!

细心的学习者会意识到以下内容是等效的:

hacker@dojo:~$ echo hi | rev
ih
hacker@dojo:~$ echo hi > >(rev)
ih
hacker@dojo:~$

管道数据的方法不止一种! 当然,第二条路线更难阅读,也更难扩展。 例如:

hacker@dojo:~$ echo hi | rev | rev
hi
hacker@dojo:~$ echo hi > >(rev | rev)
hi
hacker@dojo:~$

那太愚蠢了!这里的教训是,虽然过程替代是工具箱中一个强大的工具,但它是一个非常专业的工具;不要什么都用它!

查看解析
/challenge/hack | tee >(/challenge/the) >(/challenge/planet)
通过使用"tee"将"pwn"程序的输出流复制到"output"

Split-piping stderr and stdout 拆分管道stderr和stdout

现在,让我们把你的知识放在一起。您必须掌握最终的管道任务:将 stdout 重定向到一个程序,将 stderr 重定向到另一个程序。

当然,这里的挑战在于 | 运算符将左侧命令的 stdout 与右侧命令的 stdin 链接起来。当然,您已经使用 2>&1 将 stderr 重定向到 stdout,因此,管道 stderr 重叠,但这会混合 stderr 和 stdout。如何保持不混合?

您需要结合您对 >(),2>,|的知识和理解,完成我给你留下的任务。

在本次挑战中,给出以下提示:

  • /challenge/hack:该程序会在 stdoutstderr 上生成数据
  • /challenge/the: 您必须将 Hackstderr 重定向到此程序
  • /challenge/planet: 您必须将 Hackstdout 重定向到此程序

Go get the flag! 去拿flag吧!

查看解析
/challenge/hack > >(/challenge/planet) 2> >(/challenge/the)
这里试着解释一下为什么
/challenge/hack >(/challenge/planet) 2>(/challenge/the)
不行
使用 `>(command)` 时,它会创建一个可用于重定向的文件描述符,而不是用作参数
`>`用于提取出输出流,`>()`用于指定程序输入流的管道

image-20241020204553520

Shell Variables Shell 变量

Printing Variables 打印变量

让我们从打印变量开始。这次/challenge/run 程序不会也不能给你flag,但这没关系,因为这个flag已经被放到名为 “FLAG” 的变量中了!就让你的shell打印出来吧!

您可以使用多种方法完成此操作,但我们将从 echo 开始。此命令仅打印内容。例如:

hacker@dojo:~$ echo Hello Hackers!
Hello Hackers!

你也可以通过在变量名称前加上 $ 来打印出带有 echo 的变量。例如,有一个变量 PWD,它始终保存当前 shell 的当前工作目录。您可以按如下方式打印出来:

hacker@dojo:~$ echo $PWD
/home/hacker

现在轮到你了。让您的 shell 打印出 FLAG 变量并解决此挑战!

查看解析
echo $FLAG
我们通过"$"符来指定变量

Setting Variables 设置变量

当然,除了读取存储在变量中的值外,您还可以将值写入变量。与许多其他语言一样,这是使用 = 完成的。要将变量 VAR 设置为值 1337,您可以使用:

hacker@dojo:~$ VAR=1337

请注意=的使用!如果你加上空格(例如,VAR = 1337),shell 将无法识别变量赋值,而是尝试运行 VAR 命令(不存在)

还要注意,这使用 VAR 而不是 $VAR$ 仅用于访问变量。在 shell 术语中,这个 $ 的前缀会触发所谓的变量扩展,并且令人惊讶地,它是许多潜在漏洞的来源(如果您对此感兴趣,请在熟悉命令行后查看 Art of the Shell 道场(pwn.college)!

设置变量后,您可以使用之前学到的技术访问它们,例如:

hacker@dojo:~$ echo $VAR
1337

要解决此关卡问题,必须将 PWN 变量设置为值 COLLEGE。注意:变量的名称和值都区分大小写!PWNpwn 不同,COLLEGECollege 不同

查看解析
PWN=COLLEGE
我们通过"="符来设置变量

Multi-word Variables 多字变量

在这个关卡,您将学习报价。空格在 shell 中具有特殊意义,有些地方你不能随意使用它们。回想一下我们的变量设置:

hacker@dojo:~$ VAR=1337

这会将 VAR 变量设置为 1337,但如果要将其设置为 1337 SAUCE,该怎么办?您可以尝试以下操作:

hacker@dojo:~$ VAR=1337 SAUCE

这看起来很合理,但它不起作用,原因与需要在 = 周围没有空格的原因类似。当 shell 看到空格时,它会结束变量赋值并将下一个单词(在本例中为 SAUCE)解释为命令。要将 VAR 设置为 1337 SAUCE,您需要引用它:

hacker@dojo:~$ VAR="1337 SAUCE"

在这里,shell 将 1337 SAUCE 读取为单个标记,并愉快地将该值设置为 VAR。在此关卡中,您需要将变量 PWN 设置为 COLLEGE YEAH。祝你好运!

查看解析
PWN="COLLEGE YEAH"

Exporting Variables 导出变量

默认情况下,您在 shell 会话中设置的变量是该 shell 进程的本地变量。也就是说,您运行的其他命令不会继承它们。您可以通过简单地在自己的 shell 中调用另一个 shell 进程来对此进行试验,如下所示:

hacker@dojo:~$ VAR=1337
hacker@dojo:~$ echo "VAR is: $VAR"
VAR is: 1337
hacker@dojo:~$ sh
$ echo "VAR is: $VAR"
VAR is: 

在上面的输出中,$ 提示符是 sh 的提示符,sh 是作为主 shell 进程的进程调用的最小 shell 实现。而且它不会接收 VAR 变量!

这当然是有道理的。你的 shell 变量可能包含敏感或奇怪的数据,除非它明确应该泄露给你运行的其他程序,否则你不会希望它泄露给你运行的其他程序的。你应该怎么标记它呢?您导出变量。导出变量时,它们将传递到子进程的环境变量中。您将在其他挑战中遇到环境变量的概念,但您将在此处观察它们的效果。下面是一个示例:

hacker@dojo:~$ VAR=1337
hacker@dojo:~$ export VAR
hacker@dojo:~$ sh
$ echo "VAR is: $VAR"
VAR is: 1337

在这里,子 shell 收到了 VAR 的值,并能够将其打印出来!您还可以合并前两行。

hacker@dojo:~$ export VAR=1337
hacker@dojo:~$ sh
$ echo "VAR is: $VAR"
VAR is: 1337

在此挑战中,您调用 /challenge/run前,要将 PWN 变量导出并设置为值 COLLEGE,并将 COLLEGE 变量设置为值 PWN 但不导出(不被 /challenge/run 继承)。祝你好运!

查看解析
PWN=COLLEGE
COLLEGE=PWN
export PWN
/challenge/run
我们使用"export"命令导出变量

Printing Exported Variables 打印导出的变量

有多种方法可以访问 bash 中的变量。Echo 只是其中之一,我们现在将在这次挑战中至少再学习一个。

试试 env 命令:它会打印出 shell 中设置的每个导出变量,你可以查看该输出以找到 FLAG 变量!

查看解析
env | grep FLAG
我们使用"env"命令查看变量

Storing Command Outpt 存储命令输出

在使用 shell 的过程中,您经常希望将某些命令的输出存储到变量中。幸运的是,shell 使用称为 Command Substitution 的东西使这变得非常容易!观察:

hacker@dojo:~$ FLAG=$(cat /flag)
hacker@dojo:~$ echo "$FLAG"
pwn.college{blahblahblah}
hacker@dojo:~$

现在是你的练习时刻。将 /challenge/run 命令的输出直接读取到名为 PWN 的变量中,它将包含flag!


补充:你也可以用反引号代替 $()在上面的例子中,

FLAG=`cat /flag` 

而不是 FLAG=$(cat /flag)。这是一种较旧的格式,并且有一些缺点(例如,假设您想要嵌套命令替换)。你会怎么用? $(cat $(find / -name flag))吗?pwn.college 的官方立场是你应该使用 $(blah) 而不是

`blah`
查看解析
PWN=$(/challenge/run)
cat $PWN

Reading Input 读取输入

我们将从读取用户 (你) 的输入开始。这是使用恰如其分地命名为 read builtin 完成的,它读取 input!

下面是一个使用 -p 参数的示例,它允许您指定一个提示符(否则,现在阅读本文时,您将很难在下面的示例中将输入与输出分开):

hacker@dojo:~$ read -p "INPUT: " MY_VARIABLE
INPUT: Hello!
hacker@dojo:~$ echo "You entered: $MY_VARIABLE"
You entered: Hello!

请记住,read会从您的标准输入中读取数据!上面的第一个 Hello!input 而不是 output。让我们试着更明确地说明这一点。在这里,我们对每行的开头进行了注释,该行是表示用户的 INPUT 还是用户的 OUTPUT

 INPUT: hacker@dojo:~$ echo $MY_VARIABLE
OUTPUT:INPUT: hacker@dojo:~$ read MY_VARIABLEINPUT: Hello!INPUT: hacker@dojo:~$ echo "You entered: $MY_VARIABLE"
OUTPUT: You entered: Hello!

在这个挑战中,你的工作是使用 readPWN 变量设置为值 COLLEGE。祝你好运!

查看解析
read PWN
COLLEGE
我们使用"read"指令来输入设置变量

Reading Files 读入文件

通常,当 shell 用户想要将文件读入环境变量时,他们会执行以下操作:

hacker@dojo:~$ echo "test" > some_file
hacker@dojo:~$ VAR=$(cat some_file)
hacker@dojo:~$ echo $VAR
test

这很有效,但它代表了牢骚满腹的黑客所说的cat命令的无效使用。也就是说,运行一个完全不同的程序来读取文件是一种浪费。事实证明,你可以直接使用 shell 的力量!

之前,您将用户输入read到一个变量中(将用户输入读入一个变量)。您之前还将文件重定向到命令输入!将它们放在一起,您就可以使用 shell 读取文件。

hacker@dojo:~$ echo "test" > some_file
hacker@dojo:~$ read VAR < some_file
hacker@dojo:~$ echo $VAR
test

上面发生了什么?该示例将 some_file重定向到 read 的标准输入,因此当 read 读入 VAR 时,它会从文件中读取!

现在,使用上述方法将 /challenge/read_me 读取到 PWN 环境变量中,我们将为您提供flag!/challenge/read_me 会不断变化,因此您需要使用一个命令将其直接读取到 PWN 变量中!

查看解析
read PWN < /challenge/read_me

Processes and Jobs 进程和作业

Listing Prcocess 列出进程

首先,我们将学习使用 ps 命令列出正在运行的进程。ps 代表 “进程快照” 或 “进程状态”,它列出了进程。默认情况下,ps 只列出在你的终端中运行的进程,老实说,这并不是很有用:

hacker@dojo:~$ psPID TTY          TIME CMD329 pts/0    00:00:00 bash349 pts/0    00:00:00 ps
hacker@dojo:~$

在上面的示例中,我们列出正在终端中运行的进程有 shell (bash) 和 ps 进程本身,这就是全部内容。我们还看到每个进程都有一个数字标识符(进程 ID 或 PID),这是一个唯一标识 Linux 环境中每个正在运行的进程的数字。我们还可以看到运行命令的终端(在本例中为名称 pts/0),以及到目前为止该进程已经消耗的 cpu 时间总量(因为这些进程的CPU消耗需求非常低,它们甚至还没有消耗 1 秒!)

在大多数情况下,这就是您在默认 ps 中看到的全部内容。为了使其有用,我们需要传递一些参数。

由于 ps 是一个非常古老的实用程序,因此它的使用有点混乱。有两种方法可以指定参数。

“标准”语法:在此语法中,您可以使用 -e 列出“每个”进程,使用 -f 列出“完整格式”输出,包括参数。这些可以组合成一个参数 -ef

“BSD” 语法:在此语法中,您可以使用 a 列出所有用户的进程,使用 x 列出未在终端中运行的进程,使用 u 表示“用户可读”输出。这些可以组合成一个参数 aux

ps -efps aux 这两种方法产生的输出略有不同,但可以交叉识别。

让我们在 dojo虚拟机 中尝试一下:

hacker@dojo:~$ ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
hacker         1       0  0 05:34 ?        00:00:00 /sbin/docker-init -- /bin/sleep 6h
hacker         7       1  0 05:34 ?        00:00:00 /bin/sleep 6h
hacker       102       1  1 05:34 ?        00:00:00 /usr/lib/code-server/lib/node /usr/lib/code-server --auth=none -
hacker       138     102 11 05:34 ?        00:00:07 /usr/lib/code-server/lib/node /usr/lib/code-server/out/node/entr
hacker       287     138  0 05:34 ?        00:00:00 /usr/lib/code-server/lib/node /usr/lib/code-server/lib/vscode/ou
hacker       318     138  6 05:34 ?        00:00:03 /usr/lib/code-server/lib/node --dns-result-order=ipv4first /usr/
hacker       554     138  3 05:35 ?        00:00:00 /usr/lib/code-server/lib/node /usr/lib/code-server/lib/vscode/ou
hacker       571     554  0 05:35 pts/0    00:00:00 /usr/bin/bash --init-file /usr/lib/code-server/lib/vscode/out/vs
hacker       695     571  0 05:35 pts/0    00:00:00 ps -ef
hacker@dojo:~$

您可以在此处看到,有一些进程正在运行:用于初始化挑战环境 (docker-init)、自动终止挑战前的超时以保留计算资源(sleep 6h,6 小时后超时)、VSCode 环境(多个code-server帮助进程)、shell (bash) 和我的 ps -ef 命令。这与 ps aux 基本相同:

hacker@dojo:~$ ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
hacker         1  0.0  0.0   1128     4 ?        Ss   05:34   0:00 /sbin/docker-init -- /bin/sleep 6h
hacker         7  0.0  0.0   2736   580 ?        S    05:34   0:00 /bin/sleep 6h
hacker       102  0.4  0.0 723944 64660 ?        Sl   05:34   0:00 /usr/lib/code-server/lib/node /usr/lib/code-serve
hacker       138  3.3  0.0 968792 106272 ?       Sl   05:34   0:07 /usr/lib/code-server/lib/node /usr/lib/code-serve
hacker       287  0.0  0.0 717648 53136 ?        Sl   05:34   0:00 /usr/lib/code-server/lib/node /usr/lib/code-serve
hacker       318  3.3  0.0 977472 98256 ?        Sl   05:34   0:06 /usr/lib/code-server/lib/node --dns-result-order=
hacker       554  0.4  0.0 650560 55360 ?        Rl   05:35   0:00 /usr/lib/code-server/lib/node /usr/lib/code-serve
hacker       571  0.0  0.0   4600  4032 pts/0    Ss   05:35   0:00 /usr/bin/bash --init-file /usr/lib/code-server/li
hacker      1172  0.0  0.0   5892  2924 pts/0    R+   05:38   0:00 ps aux
hacker@dojo:~$

ps -efps aux 之间有许多共同点:都显示用户(USER 列)、PID、TTY、进程的开始时间 (STIME/START)、总利用的 CPU 时间 (TIME) 和命令 (CMD/COMMAND)。ps -ef 还输出父进程 IDPPID),就是与进程启动相关的进程的 PID,而 ps aux 输出进程正在使用的系统 CPU 和内存总数的百分比。另外,还有许多其他内容我们现在不会讨论。

image-20241020221511143

无论如何!让我们练习一下。在这个关卡中,我再次将 /challenge/run 重命名为随机文件名,这一次你不能ls /challenge 目录!但是我也启动了它,所以可以在正在运行的进程列表中找到它,找出文件名,然后直接为flag重新启动它!祝你好运!

注意:ps -efps aux 都将命令列表截断到终端的宽度(这就是为什么上面的示例在屏幕右侧排列得如此漂亮。如果您无法读取进程的整个路径,则可能需要放大终端(或将输出重定向到某个位置以避免这种截断行为)!

查看解析
ps -ef
使用"ps -ef"命令查看正在运行的进程,其中包含了/challenge/run的程序名< /challenge/read_me

Killing Processes kill进程

您已经启动了流程,查看了流程,现在您将学习如何终止流程!在 Linux 中,这是使用名称激进的 kill 命令完成的。使用默认选项(这就是我们将在本关卡中介绍的全部内容),kill 将终止一个进程,使其有机会在不再存在之前将其事务整理好。

假设您在另一个终端中启动了一个讨厌的 sleep 进程(sleep 是一个程序,它只是在命令行上指定的秒数内挂起,在本例中为 1337 秒),如下所示:

hacker@dojo:~$ sleep 1337

我们如何摆脱它?您可以通过将进程标识符(来自 psPID)作为参数传递来使用 kill 来终止它,如下所示:

hacker@dojo:~$ ps -e | grep sleep342 pts/0    00:00:00 sleep
hacker@dojo:~$ kill 342
hacker@dojo:~$ ps -e | grep sleep
hacker@dojo:~$

现在,是时候终止您的第一个进程了!在这个挑战中,/challenge/run 将拒绝在 /challenge/dont_run 运行时运行!您必须找到dont_run进程并终止它。如果你失败了,pwn.college 将不认为你理解了知识点。祝你好运。

查看解析
使用"ps -ef"命令查看正在运行的"dont_run"程序的PID,然后使用"kill"命令终止"dont_run"进程< /challenge/read_me

Interrupting Processes 中断进程

您已经学会了如何使用 kill 命令杀死其他进程,但有时您只想摆脱阻塞终端的进程!幸运的是,终端有一个热键:Ctrl-C(例如,按住 Ctrl 键并按 C)向正在等待终端输入的任何应用程序发送“中断”,通常,这会导致应用程序干净地退出。

在这里试试吧!/challenge/run 将拒绝给你flag,直到你中断它。祝你好运!


对于非常感兴趣的人,请查看这篇关于终端和“控制代码”(例如 Ctrl^C)的文章。

查看解析
/challenge/run
Ctrl+c

Suspending Process 暂停进程

您已经学会了使用 Ctrl-C 中断进程,但您可以使用不那么激烈的措施来恢复您的终端!您可以使用 Ctrl-Z 将进程挂起到后台。在这个关卡中,我们将探索它是如何工作的,在下一个关卡中,我们将弄清楚如何恢复那些暂停的进程!

查看解析
/challenge/run
Ctrl+z
/challenge/run

Resuming Process 恢复进程

通常,当您暂停进程时,您需要在某个时候恢复它们。否则,为什么不直接终止他们呢?为了恢复进程,您的 shell 提供了 fg 命令,这是一个内置命令,用于获取暂停的进程,恢复它,并将其放回终端的前台。

快来试试吧!此挑战的run进程需要您暂停它,然后恢复它。祝你好运!

查看解析
/challenge/run
Ctrl+z
fg

Backgrounding Processes 后台进程

您已使用 fg 命令在前台恢复了进程。您还可以使用 bg 命令在后台恢复进程!这将允许进程继续运行,同时将 shell 交还给你以调用更多命令。

此关卡的run希望看到自己的另一个副本正在运行,而不是暂停,并且使用相同的终端。如何?使用终端启动它,然后暂停它,然后使用 bg 将其置于后台,并在第一个副本在后台运行时启动另一个副本!


提高:如果您对一些更深入的细节感兴趣,请查看如何查看暂停和后台属性之间的差异!请允许我演示一下。首先,让我们暂停sleep

hacker@dojo:~$ sleep 1337
^Z
[1]+  Stopped                 sleep 1337
hacker@dojo:~$

sleep进程现在在后台暂停。我们可以通过使用 -o 选项启用 stat 列输出来通过 ps 看到这一点:

hacker@dojo:~$ ps -o user,pid,stat,cmd
USER         PID STAT CMD
hacker       702 Ss   bash
hacker       762 T    sleep 1337
hacker       782 R+   ps -o user,pid,stat,cmd
hacker@dojo:~$ 

看到那个 T 了吗?这意味着由于我们的 Ctrl-Z,进程已暂停。bashSTAT 列中的 S 表示 bash 在等待输入时处于休眠状态。ps 列中的 R 表示它正在积极运行,+ 表示它位于前台!

观察当我们在后台恢复sleep进程时会发生什么:

hacker@dojo:~$ bg
[1]+ sleep 1337 &
hacker@dojo:~$ ps -o user,pid,stat,cmd
USER         PID STAT CMD
hacker       702 Ss   bash
hacker       762 S    sleep 1337
hacker      1224 R+   ps -o user,pid,stat,cmd
hacker@dojo:~$

BOOM!sleep现在有一个 S。它在运行的时候,就是在睡觉而已,但它并没有暂停!它也在后台运行,因此没有 +

查看解析
/challenge/run
Ctrl+z
bg
/challenge/run

Foregrounding Processes 前台进程

假设您有一个后台进程,并且您希望对它进行更多操作。你是做什么工作的?好吧,您可以使用 fg 将后台进程置于前台,就像将暂停的进程置于前台一样!这个关卡将引导您完成这个任务!

查看解析
/challenge/run
Ctrl+z
bg
fg

Starting Backgrounded Processes 后台启动进程

当然,您不必暂停进程来使它们成为后台:您可以立即后台启动进程!这很容易;您只需在命令后附加一个&,就像这样:

hacker@dojo:~$ sleep 1337 &
[1] 1771
hacker@dojo:~$ ps -o user,pid,stat,cmd
USER         PID STAT CMD
hacker      1709 Ss   bash
hacker      1771 S    sleep 1337
hacker      1782 R+   ps -o user,pid,stat,cmd
hacker@dojo:~$ 

在这里,sleep 在后台主动运行,而没有暂停。现在轮到你练习了!在的后台启动 /challenge/run进程!

查看解析
/challenge/run &

Process Exit Codes 处理退出代码

每个 shell 命令,包括每个程序和每个内置命令,在完成运行并终止时都会以退出代码退出,shell 或 shell 的用户(就是您)可以使用它来检查进程是否成功实现了其功能(当然,这个决定首先取决于进程应该做什么)

您可以使用特殊的变量?来访问最近终止的命令的退出代码(不要忘记在它前面加上 $ 以读取其值!

hacker@dojo:~$ touch test-file
hacker@dojo:~$ echo $?
0
hacker@dojo:~$ touch /test-file
touch: cannot touch '/test-file': Permission denied
hacker@dojo:~$ echo $?
1
hacker@dojo:~$

如您所见,成功的命令通常返回 0,失败的命令通常返回非零值,最常见的是 1,但有时是标识特定故障模式的错误代码

在此关卡中,您必须检索 /challenge/get-code 返回的退出代码,然后使用该错误代码作为参数运行 /challenge/submit-code。祝你好运!

查看解析
/challenge/get-code
echo $?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/73985.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

记一次 edu 证书站失败的逻辑漏洞

记一次 edu 证书站失败的逻辑漏洞 闲来无事,在礼物中心看到个证书站,看名称感觉应该挺好挖的,简单信息搜集一波,在 hunter 上查看子域名,发现有个管理系统访问该链接,是个登录框现在需要去搞一手学号什么的了(因为是随便看看的所以没有先信息搜集),利用 hack 语法找了…

源计划智能工厂MES系统(开源版)

在gitee中找到了一个mes系统,这个系统有详细的部署教程,但是我还是遇到了很多问题 下面是自己将其部署到本地的经历 yjh-mes: 源计划MES,后端服务+后台前端界面 (gitee.com) 首先是node版本不对应,而且我没有下载nvm管理node 所以要将node删除后下载nvm。 首先在控制面板…

#2024-2025-1 20241419《计算机基础与程序设计》第四周学习总结

作业信息 课程 要求 目标:门电路 组合电路,逻辑电路 冯诺依曼结构 CPU,内存,IO管理 嵌入式系统,并行结构 物理安全 作业正文 教程学习内容总结: 数字电路: 门电路:实现逻辑运算的单元电路,包括与、或、非等。 组合电路:输出仅与当前输入有关的数字电路。 逻辑电路:由…

2024-2025 20241318 《计算机基础与程序设计》第四周学习总结

这个作业属于哪个课程 https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP这个作业要求在哪里 https://www.cnblogs.com/rocedu/p/9577842.html#WEEK04这个作业的目标 自学教材计算机科学概论(第七版)第4章,第5章 并完成云班课测试 《C语言程序设计》第3章并完成云班课…

虚拟文件系统和文件系统的挂载

虚拟文件系统 虚拟文件系统(VFS)屏蔽了不同文件系统的差异和操作细节,向上为用户提供了文件操作的统一调用接口,如图 4.24 所示。当用户程序访问文件时,通过 VFS 提供的统一调用函数(如open()等)来操作不同文件系统的文件,而无须考虑具体的文件系统和实际的存储介质。虚拟文…

#2024-2025-1学号20241309《计算机基础与程序设计》第四周学习总结

作业信息这个作业属于哪个课程 2024-2025-1-计算机基础与程序设计这个作业要求在哪里 2024-2025-1计算机基础与程序设计第四周作业这个作业的目标|作业正文|2024-2025-1学号20241309《计算机基础与程序设计》第四周学习总结 教材学习内容总结 《计算机科学概论》第四章 《计算机…

对于 CF,AT,CSP-S,NOIP,我想说

尽管我是 div2 一题水平,但是