网安导实验一教程

网安导实验一:“配置 Linux 环境、熟悉 Linux” 的教程。

在本系列教程中,我将会尽可能的写清楚步骤和原理,以便你能完成实验;然而,尽管这里列出了“答案”,自学、搜索、查阅文档的能力是非常重要的,请不要过于依赖这里的内容。

Ubuntu 安装

共介绍三种方式:WSL、VMware、直接运行在物理机上。

参照官方文档安装 WSL。

参考这个

参考此 本站教程

在安装前,建议阅读 系统与引导 部分。

知识介绍

此部分将作为阅读材料提供可能用到的知识。

系统与引导

操作系统控制计算机的硬件与软件资源与用户交互,是计算机系统的核心部分。例如,用户打开多个程序,操作系统要调用分配 CPU 时间片,管理内存,调用硬盘读写等等资源,以保证程序的正常运行。

操作系统的启动需要通过引导程序来完成。当电脑主板通电并完成自检后,会加载 BIOS/UEFI,然后 BIOS/UEFI 会加载引导程序。引导程序会加载操作系统内核,然后操作系统内核会加载其他的系统服务。

在这个过程中,BIOS 程序是存在 ROM (通常是 EEPROM,电可擦除可编程只读存储器,使其可以升级) 中的,而其他设置(比如启动顺序)是存在 CMOS 中的。BIOS 会读取 CMOS 中的设置,然后根据设置的启动顺序加载引导程序。

我们在安装 Linux 时,同时完成了引导程序的安装。引导程序会在电脑启动时加载 Linux 内核。

UEFI 与 BIOS、MBR 与 GPT

BIOS 是旧的引导方式,它使用 MBR 分区表。MBR 分区表有很多限制,比如只能有 4 个主分区,每个分区最大 2TB 等等。BIOS 进行引导时,会读取 MBR 的第一个扇区,然后加载引导程序。若始终无法引导,则会显示“Missing operating system”等错误。

UEFI 是新的引导方式,它使用 GPT 分区表。GPT 分区表没有 MBR 的限制,可以有 128 个分区,每个分区最大 18EB 等等。UEFI 进行引导时,会读取 EFI 系统分区(ESP)中的引导程序,随后加载 .efi 文件进行引导。同时,UEFI 向下兼容 BIOS,可以通过 CSM 模式(Compatibility Support Module)来引导 BIOS 系统。

现在电脑大多为 UEFI 引导,尽管我们有时仍然称之为 BIOS。

BIOS vs UEFI
特性 BIOS UEFI
启动方式 依赖 MBR,逐扇区扫描 直接读取 ESP 分区文件
硬盘支持 最大 2TB,MBR 分区 支持 18EB 超大硬盘,GPT 分区
启动速度 较慢 更快(并行初始化硬件)
图形界面 纯文本 支持鼠标操作的图形界面
安全机制 Secure Boot
MBR vs GPT
对比项 MBR GPT
最大分区数量 4 个主分区(或扩展分区) 128 个主分区(Windows 默认)
单分区大小限制 2TB 18EB(1EB=100 万 TB)
数据安全性 分区表无备份,易损坏 多份备份分区表,CRC 校验
兼容性 所有系统支持 需 UEFI 固件支持

Secure Boot 是 UEFI 的一个安全机制,它会检查引导程序的签名,以防止恶意程序的引导。但 Secure Boot 也会阻止一些自定义的引导程序,比如 GRUB2,因此安装 Linux 时需要关闭 Secure Boot。

shell 与 bash

shell 是一个命令解释器,它接收用户输入的命令,然后调用操作系统的 API 来执行这些命令。shell 有很多种,比如 bash、zsh、fish 等等。bash 是最常用的 shell,它是 GNU 项目的一部分。

bash 的命令行提示符通常是 $ 或者 #$ 表示普通用户,# 表示 root 用户。bash 的命令行支持很多功能,比如命令补全、命令历史、管道、重定向等等。

bash 的命令行支持很多快捷键,比如:

  • Ctrl + C 终止当前命令(SIGINT)
  • Ctrl + D 退出 shell(EOF)
  • Ctrl + L 清屏
  • Ctrl + A 光标移动到行首
  • Ctrl + E 光标移动到行尾
  • Ctrl + U 删除光标前的内容
  • Ctrl + R 搜索历史命令
  • Ctrl + W 删除光标前的单词
  • Ctrl + Z 暂停当前命令(SIGTSTP,挂起时可用 bgfg 恢复。)

