The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  ВХОД  слежка  RSS
"помогите пересчитать TCP checksum"
Вариант для распечатки  
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [Проследить за развитием треда]

"помогите пересчитать TCP checksum"  
Сообщение от tcp on 27-Сен-06, 11:48 
помогите пересчитать TCP checksum
packet - полученный пакет

ethernet = (struct ether_header*)(packet);
iph = (struct ip*)(packet + size_ethernet);
tcph = (struct tcphdr*)(packet + size_ethernet + size_ip);

IP checksum получилось подсчитать, но с TCP немного запутался

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

 Оглавление

Сообщения по теме [Сортировка по времени, UBB]


1. "помогите пересчитать TCP checksum"  
Сообщение от vic (??) on 27-Сен-06, 12:30 
>помогите пересчитать TCP checksum
>packet - полученный пакет
>
>ethernet = (struct ether_header*)(packet);
>iph = (struct ip*)(packet + size_ethernet);
>tcph = (struct tcphdr*)(packet + size_ethernet + size_ip);
>
>IP checksum получилось подсчитать, но с TCP немного запутался

rfc-793 пункт 3.1
что не понятно? как считаем?

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

2. "помогите пересчитать TCP checksum"  
Сообщение от tcp on 27-Сен-06, 13:13 
>rfc-793 пункт 3.1
>что не понятно? как считаем?

inline u_short in_cksum(u_short *addr, int len)
{
    register int nleft = len;
    register u_short *w = addr;
    register int sum = 0;
    u_short answer = 0;

     /* Our algorithm is simple, using a 32 bit accumulator (sum), we add
      * sequential 16 bit words to it, and at the end, fold back all the
      * carry bits from the top 16 bits into the lower 16 bits. */

     while (nleft > 1)  {
         sum += *w++;
         nleft -= 2;
     }

     /* mop up an odd byte, if necessary */
     if (nleft == 1) {
         *(u_char *)(&answer) = *(u_char *) w;
         sum += answer;
     }

     /* add back carry outs from top 16 bits to low 16 bits */
     sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
     sum += (sum >> 16);                /* add carry */
     answer = ~sum;                     /* truncate to 16 bits */
     return(answer);
}

struct cksum {
    struct pseudo_hdr pseudo;
    struct tcp_hdr tcp;
};

tcp->th_sum           = in_cksum((void *)cksum, sizeof(struct cksum));

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

3. "помогите пересчитать TCP checksum"  
Сообщение от vic (??) on 27-Сен-06, 13:33 
struct cksum {
    struct pseudo_hdr pseudo;
    struct tcp_hdr tcp;
};

tcp->th_sum           = in_cksum((void *)cksum, sizeof(struct cksum));

1. rfc 793 пункт 3.1 :)
2. checksum в TCP считается за весь TCP-пакет (включая заголовок) плюс псевдозаголовок. У вас только заголовок TCP + псевдозаголовок.
3. выравнивание в pack(1)для стуктур стоит?

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

4. "помогите пересчитать TCP checksum"  
Сообщение от tcp on 27-Сен-06, 13:57 
>2. checksum в TCP считается за весь TCP-пакет (включая заголовок) плюс псевдозаголовок.
>У вас только заголовок TCP + псевдозаголовок.
что значит включая заголовок?

>3. выравнивание в pack(1)для стуктур стоит?
нет


Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

5. "помогите пересчитать TCP checksum"  
Сообщение от vic (??) on 27-Сен-06, 14:24 
>>2. checksum в TCP считается за весь TCP-пакет (включая заголовок) плюс псевдозаголовок.
>>У вас только заголовок TCP + псевдозаголовок.
>что значит включая заголовок?

struct cksum {
    struct pseudo_hdr pseudo;
    struct tcp_hdr tcp;
};
здесь:
struct tcp_hdr tcp;
это tcp заголовок, судя по названию. А должен быть весь TCP-пакет (заголовок и данные).
об этом написано в rfc (азбука для сетевого программирования).
http://www.faqs.org/rfcs/rfc793.html

>>3. выравнивание в pack(1)для стуктур стоит?
>нет
сделать обязательно для тех стуктур что накладываются на сырые данные (из сокета или из файла). по умолчанию размер структуры не равен сумме размеров членов структуры т.к. используется выравнивание (в разных системах по разному).

struct aaa1
{
int  mmm;
char bbb;
} a1;

