ARP帧数据结构

  1. #define BROADMAC        {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF} //广播MAC
  2. #define EH_TYPE            0x0806                            //ARP类型
  3. #define ARP_HRD            0X0001                            //硬件类型:以太网接口类型为
  4. #define ARP_PRO            0x0800                            //协议类型:IP协议类型为X0800
  5. #define ARP_HLN            0x06                            //硬件地址长度:MAC地址长度为B
  6. #define ARP_PLN            0x04                            //协议地址长度:IP地址长度为B
  7. #define ARP_REQUEST        0x0001                            //操作:ARP请求为
  8. #define ARP_REPLY        0x0002                            //操作:ARP应答为
  9. #define ARP_THA            {0,0,0,0,0,0}                    //目的MAC地址:ARP请求中该字段没有意义,设为;ARP响应中为接收方的MAC地址
  10. #define ARP_PAD            {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} //18字节的填充数据
  11. #define SPECIAL            0x70707070                        //定义获得自己MAC地址的特殊源IP,.112.112.112
  12. #define ETH_HRD_DEFAULT    {BROADMAC, {0,0,0,0,0,0}, htons(EH_TYPE)} //广播ARP包帧头
  13. #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}
  14. #define IPTOSBUFFERS 12
  15. #define WM_PACKET    WM_USER + 105    //用户自定义消息
  16. struct ethernet_head
  17. {// 物理帧帧头结构
  18. unsigned char dest_mac[6];                                    //目标主机MAC地址(6字节)
  19. unsigned char source_mac[6];                                //源端MAC地址(6字节)
  20. unsigned short eh_type;                                        //以太网类型(2字节)
  21. };
  22. struct arp_head
  23. {//ARP数据帧
  24. unsigned short hardware_type;                                //硬件类型:以太网接口类型为
  25. unsigned short protocol_type;                                //协议类型:IP协议类型为X0800
  26. unsigned char add_len;                                        //硬件地址长度:MAC地址长度为B
  27. unsigned char pro_len;                                        //协议地址长度:IP地址长度为B
  28. unsigned short option;                                        //操作:ARP请求为,ARP应答为
  29. unsigned char sour_addr[6];                                    //源MAC地址:发送方的MAC地址
  30. unsigned long sour_ip;                                        //源IP地址:发送方的IP地址
  31. unsigned char dest_addr[6];                                    //目的MAC地址:ARP请求中该字段没有意义;ARP响应中为接收方的MAC地址
  32. unsigned long dest_ip;                                        //目的IP地址:ARP请求中为请求解析的IP地址;ARP响应中为接收方的IP地址
  33. unsigned char padding[18];
  34. };
  35. struct arp_packet                                        //最终arp包结构
  36. {//物理帧结构
  37. ethernet_head eth;                                    //以太网头部
  38. arp_head arp;                                        //arp数据包头部
  39. };

获取本机的网络适配器

  1. int i = 1;
  2. string strDev = "";
  3. m_Dev.AddString("经分析,本系统网络适配器列表如下:");
  4. pcap_if_t* alldevs = 0;
  5. pcap_if_t* pDev = 0;
  6. pcap_addr_t* pAdr = 0;
  7. char errbuf[PCAP_ERRBUF_SIZE+1];
  8. if (pcap_findalldevs(&alldevs, errbuf) == -1)
  9. {// 获得设备列表
  10. MessageBox(errbuf, NULL, MB_OK | MB_ICONINFORMATION);// 若没有设备则弹出警告
  11. exit(1);
  12. }
  13. for(pDev = alldevs; pDev; pDev = pDev->next)
  14. {// 遍历所有成员
  15. if (pDev->description)
  16. {
  17. strDev = char(i + 48);
  18. strDev += ". ";
  19. strDev += DelSpace(pDev->description);//去掉网卡描述过多的空格
  20. pAdr = pDev->addresses;//IP地址
  21. if (pAdr!=NULL)
  22. {
  23. if (pAdr->addr->sa_family == AF_INET)
  24. {//pAdr->addr是否IP地址类型
  25. strDev += " -> ";
  26. strDev += IpToStr(((struct sockaddr_in *)pAdr->addr)->sin_addr.s_addr);
  27. if(IpToStr(((struct sockaddr_in *)pAdr->addr)->sin_addr.s_addr)[0] != '0')
  28. {
  29. m_Dev_No = i;
  30. UpdateData(FALSE);//传递变量值去界面
  31. }
  32. strDev += " & [";
  33. strDev += IpToStr(((struct sockaddr_in *)pAdr->netmask)->sin_addr.s_addr);//子网掩码
  34. strDev += "]";
  35. GetDlgItem(IDC_GET_MAC)->EnableWindow(TRUE);//若网卡有IP地址,则使抓包按钮可用
  36. }
  37. }
  38. m_Dev.InsertString(i++, strDev.c_str());
  39. }
  40. }
  41. pcap_freealldevs(alldevs);//不再需要网络适配器列表, 释放