bash 的配置文件有很多,比如:

  • /etc/profile 全局配置文件
  • ~/.bashrc 用户配置文件
  • ~/.bash_profile 用户登录时执行的配置文件

在此不做解释。

常用命令

命令速查表

命令 说明 用法示例
sh 普通的 shell sh
bash 默认的 shell bash
help 显示 shell 内置命令的帮助文档 help <command>
man 查看命令或系统 API 的文档 man <command>
ls 列出当前目录或某个目录里的文件 (list) ls [<dirname>]
pwd 输出当前所在目录 (print working directory) pwd
cd 改变当前目录 (change directory) cd <dirname>; cd ..; cd .
cat 输出一个文件的内容 cat <filename>
less 用滚动方式查看长文件 less <filename>
touch 创建空文件或更新文件访问日期 touch <filename>
cp 复制文件 cp <filename> <destination>
mkdir 创建目录 mkdir <dirname>
rm 删除文件或目录 rm <filename>; rm -r <dirname>
chmod 改变文件、文件夹权限 chmod 755 <filename>
echo 显示一行字 echo <text>
sudo 提升至 root 权限 sudo <command...>
kill 按进程 pid 杀掉进程 kill <pid>
vim/emacs/gedit/... 编辑文件 gedit <filename>
date 打印日期 date
id 打印当前用户与组的信息 id
hexdump/xxd 以十六进制方式打印文件 hexdump <filename> | less
nc 发起 TCP 连接并通过终端与服务器交互 nc <host> <port>
wget 下载文件 wget <url>
ping ping 远程主机 ping <host>
ifconfig 获取当前虚拟机 IP、MAC 地址等信息 ifconfig
netstat 显示网络状态 netstat
ps 显示进程信息 ps
top 显示系统资源使用情况 top
tar 打包/解包文件 tar -cvf <filename>.tar <dirname>
whoami 显示当前用户名 whoami
uname 显示系统信息 uname -a

命令详解

shbash

sh 是一个 shell,它是 POSIX 标准的 shell。bash 是 GNU 项目的 shell,它是 sh 的增强版。在大多数系统中,shbash 的软链接。

大多数情况下,我们使用 bash

ls

ls 是列出文件的命令。ls 有很多参数,比如:

  • -l 显示详细信息
  • -a 显示所有文件(包括隐藏文件)
  • -h 人类可读的文件大小(文件大小以 1000 进位)
  • -t 按时间排序

其中,ls -l 等效于 llls -a 等效于 la

rm

rm 是删除文件的命令。rm 有很多参数,比如:

  • -r 递归删除。
  • -f 强制删除。
  • -d 删除空目录。
  • -i 删除前询问;-I 在删除超过三个文件或者递归删除前询问一次;此选项比 -i 提示次数更少,但仍可以避免大多数错误的发生。

注意!

在 Windows 中,当文件被使用时会有文件句柄进行标记,此时无法删除文件,也因此不必担心删除重要文件。但在 Linux 中所有文件都是可删除的,因此谨慎使用 rm 命令!若删除内核文件,系统下次将无法启动。

此外,请区别 /.// 表示根目录,./ 表示当前目录。

cd

在 Linux 文件系统中,.. 表示上级目录,. 表示当前目录,~ 表示用户的家目录。

Vim

上文中提到的 gedit 是一个图形化的文本编辑器,nano 是一个命令行下的功能较简单的文本编辑器,并提供了使用说明。

Vim 不提供命令提示,因此你在使用时至少应该知道以下的内容:

  • Vim 有三种模式:命令模式、插入模式和可视模式。
  • 命令模式是进入 Vim 后的默认模式,可以使用各种命令。具体方法为:
    • 按下 i 进入插入模式,按下 Esc 退出插入模式。
    • 按下 : 进入命令行模式(底线命令模式),可以输入命令,其中:
      • :w 保存文件
      • :q 退出
      • :wq 保存并退出
      • :q! 强制退出
    • 按下 v 进入可视模式,可以选择文本。同样,按下 Esc 退出可视模式。
  • 在插入模式下,你可以输入文本。
  • 在可视模式下,你可以选择文本,其中:
    • v 选择字符
    • V 选择行
    • Ctrl + V 选择块

知道以上内容你至少可以打开文件、编辑文件、保存文件、退出 Vim,尽管不太流畅。Vim 完整使用方法请自行查阅。通常来说,若你能熟练使用 Vim,你可以完全在命令行下、不使用鼠标的完成工作,这将使你的工作效率大大提高(尽管学习曲线可能会很陡峭)。