#pragma pack(push,1)
struct aaa2
{
int  mmm;
char bbb;
} a2;
#pragma pack(pop)

sizeof(a1) != sizeof(a2)

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

6. "помогите пересчитать TCP checksum"  
Сообщение от tcp on 27-Сен-06, 15:20 
>struct cksum {
>    struct pseudo_hdr pseudo;
>    struct tcp_hdr tcp;
>};
>здесь:
>struct tcp_hdr tcp;
>это tcp заголовок, судя по названию. А должен быть весь TCP-пакет (заголовок
>и данные).
>об этом написано в rfc (азбука для сетевого программирования).
>http://www.faqs.org/rfcs/rfc793.html

эм...
сделал так

payload = (u_char *)(packet + size_ethernet + size_ip + size_tcp);
struct cksum {
    struct pseudo_hdr pseudo;
    struct tcp_hdr tcp;
    u_char *payload;
};

функция подсчёта

inline u_short tcp_sum(u_short *addr, int len)
{
    register int nleft = len;
    register u_short *w = addr;
    register int sum = 0;
    u_short answer = 0;

     /* Our algorithm is simple, using a 32 bit accumulator (sum), we add
      * sequential 16 bit words to it, and at the end, fold back all the
      * carry bits from the top 16 bits into the lower 16 bits. */

     while (nleft > 1)  {
         sum += *w++;
         nleft -= 2;
     }

     /* mop up an odd byte, if necessary */
     if (nleft == 1) {
         *(u_char *)(&answer) = *(u_char *) w;
         sum += answer;
     }

     /* add back carry outs from top 16 bits to low 16 bits */
     sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
     sum += (sum >> 16);                /* add carry */
     answer = ~sum;                     /* truncate to 16 bits */
     return(answer);
}

но всё равно не правильно :(
>сделать обязательно для тех стуктур что накладываются на сырые данные (из сокета
>или из файла). по умолчанию размер структуры не равен сумме размеров
>членов структуры т.к. используется выравнивание (в разных системах по разному).
>
>struct aaa1
>{
>int  mmm;
>char bbb;
>} a1;
>
>#pragma pack(push,1)
>struct aaa2
>{
>int  mmm;
>char bbb;
>} a2;
>#pragma pack(pop)
>
>sizeof(a1) != sizeof(a2)

спасибо, на счёт выравнивания всё поправил

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

7. "помогите пересчитать TCP checksum"  
Сообщение от tcp on 27-Сен-06, 15:28 
не
struct cksum {
    struct pseudo_hdr pseudo;
    struct tcp_hdr tcp;
    u_char *payload;
};

а
struct cksum {
    struct pseudo_hdr pseudo;
    struct tcp_hdr tcp;
    u_char payload;
};

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

8. "помогите пересчитать TCP checksum"  
Сообщение от vic (??) on 27-Сен-06, 17:58 
>не
>struct cksum {
>    struct pseudo_hdr pseudo;
>    struct tcp_hdr tcp;
>    u_char *payload;
>};
>

>struct cksum {
>    struct pseudo_hdr pseudo;
>    struct tcp_hdr tcp;
>    u_char payload;
>};

>    u_char payload;
один байт?

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

9. "помогите пересчитать TCP checksum"  
Сообщение от tcp on 27-Сен-06, 18:05 
попробовал вообще другим путём,

u_short tcp_checksum (u_short *addr, int len) {
u_short *w = addr;
int i=len;
int sum=0;
//u_short answer;
while (i > 0) {
sum += *w++;
i -= 2;
}
if (i ==1) sum +=*(u_char *)w;
sum = (sum >> 16) + (sum & 0xffff);
sum = sum + (sum >> 16);
return (~sum);
}

struct _pseudoheader {
struct in_addr source_addr;
struct in_addr destination_addr;
u_char zero; /* зеpо */
u_char protocol;
u_short length;
} pseudoheader;

u_char *pseudopacket;

pseudoheader.source_addr = iph->ip_src;
pseudoheader.destination_addr = iph->ip_dst;
pseudoheader.zero = 0;
pseudoheader.protocol = IPPROTO_TCP;
pseudoheader.length = size_tcp + size_payload;

pseudopacket = (char *)malloc(sizeof(pseudoheader) + sizeof(struct tcphdr) + size_payload);
if ( !pseudopacket ) {
perror ("malloc");
exit (1);
}

memcpy (pseudopacket, &pseudoheader, sizeof (pseudoheader));

memcpy (pseudopacket + sizeof (pseudoheader),packet + +size_ethernet + sizeof (struct ip),sizeof (struct tcphdr));
memcpy (pseudopacket + sizeof (pseudoheader) + size_tcp, packet + size_ethernet + size_ip + size_tcp, size_payload);


tcph->th_sum = 0;
tcph->th_sum = tcp_checksum ((u_short *)pseudopacket, sizeof (pseudoheader)+sizeof(struct tcphdr));

взято из http://dims.karelia.ru/~alexmou/nets_tele/lab05_raw_sockets.pdf

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

10. "помогите пересчитать TCP checksum"  
Сообщение от vic (??) on 27-Сен-06, 19:00 
>попробовал вообще другим путём,
зачет. очень хорошо что пробовал.
военная тайна: есть еще один путь - без копирования заголовков и данных, но это уже дзен.

>tcph->th_sum = tcp_checksum ((u_short *)pseudopacket, sizeof (pseudoheader)+sizeof(struct tcphdr));
забыл самую малость (данные):
tcph->th_sum = tcp_checksum ((u_short *)pseudopacket, sizeof (pseudoheader)+sizeof(struct tcphdr)+ size_payload);


>взято из http://dims.karelia.ru/~alexmou/nets_tele/lab05_raw_sockets.pdf
читал и плакал. красные комменты смешные. куча ошибок :)

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