获取本机MAC地址

  1. unsigned char* BuildArpRequestPacket(unsigned char* source_mac, unsigned char* arp_sha, unsigned long chLocalIP, unsigned long arp_tpa, int PackSize)
  2. {//封装ARP请求包
  3. static arp_packet arpPackStru;
  4. static const arp_packet arpDefaultPack= {ETH_HRD_DEFAULT,ARP_HRD_DEFAULT};
  5. memcpy(&arpPackStru,&arpDefaultPack,sizeof(arpDefaultPack));
  6. //填充源MAC地址
  7. memcpy(arpPackStru.eth.source_mac,source_mac,6);//源MAC
  8. memcpy(arpPackStru.arp.sour_addr,arp_sha,6);//源MAC
  9. arpPackStru.arp.sour_ip=chLocalIP;//源IP地址
  10. arpPackStru.arp.dest_ip=arp_tpa;//目的IP地址
  11. return (unsigned char *)&arpPackStru;
  12. }
  13. unsigned char* GetSelfMac(char* pDevName, unsigned long chLocalIP)
  14. {//获得本机MAC地址,pDevName为网卡名称,chLocalIP为本机IP地址
  15. pcap_t* pAdaptHandle;
  16. char errbuf[PCAP_ERRBUF_SIZE + 1];
  17. //打开网卡适配器
  18. if((pAdaptHandle = pcap_open_live(pDevName, 60, 1, 100, errbuf)) == NULL)
  19. {
  20. MessageBox(NULL, "无法打开适配器,可能与之不兼容!", "Note", MB_OK);
  21. return NULL;
  22. }
  23. struct pcap_pkthdr *header;//包头部
  24. const u_char *pkt_data;//包数据部
  25. int res;
  26. unsigned short arp_op;
  27. static unsigned char arp_sha[6];
  28. unsigned long arp_spa = 0;
  29. unsigned long arp_tpa = 0;
  30. unsigned char source_mac[6] = {0,0,0,0,0,0};
  31. unsigned char* arp_packet_for_self;
  32. arp_packet_for_self = BuildArpRequestPacket(source_mac, source_mac, SPECIAL, chLocalIP, 60);//把自己作为目的,构建一个广播ARP请求包,伪造请求来自.112.112.112
  33. while(!GetMacSignal)
  34. {
  35. pcap_sendpacket(pAdaptHandle, arp_packet_for_self, 60);//发送ARP请求包
  36. Sleep(10);
  37. res = pcap_next_ex(pAdaptHandle, &header, &pkt_data);
  38. if(res == 0)
  39. {
  40. continue;
  41. }
  42. //物理帧头部占字节,然后是硬件类型,上层协议类型,硬件地址长度,IP地址长度,这四个占去字节,具体参看ARP帧的数据结构
  43. memcpy(&arp_op, pkt_data + 20, 2);//操作类型(请求或应答)
  44. memcpy(arp_sha, pkt_data + 22, 6);//源MAC
  45. memcpy(&arp_spa, pkt_data + 28, 4);//源IP
  46. memcpy(&arp_tpa, pkt_data + 38, 4);//目标IP
  47. if(arp_op == htons(ARP_REPLY) && arp_spa == chLocalIP && arp_tpa == SPECIAL)
  48. {//是本机
  49. GetMacSignal = 1;
  50. pcap_close(pAdaptHandle);
  51. return arp_sha;
  52. }
  53. Sleep(100);//若不成功再等ms再发,让网卡歇歇
  54. }
  55. pcap_close(pAdaptHandle);
  56. return arp_sha;
  57. }

