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

基於 libpcap 的 QQ 號碼網絡嗅探實戰:UDP 協議分析、報文過濾與異步抓包完整實現

     編輯:關於C語言

從 Wireshark 分析到 libpcap 代碼:QQ 登錄協議逆向與實時號碼捕獲

本項目實現基於 libpcap 的網絡數據包捕獲程序,針對 QQ 客戶端登錄過程中的 UDP/OICQ 協議數據包,從以太網幀中提取 QQ 號碼(位於固定偏移量 49-52 字節,4 字節無符號整數)。涵蓋協議逆向分析、BPF 過濾器設計、數據包解析架構、端口特徵識別、異常處理等完整工程流程。

一、 協議逆向分析與特徵提取

1. QQ 通訊協議特徵

  • 傳輸層:UDP(客戶端端口 4000 起遞增,服務端固定 8000)。
  • 應用層:OICQ 協議(UDP 封裝),控制命令如 Request KEY (29)、Request login (98) 等攜帶 QQ 號。
  • 關鍵發現:在 UDP 負載固定偏移 49-52 字節 (0-based) 存儲明文 QQ 號(大端序 4 字節無符號整數)。

2. Wireshark 過濾器驗證

# 精確匹配 OICQ 協議包含 QQ 號的包
oicq && udp.srcport < 4100

# 僅 UDP 端口過濾(libpcap 支持)
udp dst port 8000 and udp src port < 4100

經驗證,UDP 負載同偏移位置同樣包含明文 QQ 號,無需解析 OICQ 協議層,大幅簡化解析邏輯。

二、 libpcap 開發框架與數據結構定義

1. 協議頭部結構體定義 (sniffer.h)

#ifndef __SNIFFER_H__
#define __SNIFFER_H__

#include 
#include 
#include  // ETHER_ADDR_LEN

// 以太網幀頭 (14 字節)
struct sniff_ethernet {
    u_char ether_dhost[ETHER_ADDR_LEN];
    u_char ether_shost[ETHER_ADDR_LEN];
    u_short ether_type;
};

// IP 頭部 (最小 20 字節,含選項可變)
struct sniff_ip {
    u_char ip_vhl;      // 版本(4位) + 首部長度(4位)
    u_char ip_tos;
    u_short ip_len;
    u_short ip_id;
    u_short ip_off;
    u_char ip_ttl;
    u_char ip_p;        // 協議號 (IPPROTO_UDP = 17)
    u_short ip_sum;
    struct in_addr ip_src, ip_dst;
};

// UDP 頭部 (固定 8 字節)
struct sniff_udp {
    u_short uh_sport;   // 源端口
    u_short uh_dport;   // 目的端口
    u_short uh_ulen;    // 長度
    u_short uh_sum;     // 校驗和
};

#endif

2. 關鍵點:字節序與對齊

  • 網絡字節序為大端序,主機通常為小端序,必須用 ntohs()/ntohl() 轉換端口、長度、IP 地址。
  • 結構體定義需匹配協議頭部無填充對齊,或使用 #pragma pack(1),或手動計算偏移(推薦手動偏移,避免編譯器差異)。

三、 核心回調函數實現 (getPacket)

#include "sniffer.h"

void getPacket(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) {
    static int count = 0;
    
    // 1. 手動計算偏移解析(避免結構體對齊陷阱)
    const int eth_len = 14;
    const u_char *ip_ptr = packet + eth_len;
    
    // IP 版本與首部長度
    u_char ip_vhl = ip_ptr[0];
    int ip_hl = (ip_vhl & 0x0F) * 4; // 低4位 * 4 = 首部字節長度
    if (ip_hl < 20) return; // 異常包
    
    // 協議判斷:IP 头第 9 字節 (偏移 8) 為協議號
    if (ip_ptr[9] != IPPROTO_UDP) return; // 非 UDP 丟棄
    
    const u_char *udp_ptr = ip_ptr + ip_hl;
    int udp_len = 8; // UDP 固定頭部 8 字節
    
    // 端口提取 (網絡序轉主機序)
    u_short sport = ntohs(*(u_short*)(udp_ptr + 0));
    u_short dport = ntohs(*(u_short*)(udp_ptr + 2));
    
    // 2. 過濾邏輯:目標端口 8000,源端口 4000-4099 (單機多 QQ 實例)
    if (dport != 8000 || sport < 4000 || sport >= 4100) return;
    
    // 3. 提取 QQ 號:UDP 負載起始 + 41 字節偏移 (UDP頭8 + 負載偏移41 = 總偏移49)
    // 實測:以太網幀第 49-52 字節 (索引 48-51)
    const u_char *payload = udp_ptr + udp_len;
    if (header->caplen < eth_len + ip_hl + udp_len + 41 + 4) return; // 長度不足
    
    uint32_t qq = ntohl(*(uint32_t*)(payload + 41)); // 大端序轉主機序
    
    // 4. 輸出結果
    char src_ip[INET_ADDRSTRLEN], dst_ip[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, (void*)(ip_ptr+12), src_ip, sizeof(src_ip));
    inet_ntop(AF_INET, (void*)(ip_ptr+16), dst_ip, sizeof(dst_ip));
    
    printf("Packet #%d: %s:%d -> %s:%d  QQ: %u\n", 
           ++count, src_ip, sport, dst_ip, dport, qq);
}

四、 主程序:設備選擇、過濾器編譯、循環抓包

int main(int argc, char **argv) {
    char errbuf[PCAP_ERRBUF_SIZE];
    char *dev = pcap_lookupdev(errbuf);
    if (!dev) { fprintf(stderr, "找不到設備: %s\n", errbuf); return -1; }
    printf("監聽設備: %s\n", dev);
    
    // 打開設備:混雜模式、快照長度 65535、超時 1ms
    pcap_t *handle = pcap_open_live(dev, 65535, 1, 1000, errbuf);
    if (!handle) { fprintf(stderr, "打開失敗: %s\n", errbuf); return -1; }
    
    // 編譯並設置 BPF 過濾器:只抓目的端口 8000 的 UDP
    struct bpf_program fp;
    char filter_exp[] = "udp dst port 8000";
    if (pcap_compile(handle, &fp, filter_exp, 1, PCAP_NETMASK_UNKNOWN) == -1) {
        fprintf(stderr, "過濾器編譯失敗: %s\n", pcap_geterr(handle));
        return -1;
    }
    if (pcap_setfilter(handle, &fp) == -1) {
        fprintf(stderr, "設置過濾器失敗: %s\n", pcap_geterr(handle));
        return -1;
    }
    pcap_freecode(&fp);
    
    // 進入無限循環抓包
    pcap_loop(handle, -1, getPacket, NULL);
    
    pcap_close(handle);
    return 0;
}

五、 編譯運行與權限說明

# 編譯 (需鏈接 libpcap)
gcc sniffer.c -o sniffer -lpcap

# 運行 (需要 root 權限或 CAP_NET_RAW)
sudo ./sniffer

六、 已知問題與優化方向

  1. OICQ 協議變體:極少數 MEMO Operation (62) 包中出現非目標 QQ 號,原因未明(可能為群消息轉發、好友狀態同步等)。建議結合命令字節 (負載偏移 0-1) 進一步過濾登錄相關命令 (29, 98)。
  2. IP 分片重組:大包可能分片,導致 UDP 負載不完整。需引入分片重組邏輯(識別 IP 標識/標志/偏移)。
  3. IPv6 支持:當前僅解析 IPv4,需擴展支持 IPv6 (協議號 41, 17)。
  4. 性能優化:高流量下 pcap_loop 回調開銷大,可用 pcap_dispatch 批量處理或 PF_RING/AF_XDP 零拷貝框架。
  5. 校驗和驗證:驗證 UDP 校驗和排除偽造/損壞包。

七、 法律與道德邊界

警告:網絡嗅探屬於敏感技術。僅授權在自己管理的網絡、針對自己帳號、用於學習協議分析/安全審計時使用。未經授權捕獲他人數據包、提取帳號信息,違反《網絡安全法》《計算機信息網絡國際聯網管理暫行規定》等法律法規,構成非法獲取計算機信息系統數據罪風險。本代碼僅供教學研究參考,請嚴格遵守法律法規與道德規範。

技術總結:本項目展示了從協議逆向分析 (Wireshark) → 特徵提取 (固定偏移 QQ 號) → BPF 過濾器設計 (udp dst port 8000) → libpcap 異步回調架構 → 手動偏移解析避免對齊坑 → 字節序轉換 (ntohs/ntohl) 的完整網絡嗅探工程閉環。核心難點在於協議層疊偏移精確計算與異常包健壯性處理。

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