0x00 引言
从终端窗口浏览Linux文件系统可以使用 tree 工具来显示Linux目录树的地图。
1 | # tree使用方法 |
0x01 目录结构
1 | 1 /bin |
1. /bin
/bin 是包含二进制文件的目录,即可以运行的某些应用程序和程序。您将在此目录中找到上面提到的ls程序,以及用于创建和删除文件和目录,在文件中移动它们的其他基本工具,等等。文件系统树的其他部分中还有更多的 bin 目录,但稍后我们将讨论它们。
2. /boot
/boot 目录包含启动系统所需的文件。如果您弄乱了其中的一个文件,则可能无法运行Linux,并且很难修复。另一方面,必须具有超级用户权限才能执行此操作。
3. /dev
/dev 包含设备文件,其中许多是在启动时甚至在运行时生成的。例如,如果您将新的网络摄像头或USB随身碟插入计算机,则会在此处自动弹出一个新的设备条目。
/dev/char/ 字符设备的软链接存放目录,实际查看可使用’ls -l /dev/char’命令
/dev/block/ 块设备的软链接存放目录,实际查看可使用’ls -l /dev/block’命令
字符设备:提供连续的数据流,应用程序可以顺序读取,通常不支持随机存取。相反,此类设备支持按字节自/字符来读写数据。举例来说,百键盘、串口、调制解调器都是典型的字符设备。
块设备:应用程序可以随机访问设备数据,程序可自行确定读取数据的位置。硬盘、软盘、CD-ROM驱动器和闪存都是典型度的块设备,应用程序可以寻址磁盘上的任何位置,并由此读取数据。此外,数据的读写知只能以块(通常是512B)的倍数进行。与字符设备不同,块设备并不支持基于字符的寻址。
这两种类型的设备的根本区别在于它们是否可以被随机访问。字符设备只能顺序读取道,块设备可以随机读取。
4. /etc
/etc 包含大多数系统范围的配置文件。例如,包含系统名称,用户及其密码,网络上的计算机名称以及何时以及在何处安装硬盘上的分区的文件均位于此处。
5. /home
/home 是存放用户个人目录的位置。
6. /lib
/lib 是库所在的位置,库是包含应用程序可以使用的代码的文件。它们包含应用程序用来在桌面上绘制窗口,控制外围设备或将文件发送到硬盘的代码片段。
7. /media
/media 目录用于自动挂载外部存储。
8. /mnt
/mnt 目录,可以在此处手动安装存储设备或分区,它并不经常被使用。
9. /opt
/opt 目录中编译软件,应用程序将最终在 /opt/bin 目录中,并将库文件存放在 /opt/lib 目录中。
注意:应用程序和库存放的另一个位置是 /usr/local ,在这里安装软件时,还将有 /usr/local/bin 和 /usr/local/lib 目录。开发人员如何配置用于控制编译和安装过程的文件,这决定了将哪种软件运往何处。
10. /proc
/proc 就像 /dev 是一个虚拟目录,它包含有关您的计算机的信息。例如有关您的CPU和Linux系统正在运行的内核的信息。
/proc/stat 提供的是系统的CPU和任务统计信息。
/proc/net/tcp 文件提供了tcp的连接信息。
/proc/‘pid’/stat 提供的是进程的CPU和任务统计信息。
/proc/‘pid’/limits 提供该进程的资源限制。
/proc/‘pid’/sessionid 提供的是拉起该进程的终端会话ID
/proc/cpuinfo cpu信息
/proc/pci 板卡信息,可用lspci命令查看
/proc/meminfo 内存信息
/proc/bus/usb/devices USB设备信息
/proc/bus/input/devices 键盘和鼠标信息
/proc/interrupts 各设备中断请求
/proc/devices 所有硬件设备信息
/proc/swaps 交换空间大小
11. /root
/root 是系统超级用户的主目录,它与其他用户主目录分开。
12. /run
/run 目录,系统进程使用它来存储临时数据,不要随意修改该文件。
13. /sbin
/sbin 与 /bin 相似,但是 /sbin 包含仅超级用户所需的应用程序。/sbin 通常包含可以安装内容,删除内容和格式化内容的工具,需小心使用。
14. /usr
/usr 目录是UNIX早期最初保留用户主目录的位置。现在,该目录包含应用程序、库文件、文档、壁纸、图表以及其他应用和服务共享的文件。
/usr/bin、/usr/sbin、/usr/lib 目录内包含了用户安装的程序、库文件。
15. /srv
/srv 目录包含了服务器数据。如果你在运行网页服务器,你的HTML文件会进入 /srv/http(或/srv/www)目录。如果你在运行FTP服务,你的文件会进入 /srv/ftp 目录。
16. /sys
/sys 是一个虚拟目录(类似 /proc 和 /dev),并且包含了远程连接设备的信息。
比如可以通过修改文件 /sys/devices/pci0000:00/0000:00:02.0/drm/card1/card1-eDP-1/intel_backlight/brightness 改变屏幕亮度。不要轻易改动 /sys 目录。
17. /tmp
/tmp 包含正在运行的应用程序生成的临时文件。文件和目录经常包含应用程序当前不需要但以后可能需要的数据。
18. /var
/var 目录存放的是经常改变内容的文件,比如日志存放于 /var/log 。
0x02 常用目录
1 | # 已有的shell查看 |
常见日志文件路径
地址 | 功能 |
---|---|
/var/log/messages | 系统启动后的信息和错误日志 |
/var/log/secure | 与安全相关的日志信息 |
/var/log/maillog | 与邮件相关的日志信息 |
/var/log/cron | 与定时任务相关的日志信息 |
/var/log/spooler | 与UUCP和news设备相关的日志信息 |
/var/log/boot.log | 守护进程启动和停止相关的日志消息 |
/var/log/wtmp | 永久记录每个用户登录、注销及系统的启动、停机的事件 |
/var/run/utmp | 记录当前正在登录系统的用户信息(可用who命令查看),通常为/run/utmp的软链接 |
/var/log/btmp | 记录失败的登录尝试信息 |
/var/log/dmesg | 记录开机日志以及系统故障信息 |
/var/log/crash | 系统崩溃日志 |
/var/log/audit/audit.log | 系统审计日志 |
~/.xession-error | 记录登录桌面失败的信息 |
0x03 环境变量
环境变量分为系统级变量和用户级环境变量。关于系统级变量的配置文件如下:
1 | # /etc/profile |
关于用户级变量的配置文件如下:
1 | # ~/.profile(推荐首选) |
当然如果只是希望使可执行文件能直接使用,推荐软链接的方式
1 | # 为原文件创造一个新的指针,类似于Windows的快捷方式 |
0x04 依赖
1 | 1. 三方库使用条件 |
1、三方库使用条件
在编译时,第三方库必须要有静态库或动态库以及头文件。在运行时,第三方库只需要有静态库或动态库即可。
2、编译时依赖
关于编译时依赖查看CMAKE相关文章。
3、运行时依赖
Windows进程运行时依赖于当前文件夹与环境变量。
Linux进程运行时依赖于RPATH,关于进程的依赖可通过下面两个命令获取:
1 | # 查看可执行程序的依赖 |
4、依赖库与头文件查找顺序
1 | # gcc 编译程序时查找SO顺序 |
5、Linux动态库与静态库
1).进程依赖动态库,则编译时需要.so文件与头文件,运行时需要.so文件;
2).进程依赖静态库,则编译时需要.a文件与头文件,运行时无需其他文件(本质是把符号表都合入到进程中);
3).进程依赖静态库,但是静态库本身又依赖其他动态库,则编译时需要所有.a文件、.so文件以及头文件,运行时需要静态库依赖的.so文件。
6、Windows动态库与静态库
1).后缀.dll文件为动态库;
2).后缀.lib文件分为静态库.lib与导入库.lib,前者与Linux系统下的一样本身就包含了实际执行代码、符号表等等,后者的导入库只包含了地址符号表等确保程序找到对应函数的一些基本地址信息。
7、libc.so.6/libstdc++.so.6
这两个分别是c与c++的运行时库。
8、其他相关知识
库文件的文件头中是会含有库名相关的信息的(比如“libc.so.6”,可用strings命令察看),仅通过修改文件名以冒充某已被识别的库是行不通的,需要使用Makefile修改库名重新编译。
1 | $ strings /lib/libc.so.6 |grep GLIBC_2. |awk -F . '{print$2}' |grep '[1][2-9]' |wc -l |
0x05 桌面图标生成
1 | 1. 生成任务栏图标 |
1、生成任务栏图标
在linux系统中,要在任务栏中生成一个可以打开某个程序的图标,需要在/usr/share/applications目录中添加一个.desktop文件:
1 | [Desktop Entry] |
2、生成桌面图标
生成桌面图标有三种方法:1.硬链接/usr/share/applications/XXX.desktop到指定用户桌面;2.软链接/usr/share/applications/XXX.desktop到指定用户桌面;3.拷贝/usr/share/applications/XXX.desktop到指定用户桌面。
由于后两者无法同时改动桌面与源文件,因此这边只推荐使用硬链接:
1 | ln /usr/share/applications/XXX.desktop 'Desktop文件夹目录/XXX.desktop' |
3、指令对照表
Key | 描述 | Value 类型 | 是否必须? | 生效的类型 |
---|---|---|---|---|
Type | Application (type1), Link (type2), Direcory (type3) | string | Yes | |
Version | 版本,例如1.1 | string | No | 1-3 |
Name | 应用程序的特定名称,例如“Mozilla”。 | localestring | Yes | 1-3 |
GenericName | 应用程序的通用名称,例如“Web浏览器”。 | localestring | No | 1-3 |
NoDisplay | 不在菜单中显示, 但可以与MIME类型相关联 | boolean | No | 1-3 |
Comment | 应用描述 | ocalestring | No | 1-3 |
Icon | 要么绝对路径,要么符合图标主题规范 | localestring | No | 1-3 |
Hidden | 是否隐藏,等同于不存在的文件 | boolean | No | 1-3 |
OnlyShowIn, NotShowIn | 一般不用此字段 | boolean | No | 1-3 |
DBusActivatable | DBus激活,默认false。参阅D-Bus激活。应包含Exec行,实现兼容 | boolean | No | |
TryExec | 如果文件不存在, 则忽略该文件,并不在菜单中出现 | string | No | 1 |
Exec | 执行路径 。参阅Exec Key | string | No | 1 |
Path | 当Type=Application时,程序运行的目录 | string No | 1 | |
Terminal | 程序是否在终端窗口中运行。 | boolean | No | 1 |
Actions | 为其他组提供接口,比如Action=Gallery;,那么其他组就为[Desktop Action Gallery] | string(s) | No | 1 |
MimeType | 此应用支持打开的类型,具体类型可以百度 | string(s) | No | 1 |
Categories | 参阅桌面菜单规范 | string(s) | No | 1 |
Implements | 默认情况下,桌面文件不实现任何接口。参阅接口 | string(s) | No | |
Keywords | 用于搜索,不应该是Name或者为多余的值 GenericName。 | localestring(s) | No | 1 |
StartupNotify | 如果不存在,则合理的处理取决于实现(假设为false,使用StartupWMClass等)。参阅启动通知协议规范 | boolean | No | 1 |
StartupWMClass | 一般跟Name相同即可 | string | No | 1 |
URL | 只适用于Type=Link | string | Yes | 2 |
0x06 权限
1 | 1 文件权限描述 |
1、文件权限描述
Linux系统中使用UID(用户ID)与GID(组ID)对用户进行管理,每个文件都拥有自己的权限描述,可以用以下方式查看与设置:
1 | # ===== 查看方式 ===== |
下面开始解析上述输出的含义:
权限项 | 文件类型 | 读 | 写 | 执行 | 读 | 写 | 执行 | 读 | 写 | 执行 |
---|---|---|---|---|---|---|---|---|---|---|
字符表示 | (d/l/c/s/p/-) | r | w | x | r | w | x | r | w | x |
数字表示 | 4 | 2 | 1 | 4 | 2 | 1 | 4 | 2 | 1 | |
权限分配 | 文件所有者 | 文件所属组用户 | 其他用户 |
1 | # 文件类型中 |
2、文件特殊权限
除了上述rwx三种权限之外,还存在三种特殊权限 SUID/SGID/Sticky 。
- SUID - 特殊权限,一般设置可执行文件。可执行的文件搭配这个权限,便能得到特权,任意存取该文件的所有者能使用的全部系统资源;
- SGID - 特殊权限组,一般设置可执行文件。其效果与SUID相同,只不过将文件所有者换成用户组,该文件就可以任意存取整个用户组所能使用的系统资源;
- Sticky - 粘滞位,一般设置文件夹。如果想在文件夹中新建文件,则必须获取该文件夹的写权限,那么如何让用户在文件夹中只能新建文件而不能删除文件呢?设置粘滞位的文件夹,任意用户可以在文件夹中新建文件,但是不能删除其他用户新建的文件。
其表现在执行位置上:
1 | # ===== 设置方法 ===== |
3、进程权限
内核为每个进程维护了三个UID值,这三个UID分别是实际用户ID、有效用户ID、保存的设置用户ID。
- 实际用户ID: 当前登录的用户。运行程序的实际用户ID就是这个用户的ID
- 有效用户ID: 运行当前进程的用户ID。一般情况下是实际用户ID,如果可执行文件具有了SUID权限,那么它的有效用户ID就是可执行文件的拥有者
- 保存的设置用户ID: 有效用户ID的一个副本,与SUID权限有关
1
2
3
4
5
6
7
8
9
10
11
// 读取进程权限
uid_t ruid,euid,suid;
getresuid(&ruid,&euid,&suid);
printf("real:%d\teffective:%d\tset-user-id:%d\n",ruid,euid,suid);
// 设置进程权限(root)
setuid(1000);
4、隐藏属性
文件有隐藏属性,隐藏属性对系统安全性有很大的帮助
1 | # 可修改文件/文件夹的"隐藏权限" |
5、capability机制
由于rwx权限机制不够灵活,比如有很多权限是不需要操作文件的。从Linux 2.2开始引入了capability权限机制。
1 | # 设置capability权限(shell命令) |
capability 名称 | 描述 |
---|---|
CAP_AUDIT_CONTROL | 启用和禁用内核审计;改变审计过滤规则;检索审计状态和过滤规则 |
CAP_AUDIT_READ | 允许通过 multicast netlink 套接字读取审计日志 |
CAP_AUDIT_WRITE | 将记录写入内核审计日志 |
CAP_BLOCK_SUSPEND | 使用可以阻止系统挂起的特性 |
CAP_CHOWN | 修改文件所有者的权限 |
CAP_DAC_OVERRIDE | 忽略文件的 DAC 访问限制 |
CAP_DAC_READ_SEARCH | 忽略文件读及目录搜索的 DAC 访问限制 |
CAP_FOWNER | 忽略文件属主 ID 必须和进程用户 ID 相匹配的限制 |
CAP_FSETID | 允许设置文件的 setuid 位 |
CAP_IPC_LOCK | 允许锁定共享内存片段 |
CAP_IPC_OWNER | 忽略 IPC 所有权检查 |
CAP_KILL | 允许对不属于自己的进程发送信号 |
CAP_LEASE | 允许修改文件锁的 FL_LEASE 标志 |
CAP_LINUX_IMMUTABLE | 允许修改文件的 IMMUTABLE 和 APPEND 属性标志 |
CAP_MAC_ADMIN | 允许 MAC 配置或状态更改 |
CAP_MAC_OVERRIDE | 覆盖 MAC(Mandatory Access Control) |
CAP_MKNOD | 允许使用 mknod() 系统调用 |
CAP_NET_ADMIN | 允许执行网络管理任务 |
CAP_NET_BIND_SERVICE | 允许绑定到小于 1024 的端口 |
CAP_NET_BROADCAST | 允许网络广播和多播访问 |
CAP_NET_RAW | 允许使用原始套接字 |
CAP_SETGID | 允许改变进程的 GID |
CAP_SETFCAP | 允许为文件设置任意的 capabilities |
CAP_SETPCAP | 参考 capabilities man page |
CAP_SETUID | 允许改变进程的 UID |
CAP_SYS_ADMIN | 允许执行系统管理任务,如加载或卸载文件系统、设置磁盘配额等 |
CAP_SYS_BOOT | 允许重新启动系统 |
CAP_SYS_CHROOT | 允许使用 chroot() 系统调用 |
CAP_SYS_MODULE | 允许插入和删除内核模块 |
CAP_SYS_NICE | 允许提升优先级及设置其他进程的优先级 |
CAP_SYS_PACCT | 允许执行进程的 BSD 式审计 |
CAP_SYS_PTRACE | 允许跟踪任何进程 |
CAP_SYS_RAWIO | 允许直接访问 /devport、/dev/mem、/dev/kmem 及原始块设备 |
CAP_SYS_RESOURCE | 忽略资源限制 |
CAP_SYS_TIME | 允许改变系统时钟 |
CAP_SYS_TTY_CONFIG | 允许配置 TTY 设备 |
CAP_SYSLOG | 允许使用 syslog() 系统调用 |
CAP_WAKE_ALARM | 允许触发一些能唤醒系统的东西(比如 CLOCK_BOOTTIME_ALARM 计时器) |
0x07 开机自启动
1 | 1 服务进程 |
1、服务进程
在Linux中,服务进程的启动脚本放在/etc/init.d目录下。然而要实现开机自启动,可以采用rc文件与systemd来实现。
1.1、rc文件自启动
在目录/etc目录下,包含rc0.d/ ~ rc6.d/目录。只需要把/etc/init.d目录下的文件通过软链接或者直接复制到此处,即可实现开机自启动。
- rcN.d目录下都是一些符号链接文件,这些链接文件都指向init.d目录下的文件,命名规则为K+nn+服务名或S+nn+服务名(K开头代表以stop为参数运行服务文件,S开头代表以start为参数),其中nn为两位数字(代表启动顺序,从小到大)
- 对于以K开头的文件,系统将终止对应的服务;对于以S开头的文件,系统将启动对应的服务
- rcN中的N代表该目录下的服务需要在哪个进程运行,查看运行级别用:runlevel
- 进入其它运行级别用:init N
下面详细描述七个级别N的具体含义:1
2
3
4
5
6
7运行级别0:系统停机状态
运行级别1:单用户工作状态,root权限,用于系统维护,禁止远程登陆
运行级别2:多用户状态(没有NFS)
运行级别3:完全的多用户状态(有NFS),登陆后进入控制台命令行模式
运行级别4:系统未使用,保留
运行级别5:X11控制台
运行级别6:系统正常关闭并重启
服务文件需要满足一定的格式,这里提供一个示例。首先新建一个示例文件 test-server,将其放置于/etc/init.d,再生成软链接于(假设runlevel为3)/etc/rc3.d/S80test-server
示例文件 test-server :
1 |
|
1.2、systemd自启动
将一个.service文件放置在/etc/systemd/system目录下,然后使用如下命令设置服务:
1 | # 开启服务: |
有关于.service文件的具体写法,查看文献
2、普通进程
首先要在/usr/share/applications目录中添加桌面图标.desktop文件,并将其软链接或直接复制到以下目录:
1 | # root用户的普通进程自启动 |
0x08 编译相关
1 | 1 g++与c++11 |
1、g++与c++11
g++4.8、g++4.9包含c++11但是默认不开启,g++5.1开始默认开启c++11(提供了一个宏来控制其是否使用 _GLIBCXX_USE_CXX11_ABI)
- 进程依赖动态库,动态库使用g++4编译且不开启c++11。进程可使用g++4编译(c++11开启与关闭均可);进程可使用g++5编译(必须通过宏关闭c++11)
- 进程依赖动态库,动态库使用g++5编译且开启(默认开启)。进程可使用g++5编译(通过宏关闭c++11后无法编译通过)
下面记录直接使用g++以及使用cmake分别在g++4/g++5下如何控制c++11的开启与关闭: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# ===== 使用g++4编译 =====
# 1.关闭c++11(默认关闭)
g++ 'XXX.cpp' -o 'XXX'
# 2.开启c++11
g++ -std=c++11 'XXX.cpp' -o 'XXX'
# 或者
g++ -std=c++0x 'XXX.cpp' -o 'XXX'
# ===== 使用g++5编译 =====
# 1.关闭c++11
g++ -D_GLIBCXX_USE_CXX11_ABI=0 'XXX.cpp' -o 'XXX'
# 2.开启c++11(默认开启)
g++ 'XXX.cpp' -o 'XXX'
# ===== cmake/g++4 =====
# 1.关闭c++11(默认关闭)
# 2.开启c++11
set(CMAKE_CXX_STANDARD 11) # cmake3.1以后支持该设置方法
# 或者
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
# ===== cmake/g++5 =====
# 1.关闭c++11
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
# 2.开启c++11(默认开启)
2、编译参数 -fPIC
-fPIC编译参数在产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。
如果Linux机器要编译带有-fPIC参数的.so动态库,则必须加这个编译选项。并且该动态库所依赖的所有动态、静态库都需要在编译时加入-fPIC参数,否则会报下面的错误:
error1: relocation R_X86_64_32 against `a local symbol’ can not be used when making a shared object; recompile with -fPIC
error2: unresolvable R_AARCH64_ADR_PREL_PG_HI21 relocation against symbol stdin@@GLIBC_2.17
3、编译参数 -Wl,-rpath=./ -Wl,-Bsymbolic
是在gcc编译的时候为二进制添加rpath的参数
4、MSVC编译参数 /MT /MD
这两个参数是Windows下的MSVC编译器参数,在编译静态库时被用到。
/MD(Release版本) /MDD(Debug版本): 表示运行时库由操作系统提供一个DLL,程序里不集成。编译出来的文件比较小。使用的库文件是MSVCRT.lib
/MT(Release版本) /MTD(Debug版本): 表示运行时库由程序集成。编译出来的文件比较大。在运行的机器上不需要安装依赖的VS的动态库,使用的库文件是LIBCMT.lib
5、MSVC编译参数 /Zi
/Zi选项生成一个单独的 PDB 文件,其中包含用于调试器的所有符号调试信息
6、MSVC编译参数 /Debug
/DEBUG选项为可执行文件创建调试信息文件
7、MSVC编译参数 /OPT:REF /OPT:NOREF
/OPT:REF(Release版本) /OPT:ICF(Debug版本) : 消除从未被引用的函数和数据
/OPT:NOREF(Release版本) /OPT:NOICF(Debug版本) : 默认使用。保留从未引用的函数和数据。
0x09 用户信息
1 | 1 ID |
1、ID
1 | # RUID |
0x10 审计
1 | 1 Linux PROMPT_COMMAND |
1、Linux PROMPT_COMMAND
记录用户、时间、操作,然后将查到的信息记录到一个文件里。
1 | # 记录到指定文件中 |
0x11 inode
1 | 1 inode基础 |
1、inode基础
理解inode,要从文件储存说起。
硬盘的最小存储单位叫做扇区,每个扇区储存512字节。
操作系统存取文件的最小单位是块,最常见的是4KB,即连续的8个扇区。
文件数据都储存在块中,而每一个文件的元信息(比如文件的创建者、文件的创建日期、文件的大小等)存储在inode中。
1 | # inode元信息 |
2、软/硬链接与inode关系
硬链接是多个文件同时指向同个inode,可通过stat的Links数量观察到。
软链接是指向源文件的文件路径。
3、文件拷贝、移动与库动态加载
1 | # 拷贝改变文件inode |