发送ARP请求线程

  1. void SendArpRequest(pcap_if_t* pDev, unsigned char* bLocalMac)
  2. {//发送ARP请求
  3. pcap_addr_t* pAdr = 0;
  4. unsigned long chLocalIp = 0;//存放本地ip地址
  5. unsigned long arp_tpa = 0;
  6. unsigned long snd_tpa = 0;
  7. unsigned long nlNetMask = 0;
  8. int netsize = 0;
  9. const char* pDevName = strSelDeviceName.c_str();
  10. pcap_t* pAdaptHandle;
  11. char errbuf[PCAP_ERRBUF_SIZE + 1];
  12. //打开网卡适配器
  13. if((pAdaptHandle = pcap_open_live(pDev->name, 60, 0, 100, errbuf)) == NULL)
  14. {
  15. MessageBox(NULL, "无法打开适配器,可能与之不兼容!", "Send", MB_OK);
  16. return;
  17. }
  18. unsigned char* arp_packet_for_req;
  19. arp_packet_for_req = BuildArpRequestPacket(bLocalMac, bLocalMac, chLocalIp, chLocalIp, 60);    //构造包
  20. unsigned long ulOldMask=0;
  21. for (pAdr = pDev->addresses; pAdr; pAdr = pAdr->next)
  22. {
  23. if (!nThreadSignal)
  24. {//判断线程是否应该中止
  25. break;
  26. }
  27. chLocalIp = ((struct sockaddr_in *)pAdr->addr)->sin_addr.s_addr;//得到本地ip
  28. if (!chLocalIp)
  29. {
  30. continue;
  31. }
  32. nlNetMask = ((struct sockaddr_in *)(pAdr->netmask))->sin_addr.S_un.S_addr;//得到子网掩码
  33. if(ulOldMask==nlNetMask)
  34. {
  35. continue;
  36. }
  37. ulOldMask=nlNetMask;
  38. netsize = ~ntohl(nlNetMask);//子网大小
  39. arp_tpa = ntohl(chLocalIp & nlNetMask);//IP地址
  40. for (int i=0; i < netsize; i++)
  41. {
  42. if (!nThreadSignal)
  43. {
  44. break;
  45. }
  46. arp_tpa++;
  47. snd_tpa = htonl(arp_tpa);
  48. memcpy(arp_packet_for_req + 38, &snd_tpa, 4);//目的IP在子网范围内按序增长
  49. pcap_sendpacket(pAdaptHandle, arp_packet_for_req, 60);//发送ARP请求包
  50. Sleep(5);//休息一下再发ARP请求包
  51. }
  52. }
  53. }
  54. UINT StartArpScan(LPVOID mainClass)
  55. {//发送ARP请求线程
  56. AfxGetApp()->m_pMainWnd->SendMessage(WM_PACKET, 0, 1);//开始发送ARP请求包
  57. SendArpRequest(pDevGlobalHandle, bLocalMac);                                    //对选中设备的所有绑定的IP网段进行ARP请求
  58. AfxGetApp()->m_pMainWnd->SendMessage(WM_PACKET, 0, 2);//全部ARP请求包发送完毕
  59. return 0;
  60. }

