Hello!

I do laboratory work:

Implementing a TCP packet generator (on Raw sockets) in accordance with the RFC 793 standard.

  1. Requirements for implementation

• The application must perform TCP packet generation functions. ... the rest is not so important ...

It is important to create a "hands" tcp package, and send it somewhere, say 127.0.0.1 to port 1000.

Somehow I collected the packet generator ... And it does not work ... It does not generate errors during compilation, and when sendto (...) works, WSAGetLastError () gives error 10022. Here is the code:

header.h struct tcp_header { unsigned short src_port; // Порт отправителя unsigned short dst_port; // Порт получателя unsigned int seq_n; // Номер очереди unsigned int ack_n; // Номер подтверждения unsigned char offset; // Смещение данных (4 бита) // + Зарезервировано (4 бита) unsigned char flags; // Зарезервировано (2 бита) // + Флаги (6 бит) unsigned short win; // Размер окна unsigned short crc; // Контрольная сумма заголовка unsigned short padding; // Дополнение до 20 байт }; //Также необходимо ввести структуру псевдозаголовка, которая позволит вычислять контрольную сумму в TCP и UDP пакетах. struct pseudo_header { unsigned int src_addr; // адрес отправителя unsigned int dst_addr; // адрес получателя unsigned char zero ; // начальная установка unsigned char proto; // протокол unsigned short length; // длина заголовка //struct tcp_header tcp; }; //-------=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= struct ip_header { unsigned char ver_ihl; // Длина заголовка (4 бита) // (измеряется в словах по 32 бита) + // + Номер версии протокола (4 бита) unsigned char tos; // Тип сервиса unsigned short tlen; // Общая длина пакета unsigned short id; // Идентификатор пакета unsigned short flags_fo; // Управляющие флаги (3 бита) // + Смещение фрагмента (13 бит) unsigned char ttl; // Время жизни пакета unsigned char proto; // Протокол верхнего уровня unsigned short crc; // CRC заголовка unsigned int src_addr; // IP-адрес отправителя unsigned int dst_addr; // IP-адрес получателя }; ip_header iph; tcp_header tcph; SOCKET s; //-------=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //Далее поговорим о подсчете контрольных сумм в генерируемых пакетах. //Контрольную сумму в IP и ICMP пакетах считает следующая функция: unsigned short rs_crc (unsigned short * buffer, int length) { unsigned long crc = 0; // Вычисление CRC while (length > 1) { crc += *buffer++; length -= sizeof (unsigned short); } if (length) crc += *(unsigned char*) buffer; // Закончить вычисления crc = (crc >> 16) + (crc & 0xffff); crc += (crc >> 16); // Возвращаем инвертированное значение return (unsigned short)(~crc); } //Для подсчета CRC в TCP и UDP пакетах необходимо воспользоваться следующей функцией, //которая сначала создает псевдозаголовок, а уже потом вычисляет контрольную сумму. unsigned short rs_pseudo_crc( char *data, int data_length,unsigned int src_addr,unsigned int dst_addr,int packet_length,unsigned char proto) { char * buffer; unsigned int full_length; unsigned char header_length; struct pseudo_header ph; unsigned short p_crc = 0; // Заполнение структуры псевдозаголовка ph.src_addr = src_addr; ph.dst_addr = dst_addr; ph.zero = 0; ph.proto = proto; ph.length = htons (packet_length); header_length = sizeof (struct pseudo_header); full_length = header_length + data_length; buffer =(char *) calloc (full_length, sizeof (char)); // Генерация псевдозаголовка memcpy (buffer, &ph, header_length); memcpy (buffer + header_length, data, data_length); // Вычисление CRC. p_crc = rs_crc ((unsigned short*) buffer, full_length); free (buffer); return p_crc; } //Установки опции TOS для сокета: int rs_set_tos (SOCKET s, unsigned char new_tos) { int tos = new_tos; int tos_len = sizeof (tos); int per=setsockopt(s, IPPROTO_IP, 3, (char *)&tos, tos_len); if (per == SOCKET_ERROR) { cout<<"setsockopt Error "<<WSAGetLastError()<<endl; return WSAGetLastError(); } return 0; } //Установка опции RAW для сокета: int rs_set_raw (SOCKET s) { unsigned int use_own_header = 1; // Установка опции RAW для сокета, что говорит о том // что мы вручную будем формировать заголовки пакетов if ( setsockopt (s, IPPROTO_IP, 2,//~IP_HDRINCL (char*)&use_own_header, sizeof(use_own_header))== SOCKET_ERROR) { cout<<"setsockopt Error "<<WSAGetLastError()<<endl; return WSAGetLastError(); } else { cout<<"TCP setsockopt - OK"<<endl; } return 0; } //Далее необходимо объявить структуры заголовков создаваемых пакетов. //После этого производится заполнение заголовка IP пакета. На следующем шаге созданием RAW -сокет, //и если нет вложений протоколов верхнего уровня в пакет IP , то отправляем его, используя следующую функцию: int rs_send_ip (SOCKET s, ip_header iph, unsigned char * data, int data_length, unsigned short dst_port_raw) { char * buffer; int result; sockaddr_in target; unsigned char header_length; unsigned int packet_length; memset (&target, 0, sizeof (target)); target.sin_family = AF_INET; target.sin_addr.s_addr = iph.dst_addr; target.sin_port = dst_port_raw; // Вычисление длины и заголовка пакета header_length = sizeof (struct ip_header); packet_length = header_length + data_length; // Установка CRC. iph.crc = 0; // Заполнение некоторых полей заголовка IP iph.ver_ihl = RS_IP_VERSION; // Если длина пакета не задана, то длина пакета // приравнивается к длине заголовка if (!(iph.ver_ihl & 0x0F)) iph.ver_ihl |= 0x0F & (header_length / 4); buffer =(char *) calloc (packet_length, sizeof (char)); // Копирование заголовка пакета в буфер ( CRC равно 0). memcpy (buffer, &iph, sizeof (struct ip_header)); // Копирование данных в буфер if (data) memcpy (buffer + header_length, data, data_length); // Вычисление CRC. iph.crc = rs_crc((unsigned short *) buffer, packet_length); // Копирование заголовка пакета в буфер (CRC посчитана). memcpy (buffer, &iph, sizeof (struct ip_header)); // Отправка IP пакета в сеть. result = sendto ( s, buffer, packet_length, 0,(struct sockaddr *)&target,sizeof (target)); if(result==SOCKET_ERROR) cout<<"TCP pakcet sended - Filed: "<<WSAGetLastError()<<endl; else cout<<"TCP sendto - OK"<<endl; printf("%s\n", buffer); free (buffer); return result; } int rs_send_tcp (SOCKET s, unsigned char * data, int data_length) { char * buffer; int result; unsigned char header_length; unsigned int packet_length; // Вычисление длин пакета и заголовка. header_length = sizeof (struct tcp_header); packet_length = header_length + data_length; // Установка CRC. tcph.crc = 0; // Установка поля offset . tcph.offset = 0xF0 & ((header_length / 4) << 4); buffer =(char *) calloc (packet_length, sizeof (char)); // Копирование заголовка пакета в буфер ( CRC равно 0). memcpy (buffer, &tcph, sizeof (struct tcp_header)); // Копирование протокола более высокого уровня (данных) if (data) memcpy (buffer + header_length, data, data_length); // Вычисление CRC. tcph.crc = rs_pseudo_crc (buffer, packet_length, iph.src_addr, iph.dst_addr, packet_length, IPPROTO_TCP); // Копирование заголовка пакета в буфер (CRC посчитано). memcpy (buffer, &tcph, sizeof (struct tcp_header)); // Посылка IP пакета с вложенным TCP пакетом result = rs_send_ip (s, iph, (unsigned char*)buffer, packet_length, tcph.dst_port); free (buffer); return result; } int rs_exit(void) { // Закрытие библиотеки Winsock if(!WSACleanup ()) cout<<"TCP WSACleanup() - OK"<<endl; else cout<<"TCP WSACleanup() Error "<<WSAGetLastError()<<endl; return 0; } 

// =============================================== ======================================= TCP.cpp

 #include <winsock2.h> #include <ws2tcpip.h> #include <Windows.h> #include <iostream> #include <stdio.h> #include <stdlib.h> #include <conio.h> using namespace std; #include "defines.h" #include "header.h" /*****************************************************************/ void ShowError() { LPVOID lpMsgBuf = NULL; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,NULL,WSAGetLastError(), MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPTSTR)&lpMsgBuf,0,NULL); CharToOem((char*)lpMsgBuf,(char*)lpMsgBuf); cout<<(LPCTSTR)lpMsgBuf<<endl; LocalFree(lpMsgBuf); } //*****************************************************************/ void main(){ WSADATA wsaData; //Первым шагом будет инициализация библиотеки Winsock 2.2. if(WSAStartup(0x0202,&wsaData)){ShowError();} else { cout<<"TCP WSAStartup - OK"<<endl; // Созлание RAW сокета. s = WSASocket (AF_INET, SOCK_RAW, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); if(s != INVALID_SOCKET){ cout<<"TCP Raw scoket is created"<<endl; rs_set_tos(s, 0); rs_set_raw(s); unsigned int use_own_header = 1; // Установка опции RAW для сокета, что говорит о том // что мы вручную будем формировать заголовки пакетов if ( setsockopt (s, IPPROTO_IP, 2,//~IP_HDRINCL (char*)&use_own_header, sizeof(use_own_header))== SOCKET_ERROR) { cout<<"setsockopt Error "<<WSAGetLastError()<<endl; } else { cout<<"TCP setsockopt - OK"<<endl; } char *ptr, szMessage[4068]; strcpy(szMessage,"HHHHHHHHEEEEEEEEEEEEEELLLLLLLLLLLLLLLLLOOOOOOOOOOOOOOOOOOOOWWWWWWWWWWWWWWWWWWWW"); ptr=szMessage; unsigned char data; data = static_cast<unsigned char>(*ptr); //************************************************************************ rs_send_tcp (s, &data, strlen(ptr)); if(closesocket(s)== SOCKET_ERROR){ cout<<"Close TCP Socket - Error"<<endl;} else{cout<<"TCP closesocket - OK"<<endl;} } } rs_exit(); getch(); } 

Corrected the code ... here it is // Sending an IP packet to the network.

  result = sendto ( s, buffer, packet_length, 0,(struct sockaddr *)&target,sizeof (target)); выявляется ошибка... 

I went through everything again with my hands, the result is less than the code, and the error is the same ...:

 char datagram[4096]; struct ip_header *iph = (struct ip_header *) datagram; struct tcp_header *tcph = (struct tcp_header *) datagram + sizeof (struct ip_header); char * data = (char *) datagram + sizeof(struct tcp_header) + sizeof(struct ip_header); struct sockaddr_in sin; WSADATA wsaData; //Первым шагом будет инициализация библиотеки Winsock 2.2. if(WSAStartup(0x0202,&wsaData)) {ShowError();} else cout<<"\n\nTCP WSAStartup - OK"<<endl; // Созлание RAW сокета. SOCKET r = WSASocket (AF_INET, SOCK_RAW, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); if(r != INVALID_SOCKET){ cout<<"TCP Raw scoket is created"<<endl; } sin.sin_family = AF_INET; sin.sin_port = htons (1000); sin.sin_addr.s_addr = inet_addr("127.0.0.1"); memset(datagram, 0, 4096); iph->ver_ihl = 5; iph->tos = 0; iph->tlen = sizeof (struct ip_header) + sizeof (struct tcp_header); iph->flags_fo = 0; iph->ttl = 255; iph->proto = 6; iph->crc = 0; iph->src_addr = inet_addr ("127.0.0.1"); iph->dst_addr = sin.sin_addr.s_addr; tcph->src_port = htons (1001); tcph->dst_port = htons (1000); tcph->seq_n = 65;// random tcph->ack_n = 0; tcph->offset = 0; tcph->flags = TCP_SYN; tcph->win = htonl (65535); tcph->crc = 0; tcph->padding = 0; iph->crc = csum ((unsigned short *) datagram, iph->tlen >> 1); memset(data, 0, sizeof(data)); unsigned int use_own_header = 1; int one = 1; const char *val = "hhhhhhh"; if(setsockopt (r,IPPROTO_IP,IP_HDRINCL,(char*)&use_own_header,sizeof(use_own_header))==SOCKET_ERROR) { cout<< "Setsockopt\tFAIL.\n"; } while(1) { int result = sendto ( r, data, strlen(data), 0,(struct sockaddr *)&sin,sizeof (sin)); if(result==SOCKET_ERROR) { cerr << "Sendto\tFAIL. "<<WSAGetLastError()<<endl; } else cout << " :) "; } 
  • minus for improper use of tags (it’s time to learn how many times they asked) ... - gecube
  • @Alerr Invalid argument msdn.microsoft.com/en-us/library/aa924071.aspx - alexlz
  • questionable which mark the thematic focus of the issue (c ++, winsock, visual-studio-2010). I remind you that ["C ++"] [1] is not the same as ["C ++"] [2] (the search engine considers them as different tags) [1]: hashcode.ru/questions/tagged/c%2B % 2B [2]: hashcode.ru/questions/tagged/%D1%81%2B%2B - gecube
  • one
    Possible without C ++. yes 'Damn you!' | nc $ host $ port where the host and port variables contain the address and port number of the receiver. In general, why do you have some raw, etc. Correct the question, add the laboratory task there. And then calculate what this program should do, there are hardly many hunters. - alexlz pm
  • No, you need to with ++ and with Raw sockets ... The task is to create a package with "hands". So far I don’t understand why I need a pseudo heading at all, and what and how to do with it ... - Alerr

1 answer 1

Pay attention, we are talking about send .

Limitations on Raw Sockets

On Windows 7, Windows XP, Service Pack 2 (SP2), and Windows XP with Service Pack 3 (SP3),

 TCP data cannot be sent over raw sockets. UDP datagrams with an invalid source address cannot be sent over raw sockets. The IP source address for any outgoing UDP datagram must exist on a network interface or the datagram is dropped. This change was made to limit the ability of malicious code to create distributed denial-of-service attacks and limits the ability to send spoofed packets (TCP/IP packets with a forged source IP address). A call to the bind function with a raw socket for the IPPROTO_TCP protocol is not allowed. Note The bind function with a raw socket is allowed for other protocols (IPPROTO_IP, IPPROTO_UDP, or IPPROTO_SCTP, for example). 

Windows Server 2008 R2, Windows Server 2008, Windows Server 2008, Windows Server 2008, or Windows Server 2008, or Windows Server 2008

See here (from Microsoft).

  • Thanks for the material. So that’s how they struggle with flooded spoolers))))))) It turns out that you can send packets to windows, but should they have a real ip source? - Alerr 4:21 pm
  • Such a question is a vozik ... I collect a package, send a sendto, I try to somehow see it in the winshark and I don’t see anything at all (I see other packages ... I don’t see my own "hands" .. Maybe Vinshark doesn’t see anything bad collected packets? Most likely due to the incorrect filling of the package, the sniffer takes it not for the tsr package ?, and generally does not accept the package ... Can it be? - Alerr