基于ARP协议获取局域网内主机MAC地址
ARP帧数据结构
- #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 IPTOSBUFFERS 12
- #define WM_PACKET WM_USER + 105 //用户自定义消息
- struct ethernet_head
- {// 物理帧帧头结构
- unsigned char dest_mac[6]; //目标主机MAC地址(6字节)
- unsigned char source_mac[6]; //源端MAC地址(6字节)
- unsigned short eh_type; //以太网类型(2字节)
- };
- struct arp_head
- {//ARP数据帧
- 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; //以太网头部
- arp_head arp; //arp数据包头部
- };
获取本机的网络适配器
- int i = 1;
- string strDev = "";
- m_Dev.AddString("经分析,本系统网络适配器列表如下:");
- pcap_if_t* alldevs = 0;
- pcap_if_t* pDev = 0;
- pcap_addr_t* pAdr = 0;
- char errbuf[PCAP_ERRBUF_SIZE+1];
- if (pcap_findalldevs(&alldevs, errbuf) == -1)
- {// 获得设备列表
- MessageBox(errbuf, NULL, MB_OK | MB_ICONINFORMATION);// 若没有设备则弹出警告
- exit(1);
- }
- for(pDev = alldevs; pDev; pDev = pDev->next)
- {// 遍历所有成员
- if (pDev->description)
- {
- strDev = char(i + 48);
- strDev += ". ";
- strDev += DelSpace(pDev->description);//去掉网卡描述过多的空格
- pAdr = pDev->addresses;//IP地址
- if (pAdr!=NULL)
- {
- if (pAdr->addr->sa_family == AF_INET)
- {//pAdr->addr是否IP地址类型
- strDev += " -> ";
- strDev += IpToStr(((struct sockaddr_in *)pAdr->addr)->sin_addr.s_addr);
- if(IpToStr(((struct sockaddr_in *)pAdr->addr)->sin_addr.s_addr)[0] != '0')
- {
- m_Dev_No = i;
- UpdateData(FALSE);//传递变量值去界面
- }
- strDev += " & [";
- strDev += IpToStr(((struct sockaddr_in *)pAdr->netmask)->sin_addr.s_addr);//子网掩码
- strDev += "]";
- GetDlgItem(IDC_GET_MAC)->EnableWindow(TRUE);//若网卡有IP地址,则使抓包按钮可用
- }
- }
- m_Dev.InsertString(i++, strDev.c_str());
- }
- }
- pcap_freealldevs(alldevs);//不再需要网络适配器列表, 释放
获取本机MAC地址
- unsigned char* BuildArpRequestPacket(unsigned char* source_mac, unsigned char* arp_sha, unsigned long chLocalIP, unsigned long arp_tpa, int PackSize)
- {//封装ARP请求包
- static arp_packet arpPackStru;
- static const arp_packet arpDefaultPack= {ETH_HRD_DEFAULT,ARP_HRD_DEFAULT};
- memcpy(&arpPackStru,&arpDefaultPack,sizeof(arpDefaultPack));
- //填充源MAC地址
- 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地址
- pcap_t* pAdaptHandle;
- char errbuf[PCAP_ERRBUF_SIZE + 1];
- //打开网卡适配器
- if((pAdaptHandle = pcap_open_live(pDevName, 60, 1, 100, errbuf)) == NULL)
- {
- MessageBox(NULL, "无法打开适配器,可能与之不兼容!", "Note", MB_OK);
- return NULL;
- }
- struct pcap_pkthdr *header;//包头部
- const u_char *pkt_data;//包数据部
- int res;
- unsigned short arp_op;
- 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
- while(!GetMacSignal)
- {
- pcap_sendpacket(pAdaptHandle, arp_packet_for_self, 60);//发送ARP请求包
- Sleep(10);
- res = pcap_next_ex(pAdaptHandle, &header, &pkt_data);
- if(res == 0)
- {
- continue;
- }
- //物理帧头部占字节,然后是硬件类型,上层协议类型,硬件地址长度,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)
- {//是本机
- GetMacSignal = 1;
- pcap_close(pAdaptHandle);
- return arp_sha;
- }
- Sleep(100);//若不成功再等ms再发,让网卡歇歇
- }
- pcap_close(pAdaptHandle);
- return arp_sha;
- }
发送ARP请求线程
- void SendArpRequest(pcap_if_t* pDev, unsigned char* bLocalMac)
- {//发送ARP请求
- pcap_addr_t* pAdr = 0;
- unsigned long chLocalIp = 0;//存放本地ip地址
- unsigned long arp_tpa = 0;
- unsigned long snd_tpa = 0;
- unsigned long nlNetMask = 0;
- int netsize = 0;
- const char* pDevName = strSelDeviceName.c_str();
- pcap_t* pAdaptHandle;
- char errbuf[PCAP_ERRBUF_SIZE + 1];
- //打开网卡适配器
- if((pAdaptHandle = pcap_open_live(pDev->name, 60, 0, 100, errbuf)) == NULL)
- {
- MessageBox(NULL, "无法打开适配器,可能与之不兼容!", "Send", MB_OK);
- return;
- }
- 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)
- {
- if (!nThreadSignal)
- {//判断线程是否应该中止
- break;
- }
- chLocalIp = ((struct sockaddr_in *)pAdr->addr)->sin_addr.s_addr;//得到本地ip
- if (!chLocalIp)
- {
- continue;
- }
- nlNetMask = ((struct sockaddr_in *)(pAdr->netmask))->sin_addr.S_un.S_addr;//得到子网掩码
- if(ulOldMask==nlNetMask)
- {
- continue;
- }
- ulOldMask=nlNetMask;
- netsize = ~ntohl(nlNetMask);//子网大小
- arp_tpa = ntohl(chLocalIp & nlNetMask);//IP地址
- for (int i=0; i < netsize; i++)
- {
- if (!nThreadSignal)
- {
- break;
- }
- arp_tpa++;
- snd_tpa = htonl(arp_tpa);
- memcpy(arp_packet_for_req + 38, &snd_tpa, 4);//目的IP在子网范围内按序增长
- pcap_sendpacket(pAdaptHandle, arp_packet_for_req, 60);//发送ARP请求包
- Sleep(5);//休息一下再发ARP请求包
- }
- }
- }
- UINT StartArpScan(LPVOID mainClass)
- {//发送ARP请求线程
- AfxGetApp()->m_pMainWnd->SendMessage(WM_PACKET, 0, 1);//开始发送ARP请求包
- SendArpRequest(pDevGlobalHandle, bLocalMac); //对选中设备的所有绑定的IP网段进行ARP请求
- AfxGetApp()->m_pMainWnd->SendMessage(WM_PACKET, 0, 2);//全部ARP请求包发送完毕
- return 0;
- }
接收ARP响应线程
- UINT WaitForArpRepeatPacket(LPVOID mainClass)
- {
- pcap_t* pAdaptHandle;
- 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);
- return -1;
- }
- string ipWithMac;
- char* filter = "ether proto\\arp";
- bpf_program fcode;
- int res;
- unsigned short arp_op = 0;
- unsigned char arp_sha [6];
- unsigned long arp_spa = 0;
- struct pcap_pkthdr *header;
- const u_char *pkt_data;
- if (pcap_compile(pAdaptHandle, &fcode, filter, 1, (unsigned long)(0xFFFF0000)) < 0)
- {
- MessageBox(NULL,"过滤条件语法错误!", "wait", MB_OK);
- return -1;
- }
- //set the filter
- if (pcap_setfilter(pAdaptHandle, &fcode) < 0)
- {
- MessageBox(NULL,"适配器与过滤条件不兼容!", "wait", MB_OK);
- return -1;
- }
- while(1)
- {
- if (!nThreadSignal)
- {
- break;
- }
- int i = 0;
- ipWithMac = "";
- res = pcap_next_ex(pAdaptHandle, &header, &pkt_data);
- if (!res)
- {
- continue;
- }
- 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 += " ";
- }
- ipWithMac += " --*-> ";
- ipWithMac += MacToStr(arp_sha);
- for (i = 6; i > 0; i--)
- {
- if (arp_sha[i - 1] != bLocalMac[i - 1])
- {
- break;
- }
- }
- if(arp_op == htons(ARP_REPLY) && i)
- {
- AfxGetApp()->m_pMainWnd->SendMessage(WM_PACKET, WPARAM(&ipWithMac), 0);//通知主线程更新界面
- }
- }
- return 0;
- }
主线程消息处理
- LRESULT CArpByWinpcapDlg::OnPacket(WPARAM wParam, LPARAM lParam)
- {
- string* transPack = (string*)wParam;
- //处理捕获到的数据包
- if (lParam == 0)
- {
- m_Mac_list.AddString(transPack->c_str());
- m_count = "发现 ";
- char buffer[5];
- itoa(m_Mac_list.GetCount(), buffer, 10); //将数量转化为进制字符串;
- m_count += buffer;
- m_count += " 台活动主机";
- }
- else if (lParam == 1)
- {
- m_sending = "正在发送ARP请求包!";
- }
- else if (lParam == 2)
- {
- if (nThreadSignal)
- {
- m_sending = "全部ARP请求包发送完毕!"; //判断是自行发送完毕还是用户终止的?
- };
- }
- UpdateData(FALSE);
- return 0;
- }
参考资料:《Winpcap网络开发库入门》
转载于:https://blog.51cto.com/phinecos/368157
基于ARP协议获取局域网内主机MAC地址相关推荐
- python获取局域网在线主机_python通过scapy获取局域网所有主机mac地址示例
python通过scapy获取局域网所有主机mac地址示例 发布于 2014-10-10 20:34:48 | 607 次阅读 | 评论: 0 | 来源: 网友投递 Python编程语言Python ...
- Android 获取局域网内网IP地址
Android 获取局域网内网IP地址 废话 上代码 完事 废话 拿局域网IP一般用在tcp通讯或udp通讯上,下次再整理下这类通讯的框架 上代码 /*** 网络工具* 获得局域网IP地址* @aut ...
- java获取局域网内主机,java怎么获取局域网内所有主机ip
java怎么获取局域网内所有主机ip 关注:53 答案:2 mip版 解决时间 2021-01-27 21:31 提问者夢岭杺 2021-01-27 12:02 java怎么获取局域网内所有主机i ...
- android 访问内网ip_android 获取局域网IP与MAC 地址 毫秒级(详解)
两个 linux命令 开始理清思路:主要使用 linux 两个命令(2017-07-21 fix:这个思路不好,后面使用udp取代[毫秒级]) [ping]: 查询某个ip是否被设备占用 [cat] ...
- 怎么查同一网络下的计算机,Windows下查看同局域网其它主机MAC地址
事情是这样的,今天去面试的时候笔试有一道题问到:Windows下使用什么命令来获知同局域网内其他主机的MAC地址.一开始看到感觉很熟悉,但是却答不上来.原来建站这么就,很多使用都要使用ping命令来测 ...
- 局域网内知道Mac地址查询对应IP
环境: 1. 知道cubietruck的Mac地址为A:B:C:D:E:F 2. 同一局域网内的一台计算机(这里为Ubuntu) 一.ping 255 获取广播地址 ifconfig | grep ' ...
- 安卓基于MDNS协议的局域网内服务发现
mDNS简介 mdns 即多播(组播)dns(Multicast DNS),用于本地局域网服务发现的协议,在Apple 的设备上(电脑,笔记本,iphone,ipad等设备)都提供了这个服务(Bonj ...
- Python获取局域网内所有机器IP地址与网卡MAC地址
已发相关文章请参考Python获取本机所有网卡的MAC地址 本文代码使用ARP协议获取局域网内所有计算机的IP地址与MAC地址,思路是使用系统命令arp获取ARP表并生成文本文件,然后从文件中读取和解 ...
- ARP协议及局域网断网攻击(scapy)
ARP协议攻击 地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议.主机发送信息时将包含目标IP地址的ARP请求广播到网 ...
最新文章
- 无效0_一场时代的变革,一场与时间的较量,“0”无效载体、“0”空气氧化、“0”细菌生存。...
- 使用 cglib_CGLib 动态代理 原理解析
- 功能性农业未来方向-农业大健康·徐春晖:农业品牌市场规范
- 开发管理 (3) -项目启动会议
- 搜索引擎反作弊之:整体技术思路
- mysql 分段执行_了解一下项目中常用的19条MySQL优化
- Python数据挖掘 环境搭建
- Spring mvc 拦截器 配置心得
- navicat运行db文件_在 Navicat for MongoDB 使用文档
- python实现简单购物系统
- 人人对战五子棋 C++
- 「教程」Windows程序未响应,怎么分析确认具体原因
- 我所学过看过的计算机语言入门书籍推荐
- 写一函数,将一个3x3的整型矩阵转置
- kafka报错Error while fetching metadata with correlation
- Ajax传递二维数组至后台ThinkPHP控制器
- properties解耦数据库参数和SQL参数的传递
- July 16th 模拟赛C T4 奶牛排队 Solution
- mysql 1677_mysql之数据库主从复制配置报错1677
- JavaScript从初级往高级走系列————prototype