11. "помогите пересчитать TCP checksum"  
Сообщение от tcp on 27-Сен-06, 19:50 
>>попробовал вообще другим путём,
>зачет. очень хорошо что пробовал.
>военная тайна: есть еще один путь - без копирования заголовков и данных,
>но это уже дзен.
я уже запарился, мне главное чтобы правильно подсчитать :(

>>tcph->th_sum = tcp_checksum ((u_short *)pseudopacket, sizeof (pseudoheader)+sizeof(struct tcphdr));
>забыл самую малость (данные):
>tcph->th_sum = tcp_checksum ((u_short *)pseudopacket, sizeof (pseudoheader)+sizeof(struct tcphdr)+ size_payload);

попробовал, не вышло

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

12. "помогите пересчитать TCP checksum"  
Сообщение от vic (??) on 28-Сен-06, 01:49 
>попробовал, не вышло
видимо где-то еще ошибка при формировании пакета. Как ты определяешь что посчиталось криво?
какая функция возвращает ошибку и какую?


Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

13. "помогите пересчитать TCP checksum"  
Сообщение от tcp on 28-Сен-06, 11:49 
>>попробовал, не вышло
>видимо где-то еще ошибка при формировании пакета. Как ты определяешь что посчиталось
>криво?
>какая функция возвращает ошибку и какую?

вобщем я захватил пакет с помощью сниффера, смотрю какая там сумма, пытаюсь пересчитать и получаю совершенно другой ответ, хотя он должен быть идентичный

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

14. "помогите пересчитать TCP checksum"  
Сообщение от vic (??) on 28-Сен-06, 12:19 
>>>попробовал, не вышло
>>видимо где-то еще ошибка при формировании пакета. Как ты определяешь что посчиталось
>>криво?
>>какая функция возвращает ошибку и какую?
>
>вобщем я захватил пакет с помощью сниффера, смотрю какая там сумма, пытаюсь
>пересчитать и получаю совершенно другой ответ, хотя он должен быть идентичный
>

какой сниффер? под какой операционкой?
под виндой в одном снифере кажись даже не в одном - всегда отображается неправильная сумма :)

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

15. "помогите пересчитать TCP checksum"  
Сообщение от tcp on 28-Сен-06, 12:44 
>какой сниффер? под какой операционкой?
>под виндой в одном снифере кажись даже не в одном - всегда
>отображается неправильная сумма :)

http://www.tcpdump.org/sniffex.c
freebsd 6.1 :)
суть в том что я получаю пакет, изменяю там пару данных, пересчитываю сумму и посылаю (типа дублирую его только на другой хост) , пакет доходит до машины назначения но когда машина раскрывает его и доходит до TCP то сразу отбрасывает так как чексумма не правильная, с подсчётом IP чексуммы всё нормально.

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

