#define BROADMAC {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF} //广播MAC
#define EH_TYPE 0x0806 //ARP类型
#define ARP_HRD 0X0001 //硬件类型:以太网接口类型为
#define ARP_PRO 0x0800 //协议类型:IP协议类型为X0800
#define ARP_HLN 0x06 //硬件地址长度:MAC地址长度为B
#define ARP_PLN 0x04 //协议地址长度:IP地址长度为B
#define ARP_REQUEST 0x0001 //操作:ARP请求为
#define ARP_REPLY 0x0002 //操作:ARP应答为
#define ARP_THA {0,0,0,0,0,0} //目的MAC地址:ARP请求中该字段没有意义,设为;ARP响应中为接收方的MAC地址
#define ARP_PAD {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} //18字节的填充数据
#define SPECIAL 0x70707070 //定义获得自己MAC地址的特殊源IP,.112.112.112
#define ETH_HRD_DEFAULT {BROADMAC, {0,0,0,0,0,0}, htons(EH_TYPE)} //广播ARP包帧头
#define ARP_HRD_DEFAULT {htons(ARP_HRD), htons(ARP_PRO), ARP_HLN, ARP_PLN, htons(ARP_REQUEST), {0,0,0,0,0,0}, 0, ARP_THA, 0, ARP_PAD}
#define WM_PACKET WM_USER + 105 //用户自定义消息
unsigned char dest_mac[6]; //目标主机MAC地址(6字节)
unsigned char source_mac[6]; //源端MAC地址(6字节)
unsigned short eh_type; //以太网类型(2字节)
unsigned short hardware_type; //硬件类型:以太网接口类型为
unsigned short protocol_type; //协议类型:IP协议类型为X0800
unsigned char add_len; //硬件地址长度:MAC地址长度为B
unsigned char pro_len; //协议地址长度:IP地址长度为B
unsigned short option; //操作:ARP请求为,ARP应答为
unsigned char sour_addr[6]; //源MAC地址:发送方的MAC地址
unsigned long sour_ip; //源IP地址:发送方的IP地址
unsigned char dest_addr[6]; //目的MAC地址:ARP请求中该字段没有意义;ARP响应中为接收方的MAC地址
unsigned long dest_ip; //目的IP地址:ARP请求中为请求解析的IP地址;ARP响应中为接收方的IP地址
unsigned char padding[18];
struct arp_packet //最终arp包结构
ethernet_head eth; //以太网头部
m_Dev.AddString("经分析,本系统网络适配器列表如下:");
char errbuf[PCAP_ERRBUF_SIZE+1];
if (pcap_findalldevs(&alldevs, errbuf) == -1)
MessageBox(errbuf, NULL, MB_OK | MB_ICONINFORMATION);// 若没有设备则弹出警告
for(pDev = alldevs; pDev; pDev = pDev->next)
strDev += DelSpace(pDev->description);//去掉网卡描述过多的空格
pAdr = pDev->addresses;//IP地址
if (pAdr->addr->sa_family == AF_INET)
strDev += IpToStr(((struct sockaddr_in *)pAdr->addr)->sin_addr.s_addr);
if(IpToStr(((struct sockaddr_in *)pAdr->addr)->sin_addr.s_addr)[0] != '0')
UpdateData(FALSE);//传递变量值去界面
strDev += IpToStr(((struct sockaddr_in *)pAdr->netmask)->sin_addr.s_addr);//子网掩码
GetDlgItem(IDC_GET_MAC)->EnableWindow(TRUE);//若网卡有IP地址,则使抓包按钮可用
m_Dev.InsertString(i++, strDev.c_str());
pcap_freealldevs(alldevs);//不再需要网络适配器列表, 释放
unsigned char* BuildArpRequestPacket(unsigned char* source_mac, unsigned char* arp_sha, unsigned long chLocalIP, unsigned long arp_tpa, int PackSize)
static arp_packet arpPackStru;
static const arp_packet arpDefaultPack= {ETH_HRD_DEFAULT,ARP_HRD_DEFAULT};
memcpy(&arpPackStru,&arpDefaultPack,sizeof(arpDefaultPack));
memcpy(arpPackStru.eth.source_mac,source_mac,6);//源MAC
memcpy(arpPackStru.arp.sour_addr,arp_sha,6);//源MAC
arpPackStru.arp.sour_ip=chLocalIP;//源IP地址
arpPackStru.arp.dest_ip=arp_tpa;//目的IP地址
return (unsigned char *)&arpPackStru;
unsigned char* GetSelfMac(char* pDevName, unsigned long chLocalIP)
{//获得本机MAC地址,pDevName为网卡名称,chLocalIP为本机IP地址
char errbuf[PCAP_ERRBUF_SIZE + 1];
if((pAdaptHandle = pcap_open_live(pDevName, 60, 1, 100, errbuf)) == NULL)
MessageBox(NULL, "无法打开适配器,可能与之不兼容!", "Note", MB_OK);
struct pcap_pkthdr *header;//包头部
const u_char *pkt_data;//包数据部
static unsigned char arp_sha[6];
unsigned long arp_spa = 0;
unsigned long arp_tpa = 0;
unsigned char source_mac[6] = {0,0,0,0,0,0};
unsigned char* arp_packet_for_self;
arp_packet_for_self = BuildArpRequestPacket(source_mac, source_mac, SPECIAL, chLocalIP, 60);//把自己作为目的,构建一个广播ARP请求包,伪造请求来自.112.112.112
pcap_sendpacket(pAdaptHandle, arp_packet_for_self, 60);//发送ARP请求包
res = pcap_next_ex(pAdaptHandle, &header, &pkt_data);
//物理帧头部占字节,然后是硬件类型,上层协议类型,硬件地址长度,IP地址长度,这四个占去字节,具体参看ARP帧的数据结构
memcpy(&arp_op, pkt_data + 20, 2);//操作类型(请求或应答)
memcpy(arp_sha, pkt_data + 22, 6);//源MAC
memcpy(&arp_spa, pkt_data + 28, 4);//源IP
memcpy(&arp_tpa, pkt_data + 38, 4);//目标IP
if(arp_op == htons(ARP_REPLY) && arp_spa == chLocalIP && arp_tpa == SPECIAL)
pcap_close(pAdaptHandle);
Sleep(100);//若不成功再等ms再发,让网卡歇歇
pcap_close(pAdaptHandle);
void SendArpRequest(pcap_if_t* pDev, unsigned char* bLocalMac)
unsigned long chLocalIp = 0;//存放本地ip地址
unsigned long arp_tpa = 0;
unsigned long snd_tpa = 0;
unsigned long nlNetMask = 0;
const char* pDevName = strSelDeviceName.c_str();
char errbuf[PCAP_ERRBUF_SIZE + 1];
if((pAdaptHandle = pcap_open_live(pDev->name, 60, 0, 100, errbuf)) == NULL)
MessageBox(NULL, "无法打开适配器,可能与之不兼容!", "Send", MB_OK);
unsigned char* arp_packet_for_req;
arp_packet_for_req = BuildArpRequestPacket(bLocalMac, bLocalMac, chLocalIp, chLocalIp, 60); //构造包
unsigned long ulOldMask=0;
for (pAdr = pDev->addresses; pAdr; pAdr = pAdr->next)
chLocalIp = ((struct sockaddr_in *)pAdr->addr)->sin_addr.s_addr;//得到本地ip
nlNetMask = ((struct sockaddr_in *)(pAdr->netmask))->sin_addr.S_un.S_addr;//得到子网掩码
netsize = ~ntohl(nlNetMask);//子网大小
arp_tpa = ntohl(chLocalIp & nlNetMask);//IP地址
for (int i=0; i < netsize; i++)
snd_tpa = htonl(arp_tpa);
memcpy(arp_packet_for_req + 38, &snd_tpa, 4);//目的IP在子网范围内按序增长
pcap_sendpacket(pAdaptHandle, arp_packet_for_req, 60);//发送ARP请求包
UINT StartArpScan(LPVOID mainClass)
AfxGetApp()->m_pMainWnd->SendMessage(WM_PACKET, 0, 1);//开始发送ARP请求包
SendArpRequest(pDevGlobalHandle, bLocalMac); //对选中设备的所有绑定的IP网段进行ARP请求
AfxGetApp()->m_pMainWnd->SendMessage(WM_PACKET, 0, 2);//全部ARP请求包发送完毕
UINT WaitForArpRepeatPacket(LPVOID mainClass)
const char* pDevName = strSelDeviceName.c_str();
char errbuf[PCAP_ERRBUF_SIZE + 1];
if((pAdaptHandle = pcap_open_live(pDevName, 60, 0, 100, errbuf)) == NULL)
MessageBox(NULL, "无法打开适配器,可能与之不兼容!", "wait", MB_OK);
char* filter = "ether proto\\arp";
unsigned short arp_op = 0;
unsigned char arp_sha [6];
unsigned long arp_spa = 0;
struct pcap_pkthdr *header;
if (pcap_compile(pAdaptHandle, &fcode, filter, 1, (unsigned long)(0xFFFF0000)) < 0)
MessageBox(NULL,"过滤条件语法错误!", "wait", MB_OK);
if (pcap_setfilter(pAdaptHandle, &fcode) < 0)
MessageBox(NULL,"适配器与过滤条件不兼容!", "wait", MB_OK);
res = pcap_next_ex(pAdaptHandle, &header, &pkt_data);
memcpy(&arp_op, pkt_data + 20, 2);//包的操作类型
memcpy(arp_sha, pkt_data + 22, 6);//源MAC地址
memcpy(&arp_spa, pkt_data + 28, 4);//源IP地址
ipWithMac += IpToStr(arp_spa);
for (int j = strlen(IpToStr(arp_spa)); j < 16; j++)
ipWithMac += MacToStr(arp_sha);
if (arp_sha[i - 1] != bLocalMac[i - 1])
if(arp_op == htons(ARP_REPLY) && i)
AfxGetApp()->m_pMainWnd->SendMessage(WM_PACKET, WPARAM(&ipWithMac), 0);//通知主线程更新界面
LRESULT CArpByWinpcapDlg::OnPacket(WPARAM wParam, LPARAM lParam)
string* transPack = (string*)wParam;
m_Mac_list.AddString(transPack->c_str());
itoa(m_Mac_list.GetCount(), buffer, 10); //将数量转化为进制字符串;
m_sending = "正在发送ARP请求包!";
m_sending = "全部ARP请求包发送完毕!"; //判断是自行发送完毕还是用户终止的?
本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2009/01/04/1368466.html,如需转载请自行联系原作者