接收ARP响应线程

  1. UINT WaitForArpRepeatPacket(LPVOID mainClass)
  2. {
  3. pcap_t* pAdaptHandle;
  4. const char* pDevName = strSelDeviceName.c_str();
  5. char errbuf[PCAP_ERRBUF_SIZE + 1];
  6. //打开网卡适配器
  7. if((pAdaptHandle = pcap_open_live(pDevName, 60, 0, 100, errbuf)) == NULL)
  8. {
  9. MessageBox(NULL, "无法打开适配器,可能与之不兼容!", "wait", MB_OK);
  10. return -1;
  11. }
  12. string ipWithMac;
  13. char* filter = "ether proto\\arp";
  14. bpf_program fcode;
  15. int res;
  16. unsigned short arp_op = 0;
  17. unsigned char arp_sha [6];
  18. unsigned long arp_spa = 0;
  19. struct pcap_pkthdr *header;
  20. const u_char *pkt_data;
  21. if (pcap_compile(pAdaptHandle, &fcode, filter, 1, (unsigned long)(0xFFFF0000)) < 0)
  22. {
  23. MessageBox(NULL,"过滤条件语法错误!", "wait", MB_OK);
  24. return -1;
  25. }
  26. //set the filter
  27. if (pcap_setfilter(pAdaptHandle, &fcode) < 0)
  28. {
  29. MessageBox(NULL,"适配器与过滤条件不兼容!", "wait", MB_OK);
  30. return -1;
  31. }
  32. while(1)
  33. {
  34. if (!nThreadSignal)
  35. {
  36. break;
  37. }
  38. int i = 0;
  39. ipWithMac = "";
  40. res = pcap_next_ex(pAdaptHandle, &header, &pkt_data);
  41. if (!res)
  42. {
  43. continue;
  44. }
  45. memcpy(&arp_op, pkt_data + 20, 2);//包的操作类型
  46. memcpy(arp_sha, pkt_data + 22, 6);//源MAC地址
  47. memcpy(&arp_spa, pkt_data + 28, 4);//源IP地址
  48. ipWithMac += IpToStr(arp_spa);
  49. for (int j = strlen(IpToStr(arp_spa)); j < 16; j++)
  50. {
  51. ipWithMac += " ";
  52. }
  53. ipWithMac += "  --*->   ";
  54. ipWithMac += MacToStr(arp_sha);
  55. for (i = 6; i > 0; i--)
  56. {
  57. if (arp_sha[i - 1] != bLocalMac[i - 1])
  58. {
  59. break;
  60. }
  61. }
  62. if(arp_op == htons(ARP_REPLY) && i)
  63. {
  64. AfxGetApp()->m_pMainWnd->SendMessage(WM_PACKET, WPARAM(&ipWithMac), 0);//通知主线程更新界面
  65. }
  66. }
  67. return 0;
  68. }

主线程消息处理

  1. LRESULT CArpByWinpcapDlg::OnPacket(WPARAM wParam, LPARAM lParam)
  2. {
  3. string* transPack = (string*)wParam;
  4. //处理捕获到的数据包
  5. if (lParam == 0)
  6. {
  7. m_Mac_list.AddString(transPack->c_str());
  8. m_count = "发现 ";
  9. char buffer[5];
  10. itoa(m_Mac_list.GetCount(), buffer, 10);    //将数量转化为进制字符串;
  11. m_count += buffer;
  12. m_count += "  台活动主机";
  13. }
  14. else if (lParam == 1)
  15. {
  16. m_sending = "正在发送ARP请求包!";
  17. }
  18. else if (lParam == 2)
  19. {
  20. if (nThreadSignal)
  21. {
  22. m_sending = "全部ARP请求包发送完毕!";    //判断是自行发送完毕还是用户终止的?
  23. };
  24. }
  25. UpdateData(FALSE);
  26. return 0;
  27. }

参考资料:《Winpcap网络开发库入门》

转载于:https://blog.51cto.com/phinecos/368157

