理解命令


Linux 启明道场.

本模块将介绍一些实用的 Linux 命令,它们将在你接下来的学习中大有用处! 这里的内容远不是一份完整的命令清单,我们也会继续扩充本模块,但这些已经足够帮你入门了。

话不多说,开始学习命令吧!


cat 是 Linux 中最重要的命令之一。 cat 最常见的用途是输出文件内容,如下所示:

hacker@dojo:~$ cat /path/to/file
Hello Hackers!

如果传入多个参数,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 就会读取终端输入并将其输出。 我们会在后面的挑战中探索这种用法……

在这个挑战中,我会把 flag 复制到你主目录下的 flag 文件中,也就是 shell 启动时所在的目录。 用 cat 读出它吧!

上一关中,你用 cat flag 读取了主目录中的 flag! 当然,你也可以用绝对路径指定 cat 的参数:

hacker@dojo:~$ cat /path/to/file
Hello Hackers!

这个挑战中,我不会将 flag 复制到你的主目录,但会让你有权限读取它。 你可以用 cat 通过绝对路径 /flag 读取它。


小知识: 在 pwn.college 中,/flag 是 flag 始终保存的位置。但通常不像这一关这样,你无法直接访问这个文件。

你可以将各种路径作为参数传给命令,我们再用 cat 多练习一下。 这一关中,我会将 flag 放在一个很偏僻的目录里,而且不允许你用 cd 切换目录,所以不能直接使用 cat flag。 无论 flag 在哪里,你都必须通过绝对路径读取它。

有时,用 cat 输出的文件实在太大了。 好在我们可以用 grep 命令搜索需要的内容! 这个挑战将带你学习它。

grep 有很多种用法,这里先学习其中一种:

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

这样调用时,grep 会在文件中查找包含 SEARCH_STRING 的文本行,并将它们输出到终端。

这个挑战中,我在 /challenge/data.txt 文件里放了十万行文本。 用 grep 从中找出 flag 吧!

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

想找出两个相似文件之间的变化,光靠肉眼对比可能并不高效! 这时,diff 命令就派上用场了。

diff 会逐行比较两个文件,准确展示它们的差异。 例如:

hacker@dojo:~$ cat file1
hello
world
hacker@dojo:~$ cat file2
hello
universe
hacker@dojo:~$ diff file1 file2
2c2
< world
---
> universe

输出告诉我们,第 2 行发生了变化(2c2):第一个文件(<)中的 world 被替换成了第二个文件(>)中的 universe。

有时,如果新增了文本行,你会看到这样的输出:

hacker@dojo:~$ cat old
pwn
hacker@dojo:~$ cat new
pwn
college
hacker@dojo:~$ diff old new
1a2
> college

它表示,相对于第一个文件,第二个文件在第 1 行之后新增了一行(1a2 的意思是"在 file1 的第 1 行之后,添加 file2 的第 2 行")。

现在开始挑战! /challenge 中有两个文件:

  • /challenge/decoys_only.txt 包含 100 个假 flag
  • /challenge/decoys_and_real.txt 包含全部 100 个假 flag,以及唯一一个真正的 flag

用 diff 找出这两个文件的差异,拿到你的 flag 吧!

到目前为止,我们都会告诉你需要操作哪些文件。 但目录中可能有许多文件和其他目录,而我们不会总在一旁告诉你它们的名字。 你需要学会列出目录内容,也就是 list,使用的命令是 ls!

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 中的文件,找出它。 然后,使用找到的绝对路径执行程序,获得 flag。

当然,你也可以创建文件! 创建文件有多种方法,这里我们先看一个简单的命令。 要创建一个新的空文件,可以用 touch(触碰)的方式,也就是使用 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!

文件随处可见。 就像糖纸一样,积攒久了就会越来越多。 这一关,我们来学习如何清理它们!

在 Linux 中,删除文件也就是 remove,可以使用 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 给你!

你还可以移动文件,使用的命令是 mv。 用法很简单:

hacker@dojo:~$ ls
my-file
hacker@dojo:~$ cat my-file
PWN!
hacker@dojo:~$ mv my-file your-file
hacker@dojo:~$ ls
your-file
hacker@dojo:~$ cat your-file
PWN!
hacker@dojo:~$

这个挑战要求你将 /flag 文件移动到 /tmp/hack-the-planet,动手吧! 注意,你必须使用 mv 命令,而不能使用其他方法,例如在 VSCode 中重命名文件。 完成后,运行 /challenge/check,程序会检查结果并给你 flag。

