目錄
- 常用基礎(chǔ)命令
- Bash 快捷鍵
- 根目錄結(jié)構(gòu)
- 進程管理
- UID 和 GID
- 權(quán)限設(shè)置
- 字節(jié)序
- 輸入輸出
- 文件描述符
- 核心轉(zhuǎn)儲
- 調(diào)用約定
- 環(huán)境變量
- procfs
- 參考資料
常用基礎(chǔ)命令
ls 用來顯示目標列表
cd [path] 用來切換工作目錄
pwd 以絕對路徑的方式顯示用戶當前工作目錄
man [command] 查看Linux中的指令幫助、配置文件幫助和編程幫助等信息
apropos [whatever] 在一些特定的包含系統(tǒng)命令的簡短描述的數(shù)據(jù)庫文件里查找關(guān)鍵字
echo [string] 打印一行文本,參數(shù)“-e”可激活轉(zhuǎn)義字符
cat [file] 連接文件并打印到標準輸出設(shè)備上
less [file] 允許用戶向前或向后瀏覽文字檔案的內(nèi)容
mv [file1] [file2] 用來對文件或目錄重新命名若河,或者將文件從一個目錄移到另一個目錄中
cp [file1] [file2] 用來將一個或多個源文件或者目錄復制到指定的目的文件或目錄
rm [file] 可以刪除一個目錄中的一個或多個文件或目錄,也可以將某個目錄及其下屬的所有文件及其子目錄均刪除掉
ps 用于報告當前系統(tǒng)的進程狀態(tài)
top 實時查看系統(tǒng)的整體運行情況
kill 殺死一個進程
ifconfig 查看或設(shè)置網(wǎng)絡(luò)設(shè)備
ping 查看網(wǎng)絡(luò)上的主機是否工作
netstat 顯示網(wǎng)絡(luò)連接挥吵、路由表和網(wǎng)絡(luò)接口信息
nc(netcat) 建立 TCP 和 UDP 連接并監(jiān)聽
su 切換當前用戶身份到其他用戶身份
touch [file] 創(chuàng)建新的空文件
mkdir [dir] 創(chuàng)建目錄
chmod 變更文件或目錄的權(quán)限
chown 變更某個文件或目錄的所有者和所屬組
nano / vim / emacs 字符終端的文本編輯器
exit 退出 shell
管道命令符 "|" 將一個命令的標準輸出作為另一個命令的標準輸入
使用變量:
var=value 給變量var賦值value
$var, ${var} 取變量的值
`cmd`, $(cmd) 代換標準輸出
'string' 非替換字符串
"string" 可替換字符串
$ var="test";
$ echo $var
test
$ echo 'This is a $var';
This is a $var
$ echo "This is a $var";
This is a test
$ echo `date`;
2017年 11月 06日 星期一 14:40:07 CST
$ $(bash)
$ echo $0
/bin/bash
$ $($0)
Bash 快捷鍵
Up(Down) 上(下)一條指令
Ctrl + c 終止當前進程
Ctrl + z 掛起當前進程,使用“fg”可喚醒
Ctrl + d 刪除光標處的字符
Ctrl + l 清屏
Ctrl + a 移動到命令行首
Ctrl + e 移動到命令行尾
Ctrl + b 按單詞后移(向左)
Ctrl + f 按單詞前移(向右)
Ctrl + Shift + c 復制
Ctrl + Shift + v 粘貼
更多細節(jié)請查看:Bash Keyboard Shortcuts
根目錄結(jié)構(gòu)
$ uname -a
Linux manjaro 4.11.5-1-ARCH #1 SMP PREEMPT Wed Jun 14 16:19:27 CEST 2017 x86_64 GNU/Linux
$ ls -al /
drwxr-xr-x 17 root root 4096 Jun 28 20:17 .
drwxr-xr-x 17 root root 4096 Jun 28 20:17 ..
lrwxrwxrwx 1 root root 7 Jun 21 22:44 bin -> usr/bin
drwxr-xr-x 4 root root 4096 Aug 10 22:50 boot
drwxr-xr-x 20 root root 3140 Aug 11 11:43 dev
drwxr-xr-x 101 root root 4096 Aug 14 13:54 etc
drwxr-xr-x 3 root root 4096 Apr 8 19:59 home
lrwxrwxrwx 1 root root 7 Jun 21 22:44 lib -> usr/lib
lrwxrwxrwx 1 root root 7 Jun 21 22:44 lib64 -> usr/lib
drwx------ 2 root root 16384 Apr 8 19:55 lost+found
drwxr-xr-x 2 root root 4096 Oct 1 2015 mnt
drwxr-xr-x 15 root root 4096 Jul 15 20:10 opt
dr-xr-xr-x 267 root root 0 Aug 3 09:41 proc
drwxr-x--- 9 root root 4096 Jul 22 22:59 root
drwxr-xr-x 26 root root 660 Aug 14 21:08 run
lrwxrwxrwx 1 root root 7 Jun 21 22:44 sbin -> usr/bin
drwxr-xr-x 4 root root 4096 May 28 22:07 srv
dr-xr-xr-x 13 root root 0 Aug 3 09:41 sys
drwxrwxrwt 36 root root 1060 Aug 14 21:27 tmp
drwxr-xr-x 11 root root 4096 Aug 14 13:54 usr
drwxr-xr-x 12 root root 4096 Jun 28 20:17 var
由于不同的發(fā)行版會有略微的不同,我們這里使用的是基于 Arch 的發(fā)行版 Manjaro,以上就是根目錄下的內(nèi)容劫映,我們介紹幾個重要的目錄:
-
/bin
、/sbin
:鏈接到/usr/bin
刹前,存放 Linux 一些核心的二進制文件,其包含的命令可在 shell 上運行雌桑。 -
/boot
:操作系統(tǒng)啟動時要用到的程序喇喉。 -
/dev
:包含了所有 Linux 系統(tǒng)中使用的外部設(shè)備。需要注意的是這里并不是存放外部設(shè)備的驅(qū)動程序校坑,而是一個訪問這些設(shè)備的端口拣技。 -
/etc
:存放系統(tǒng)管理時要用到的各種配置文件和子目錄千诬。 -
/etc/rc.d
:存放 Linux 啟動和關(guān)閉時要用到的腳本。 -
/home
:普通用戶的主目錄膏斤。 -
/lib
徐绑、/lib64
:鏈接到/usr/lib
,存放系統(tǒng)及軟件需要的動態(tài)鏈接共享庫莫辨。 -
/mnt
:這個目錄讓用戶可以臨時掛載其他的文件系統(tǒng)傲茄。 -
/proc
:虛擬的目錄,是系統(tǒng)內(nèi)存的映射沮榜∨陶ィ可直接訪問這個目錄來獲取系統(tǒng)信息。 -
/root
:系統(tǒng)管理員的主目錄蟆融。 -
/srv
:存放一些服務(wù)啟動之后需要提取的數(shù)據(jù)草巡。 -
/sys
:該目錄下安裝了一個文件系統(tǒng) sysfs。該文件系統(tǒng)是內(nèi)核設(shè)備樹的一個直觀反映型酥。當一個內(nèi)核對象被創(chuàng)建時山憨,對應(yīng)的文件和目錄也在內(nèi)核對象子系統(tǒng)中被創(chuàng)建。 -
/tmp
:公用的臨時文件存放目錄弥喉。 -
/usr
:應(yīng)用程序和文件幾乎都在這個目錄下郁竟。 -
/usr/src
:內(nèi)核源代碼的存放目錄。 -
/var
:存放了很多服務(wù)的日志信息档桃。
進程管理
- top
- 可以實時動態(tài)地查看系統(tǒng)的整體運行情況枪孩。
- ps
- 用于報告當前系統(tǒng)的進程狀態(tài)。可以搭配 kill 指令隨時中斷掏秩、刪除不必要的程序入偷。
- 查看某進程的狀態(tài):
$ ps -aux | grep [file]
,其中返回內(nèi)容最左邊的數(shù)字為進程號(PID)攻询。
- kill
- 用來刪除執(zhí)行中的程序或工作。
- 刪除進程某 PID 指定的進程:
$ kill [PID]
UID 和 GID
Linux 是一個支持多用戶的操作系統(tǒng)州弟,每個用戶都有 User ID(UID) 和 Group ID(GID)钧栖,UID 是對一個用戶的單一身份標識,而 GID 則對應(yīng)多個 UID婆翔。知道某個用戶的 UID 和 GID 是非常有用的拯杠,一些程序可能就需要 UID/GID 來運行】信可以使用 id
命令來查看:
$ id root
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),19(log)
$ id firmy
uid=1000(firmy) gid=1000(firmy) groups=1000(firmy),3(sys),7(lp),10(wheel),90(network),91(video),93(optical),95(storage),96(scanner),98(power),56(bumblebee)
UID 為 0 的 root 用戶類似于系統(tǒng)管理員潭陪,它具有系統(tǒng)的完全訪問權(quán)。我自己新建的用戶 firmy,其 UID 為 1000依溯,是一個普通用戶老厌。GID 的關(guān)系存儲在 /etc/group
文件中:
$ cat /etc/group
root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
sys:x:3:root,bin,firmy
......
所有用戶的信息(除了密碼)都保存在 /etc/passwd
文件中,而為了安全起見黎炉,加密過的用戶密碼保存在 /etc/shadow
文件中枝秤,此文件只有 root 權(quán)限可以訪問。
$ sudo cat /etc/shadow
root:$6$root$wvK.pRXFEH80GYkpiu1tEWYMOueo4tZtq7mYnldiyJBZDMe.mKwt.WIJnehb4bhZchL/93Oe1ok9UwxYf79yR1:17264::::::
firmy:$6$firmy$dhGT.WP91lnpG5/10GfGdj5L1fFVSoYlxwYHQn.llc5eKOvr7J8nqqGdVFKykMUSDNxix5Vh8zbXIapt0oPd8.:17264:0:99999:7:::
由于普通用戶的權(quán)限比較低慷嗜,這里使用 sudo
命令可以讓普通用戶以 root 用戶的身份運行某一命令淀弹。使用 su
命令則可以切換到一個不同的用戶:
$ whoami
firmy
$ su root
# whoami
root
whoami
用于打印當前有效的用戶名稱,shell 中普通用戶以 $
開頭洪添,root 用戶以 #
開頭垦页。在輸入密碼后,我們已經(jīng)從 firmy 用戶轉(zhuǎn)換到 root 用戶了干奢。
權(quán)限設(shè)置
在 Linux 中痊焊,文件或目錄權(quán)限的控制分別以讀取、寫入忿峻、執(zhí)行 3 種一般權(quán)限來區(qū)分薄啥,另有 3 種特殊權(quán)限可供運用。
使用 ls -l [file]
來查看某文件或目錄的信息:
$ ls -l /
lrwxrwxrwx 1 root root 7 Jun 21 22:44 bin -> usr/bin
drwxr-xr-x 4 root root 4096 Jul 28 08:48 boot
-rw-r--r-- 1 root root 18561 Apr 2 22:48 desktopfs-pkgs.txt
第一欄從第二個字母開始就是權(quán)限字符串逛尚,權(quán)限表示三個為一組垄惧,依次是所有者權(quán)限、組權(quán)限绰寞、其他人權(quán)限到逊。每組的順序均為 rwx
,如果有相應(yīng)權(quán)限滤钱,則表示成相應(yīng)字母觉壶,如果不具有相應(yīng)權(quán)限,則用 -
表示件缸。
-
r
:讀取權(quán)限,數(shù)字代號為 “4” -
w
:寫入權(quán)限他炊,數(shù)字代號為 “2” -
x
:執(zhí)行或切換權(quán)限,數(shù)字代號為 “1”
通過第一欄的第一個字母可知蚕苇,第一行是一個鏈接文件 (l
),第二行是個目錄(d
)凿叠,第三行是個普通文件(-
)涩笤。
用戶可以使用 chmod
指令去變更文件與目錄的權(quán)限。權(quán)限范圍被指定為所有者(u
)、所屬組(g
)履恩、其他人(o
)和所有人(a
)锰茉。
- -R:遞歸處理,將指令目錄下的所有文件及子目錄一并處理切心;
- <權(quán)限范圍>+<權(quán)限設(shè)置>:開啟權(quán)限范圍的文件或目錄的該選項權(quán)限設(shè)置
-
$ chmod a+r [file]
:賦予所有用戶讀取權(quán)限
-
- <權(quán)限范圍>-<權(quán)限設(shè)置>:關(guān)閉權(quán)限范圍的文件或目錄的該選項權(quán)限設(shè)置
-
$ chmod u-w [file]
:取消所有者寫入權(quán)限
-
- <權(quán)限范圍>=<權(quán)限設(shè)置>:指定權(quán)限范圍的文件或目錄的該選項權(quán)限設(shè)置;
-
$ chmod g=x [file]
:指定組權(quán)限為可執(zhí)行 -
$ chmod o=rwx [file]
:制定其他人權(quán)限為可讀绽昏、可寫和可執(zhí)行
-
[圖片上傳失敗...(image-299768-1561871018467)]
字節(jié)序
目前計算機中采用兩種字節(jié)存儲機制:大端(Big-endian)和小端(Little-endian)。
MSB (Most Significan Bit/Byte):最重要的位或最重要的字節(jié)肤晓。
LSB (Least Significan Bit/Byte):最不重要的位或最不重要的字節(jié)认然。
Big-endian 規(guī)定 MSB 在存儲時放在低地址,在傳輸時放在流的開始卷员;LSB 存儲時放在高地址,在傳輸時放在流的末尾削饵。Little-endian 則相反未巫。常見的 Intel 處理器使用 Little-endian,而 PowerPC 系列處理器則使用 Big-endian尤仍,另外 TCP/IP 協(xié)議和 Java 虛擬機的字節(jié)序也是 Big-endian狭姨。
例如十六進制整數(shù) 0x12345678 存入以 1000H 開始的內(nèi)存中:
[圖片上傳失敗...(image-6dac46-1561871018467)]
我們在內(nèi)存中實際地看一下,在地址 0xffffd584
處有字符 1234
饼拍,在地址 0xffffd588
處有字符 5678
。
gdb-peda$ x/w 0xffffd584
0xffffd584: 0x34333231
gdb-peda$ x/4wb 0xffffd584
0xffffd584: 0x31 0x32 0x33 0x34
gdb-peda$ python print('\x31\x32\x33\x34')
1234
gdb-peda$ x/w 0xffffd588
0xffffd588: 0x38373635
gdb-peda$ x/4wb 0xffffd588
0xffffd588: 0x35 0x36 0x37 0x38
gdb-peda$ python print('\x35\x36\x37\x38')
5678
gdb-peda$ x/2w 0xffffd584
0xffffd584: 0x34333231 0x38373635
gdb-peda$ x/8wb 0xffffd584
0xffffd584: 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38
gdb-peda$ python print('\x31\x32\x33\x34\x35\x35\x36\x37\x38')
123455678
db-peda$ x/s 0xffffd584
0xffffd584: "12345678"
輸入輸出
- 使用命令的輸出作為可執(zhí)行文件的輸入?yún)?shù)
-
$ ./vulnerable
your_command_here`` $ ./vulnerable $(your_command_here)
-
- 使用命令作為輸入
$ your_command_here | ./vulnerable
- 將命令行輸出寫入文件
$ your_command_here > filename
- 使用文件作為輸入
$ ./vulnerable < filename
文件描述符
在 Linux 系統(tǒng)中一切皆可以看成是文件漓柑,文件又分為:普通文件、目錄文件辆布、鏈接文件和設(shè)備文件。文件描述符(file descriptor)是內(nèi)核管理已被打開的文件所創(chuàng)建的索引景用,使用一個非負整數(shù)來指代被打開的文件惭蹂。
標準文件描述符如下:
文件描述符 | 用途 | stdio 流 |
---|---|---|
0 | 標準輸入 | stdin |
1 | 標準輸出 | stdout |
2 | 標準錯誤 | stderr |
當一個程序使用 fork()
生成一個子進程后,子進程會繼承父進程所打開的文件表,此時弃鸦,父子進程使用同一個文件表,這可能導致一些安全問題。如果使用 vfork()
碳抄,子進程雖然運行于父進程的空間徐裸,但擁有自己的進程表項贫贝。
核心轉(zhuǎn)儲
當程序運行的過程中異常終止或崩潰患雇,操作系統(tǒng)會將程序當時的內(nèi)存、寄存器狀態(tài)酪术、堆棧指針翠储、內(nèi)存管理信息等記錄下來,保存在一個文件中咧七,這種行為就叫做核心轉(zhuǎn)儲(Core Dump)任斋。
會產(chǎn)生核心轉(zhuǎn)儲的信號
Signal | Action | Comment |
---|---|---|
SIGQUIT | Core | Quit from keyboard |
SIGILL | Core | Illegal Instruction |
SIGABRT | Core | Abort signal from abort |
SIGSEGV | Core | Invalid memory reference |
SIGTRAP | Core | Trace/breakpoint trap |
開啟核心轉(zhuǎn)儲
輸入命令
ulimit -c
,輸出結(jié)果為0
瘟檩,說明默認是關(guān)閉的澈蟆。輸入命令
ulimit -c unlimited
即可在當前終端開啟核心轉(zhuǎn)儲功能。-
如果想讓核心轉(zhuǎn)儲功能永久開啟睹簇,可以修改文件
/etc/security/limits.conf
,增加一行:#<domain> <type> <item> <value> * soft core unlimited
修改轉(zhuǎn)儲文件保存路徑
-
通過修改
/proc/sys/kernel/core_uses_pid
磨淌,可以使生成的核心轉(zhuǎn)儲文件名變?yōu)?core.[pid]
的模式凿渊。# echo 1 > /proc/sys/kernel/core_uses_pid
-
還可以修改
/proc/sys/kernel/core_pattern
來控制生成核心轉(zhuǎn)儲文件的保存位置和文件名格式。# echo /tmp/core-%e-%p-%t > /proc/sys/kernel/core_pattern
此時生成的文件保存在
/tmp/
目錄下搪锣,文件名格式為core-[filename]-[pid]-[time]
彩掐。
使用 gdb 調(diào)試核心轉(zhuǎn)儲文件
gdb [filename] [core file]
例子
$ cat core.c
#include <stdio.h>
void main(int argc, char **argv) {
char buf[5];
scanf("%s", buf);
}
$ gcc -m32 -fno-stack-protector core.c
$ ./a.out
AAAAAAAAAAAAAAAAAAAA
Segmentation fault (core dumped)
$ file /tmp/core-a.out-12444-1503198911
/tmp/core-a.out-12444-1503198911: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, from './a.out', real uid: 1000, effective uid: 1000, real gid: 1000, effective gid: 1000, execfn: './a.out', platform: 'i686'
$ gdb a.out /tmp/core-a.out-12444-1503198911 -q
Reading symbols from a.out...(no debugging symbols found)...done.
[New LWP 12444]
Core was generated by `./a.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x5655559b in main ()
gdb-peda$ info frame
Stack level 0, frame at 0x41414141:
eip = 0x5655559b in main; saved eip = <not saved>
Outermost frame: Cannot access memory at address 0x4141413d
Arglist at 0x41414141, args:
Locals at 0x41414141, Previous frame's sp is 0x41414141
Cannot access memory at address 0x4141413d
調(diào)用約定
函數(shù)調(diào)用約定是對函數(shù)調(diào)用時如何傳遞參數(shù)的一種約定佩谷。關(guān)于它的約定有許多種监嗜,下面我們分別從內(nèi)核接口和用戶接口介紹 32 位和 64 位 Linux 的調(diào)用約定。
內(nèi)核接口
x86-32 系統(tǒng)調(diào)用約定:Linux 系統(tǒng)調(diào)用使用寄存器傳遞參數(shù)桐猬。eax
為 syscall_number刽肠,ebx
、ecx
音五、edx
躺涝、esi
、ebp
用于將 6 個參數(shù)傳遞給系統(tǒng)調(diào)用坚嗜。返回值保存在 eax
中苍蔬。所有其他寄存器(包括 EFLAGS)都保留在 int 0x80
中。
x86-64 系統(tǒng)調(diào)用約定:內(nèi)核接口使用的寄存器有:rdi
碟绑、rsi
、rdx
辜荠、r10
、r8
造烁、r9
午笛。系統(tǒng)調(diào)用通過 syscall
指令完成。除了 rcx
告组、r11
和 rax
癌佩,其他的寄存器都被保留。系統(tǒng)調(diào)用的編號必須在寄存器 rax
中傳遞我碟。系統(tǒng)調(diào)用的參數(shù)限制為 6 個姚建,不直接從堆棧上傳遞任何參數(shù)。返回時厘托,rax
中包含了系統(tǒng)調(diào)用的結(jié)果稿湿。而且只有 INTEGER 或者 MEMORY 類型的值才會被傳遞給內(nèi)核。
用戶接口
x86-32 函數(shù)調(diào)用約定:參數(shù)通過棧進行傳遞伊群。最后一個參數(shù)第一個被放入棧中策精,直到所有的參數(shù)都放置完畢,然后執(zhí)行 call 指令丸卷。這也是 Linux 上 C 語言函數(shù)的方式询刹。
x86-64 函數(shù)調(diào)用約定:x86-64 下通過寄存器傳遞參數(shù)萎坷,這樣做比通過棧有更高的效率沐兰。它避免了內(nèi)存中參數(shù)的存取和額外的指令住闯。根據(jù)參數(shù)類型的不同,會使用寄存器或傳參方式比原。如果參數(shù)的類型是 MEMORY量窘,則在棧上傳遞參數(shù)。如果類型是 INTEGER蚌铜,則順序使用 rdi
冬殃、rsi
、rdx
造壮、rcx
耳璧、r8
和 r9
展箱。所以如果有多于 6 個的 INTEGER 參數(shù),則后面的參數(shù)在棧上傳遞攀隔。
環(huán)境變量
環(huán)境變量字符串都是 name=value
這樣的形式栖榨。大多數(shù) name 由大寫字母加下畫線組成,一般把 name 部分叫做環(huán)境變量名满粗,value 部分則是環(huán)境變量的值愚争,而且 value 需要以 "/0" 結(jié)尾挤聘,環(huán)境變量定義了該進程的運行環(huán)境捅彻。
分類
- 按照生命周期劃分
- 永久環(huán)境變量:修改相關(guān)配置文件步淹,永久生效。
- 臨時環(huán)境變量:使用
export
命令广料,在當前終端下生效幼驶,關(guān)閉終端后失效。
- 按照作用域劃分
- 系統(tǒng)環(huán)境變量:對該系統(tǒng)中所有用戶生效购桑。
- 用戶環(huán)境變量:對特定用戶生效氏淑。
設(shè)置方法
-
在文件
/etc/profile
中添加變量,這種方法對所有用戶永久生效缭贡。如:# Set our default path PATH="/usr/local/sbin:/usr/local/bin:/usr/bin" export PATH
添加后執(zhí)行命令
source /etc/profile
使其生效辉懒。 在文件
~/.bash_profile
中添加變量,這種方法對當前用戶永久生效莹汤。其余同上颠印。直接運行命令
export
定義變量,這種方法只對當前終端臨時生效止潮。
常用變量
使用命令 echo
打印變量:
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl
$ echo $HOME
/home/firmy
$ echo $LOGNAME
firmy
$ echo $HOSTNAME
firmy-pc
$ echo $SHELL
/bin/bash
$ echo $LANG
en_US.UTF-8
使用命令 env
可以打印出所有環(huán)境變量:
$ env
COLORFGBG=15;0
COLORTERM=truecolor
...
使用命令 set
可以打印處所有本地定義的 shell 變量:
$ set
'!'=0
'#'=0
...
使用命令 unset
可以清除變量:
unset $變量名
LD_PRELOAD
該環(huán)境變量可以定義在程序運行前優(yōu)先加載的動態(tài)鏈接庫钞楼。在 pwn 題目中,我們可能需要一個特定的 libc仅偎,這時就可以定義該變量:
LD_PRELOAD=/path/to/libc.so ./binary
一個例子:
$ ldd /bin/true
linux-vdso.so.1 => (0x00007fff9a9fe000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1c083d9000)
/lib64/ld-linux-x86-64.so.2 (0x0000557bcce6c000)
$ LD_PRELOAD=~/libc.so.6 ldd /bin/true
linux-vdso.so.1 => (0x00007ffee55e9000)
/home/firmy/libc.so.6 (0x00007f4a28cfc000)
/lib64/ld-linux-x86-64.so.2 (0x000055f33bc50000)
注意橘沥,在加載動態(tài)鏈接庫時需要使用 ld.so
進行重定位,通常被符號鏈接到 /lib64/ld-linux-x86-64.so
中痢艺。動態(tài)鏈接庫在編譯時隱式指定 ld.so
的搜索路徑介陶,并寫入 ELF Header 的 INTERP 字段中。從其他發(fā)行版直接拷貝已編譯的 .so
文件可能會引發(fā) ld.so
搜索路徑不正確的問題舌缤。相似的某残,在版本依賴高度耦合的發(fā)行版中(如 ArchLinux),版本相差過大也會引發(fā) ld.so
的運行失敗介牙。
本地同版本編譯后通常不會出現(xiàn)問題澳厢。如果有直接拷貝已編譯版本的需要剩拢,可以對比 interpreter
確定是否符合要求,但是不保證不會失敗裸扶。
上面的例子中兩個 libc 是這樣的:
$ file /lib/x86_64-linux-gnu/libc-2.23.so
/lib/x86_64-linux-gnu/libc-2.23.so: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=088a6e00a1814622219f346b41e775b8dd46c518, for GNU/Linux 2.6.32, stripped
$ file ~/libc.so.6
/home/firmy/libc.so.6: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=088a6e00a1814622219f346b41e775b8dd46c518, for GNU/Linux 2.6.32, stripped
都是 interpreter /lib64/ld-linux-x86-64.so.2
呵晨,所以可以替換熬尺。
而下面的例子是在 Arch Linux 上使用一個 Ubuntu 的 libc,就會出錯:
$ ldd /bin/true
linux-vdso.so.1 (0x00007ffc969df000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f7ddde17000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f7dde3d7000)
$ LD_PRELOAD=~/libc.so.6 ldd /bin/true
Illegal instruction (core dumped)
$ file /usr/lib/libc-2.26.so
/usr/lib/libc-2.26.so: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /usr/lib/ld-linux-x86-64.so.2, BuildID[sha1]=458fd9997a454786f071cfe2beb234542c1e871f, for GNU/Linux 3.2.0, not stripped
$ file ~/libc.so.6
/home/firmy/libc.so.6: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=088a6e00a1814622219f346b41e775b8dd46c518, for GNU/Linux 2.6.32, stripped
一個在 interpreter /usr/lib/ld-linux-x86-64.so.2
季二,而另一個在 interpreter /lib64/ld-linux-x86-64.so.2
胯舷。
environ
libc 中定義的全局變量 environ
指向環(huán)境變量表。而環(huán)境變量表存在于棧上桑嘶,所以通過 environ
指針的值就可以泄露出棧地址逃顶。
gdb-peda$ vmmap libc
Start End Perm Name
0x00007ffff7a1c000 0x00007ffff7bcf000 r-xp /usr/lib/libc-2.27.so
0x00007ffff7bcf000 0x00007ffff7dce000 ---p /usr/lib/libc-2.27.so
0x00007ffff7dce000 0x00007ffff7dd2000 r--p /usr/lib/libc-2.27.so
0x00007ffff7dd2000 0x00007ffff7dd4000 rw-p /usr/lib/libc-2.27.so
gdb-peda$ vmmap stack
Start End Perm Name
0x00007ffffffde000 0x00007ffffffff000 rw-p [stack]
gdb-peda$ shell nm -D /usr/lib/libc-2.27.so | grep environ
00000000003b8ee0 V environ
00000000003b8ee0 V _environ
00000000003b8ee0 B __environ
gdb-peda$ x/gx 0x00007ffff7a1c000 + 0x00000000003b8ee0
0x7ffff7dd4ee0 <environ>: 0x00007fffffffde48
gdb-peda$ x/5gx 0x00007fffffffde48
0x7fffffffde48: 0x00007fffffffe1da 0x00007fffffffe1e9
0x7fffffffde58: 0x00007fffffffe1fd 0x00007fffffffe233
0x7fffffffde68: 0x00007fffffffe25f
gdb-peda$ x/5s 0x00007fffffffe1da
0x7fffffffe1da: "COLORFGBG=15;0"
0x7fffffffe1e9: "COLORTERM=truecolor"
0x7fffffffe1fd: "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus"
0x7fffffffe233: "DESKTOP_SESSION=/usr/share/xsessions/plasma"
0x7fffffffe25f: "DISPLAY=:0"
procfs
procfs 文件系統(tǒng)是 Linux 內(nèi)核提供的虛擬文件系統(tǒng),為訪問系統(tǒng)內(nèi)核數(shù)據(jù)的操作提供接口霸褒。之所以說是虛擬文件系統(tǒng)盈蛮,是因為它不占用存儲空間眉反,而只是占用了內(nèi)存。用戶可以通過 procfs 查看有關(guān)系統(tǒng)硬件及當前正在運行進程的信息梳凛,甚至可以通過修改其中的某些內(nèi)容來改變內(nèi)核的運行狀態(tài)梳杏。
/proc/cmdline
在啟動時傳遞給內(nèi)核的相關(guān)參數(shù)信息,通常由 lilo 或 grub 等啟動管理工具提供:
$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-4.14-x86_64 root=UUID=8e79a67d-af1b-4203-8c1c-3b670f0ec052 rw quiet resume=UUID=a220ecb1-7fde-4032-87bf-413057e9c06f
/proc/cpuinfo
記錄 CPU 相關(guān)的信息:
$ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 60
model name : Intel(R) Core(TM) i5-4210H CPU @ 2.90GHz
stepping : 3
microcode : 0x24
cpu MHz : 1511.087
cache size : 3072 KB
physical id : 0
siblings : 4
core id : 0
cpu cores : 2
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm cpuid_fault epb invpcid_single pti ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt dtherm ida arat pln pts
bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass
bogomips : 5788.66
clflush size : 64
cache_alignment : 64
address sizes : 39 bits physical, 48 bits virtual
power management:
...
/proc/crypto
已安裝的內(nèi)核所使用的密碼算法及算法的詳細信息:
$ cat /proc/crypto
name : ccm(aes)
driver : ccm_base(ctr(aes-aesni),cbcmac(aes-aesni))
module : ccm
priority : 300
refcnt : 2
selftest : passed
internal : no
type : aead
async : no
blocksize : 1
ivsize : 16
maxauthsize : 16
geniv : <none>
...
/proc/devices
已加載的所有塊設(shè)備和字符設(shè)備的信息叛溢,包含主設(shè)備號和設(shè)備組(與主設(shè)備號對應(yīng)的設(shè)備類型)名:
$ cat /proc/devices
Character devices:
1 mem
4 /dev/vc/0
4 tty
4 ttyS
5 /dev/tty
5 /dev/console
...
/proc/interrupts
X86/X86_64 系統(tǒng)上每個 IRQ 相關(guān)的中斷號列表楷掉,多路處理器平臺上每個 CPU 對于每個 I/O 設(shè)備均有自己的中斷號:
$ cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3
0: 15 0 0 0 IR-IO-APIC 2-edge timer
1: 46235 1277 325 156 IR-IO-APIC 1-edge i8042
8: 0 1 0 0 IR-IO-APIC 8-edge rtc0
...
NMI: 0 0 0 0 Non-maskable interrupts
LOC: 7363806 5569019 6138317 5442200 Local timer interrupts
SPU: 0 0 0 0 Spurious interrupts
...
/proc/kcore
系統(tǒng)使用的物理內(nèi)存霞势,以 ELF 核心文件(core file)格式存儲:
$ sudo file /proc/kcore
/proc/kcore: ELF 64-bit LSB core file x86-64, version 1 (SYSV), SVR4-style, from 'BOOT_IMAGE=/boot/vmlinuz-4.14-x86_64 root=UUID=8e79a67d-af1b-4203-8c1c-3b670f0e'
/proc/meminfo
系統(tǒng)中關(guān)于當前內(nèi)存的利用狀況等的信息:
$ cat /proc/meminfo
MemTotal: 12226252 kB
MemFree: 4909444 kB
MemAvailable: 8776048 kB
Buffers: 288236 kB
Cached: 3953616 kB
...
/proc/mounts
每個進程自身掛載名稱空間中的所有掛載點列表文件的符號鏈接:
$ cat /proc/mounts
proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
sys /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0
dev /dev devtmpfs rw,nosuid,relatime,size=6106264k,nr_inodes=1526566,mode=755 0 0
...
/proc/modules
當前裝入內(nèi)核的所有模塊名稱列表愕贡,可以由 lsmod 命令使用。其中第一列表示模塊名墩虹,第二列表示此模塊占用內(nèi)存空間大小,第三列表示此模塊有多少實例被裝入旬昭,第四列表示此模塊依賴于其它哪些模塊菌湃,第五列表示此模塊的裝載狀態(tài):Live(已經(jīng)裝入)、Loading(正在裝入)和 Unloading(正在卸載)场梆,第六列表示此模塊在內(nèi)核內(nèi)存(kernel memory)中的偏移量:
$ cat /proc/modules
fuse 118784 3 - Live 0xffffffffc0d9b000
ccm 20480 3 - Live 0xffffffffc0d95000
rfcomm 86016 4 - Live 0xffffffffc0d7f000
bnep 24576 2 - Live 0xffffffffc0d78000
...
/proc/slabinfo
保存著監(jiān)視系統(tǒng)中所有活動的 slab 緩存的信息:
$ sudo cat /proc/slabinfo
slabinfo - version: 2.1
# name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
fuse_request 0 20 400 20 2 : tunables 0 0 0 : slabdata 1 1 0
fuse_inode 1 39 832 39 8 : tunables 0 0 0 : slabdata 1 1 0
drm_i915_gem_request 765 1036 576 28 4 : tunables 0 0 0 : slabdata 37 37 0
...
/proc/[pid]
在 /proc 文件系統(tǒng)下纯路,還有一些以數(shù)字命名的目錄驰唬,這些數(shù)字是進程的 PID 號,而這些目錄是進程目錄叫编。目錄下的所有文件如下搓逾,然后會介紹幾個比較重要的:
$ cat - &
[1] 1060
$ ls /proc/1060/
attr comm fd maps ns personality smaps syscall
autogroup coredump_filter fdinfo mem numa_maps projid_map smaps_rollup task
auxv cpuset gid_map mountinfo oom_adj root stack timers
cgroup cwd io mounts oom_score sched stat timerslack_ns
clear_refs environ limits mountstats oom_score_adj schedstat statm uid_map
cmdline exe map_files net pagemap setgroups status wchan
/proc/[pid]/cmdline
啟動當前進程的完整命令:
$ cat /proc/1060/cmdline
cat-
/proc/[pid]/exe
指向啟動當前進程的可執(zhí)行文件的符號鏈接:
$ file /proc/1060/exe
/proc/1060/exe: symbolic link to /usr/bin/cat
/proc/[pid]/root
當前進程運行根目錄的符號鏈接:
$ file /proc/1060/root
/proc/1060/root: symbolic link to /
/proc/[pid]/mem
當前進程所占用的內(nèi)存空間,由open世蔗、read和lseek等系統(tǒng)調(diào)用使用朗兵,不能被用戶讀取余掖。但可通過下面的 /proc/[pid]/maps 查看。
/proc/[pid]/maps
這個文件大概是最常用的盐欺,用于顯示進程的內(nèi)存區(qū)域映射信息:
$ cat /proc/1060/maps
56271b3a5000-56271b3ad000 r-xp 00000000 08:01 24904069 /usr/bin/cat
56271b5ac000-56271b5ad000 r--p 00007000 08:01 24904069 /usr/bin/cat
56271b5ad000-56271b5ae000 rw-p 00008000 08:01 24904069 /usr/bin/cat
56271b864000-56271b885000 rw-p 00000000 00:00 0 [heap]
7fefb66cd000-7fefb6a1e000 r--p 00000000 08:01 24912207 /usr/lib/locale/locale-archive
7fefb6a1e000-7fefb6bd1000 r-xp 00000000 08:01 24905238 /usr/lib/libc-2.27.so
7fefb6bd1000-7fefb6dd0000 ---p 001b3000 08:01 24905238 /usr/lib/libc-2.27.so
7fefb6dd0000-7fefb6dd4000 r--p 001b2000 08:01 24905238 /usr/lib/libc-2.27.so
7fefb6dd4000-7fefb6dd6000 rw-p 001b6000 08:01 24905238 /usr/lib/libc-2.27.so
7fefb6dd6000-7fefb6dda000 rw-p 00000000 00:00 0
7fefb6dda000-7fefb6dff000 r-xp 00000000 08:01 24905239 /usr/lib/ld-2.27.so
7fefb6fbd000-7fefb6fbf000 rw-p 00000000 00:00 0
7fefb6fdc000-7fefb6ffe000 rw-p 00000000 00:00 0
7fefb6ffe000-7fefb6fff000 r--p 00024000 08:01 24905239 /usr/lib/ld-2.27.so
7fefb6fff000-7fefb7000000 rw-p 00025000 08:01 24905239 /usr/lib/ld-2.27.so
7fefb7000000-7fefb7001000 rw-p 00000000 00:00 0
7ffde5659000-7ffde567a000 rw-p 00000000 00:00 0 [stack]
7ffde5748000-7ffde574b000 r--p 00000000 00:00 0 [vvar]
7ffde574b000-7ffde574d000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
/proc/[pid]/stack
這個文件表示當前進程的內(nèi)核調(diào)用棧信息找田,只有在內(nèi)核編譯啟用 CONFIG_STACKTRACE
選項着憨,才會生成該文件:
$ sudo cat /proc/1060/stack
[<ffffffff8e08fa2e>] do_signal_stop+0xae/0x1f0
[<ffffffff8e090ec1>] get_signal+0x191/0x580
[<ffffffff8e02ae56>] do_signal+0x36/0x610
[<ffffffff8e003669>] exit_to_usermode_loop+0x69/0xa0
[<ffffffff8e0039d1>] do_syscall_64+0xf1/0x100
[<ffffffff8e800081>] entry_SYSCALL_64_after_hwframe+0x3d/0xa2
[<ffffffffffffffff>] 0xffffffffffffffff
/proc/[pid]/auxv
該文件包含了傳遞給進程的解釋器信息,即 auxv(AUXiliary Vector)漆改,每一項都是由一個 unsigned long 長度的 ID 加上一個 unsigned long 長度的值構(gòu)成:
$ xxd -e -g8 /proc/1060/auxv
00000000: 0000000000000021 00007ffde574b000 !.........t.....
00000010: 0000000000000010 00000000bfebfbff ................
00000020: 0000000000000006 0000000000001000 ................
00000030: 0000000000000011 0000000000000064 ........d.......
00000040: 0000000000000003 000056271b3a5040 ........@P:.'V..
00000050: 0000000000000004 0000000000000038 ........8.......
00000060: 0000000000000005 0000000000000009 ................
00000070: 0000000000000007 00007fefb6dda000 ................
00000080: 0000000000000008 0000000000000000 ................
00000090: 0000000000000009 000056271b3a7260 ........`r:.'V..
000000a0: 000000000000000b 00000000000003e8 ................
000000b0: 000000000000000c 00000000000003e8 ................
000000c0: 000000000000000d 00000000000003e8 ................
000000d0: 000000000000000e 00000000000003e8 ................
000000e0: 0000000000000017 0000000000000000 ................
000000f0: 0000000000000019 00007ffde5678349 ........I.g.....
00000100: 000000000000001a 0000000000000000 ................
00000110: 000000000000001f 00007ffde5679fef ..........g.....
00000120: 000000000000000f 00007ffde5678359 ........Y.g.....
00000130: 0000000000000000 0000000000000000 ................
每個值具體是做什么的挫剑,可以用下面的辦法顯示出來樊破,對比看一看,更詳細的可以查看 /usr/include/elf.h
和 man ld.so
:
$ LD_SHOW_AUXV=1 cat -
AT_SYSINFO_EHDR: 0x7ffd16be5000
AT_HWCAP: bfebfbff
AT_PAGESZ: 4096
AT_CLKTCK: 100
AT_PHDR: 0x55eb4c59a040
AT_PHENT: 56
AT_PHNUM: 9
AT_BASE: 0x7f61506e8000
AT_FLAGS: 0x0
AT_ENTRY: 0x55eb4c59c260
AT_UID: 1000
AT_EUID: 1000
AT_GID: 1000
AT_EGID: 1000
AT_SECURE: 0
AT_RANDOM: 0x7ffd16bd0ce9
AT_HWCAP2: 0x0
AT_EXECFN: /bin/cat
AT_PLATFORM: x86_64
值得一提的是奔滑,AT_SYSINFO_EHDR
所對應(yīng)的值是一個叫做的 VDSO(Virtual Dynamic Shared Object) 的地址顺少。在 ret2vdso 漏洞利用方法中會用到(參考章節(jié)6.1.6)。
/proc/[pid]/environ
該文件包含了進程的環(huán)境變量:
$ strings /proc/1060/environ
GS_LIB=/home/firmy/.fonts
KDE_FULL_SESSION=true
VIRTUALENVWRAPPER_WORKON_CD=1
VIRTUALENVWRAPPER_HOOK_DIR=/home/firmy/.virtualenvs
LANG=zh_CN.UTF-8
...
/proc/[pid]/fd
該文件包含了進程打開文件的情況:
$ ls -al /proc/1060/fd
total 0
dr-x------ 2 firmy firmy 0 6月 7 23:37 .
dr-xr-xr-x 9 firmy firmy 0 6月 7 23:37 ..
lrwx------ 1 firmy firmy 64 6月 7 23:44 0 -> /dev/pts/3
lrwx------ 1 firmy firmy 64 6月 7 23:44 1 -> /dev/pts/3
lrwx------ 1 firmy firmy 64 6月 7 23:44 2 -> /dev/pts/3
/proc/[pid]/status
該文件包含了進程的狀態(tài)信息:
$ cat /proc/1060/status
Name: cat
Umask: 0022
State: T (stopped)
Tgid: 1060
Ngid: 0
Pid: 1060
PPid: 1035
TracerPid: 0
Uid: 1000 1000 1000 1000
Gid: 1000 1000 1000 1000
FDSize: 256
Groups: 3 7 10 56 90 91 93 95 96 98 1000
...
/proc/[pid]/task
一個目錄梅猿,包含當前進程的每一個線程的相關(guān)信息秒裕,每個線程的信息分別放在一個由線程號(tid)命名的目錄中:
$ ls /proc/1060/task/
1060
$ ls /proc/1060/task/1060/
attr clear_refs cwd fdinfo maps net oom_score projid_map setgroups stat uid_map
auxv cmdline environ gid_map mem ns oom_score_adj root smaps statm wchan
cgroup comm exe io mountinfo numa_maps pagemap sched smaps_rollup status
children cpuset fd limits mounts oom_adj personality schedstat stack syscall
/proc/[pid]/syscall
該文件包含了進程正在執(zhí)行的系統(tǒng)調(diào)用:
$ sudo cat /proc/1060/syscall
0 0x0 0x7fefb6fdd000 0x20000 0x22 0xffffffff 0x0 0x7ffde5677d48 0x7fefb6b07901
第一個值是系統(tǒng)調(diào)用號几蜻,后面跟著是六個參數(shù),最后兩個值分別是堆棧指針和指令計數(shù)器的值响蓉。
參考資料
來源:GitHub