標準 Socket (CSocket) 最低只能到 SOCK_RAW (IP 層),無法構造/接收數據鏈路層 (MAC/ARP) 封包。WinPcap 提供 pcap.dll + packet.dll,讓應用層直接存取網卡驅動,實現完整封包控制。
| 函式 | 用途 |
|---|---|
pcap_findalldevs | 列舉所有網卡裝置 |
pcap_open_live | 開啟網卡,設定混雜模式、快照長度、超時 |
pcap_sendpacket | 發送原始封包 |
pcap_freealldevs | 釋放裝置列表 |
pcap_close | 關閉網卡控制代碼 |
CHex:十六進制資料操作輔助 (運算子重載 <<, AddTwoByte, AddUINT 等)CYGPcap:WinPcap API 薄封裝CYGEdit:編輯控制項增強CResize:視窗大小自適應【以太網頭】 14 Bytes 目的 MAC (6) | 來源 MAC (6) | 類型 0x0806 (2) 【ARP 負載】 28 Bytes 硬體類型 1 (2) | 協議類型 0x0800 (2) | 硬體長度 6 (1) | 協議長度 4 (1) 操作碼 1=請求/2=回應 (2) 發送方 MAC (6) | 發送方 IP (4) 目的 MAC (6) | 目的 IP (4)
void CNetArpDlg::OnBtnSendArp() {
if (!UpdateData()) return;
static int nPkt = 0;
CHex pkt(64);
CString dstMac; m_edDst >> dstMac;
DWORD ip;
try {
if (dstMac.GetLength()!=12 || m_strSrc.GetLength()!=12) throw "MAC 長度錯誤";
// 以太網頭
pkt << dstMac; // 目的 MAC
pkt << m_strSrc; // 來源 MAC
pkt.AddTwoByte(0x0806); // Type = ARP
// ARP 負載
pkt.AddTwoByte(0x0001); // Hardware: Ethernet
pkt.AddTwoByte(0x0800); // Protocol: IPv4
pkt.AddOneByte(0x06); // MAC 長度
pkt.AddOneByte(0x04); // IP 長度
pkt.AddTwoByte(m_nArpType+1); // Opcode: 1=Request, 2=Reply
pkt << m_strSrc; // Sender MAC
m_IPSender.GetAddress(ip);
pkt.AddUINT(ip); // Sender IP
pkt.Add("\x00\x00\x00\x00\x00\x00", 6); // Target MAC (請求時全0)
m_IPTarget.GetAddress(ip);
pkt.AddUINT(ip); // Target IP
// 回應包補齊填充 (視實際需求)
if (m_nArpType == 1) pkt.Add("\x00...\x00", 18);
m_pcap.SendPacket(pkt);
m_edShow << "發送第" << ++nPkt << "包" << endl << pkt << endl << endl;
} catch (char* err) { AfxMessageBox(err); }
}
pcap.h, pcap.lib)pcap.lib ws2_32.lib作者初次接觸 WinPcap,代碼難免疏漏,歡迎大神指正。完整專案源碼隨文提供。