如果你想保留原文件呢?可以使用 cp 命令。 它的用法与 mv 相同,但会保留源文件。 命令格式是 cp SOURCE DESTINATION:第一个参数是现有文件,第二个参数是副本的创建位置。

这个挑战要求你将 /flag 文件复制到 /tmp/hack-the-planet,动手吧! 完成后,运行 /challenge/check,程序会检查结果并给你 flag。


注意: 如果 cp 的目标是一个目录,cp 会把副本放进该目录,并沿用源文件的名称。 在这个挑战中,/tmp/hack-the-planet 应当是副本文件本身的路径,而不是一个已经存在的目录。

有意思的是,ls 默认不会列出所有文件。 Linux 有一个约定:名称以 . 开头的文件,默认不会显示在 ls 的输出中,在其他一些场景下也会被隐藏。 要用 ls 查看它们,需要在运行 ls 时加上 -a 选项,如下所示:

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

现在轮到你了! 去找出 flag 吧,它藏在 / 下一个名称以点开头的文件中。

掌握了 cd、ls 和 cat,我们就可以玩一个小游戏了!

我们从 / 开始。 通常,你会看到:

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 藏起来了! 你需要用 ls 和 cat,顺着我留下的线索找到它! 具体玩法如下:

  1. 第一条线索位于 /。先到那里去。
  2. 用 ls 看看周围。你会找到一个名为 HINT、CLUE 或类似名称的文件!
  3. 用 cat 读取该文件中的线索!
  4. 根据线索的提示,前往下一个目录,或者留在原地。
  5. 一路追踪线索,直到找到 flag!

祝你好运!

我们已经会创建文件了。 那么,目录该怎么创建呢? 创建目录,也就是 make 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!

现在,我们已经知道如何列出、读取和创建文件了。 那么,如何查找文件呢? 使用 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:~$

当然,我们也可以指定搜索条件! 例如,下面按名称筛选:

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 可能需要一些时间,请耐心等待!

视频字幕(七牛云直连)

只要你使用 Linux 或计算机处理实际工作一段时间,迟早会遇到这样的情况:你希望两个程序访问同一份数据,但它们却要求数据位于两个不同的位置。 好在 Linux 提供了解决办法:链接。

链接分为两种:硬链接和软链接,后者也叫符号链接。 我们用一个比喻来区分它们:

  • 硬链接就像给同一套公寓使用多个地址,每个地址都直接指向同一个地方,例如 Apt 2 和 Unit 2。
  • 软链接就像搬家后,让邮政服务自动把寄到旧地址的邮件转寄到新地址。

从概念上说,文件系统中的文件就是一个地址,对应着该文件内容的存放位置。 硬链接是索引同一份数据的另一个地址——访问硬链接和访问原文件完全一样,都能直接获取所需数据。 软链接或符号链接则保存着原文件的名称。 访问符号链接时,Linux 会识别出它是符号链接,读取其中的原文件名称,然后通常会自动访问那个文件。 多数情况下,这两种方式都能访问到原始数据,但背后的机制不同。

硬链接听起来更简单(比如,上面解释硬链接只用了一句话,解释软链接却用了两句),但它存在一些缺点和实现上的陷阱,因此软链接或符号链接的使用远比硬链接普遍。

这个挑战将带你学习符号链接,也称为 symlink。 符号链接使用 ln 命令创建,语法是 ln -s TARGET LINK_NAME。 TARGET 是链接要指向的路径,LINK_NAME 则是你要创建的新路径。 例如:

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:~$

可以看到,访问符号链接就能读到原文件的内容! 在这个例子中,/tmp/myfile 是目标,/home/hacker/ourfile 是链接名称。

有几种方法可以判断一个文件是否为符号链接。 例如,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。 本挑战中的链接名称就是 /home/hacker/not-the-flag。 选择合适的链接目标,让 /challenge/catflag 上当,把 flag 交给你!


警告:如果之前的尝试在 /home/hacker/not-the-flag 留下了文件或链接,请先删除它,让 ln 能在这个位置创建符号链接。


30天排行榜:

此排行榜反映本模块在道场上线后各挑战的解出情况。

排名 黑客 徽章 得分
#1 symbol ma'r'cen't 🐧 belt 15
#2 symbol first 🐧 belt 10
#3 symbol xiaobao 🐧 belt 3