使用WinPcap(SharpPcap)实现ARP抓包以实现设备IP搜索功能
在监控摄像机安装后,往往需要设置IP等信息,在IP不知道的情况下,IP搜索是一个很常见也必须的功能。
考虑到设备IP和当前局域网可能不在同一个网段,ARP是一个不错的选择。
首先安装WinPcap软件
使用C#开发还需要以下dll:
SharpPcap.dll
PacketDotNet.dll
请自己百度下载。
设计逻辑:
用户电脑开始搜索IP时,首先发送一个arp请求然后用户电脑开始监听,监控摄像机等设备监听到后发送一个arp包,包含ip等信息回复,用户电脑监听到后解析
首先要获取当前计算机的网卡及ip和mac物理地址
ManagementObjectSearcher ms = new ManagementObjectSearcher(@"SELECT DeviceID FROM Win32_NetworkAdapter WHERE ((MACAddress Is Not NULL) AND (Manufacturer <> 'Microsoft'))");//WHERE PNPDeviceID LIKE 'PCI%' if (ms.Get().Count < 1) { MessageBox.Show("不存在真实网卡"); return; } devices1 = LibPcapLiveDeviceList.Instance; if (devices1.Count < 1) { MessageBox.Show("无法获取网卡"); return; } PhysicalAddress pmac = PhysicalAddress.Parse("FF-FF-FF-FF-FF-FF"); destinationIP = IPAddress.Broadcast; //遍历网卡 foreach (var device in devices1) { if (!device.Description.ToLower().Contains("vmware") && !device.Description.ToLower().Contains("virtual"))//排除虚拟机网卡 { DeviceNoticeThread = new Thread(new ThreadStart(() => { if (device.Addresses.Count > 0) { foreach (var address in device.Addresses) { if (address.Addr.type == SharpPcap.LibPcap.Sockaddr.AddressTypes.AF_INET_AF_INET6) { if (address.Addr.ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { localIP = address.Addr.ipAddress; break; } } } } foreach (var address in device.Addresses) { if (address.Addr.type == SharpPcap.LibPcap.Sockaddr.AddressTypes.HARDWARE) { localMAC = address.Addr.hardwareAddress; } } var ethernetPacket = new EthernetPacket(localMAC, pmac, EthernetPacketType.Arp); var arpPacket = new ARPPacket(getBas("FFFFFFFFFFFF")); ethernetPacket.PayloadPacket = arpPacket; device.Open(); device.SendPacket(ethernetPacket); })); DeviceCaptureThread = new Thread(new ThreadStart(() => { device.OnPacketArrival += new PacketArrivalEventHandler(device_OnPacketArrival); device.Open(DeviceMode.Normal, 1000); string filter = "arp"; device.Filter = filter; device.StartCapture(); })); DeviceCaptureThread.IsBackground = true; DeviceCaptureThread.Start(); DeviceNoticeThread.IsBackground = true; DeviceNoticeThread.Start(); } }
getBas函数是拼出arp包内容,这里暂定长度40,内容自己拼
private ByteArraySegment getBas(string mac) { byte[] bas = new byte[70]; bas[0] = 0;//硬件类型 - 以太网类型值0x1 bas[1] = 1; bas[2] = 08;//上层协议类型 - IP协议(0x0800) bas[3] = 00; bas[4] = 6;//MAC地址长度 bas[5] = 4;//IP地址长度 bas[6] = 0;//操作码 - 0x1表示ARP请求包,0x2表示应答包 bas[7] = 1; string sendermac = localMAC.ToString().Trim(); if (sendermac.Length == 12) { for (int i = 0; i < 6; i++) { bas[i + 8] = Convert.ToByte(sendermac.Substring(i * 2, 2), 16);//发送方mac } } string[] senderip = localIP.ToString().Trim().Split('.'); if (senderip.Length == 4) { for (int i = 0; i < senderip.Length; i++) { bas[i + 14] = Convert.ToByte(senderip[i]);//发送方ip } } string receivermac = mac; if (receivermac.Length == 12) { for (int i = 0; i < 6; i++) { bas[i + 18] = Convert.ToByte(receivermac.Substring(i * 2, 2), 16);//接收方mac } } string[] receiverip = destinationIP.ToString().Trim().Split('.'); if (receiverip.Length == 4) { for (int i = 0; i < receiverip.Length; i++) { bas[i + 24] = Convert.ToByte(receiverip[i]);//接收方ip } } string strpadding = "自定义头," + Convert2Hex(localIP.ToString().Trim()) + "," + sendermac; byte[] padding = Encoding.UTF8.GetBytes(strpadding.PadRight(40, '\0'));//自定义数据 for (int i = 0; i < 40; i++) { bas[i + 28] = padding[i]; } return new ByteArraySegment(bas); }
监听到arp包且长度一致暂定80,根据实际情况改,且头一致,就可以解析显示了
private void device_OnPacketArrival(object sender, CaptureEventArgs e) { if (bStopOnPacketArrival) return; try { Packet packet = Packet.ParsePacket(e.Device.LinkType, e.Packet.Data); if (packet is EthernetPacket) { EthernetPacket ep = (EthernetPacket)packet; if (ep.PayloadPacket is ARPPacket) { ARPPacket ap = (ARPPacket)ep.PayloadPacket; if (ep.Type == EthernetPacketType.Arp && ap.Operation == ARPOperation.Response) { byte[] data = ep.Bytes; if (data.Length == 80) { } } } } } catch (System.Exception ex) { log.ErrorFormat("解析arp包失败!错误信息:{0}", ex.Message); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架