zoukankan      html  css  js  c++  java
  • 使用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, ''));//自定义数据
                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);
                }
            }
  • 相关阅读:
    html 底部虚线
    C# 写入二进制文件
    js document 触发按键事件
    python之工作举例:通过复制NC文件来造数据
    python之多线程举例
    python之发送HTML内容的邮件
    python之打印日志logging
    python之查询指定目录下的最新文件
    python之datetime类
    python之Counter类:计算序列中出现次数最多的元素
  • 原文地址:https://www.cnblogs.com/jhlong/p/6514514.html
Copyright © 2011-2022 走看看