NeoVim 作为 Vim 的复刻,现在提供了更多的功能,比如异步插件、更好的 Lua 支持等等。如果你想使用 Vim,可以考虑使用 NeoVim。

ping

ping 命令使用 ICMP 协议向目标主机发送数据包,以测试目标主机的可达性。ping 命令会一直发送数据包,直到手动终止。不过,由于浏览器等使用的是 TCP 协议,因此 ping 命令并不能完全代表网络的连通性,所以当你想测试 VPN 可用性时,应使用 curlwget 命令。

ifconfig

请区别 ifconfigipconfig。前者为 Linux 下的网络配置命令,后者为 Windows 下的网络配置命令。ifconfig 的名称来源于“interface configuration”(接口配置)。

现在,ifconfig 命令已经被 ip 命令取代,ip 命令是一个更强大的网络配置工具。ip 命令的使用方法请自行查阅。

top

top 命令用于显示系统资源使用情况,包括 CPU、内存、进程等。现在有 btop 这种更美观清晰的开源项目做替代(btop 也是命令行下的)。

tar

tar txvf 用于解压缩 tar 包,tar cvf 用于打包 tar 文件。tar xzvf 用于解压缩 tar.gz 包,tar czvf 用于打包并压缩 tar.gz 文件。其中: - c 表示创建。 - x 表示提取。 - z 表示使用 gzip 压缩。 - v 表示显示详细信息。 - f 表示文件。

apt

apt 是 Debian 系统的包管理工具,它可以用来安装、卸载、更新软件包。apt 命令通常需要 root 权限。

比如,这样升级系统:

1
2
3
sudo apt update
sudo apt upgrade
sudo apt autoremove

当存在依赖问题时,可以使用 apt --fix-broken install 或是 apt install -f 来修复。

其前身为 apt-getapt 对其进行了封装。其“后继”为 aptitude,它在解决依赖问题等表现的更好。

超级牛力!

使用 apt -h 或是 apt-get -h 最后一行会出现“本 APT 具有超级牛力。”

使用 apt moo 会出现一只牛。

1
2
3
4
5
6
7
                 (__)
(oo)
/------\/
/ | ||
* /\---/\
~~ ~~
..."Have you mooed today?"...

aptitude -h 最后一行会有“这个 aptitude 没有超级牛力。”

如果你足够闲的话……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
crazy@13754:~$ aptitude moo
这个程序里没有复活节彩蛋。
crazy@13754:~$ aptitude moo -v
这个程序里确实没有复活节彩蛋。
crazy@13754:~$ aptitude moo -vv
我不是已经告诉你这个程序里没有复活节彩蛋了吗?
crazy@13754:~$ aptitude moo -vvv
停下来!
crazy@13754:~$ aptitude moo -vvvv
好吧,好吧,如果我给你复活节彩蛋,你会停手吗?
crazy@13754:~$ aptitude moo -vvvvv
好吧,你赢了。

/----\
-------/ \
/ \
/ |
-----------------/ --------\
----------------------------------------------
crazy@13754:~$ aptitude moo -vvvvvv
这是什么?当然是一只大象被一条蛇吞了。

管道与重定向

管道(|)用于将一个命令的输出作为另一个命令的输入。比如:

1
2
3
ls -l | less
man zsh | wc -w
echo "Hello, World\n orld, world, heoll\n awaw qwqw " | grep "World"

less 是一个分页器,它可以用来查看长文件; man 是查看命令文档的命令; wc 是一个统计命令,-w 参数表示统计单词数。

重定向用于将命令的输出重定向到文件。比如:

1
2
ls -l > file.txt
echo "Hello, World!" >> file.txt

其中,> 表示覆盖,>> 表示追加。其反向操作是 <,比如:

1
cat < file.txt

git

有足够好的教程

其没有说明的几点:

  • 本地 git 仓库(非工作区)的内容保存在 .git 文件夹中。包括分支、提交、标签等信息。
  • git 是基于快照的,即每次提交要么保存完整的文件,要么没有改动不用保存。因此 git 进行代码回溯很快,但这也意味着 git 仓库会比较大,可能需要进行整理。另一个较老的版本控制系统 SVN 是基于差异的。
  • git 的分支是轻量级的,即创建分支只是创建一个指针,不会复制文件。因此,git 鼓励多分支开发。

Git 基本配置与 SSH 密钥设置

git 是一个本机上的软件;而 GitHub 是一个远程仓库。

