首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

原始套接字實作網路封包監聽:混雜模式、封包捕獲與標頭解析

     編輯:關於VC++

前言

網路監聽工具 (Sniffer) 讓管理員檢視區域網路所有傳輸封包。核心在於將網卡設為「混雜模式」,接收非本機 MAC 位址的封包。Windows 下透過「原始套接字」即可實現,無需撰寫核心驅動,本文詳細說明原理與 VC++ 實作步驟。

網路監聽原理

  • 一般模式:網卡硬體過濾,僅接收目的 MAC 為本機或廣播的封包。
  • 混雜模式:網卡接收所有經過的封包,交由驅動程式上傳作業系統。
  • 原始套接字:繞過 TCP/IP 協議棧,直接存取資料鏈路層封包 (含 IP/TCP/UDP 標頭)。

實作關鍵步驟

  1. 初始化 Winsock:WSAStartup(MAKEWORD(2,2), &wsaData)。
  2. 建立原始套接字:socket(AF_INET, SOCK_RAW, IPPROTO_IP) (需 Administrator 權限)。
  3. 設定 IP 標頭選項:setsockopt(s, IPPROTO_IP, IP_HDRINCL, ...) 讓應用程式自行填入 IP 標頭。
  4. 綁定本機介面:bind(s, (sockaddr*)&local, sizeof(local)),local.sin_addr.s_addr 設為本機 IP。
  5. 啟用混雜模式:WSAIoctl(s, SIO_RCVALL, &opt, sizeof(opt), NULL, 0, &dwBytes, NULL, NULL),opt=TRUE。
  6. 接收封包迴圈:recvfrom(s, buf, sizeof(buf), 0, &from, &fromlen) 取得完整封包 (含 IP/TCP/UDP 標頭)。
  7. 解析標頭:依 IP Header 判斷協議 (TCP/UDP/ICMP),再解析對應傳輸層標頭、應用層資料。

核心程式碼範例


// 1. 初始化
WSADATA wsaData; WSAStartup(MAKEWORD(2,2), &wsaData);

// 2. 建立 Raw Socket
SOCKET s = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
if (s == INVALID_SOCKET) return;

// 3. 設定 IP_HDRINCL
BOOL bOpt = TRUE;
setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char*)&bOpt, sizeof(bOpt));

// 4. 綁定本機 IP
sockaddr_in local; local.sin_family = AF_INET;
local.sin_addr.s_addr = inet_addr("192.168.1.100"); // 本機 IP
local.sin_port = 0;
bind(s, (sockaddr*)&local, sizeof(local));

// 5. 啟用混雜模式
DWORD dwBytes;
WSAIoctl(s, SIO_RCVALL, &bOpt, sizeof(bOpt), NULL, 0, &dwBytes, NULL, NULL);

// 6. 接收迴圈
char buf[65536];
sockaddr_in from; int fromlen = sizeof(from);
while (running) {
    int n = recvfrom(s, buf, sizeof(buf), 0, (sockaddr*)&from, &fromlen);
    if (n > 0) ParsePacket(buf, n);
}

// 7. 關閉
closesocket(s); WSACleanup();

封包解析 ParsePacket 關鍵點


void ParsePacket(char* buf, int len) {
    IPHeader* ip = (IPHeader*)buf;
    if (len < sizeof(IPHeader)) return;

    // IP 標頭長度 (IHL * 4)
    int ipHeaderLen = (ip->ver_ihl & 0x0F) * 4;
    char* transport = buf + ipHeaderLen;

    switch (ip->protocol) {
        case IPPROTO_TCP: {
            TCPHeader* tcp = (TCPHeader*)transport;
            // 解析 Source/Dest Port, Seq, Ack, Flags...
            break;
        }
        case IPPROTO_UDP: {
            UDPHeader* udp = (UDPHeader*)transport;
            // 解析 Port, Length...
            break;
        }
        case IPPROTO_ICMP: {
            ICMPHeader* icmp = (ICMPHeader*)transport;
            // 解析 Type, Code...
            break;
        }
    }
    // 顯示來源/目的 IP、協議、資料長度、前幾位元資料...
}

限制與注意事項

  • 需 Administrator 權限:建立 SOCK_RAW 與 SIO_RCVALL 要求提升權限。
  • 無法攔截/修改封包:唯讀監聽,若需防火牆功能需改用 TDI 驅動或 WFP (Windows Filtering Platform)。
  • 不含資料鏈路層標頭:無法取得 Ethernet 標頭 (MAC 位址),也無法接收 ARP/RARP 等非 IP 封包。
  • 效能:高流量網路下 recvfrom 可能成為瓶頸,建議使用非阻塞/重疊 I/O 或專用驅動。
  • WinPcap/Npcap 替代方案:業界標準庫,支援更完整的鏈路層存取、跨平台、BPF 過濾器,生產環境建議改用。

總結

原始套接字提供了一種無需驅動開發即可實現網路封包監聽的方法,適合教學、簡易診斷工具。但受限於權限、效能與功能限制,正式產品級監聽仍建議使用 WinPcap/Npcap 或 WFP 驅動層方案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved