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

Linux C 原始套接字發送 ARP 數據包:構造以太網幀與 ARP 請求/應答完整實現

     編輯:關於C語言

前言

ARP (Address Resolution Protocol) 將 IPv4 地址解析為 MAC 地址。在 Linux 下,通過 **原始套接字 (`PF_PACKET`, `SOCK_RAW`)** 可直接發送/接收鏈路層幀,實現 ARP 掃描、代理 ARP、網路攻擊測試等功能。本文提供完整、可編譯的 C 代碼,手動構造以太網頭 + ARP 負載,支援自定義源/目標 IP/MAC。

核心協議結構


#include <linux/if_ether.h>  // 以太網頭定義
#include <netinet/if_ether.h> // ARP 結構 (部分系統)

#pragma pack(push, 1)
struct ArpPacket {
    // 以太網頭 (14 bytes)
    uint8_t  dst_mac[6];      // 目標 MAC (廣播 ff:ff:ff:ff:ff:ff)
    uint8_t  src_mac[6];      // 源 MAC
    uint16_t eth_type;        // 0x0806 = ARP

    // ARP 負載 (28 bytes for IPv4/Ethernet)
    uint16_t htype;           // 硬件類型 1 = Ethernet
    uint16_t ptype;           // 協議類型 0x0800 = IPv4
    uint8_t  hlen;            // 硬件地址長度 6
    uint8_t  plen;            // 協議地址長度 4
    uint16_t oper;            // 1=請求 2=應答
    uint8_t  sha[6];          // 發送方硬件地址
    uint8_t  spa[4];          // 發送方協議地址
    uint8_t  tha[6];          // 目標硬件地址 (請求時全 0)
    uint8_t  tpa[4];          // 目標協議地址
    uint8_t  pad[18];         // 填充至最小幀長 64B (含 FCS)
};
#pragma pack(pop)

關鍵常數


#define ETH_P_ARP 0x0806
#define ARPHRD_ETHER 1
#define ARPOP_REQUEST 1
#define ARPOP_REPLY   2
#define IFACE "eth0"  // 預設介面

完整發送程式


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <net/if_arp.h>

void die(const char* msg) { perror(msg); exit(1); }

void parse_mac(const char* str, uint8_t* mac) {
    sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
           &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
}

void parse_ip(const char* str, uint8_t* ip) {
    struct in_addr addr;
    inet_pton(AF_INET, str, &addr);
    memcpy(ip, &addr, 4);
}

int main(int argc, char* argv[]) {
    if (argc != 6) {
        fprintf(stderr,
            "Usage: %s     \n"
            "Example: %s 192.168.1.100 aa:bb:cc:dd:ee:ff 192.168.1.1 ff:ff:ff:ff:ff:ff 5\n",
            argv[0], argv[0]);
        return 1;
    }

    // 1. 建立原始套接字
    int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if (sock < 0) die("socket");

    // 2. 獲取介面索引
    struct ifreq ifr;
    strncpy(ifr.ifr_name, IFACE, IFNAMSIZ-1);
    if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) die("SIOCGIFINDEX");
    int ifindex = ifr.ifr_ifindex;

    // 3. 綁定介面
    struct sockaddr_ll sll = {0};
    sll.sll_family = AF_PACKET;
    sll.sll_ifindex = ifindex;
    sll.sll_protocol = htons(ETH_P_ARP);
    if (bind(sock, (struct sockaddr*)&sll, sizeof(sll)) < 0) die("bind");

    // 4. 解析參數
    struct ArpPacket pkt = {0};
    parse_mac(argv[2], pkt.src_mac);
    parse_mac(argv[2], pkt.sha);       // 發送方 MAC = 源 MAC
    parse_ip(argv[1], pkt.spa);        // 發送方 IP
    parse_mac(argv[4], pkt.dst_mac);   // 目標 MAC (通常廣播)
    parse_mac(argv[4], pkt.tha);       // 目標 MAC (請求時 0)
    parse_ip(argv[3], pkt.tpa);        // 目標 IP

    // 5. 填充固定字段
    pkt.eth_type = htons(ETH_P_ARP);
    pkt.htype = htons(ARPHRD_ETHER);
    pkt.ptype = htons(ETH_P_IP);
    pkt.hlen = 6;
    pkt.plen = 4;
    pkt.oper = htons(ARPOP_REQUEST);   // 發送 ARP 請求

    // 6. 發送循環
    int count = atoi(argv[5]);
    for (int i = 0; i < count; ++i) {
        ssize_t sent = sendto(sock, &pkt, sizeof(pkt), 0,
                              (struct sockaddr*)&sll, sizeof(sll));
        if (sent < 0) die("sendto");
        printf("Sent ARP request #%d\n", i+1);
        usleep(100000);  // 100ms 間隔
    }
    close(sock);
    return 0;
}

編譯與運行


gcc -std=c99 -Wall -o send_arp send_arp.c
sudo ./send_arp 192.168.1.100 aa:bb:cc:dd:ee:ff 192.168.1.1 ff:ff:ff:ff:ff:ff 3

Wireshark 驗證

  1. 啟動 Wireshark 抓包介面 `eth0`,過濾器 `arp`。
  2. 運行程式,觀察 `ARP Request who has 192.168.1.1 tell 192.168.1.100`。
  3. 若目標主機在線,會收到 `ARP Reply 192.168.1.1 is at xx:xx:xx:xx:xx:xx`。

進階擴展

功能實現要點
ARP 掃描整個子網循環 `tpa` 遍歷 1~254,非阻塞 `recvfrom` 收回應
ARP 欺騙/投毒發送偽造 `ARP Reply`,將 `sha/spa` 設為網關 IP + 攻擊者 MAC
代理 ARP路由器對非本網段 IP 回應自身 MAC,啟用 `/proc/sys/net/ipv4/conf/all/proxy_arp`
接收解析`recvfrom` + 檢查 `eth_type==0x0806` + `oper==2` 解析 `sha/spa` 更新緩存
跨平台 (Windows)WinPcap/Npcap `PacketSendPacket` + `ETHER_HEADER` + `ARP_HEADER`

安全與合規提醒

ARP 協議無認證機制,極易被利用進行中間人攻擊、流量劫持、DoS。**僅在授權網路環境、實驗室、滲透測試範圍內使用**。生產網路部署動態 ARP 檢測 (DAI)、端口安全、靜態 ARP 綁定等緩解措施。

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