1
2
git config --global user.name "Your Name"
git config --global user.email "Your Email"

为 GitHub 设置 SSH 密钥:

1
2
ssh-keygen # 一路回车
cat ~/.ssh/id_rsa.pub

将输出的内容添加到 GitHub 的 SSH 密钥中(GitHub 设置——SSH and GPG keys——New SSH key)。

版本控制系统

许多年后,当我站在被告席上时,总能清晰回忆起那个被乌云笼罩的下午。审判庭的顶灯像极了那天的电脑屏幕,刺得人睁不开眼。

“为什么不用 SVN?要跑路直接删除服务器不就行了吗?”我问道。秘书在旁边轻轻点我一下,小声道:”我们伪装的可是先进的跨国电商公司!用 SVN 这种老掉牙的东西不一下子就漏馅了吗!“

可怕的一天终究来临,虽然早有预感,可是当电话响起,老大被抓的消息传来时,我不免心中一阵恐慌,又泛起一丝悲凉。我们按照计划,立刻删除 .git 文件夹,然后把空仓库强制推送到远程仓库。然而,悲剧注定要发生,从 GitHub 上尚未删除的乱糟糟的分支到新来实习生个人电脑上没来得及删除的仓库,都成为了我们犯罪无可辩驳的证据。

而我就更惨了。打来电话时,我慌得鬼使神差的输了个 sudo rm -rf /,那一大群网警破门而入时,那个该死的命令还在终端上闪烁,它执行的太慢了,我的整个家目录还是完好无损的。

哦天杀的,或许我应该听从内心的第一个想法抱起电脑向地上砸呢,真是倒了一百万辈子血霉,整个项目就我写的代码最多,判的也最快。

铁窗里的夜晚,我总会梦见那天开会我问为什么不用 SVN 时,老板那秃头下的白眼。

是的,因此所以就是这样,学会使用 git 或是其他版本控制系统非常重要。虽然这句话和这个故事看上去没有任何关系。

本段其实是想说明,git 和 SVN 的区别。

git 的分布式的版本控制系统,每个人都存有一个完整的仓库,上面存有自 git init 以来所有的提交快照。因此,即使远程仓库删除跑路,你也可以通过本地 clone 的仓库恢复所有提交;并且,所有提交的内容进行哈希,使其不可篡改。

git 是由 Linux 之父 Linus Torvalds 开发的,你可以发现,它的设计就是为了解决开源社区编写的同步问题。或者说,git 更自由,merge 一类的操作允许多人同时对同一文件进行修改;简单的分支和本地 commit 使得你可以随时保存当前工作状态,或是在不同的工作内容间切换。

而 SVN 是集中式的版本控制系统,所有的提交都保存在服务器上。因此,如果服务器被删除,你的提交也就没了。此外,SVN 对二进制文件的支持更好。

没有哪种东西更先进一说,不过是面对不同的需求罢了。

任务

23 版问题探究对新手过于困难,我们直接略过;综合运用中我们只展示几个较实用的例子。

Wine

Wine 是一个能够在 Linux 上运行 Windows 程序的软件。你可以使用 Wine 来运行一些 Windows 程序,比如 QQ、微信等。

我们的目标是使用 Wine 运行此 Windows C 程序:

hellowrold.c
1
2
3
4
5
6
#include <windows.h>

int main() {
MessageBox(NULL, "Hello, World!", "Message Box", MB_OK | MB_ICONINFORMATION);
return 0;
}
clickme.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <windows.h>

#define BUTTON_ID 1

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
static HWND hButton, hEdit;
switch (uMsg) {
case WM_CREATE:
hButton = CreateWindow(
"BUTTON", "Click Me",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
50, 50, 100, 30,
hwnd, (HMENU) BUTTON_ID, (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE), NULL);

hEdit = CreateWindow(
"EDIT", "",
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT,
50, 100, 200, 30,
hwnd, NULL, (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE), NULL);
break;

case WM_COMMAND:
if (LOWORD(wParam) == BUTTON_ID) {
SetWindowText(hEdit, "Button Clicked!");
}
break;

case WM_DESTROY:
PostQuitMessage(0);
break;

default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
const char CLASS_NAME[] = "SimpleWindowClass";
WNDCLASS wc = { };

wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;

RegisterClass(&wc);

HWND hwnd = CreateWindowEx(
0, CLASS_NAME, "Simple GUI",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 300, 200,
NULL, NULL, hInstance, NULL);

if (hwnd == NULL) {
return 0;
}

ShowWindow(hwnd, nCmdShow);

MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return 0;
}

