什麼時候不該用封包嗅探#
有時候封包嗅探(packet sniffing)並不合適。例如你沒有擷取流量的權限——正在對一個沒有管理權限的系統做滲透測試,或面對的是一支只有受限權限 shell 的行動裝置。也有時候你只想看「受測應用程式」的流量,而封包嗅探除非用時間去關聯,否則很難做到這件事。
本節介紹幾種不靠封包嗅探工具、直接從本機應用程式取出網路流量的技術。
系統呼叫追蹤#
現代作業系統多半提供兩種執行模式:核心模式(kernel mode) 以高權限執行,內含實作作業系統核心功能的程式碼;使用者模式(user mode) 則是日常行程執行的地方。核心透過匯出一組特殊的系統呼叫(system call) 為使用者模式提供服務,讓程式能存取檔案、建立行程——而對我們最重要的——連上網路。

圖表 2-4:透過系統呼叫進行的使用者模式對核心模式網路通訊範例
當應用程式要連線到遠端伺服器,它會對核心發出特殊的系統呼叫來開啟連線,接著讀寫網路資料。依作業系統不同,你可以直接監看這些呼叫,被動地把資料從應用程式中抽取出來。
大多數類 Unix 系統的網路系統呼叫都近似 Berkeley Sockets 模型。這並不意外:IP 協定最初就是在 BSD(Berkeley Software Distribution)4.2 Unix 上實作的。這套 socket 實作也是 POSIX 的一部分,使它成為事實標準。
| 名稱 | 說明 |
|---|---|
socket | 建立新的 socket 檔案描述子(file descriptor)。 |
connect | 將 socket 連到已知的 IP 位址與連接埠。 |
bind | 將 socket 綁定到本機已知的 IP 位址與連接埠。 |
recv / read / recvfrom | 透過 socket 從網路接收資料。read 是讀取檔案描述子的通用函式,recv 與 recvfrom 則專屬於 socket API。 |
send / write / sendfrom | 透過 socket 將資料送上網路。 |
想深入了解這些系統呼叫,《The TCP/IP Guide》(No Starch Press, 2005)是很好的資源;線上資料也很多。多數類 Unix 系統本身就附有手冊,在終端機執行
man 2 syscall_name即可查閱。
Linux 上的 strace#
在 Linux 上,你可以直接從使用者程式監看系統呼叫,不需要特殊權限——除非目標應用程式是以特權使用者身分執行。許多 Linux 發行版都內建 strace 這支好用的工具;若沒有預裝,可從發行版的套件管理員下載,或自行從原始碼編譯。
把 /path/to/app 換成受測應用程式、args 換成必要參數,即可記錄該應用程式使用的網路系統呼叫:
strace -e trace=network,read,write /path/to/app args範例:解讀 strace 的輸出
以下是一支會讀寫幾個字串的網路應用程式,經 strace 監看後的輸出(為求簡潔已移除無關的記錄):
$ strace -e trace=network,read,write customapp
--snip--
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(5555),
sin_addr=inet_addr("192.168.10.1")}, 16) = 0
write(3, "Hello World!\n", 13) = 13
read(3, "Boo!\n", 2048) = 5- 第一筆建立了新的 TCP socket,取得代號
3。 - 第二筆的
connect對 IP 位址192.168.10.1的 5555 埠建立 TCP 連線。 - 接著應用程式寫出字串
Hello World!。 - 最後讀回字串
Boo!。
即使沒有高權限,也能從系統呼叫層級對應用程式的行為建立相當清楚的輪廓。
以 DTrace 監看網路連線#
DTrace 是一套非常強大的工具,可用於許多類 Unix 系統,包括 Solaris(它的發源地)、macOS 與 FreeBSD。它讓你在特殊的追蹤提供者(trace provider,含系統呼叫)上設置系統層級的探針(probe)。設定方式是以一種 C 風格語法的語言撰寫腳本。
範例:traceconnect.d 腳本與輸出
以下腳本監看 connect 系統呼叫,輸出 IPv4 的 TCP 與 UDP 連線:
/* traceconnect.d - A simple DTrace script to monitor a connect system call */
struct sockaddr_in {
short sin_family;
unsigned short sin_port;
in_addr_t sin_addr;
char sin_zero[8];
};
syscall::connect:entry
/arg2 == sizeof(struct sockaddr_in)/
{
addr = (struct sockaddr_in*)copyin(arg1, arg2);
printf("process:'%s' %s:%d", execname, inet_ntop(2, &addr->sin_addr),
ntohs(addr->sin_port));
}connect 有三個參數,在 DTrace 腳本語言中以 arg0、arg1、arg2 表示,並由核心替我們初始化:
arg0是 socket 檔案描述子,本例用不到。arg1是要連線的 socket 位址結構在使用者行程記憶體中的位址;依 socket 型別不同,大小也不同(例如 IPv4 位址就比 IPv6 小)。arg2是該位址結構的位元組長度。
腳本先定義了 IPv4 連線使用的 sockaddr_in 結構(很多情況下可直接從系統的 C 標頭檔複製過來),接著指定要監看的系統呼叫,再以 DTrace 專屬的過濾條件確保只追蹤 socket 位址大小等於 sockaddr_in 的 connect 呼叫。然後把 sockaddr_in 從目標行程複製到本地結構供 DTrace 檢視,最後把行程名稱、目的 IP 位址與連接埠印到主控台。
把腳本存成 traceconnect.d,以 root 身分執行 dtrace -s traceconnect.d。當你使用有網路連線的應用程式時,輸出會類似:
process:'Google Chrome' 173.194.78.125:5222
process:'Google Chrome' 173.194.66.95:443
process:'Google Chrome' 217.32.28.199:80
process:'ntpd' 17.72.148.53:123
process:'Mail' 173.194.67.109:993
process:'syncdefaultsd' 17.167.137.30:443
process:'AddressBookSour' 17.172.192.30:443DTrace 的輸出不一定像 Linux 上的
strace那麼有用——它列出的是連線目標而非資料內容——但它仍是價值很高的工具,上面的示範也只觸及它能力的皮毛。更多細節可參考線上的 DTrace Guide:http://www.dtracebook.com/index.php/DTrace_Guide ↗。
Windows 上的 Process Monitor#
與類 Unix 系統不同,Windows 的使用者模式網路功能並非以直接的系統呼叫實作。網路堆疊是透過驅動程式對外提供,建立連線時是用檔案的 open、read、write 系統呼叫去設定一個網路 socket。即使 Windows 有類似 strace 的機制,這種實作方式也讓「與其他平台同層級的網路監看」變得更困難。
從 Vista 之後,Windows 支援一套事件產生框架(event generation framework),讓應用程式能監看網路活動。自行實作相當複雜,所幸微軟的 Process Monitor 已經幫你做好了。