基于ARP协议获取局域网内主机MAC地址相关推荐

  1. python获取局域网在线主机_python通过scapy获取局域网所有主机mac地址示例

    python通过scapy获取局域网所有主机mac地址示例 发布于 2014-10-10 20:34:48 | 607 次阅读 | 评论: 0 | 来源: 网友投递 Python编程语言Python ...

  2. Android 获取局域网内网IP地址

    Android 获取局域网内网IP地址 废话 上代码 完事 废话 拿局域网IP一般用在tcp通讯或udp通讯上,下次再整理下这类通讯的框架 上代码 /*** 网络工具* 获得局域网IP地址* @aut ...

  3. java获取局域网内主机,java怎么获取局域网内所有主机ip

    java怎么获取局域网内所有主机ip 关注:53  答案:2  mip版 解决时间 2021-01-27 21:31 提问者夢岭杺 2021-01-27 12:02 java怎么获取局域网内所有主机i ...

  4. android 访问内网ip_android 获取局域网IP与MAC 地址 毫秒级(详解)

    两个 linux命令 开始理清思路:主要使用 linux 两个命令(2017-07-21 fix:这个思路不好,后面使用udp取代[毫秒级]) [ping]: 查询某个ip是否被设备占用 [cat]  ...

  5. 怎么查同一网络下的计算机,Windows下查看同局域网其它主机MAC地址

    事情是这样的,今天去面试的时候笔试有一道题问到:Windows下使用什么命令来获知同局域网内其他主机的MAC地址.一开始看到感觉很熟悉,但是却答不上来.原来建站这么就,很多使用都要使用ping命令来测 ...

  6. 局域网内知道Mac地址查询对应IP

    环境: 1. 知道cubietruck的Mac地址为A:B:C:D:E:F 2. 同一局域网内的一台计算机(这里为Ubuntu) 一.ping 255 获取广播地址 ifconfig | grep ' ...

  7. 安卓基于MDNS协议的局域网内服务发现

    mDNS简介 mdns 即多播(组播)dns(Multicast DNS),用于本地局域网服务发现的协议,在Apple 的设备上(电脑,笔记本,iphone,ipad等设备)都提供了这个服务(Bonj ...

  8. Python获取局域网内所有机器IP地址与网卡MAC地址

    已发相关文章请参考Python获取本机所有网卡的MAC地址 本文代码使用ARP协议获取局域网内所有计算机的IP地址与MAC地址,思路是使用系统命令arp获取ARP表并生成文本文件,然后从文件中读取和解 ...

  9. ARP协议及局域网断网攻击(scapy)

    ARP协议攻击 地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议.主机发送信息时将包含目标IP地址的ARP请求广播到网 ...

最新文章

  1. 无效0_一场时代的变革,一场与时间的较量,“0”无效载体、“0”空气氧化、“0”细菌生存。...
  2. 使用 cglib_CGLib 动态代理 原理解析
  3. 功能性农业未来方向-农业大健康·徐春晖:农业品牌市场规范
  4. 开发管理 (3) -项目启动会议
  5. 搜索引擎反作弊之:整体技术思路
  6. mysql 分段执行_了解一下项目中常用的19条MySQL优化
  7. Python数据挖掘 环境搭建
  8. Spring mvc 拦截器 配置心得
  9. navicat运行db文件_在 Navicat for MongoDB 使用文档
  10. python实现简单购物系统
  11. 人人对战五子棋 C++
  12. 「教程」Windows程序未响应,怎么分析确认具体原因
  13. 我所学过看过的计算机语言入门书籍推荐
  14. 写一函数,将一个3x3的整型矩阵转置
  15. kafka报错Error while fetching metadata with correlation
  16. Ajax传递二维数组至后台ThinkPHP控制器
  17. properties解耦数据库参数和SQL参数的传递
  18. July 16th 模拟赛C T4 奶牛排队 Solution
  19. mysql 1677_mysql之数据库主从复制配置报错1677
  20. JavaScript从初级往高级走系列————prototype

热门文章

  1. mysql主从复制延迟问题的相关知识与解决方案
  2. 异步tcp通信——APM.ConsoleDemo
  3. 如何在Cocos2D游戏中实现A*寻路算法(三)
  4. asp生成和导出excel和word数据源码和代码,简单好用(已经测试可以用)
  5. 控制自己的贪念,提升自己的能力
  6. 机器学习Sklearn学习总结
  7. 大数据精准运营需要注意的点
  8. eSIM物联网卡的优点有哪些
  9. 不限流量的物联卡是否真存在
  10. php中余数为0,PHP中余数、取余的妙用