其使用了 Windows API 中的 MessageBox 函数,用于显示一个消息框,无法在 Linux 下直接运行。

首先,你需要安装 Wine:

1
sudo apt install wine

然后,你需要编译这个程序:

1
2
sudo apt install mingw-w64
i686-w64-mingw32-gcc -o helloworld.exe helloworld.c

这使用了 MinGW-w64 编译器,它是一个能够在 Linux 下编译 Windows 程序的工具链。 最后,你可以使用 Wine 运行这个程序:

1
wine helloworld.exe
Wine 运行结果

可见其中文支持有问题。

Wine 运行结果2

这个用了不少句柄的程序还算正常。

试了解: - Wine 的更多应用; - Wine 的原理(编写 Wine 要做什么); - Wine 的配置文件。 - 其他转译方法或工具。

Hexo

我们的目标是使用 hexo 搭建一个博客,并部署到 GitHub Pages 上。

hexo 是一个静态博客框架,基于 Node.js。你可以使用 hexo 来搭建自己的博客。

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。你可以使用 Node.js 来编写服务器端的 JavaScript 程序。

它(Node.js)很快,因为它可以异步处理 I/O 操作。所以 Hexo 很快,这也正是其作者 tommy351 的初衷(Jekyll 的速度太慢了)。

其建站过程可以参考官方文档

GitHub Pages 是 GitHub 提供的静态网站托管服务。你可以使用 GitHub Pages 来托管你的博客。

其部署过程可以参考官方文档

Hexo

服务器上的静态页面是指页面内容固定不变的页面,如一个内容固定的 .html 文件。而动态页面是在用户请求时,根据脚本内容动态生成的页面,如根据 .php 读取用户身份,从而呈现不同页面内容的网页。

虽然 Hexo 只能生成静态页面,但是它可以通过插件支持动态内容,比如评论系统、搜索系统等等。这些插件会在生成静态页面时,将动态内容转换为静态内容。

Hexo 的作用是,将用户存放在 source 文件夹中的 Markdown 文件,根据主题和配置文件,生成静态页面于 public 文件夹中。

hexo shexo server 命令在 hexo g 的同时,还会在 localhost:4000 上启动一个服务器,用于预览生成的页面,并且支持热更新。

GitHub Pages 及部署

你可以在某个仓库的 Settings -> Pages 中设置 GitHub Pages 的配置,比如分支、目录等。

若没有 GitHub Pages 这样的服务,你需要自行租赁一个有公网 IP 的服务器,并购买一个域名,然后将域名解析到服务器上。然后,你需要在服务器上安装 Nginx 或 Apache 等 Web 服务器,将 Hexo 生成的静态页面放到 Web 服务器的目录中。两者效果将一致。

下面提供两种部署到 GitHub Pages 的方法。

GitHub Actions 是 GitHub 提供的持续集成服务。你可以使用 GitHub Actions 来自动化构建、测试、部署等操作。由于 Actions 升级至 v3,网上的教程大多已经过时,现给出我的配置文件:

.github/workflows/hexo.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
name: Deploy

on:
push:
branches:
- main

jobs:
build:
runs-on: ubuntu-latest
name: A job to deploy blog.
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: recursive

- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '22.9.0'

- name: Install Pandoc
run: sudo apt-get install -y pandoc

- name: Install Dependencies and Hexo CLI
run: |
npm install
npm install -g hexo-cli

- name: Generate static files
run: hexo generate

- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: './public'

deploy:
needs: build
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

其中,形如 actions/checkout@v3 是别人写好上传的 action 片段,我们可以直接使用。

本配置文件需要在仓库中 Pages 设置下选择是 GitHub Actions 部署,此外不需要其他配置。理论上,你只需要将这个配置文件放到 .github/workflows 文件夹下,然后推送到仓库中,就可以实现自动部署。

Actions 自动化流程分为两个阶段,build 阶段用于生成静态页面,deploy 阶段用于部署静态页面。build 阶段生成的静态页面会被上传到 deploy 阶段,然后部署到 GitHub Pages 上。

deploy 阶段,npm install 会根据 package.json 安装依赖,存放在 node_modules 文件夹中。

你可以使用 hexo deploy 命令来部署 Hexo 生成的静态页面。虽然 Hexo 的文档被骂的千疮百孔,但是官方文档毕竟是官方文档,还是能用的。

使用这种方法时,你需要在相应的 GitHub 库中设置 Pages 为类似 gh-pages 分支中读取这样。