16. "помогите пересчитать TCP checksum"  
Сообщение от vic (??) on 28-Сен-06, 13:15 
>>какой сниффер? под какой операционкой?
>>под виндой в одном снифере кажись даже не в одном - всегда
>>отображается неправильная сумма :)
>
>http://www.tcpdump.org/sniffex.c
>freebsd 6.1 :)
каласо :)

>суть в том что я получаю пакет, изменяю там пару данных, пересчитываю
>сумму и посылаю (типа дублирую его только на другой хост) ,
>пакет доходит до машины назначения но когда машина раскрывает его и
>доходит до TCP то сразу отбрасывает так как чексумма не правильная,
>с подсчётом IP чексуммы всё нормально.

А ты пока не изменяй данные. просто посчитай сумму - если не совпадет, тогда искать ошибку.
P.S. при подсчете суммы ее поле должно быть равно 0.

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

17. "помогите пересчитать TCP checksum"  
Сообщение от tcp on 28-Сен-06, 13:35 
>А ты пока не изменяй данные. просто посчитай сумму - если не
>совпадет, тогда искать ошибку.
>P.S. при подсчете суммы ее поле должно быть равно 0.

я сейчас так и пробую, ничего не изменяя подсчитать самому чексумму TCP и сравнить с оригиналом, c подсчётом IP чексуммы как я сказал выше проблем не возникло.
перед эти конечно обнуляю сумму, tcp->th_sum = 0; :)

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

18. "помогите пересчитать TCP checksum"  
Сообщение от vic (??) on 28-Сен-06, 14:08 
>>А ты пока не изменяй данные. просто посчитай сумму - если не
>>совпадет, тогда искать ошибку.
>>P.S. при подсчете суммы ее поле должно быть равно 0.
>
>я сейчас так и пробую, ничего не изменяя подсчитать самому чексумму TCP
>и сравнить с оригиналом, c подсчётом IP чексуммы как я сказал
>выше проблем не возникло.

>перед эти конечно обнуляю сумму, tcp->th_sum = 0; :)
судя по привиденному выше в сообщениях коду эта операция бессмысленна, т.е. надо чтобы в псевдопакете поле сумма было равно 0. а строка tcp->th_sum = 0; - это обнуление не в псевдопакете, а в некой структуре которая в самом расчете не принимает участия :)

алгоритм то простой:
1) формируем и копируем в псевдопакет псевдозаголовок.
2) копируем TCP-пакет (с tcp заголовком включительно) в псевдопакет.
3) обнуляем поле суммы в псевдопакете.
4) считаем сумму и пишим результат в поле сумма псевдопакета.

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

19. "помогите пересчитать TCP checksum"  
Сообщение от tcp on 28-Сен-06, 14:33 
>судя по привиденному выше в сообщениях коду эта операция бессмысленна, т.е. надо чтобы в псевдопакете поле сумма было равно 0. а строка tcp->th_sum = 0; - это обнуление не в псевдопакете, а в некой структуре которая в самом расчете не принимает участия :)
http://www.security.nnov.ru/files/stream3.c

inline u_short tcp_checksum(u_short *addr, int len)
{
    register int nleft = len;
    register u_short *w = addr;
    register int sum = 0;
    u_short answer = 0;

     /* Our algorithm is simple, using a 32 bit accumulator (sum), we add
      * sequential 16 bit words to it, and at the end, fold back all the
      * carry bits from the top 16 bits into the lower 16 bits. */

     while (nleft > 1)  {
         sum += *w++;
         nleft -= 2;
     }

     /* mop up an odd byte, if necessary */
     if (nleft == 1) {
         *(u_char *)(&answer) = *(u_char *) w;
         sum += answer;
     }

     /* add back carry outs from top 16 bits to low 16 bits */
     sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
     sum += (sum >> 16);                /* add carry */
     answer = ~sum;                     /* truncate to 16 bits */
     return(answer);
}

struct _pseudoheader {
struct in_addr source_addr;
struct in_addr destination_addr;
u_char zero; /* зеpо */
u_char protocol;
u_short length;
} pseudoheader;

u_char *pseudopacket;

pseudoheader.source_addr = iph->ip_src;
pseudoheader.destination_addr = iph->ip_dst;
pseudoheader.zero = 0;
pseudoheader.protocol = IPPROTO_TCP;
pseudoheader.length = htons(size_tcp + size_payload);

pseudopacket = (char *)malloc(sizeof(pseudoheader) + sizeof(struct tcphdr) + size_payload);
if ( !pseudopacket ) {
perror ("malloc");
exit (1);
}
memcpy (pseudopacket, &pseudoheader, sizeof (pseudoheader));

