相信各位都玩過SOCKET編程,用CSocket進行網絡通訊非常方便,但有時想搞點底層點東西卻非常麻煩,用windows的API最低也只能SOCK_RAW,頂多能看到IP層數據,如果想處理數據鏈路層的數據就無從下手了,幸好某天發現了winpcap東西。用了它處理底層的東西就非常方便。
winpcap主要有兩個dll供程序員直接調用,pcap.dll和packet.dll,本程序主要使用pcap.dll,至於packet.dll的使用在21期TOo2y 的《 詳談調用winpcap驅動寫arp多功能工具 》作了詳細的介紹
一、本程序主要用了下面幾個函數
1.int pcap_findalldevs ( pcap_if_t ** alldevsp, char * errbuf )
用於得到所有網絡適配器信息放在 alldevsp
2.pcap_t* pcap_open_live ( const char * device, int snaplen, int promisc, int to_ms, char * ebuf )
用於打開網絡適配器,並設置其捕獲參數
3.int pcap_sendpacket (pcap_t *p, u_char *buf, int size)
發數據包
4.void pcap_freealldevs (pcap_if_t *alldevsp)
釋放所以網絡適配器
5.void pcap_close (pcap_t *p)
關閉網絡適配器
二、類說明
CHex,主要用於處理十六進制數據
CYGPcap,主要用於對 PCAP 的那幾個函數進行封裝
CYGEdit, 主要用重載幾個操作符,方便使用
CResize,主要用於窗口變化時,子窗口的變化
三、ARP 協議格式如下:
數據鏈路層
目的 MAC 地址 6 Byte 源 MAC 地址 6 Byte 類型 2 ByteARP 層包報文
硬件類型 2 Byte 協議類型 2 Byte 硬件地址長度 1Byte 協議地址長度 1Byte 操作類型 2 Byte 發送方 MAC 6 Byte 發送方 IP 4 Byte 目的 MAC 6 Byte 目的 IP 4 Byte四、主要代碼
//發送ARP包
void CNetArpDlg::OnBtnSendarp()
{
if (!UpdateData()) return ;
static int nPacketNum=0;
CHex bPacket(64);
CString strDestMac;
DWORD dwAddress;
m_edDest>>strDestMac;
//最終報文大概的樣子
//FFFFFFFFFFFF000AE43D867408060001080006040001000AE43D8674C0A80101000000000000C0A801B5
m_edShow.SetSpace(m_IsSpace);
try
{
if (strDestMac.GetLength()!=12||m_strSrc.GetLength()!=12) throw "MAC地址有錯,應該是6個字節";
//數據鏈路層
bPacket<<strDestMac; //Destination MAC
bPacket<<m_strSrc; //Source MAC
bPacket.AddTwoByte(0x0806); //type=arp
//arp層
bPacket.AddTwoByte(0x0001); //Harware type
bPacket.AddTwoByte(0x0800); //protocol type
bPacket.AddOneByte(0x6); //hardware size
bPacket.AddOneByte(0x4); //protocol size
bPacket.AddTwoByte(m_nArpType+1); //code type
bPacket<<m_strSrc; //sender mac address
m_IPSend.GetAddress(dwAddress);
bPacket.AddUINT(dwAddress); //sender ip address
bPacket.Add((void *)"\x0\x0\x0\x0\x0\x0",6);//target mac address
m_IPTarget.GetAddress(dwAddress);
bPacket.AddUINT(dwAddress); //target ip address
// bPacket.Trace("內容");
if (1==m_nArpType) //如果是響應
bPacket.Add((void *)"\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0",18);
m_pcap.SendPacket(bPacket);
m_edShow<<"發送第"<<++nPacketNum<<"包"<<endl<<bPacket<<endl<<endl;
}
catch(char *szErr){AfxMessageBox(szErr);}
}
五、結束
詳細請看代碼,本人也是剛接觸WinPcap,所以一不定有一些錯漏的地方,請各位大蝦不要見笑。
如果程序有編譯不過去的地方,請務必先按裝winPcap庫,更新VC6的PlatformSDK