圖表 2-5:Process Monitor 擷取範例
在 Process Monitor 中套用只顯示網路連線事件的過濾器後,你會看到受監看行程的網路連線事件,細節包含涉及的主機、使用的協定與連接埠。單一 HTTP 連線的檢視會呈現這些欄位:
- 建立連線的行程名稱。
- 操作類型——本例是連線到遠端伺服器、送出初始 HTTP 請求、接收回應。
- 來源與目的位址。
- 該擷取事件的更深入資訊。

圖表 2-6:單一擷取到的連線
Process Monitor 還能擷取當下呼叫堆疊(calling stack)的狀態,幫你判斷應用程式是在哪裡建立網路連線的。這一點到第 6 章開始逆向工程二進位檔、推導網路協定時會變得很重要。
這個方法無法擷取連線所帶的資料,它只告訴你連線的存在與後設資訊。不過一旦確定了應用程式使用哪些協定,你就能把這項資訊帶進更主動的擷取方式,繼續往下分析。
被動擷取的優點與缺點#
優點
- 最大的優點是不會擾亂用戶端與伺服器之間的通訊:不改變流量的來源或目的位址,也不需要修改或重新設定應用程式。
- 當你無法直接控制用戶端或伺服器時,被動擷取往往是唯一可行的技術。通常你都能找到某種方式聽到網路流量,投入的工夫也有限。
- 收集到資料之後,你就能判斷該採用哪些主動擷取技術,以及攻擊目標協定的最佳路徑。
缺點
- 封包嗅探這類技術執行層級太低,難以還原「應用程式實際收到了什麼」。Wireshark 這類工具確實有幫助,但面對自訂協定時,不與它互動往往就無法輕易拆解。
- 被動擷取不易修改應用程式產生的流量。修改流量不是永遠必要,但在遇到加密協定、想關閉壓縮、或需要為了漏洞利用而竄改流量時就非常有用。
當「分析流量並注入新封包」得不到結果時,就該換戰術,改用主動擷取技術。