memcpy (pseudopacket + sizeof (pseudoheader),packet + size_ethernet + size_ip, size_tcp);
memcpy (pseudopacket + sizeof (pseudoheader) + size_tcp,packet + size_ethernet + size_ip + size_tcp, size_payload);


tcph->th_sum = 0;
tcph->th_sum = tcp_checksum ((u_short *)pseudopacket, sizeof (pseudoheader)+ size_tcp + size_payload);

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

21. "помогите пересчитать TCP checksum"  
Сообщение от vic (??) on 28-Сен-06, 15:02 
>struct _pseudoheader {
>struct in_addr source_addr;
>struct in_addr destination_addr;
>u_char zero; /* зеpо */
>u_char protocol;
>u_short length;
>} pseudoheader;
>
>u_char *pseudopacket;
>
>pseudoheader.source_addr = iph->ip_src;
>pseudoheader.destination_addr = iph->ip_dst;
>pseudoheader.zero = 0;
>pseudoheader.protocol = IPPROTO_TCP;
>pseudoheader.length = htons(size_tcp + size_payload);
>
>pseudopacket = (char *)malloc(sizeof(pseudoheader) + sizeof(struct tcphdr) + size_payload);
>if ( !pseudopacket ) {
>perror ("malloc");
>exit (1);
>}

// псевдохидер
>memcpy (pseudopacket, &pseudoheader, sizeof (pseudoheader));
// сам tcp-пакет
>memcpy (pseudopacket + sizeof (pseudoheader),packet + size_ethernet + size_ip, size_tcp + size_payload);

u_short *ptr = (u_short *)(psevdopacket + sizeof(psevdoheader)); // начало пакета в псевдопакете
ptr[8] = 0; // обнулили поле checksum (смещение в октетах у поля checksum = 16, т.е. в шортах 8)

// посчитали.
>sum = tcp_checksum ((u_short *)pseudopacket, sizeof (pseudoheader)+ size_tcp + size_payload);

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

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

20. "помогите пересчитать TCP checksum"  
Сообщение от tcp on 28-Сен-06, 14:37 
>судя по привиденному выше в сообщениях коду эта операция бессмысленна, т.е. надо чтобы в псевдопакете поле сумма было равно 0. а строка tcp->th_sum = 0; - это обнуление не в псевдопакете, а в некой структуре которая в самом расчете не принимает участия :)
ой, не то выложил,
что значит сумма псевдопакета должна быть 0?

>алгоритм то простой:
>1) формируем и копируем в псевдопакет псевдозаголовок.
>2) копируем TCP-пакет (с tcp заголовком включительно) в псевдопакет.
>3) обнуляем поле суммы в псевдопакете.
>4) считаем сумму и пишим результат в поле сумма псевдопакета.

а ты пробовал сделать со сниффером? у тебя получилось подсчитать?

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

22. "помогите пересчитать TCP checksum"  
Сообщение от vic (??) on 28-Сен-06, 15:04 
>>судя по привиденному выше в сообщениях коду эта операция бессмысленна, т.е. надо чтобы в псевдопакете поле сумма было равно 0. а строка tcp->th_sum = 0; - это обнуление не в псевдопакете, а в некой структуре которая в самом расчете не принимает участия :)
>ой, не то выложил,
>что значит сумма псевдопакета должна быть 0?
>
>>алгоритм то простой:
>>1) формируем и копируем в псевдопакет псевдозаголовок.
>>2) копируем TCP-пакет (с tcp заголовком включительно) в псевдопакет.
>>3) обнуляем поле суммы в псевдопакете.
>>4) считаем сумму и пишим результат в поле сумма псевдопакета.
>
>а ты пробовал сделать со сниффером? у тебя получилось подсчитать?

я на asm считал... когда для железки стек писал :) (ну не было с-компилятора, ну и что..)))

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

23. "помогите пересчитать TCP checksum"  
Сообщение от tcp on 28-Сен-06, 15:50 
>я на asm считал... когда для железки стек писал :) (ну не
>было с-компилятора, ну и что..)))

спасибо большое и респект :)

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

Архив | Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Оцените тред (1=ужас, 5=супер)? [ 1 | 2 | 3 | 4 | 5 ] [Рекомендовать для помещения в FAQ]




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру