envoyer un paquet TCP personnalisé en utilisant sendto () dans c?

Pour être précis, j’ai créé ce programme TCP simple pour envoyer un paquet TCP simple sur le réseau à une machine de destination, mais d’une manière ou d’une autre, je ne sais pas vraiment, qu’est-ce que je fais mal, mais il ne semble pas envoyer de paquets à la destination hôte. De plus, je ne le trouve pas dans mon wirehark.

rawtcp.c:

//---cat rawtcp.c--- // Run as root or SUID 0, just datagram no data/payload #include  #include  #include  #include  #include  #include  #include  #include  #include  // Packet length #define PCKT_LEN 8192 #pragma pack(push, 1) // May create separate header file (.h) for all // headers' structures // IP header's structure struct ipheader { unsigned char iph_ihl:4, /* Little-endian */ iph_ver:4; unsigned char iph_tos; unsigned short int iph_len; unsigned short int iph_ident; unsigned short int iph_offset; unsigned char iph_ttl; unsigned char iph_protocol; unsigned short int iph_chksum; unsigned int iph_sourceip; unsigned int iph_destip; }; /* Structure of a TCP header */ struct tcpheader { unsigned short int tcph_srcport; unsigned short int tcph_destport; unsigned int tcph_seqnum; unsigned int tcph_acknum; unsigned char tcph_reserved:4, tcph_offset:4; // unsigned char tcph_flags; unsigned int tcp_res1:4, /*little-endian*/ tcph_hlen:4, /*length of tcp header in 32-bit words*/ tcph_fin:1, /*Finish flag "fin"*/ tcph_syn:1, /*Synchronize sequence numbers to start a connection*/ tcph_rst:1, /*Reset flag */ tcph_psh:1, /*Push, sends data to the application*/ tcph_ack:1, /*acknowledge*/ tcph_urg:1, /*urgent pointer*/ tcph_res2:2; unsigned short int tcph_win; unsigned short int tcph_chksum; unsigned short int tcph_urgptr; }; #pragma pack(pop) // Simple checksum function, may use others such as Cyclic Redundancy Check, CRC unsigned short csum(unsigned short *buf, int len) { unsigned long sum; for(sum=0; len>0; len--) sum += *buf++; sum = (sum >> 16) + (sum &0xffff); sum += (sum >> 16); return (unsigned short)(~sum); } int main(int argc, char *argv[]) { int sd; // No data, just datagram char buffer[PCKT_LEN]; // The size of the headers struct ipheader *ip = (struct ipheader *) buffer; struct tcpheader *tcp = (struct tcpheader *) (buffer + sizeof(struct ipheader)); struct sockaddr_in sin, din; int one = 1; const int *val = &one; memset(buffer, 0, PCKT_LEN); if(argc != 5) { printf("- Invalid parameters!!!\n"); printf("- Usage: %s    \n", argv[0]); exit(-1); } sd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP); if(sd iph_ihl = 5; ip->iph_ver = 4; ip->iph_tos = 16; ip->iph_len = htons(sizeof(struct ipheader) + sizeof(struct tcpheader)); ip->iph_ident = htons(54321); ip->iph_offset = 0; ip->iph_ttl = 64; ip->iph_protocol = 6; // TCP ip->iph_chksum = 0; // Done by kernel // Source IP, modify as needed, spoofed, we accept through command line argument ip->iph_sourceip = inet_addr(argv[1]); // Destination IP, modify as needed, but here we accept through command line argument ip->iph_destip = inet_addr(argv[3]); // The TCP structure. The source port, spoofed, we accept through the command line tcp->tcph_srcport = htons(atoi(argv[2])); // The destination port, we accept through command line tcp->tcph_destport = htons(atoi(argv[4])); tcp->tcph_seqnum = htonl(1); tcp->tcph_acknum = 0; tcp->tcph_offset = 5; tcp->tcph_syn = 1; tcp->tcph_ack = 0; tcp->tcph_win = htons(32767); tcp->tcph_chksum = 0; // Done by kernel tcp->tcph_urgptr = 0; // IP checksum calculation ip->iph_chksum = htons(csum((unsigned short *) buffer, (sizeof(struct ipheader) + sizeof(struct tcpheader)))); // Inform the kernel do not fill up the headers' structure, we fabricated our own if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0) { perror("setsockopt() error"); exit(-1); } else printf("setsockopt() is OK\n"); printf("Using:::::Destination IP: %s port: %u, Source IP: %s port: %u.\n", argv[1], atoi(argv[2]), argv[3], atoi(argv[4])); // sendto() loop, send every 2 second for 50 counts unsigned int count; for(count = 0; count iph_len, 0, (struct sockaddr *)&din, sizeof(din)) < 0) // Verify { perror("sendto() error"); exit(-1); } else printf("Count #%u - sendto() is OK\n", count); sleep(2); } close(sd); return 0; } 

en le compilant, il comstack parfaitement. aussi, quand ./rawtcp 192.168.1.152 1000 192.168.1.151 1000 le programme tel qu’il est ./rawtcp 192.168.1.152 1000 192.168.1.151 1000 être ./rawtcp 192.168.1.152 1000 192.168.1.151 1000 il est écrit:

 socket()-SOCK_RAW and tcp protocol is OK. setsockopt() is OK Using:::::Destination IP: 192.168.1.151 port: 1000, Source IP: 192.168.1.152 port: 1000. Count #0 - sendto() is OK Count #1 - sendto() is OK 

mais lors du filtrage de wirehark comme tcp.port == 1000 il ne s’affiche jamais (Remarque: l’ tcp.port == 1000 IP source est 192.168.1.152 et l’adresse IP de destination est 192.168.1.151). mais si je fais un simple hping3 -p 1000 192.168.1.151 cela fonctionne très bien et je peux le voir aussi dans Wirehark.

J’apprécierais vraiment si vous pouviez me dire ce que je fais mal dans mon code 🙂

Tout d’abord, il vous manque l’en-tête , qui fournit la fonction inet_addr vous utilisez. Votre programme devrait toujours comstackr sous C89 sans cela à cause de la déclaration implicite de la fonction, mais il est déconseillé de s’en remettre à cela et cela pourrait conduire à des bogues subtils.

L’un des problèmes est votre mauvaise utilisation de #pragma pack .

Avant de déclarer vos structures, vous devez #pragma pack(push, 1) , ce qui permet de définir l’alignement de compression de structure sur 1 et de placer l’alignement précédent sur une stack. Une fois que vous avez fini de déclarer vos structures, vous pouvez ensuite effectuer une opération #pragma pack(pop) pour rétablir la structure de la structure dans les déclarations suivantes. Dans le cas de votre programme, omettre #pragma pack(pop) après vos déclarations devrait toujours fonctionner, mais il est recommandé de le réinitialiser, au cas où vous déclareriez une autre structure que vous ne souhaitez pas forcer. , ou vous incluez tous les autres fichiers d’en-tête après.

 #pragma pack(push, 1) struct a { /* ... */ }; struct b { /* ... */ }; #pragma pack(pop) 

L’autre problème avec votre struct ipheader est que vous avez à la fois un iph_flags 8 bits et un iph_flags 16 bits, tandis que le champ flags dans un en-tête IP doit être de 3 bits et le champ de décalage doit être de 13 bits (les deux réunis). jusqu’à 16 bits). Cela signifie que vous avez 8 bits supplémentaires dans votre en-tête qui ne devrait pas être là. De toute façon, puisque vous remplissez ces deux champs avec un zéro, vous pouvez résoudre ce problème en supprimant iph_flags de votre structure et en ne conservant que le seul champ iph_offset 16 bits, rempli de zéro, qui couvre en réalité l’espace du le champ de 13 bits dans l’en-tête IP.

Avec ces corrections, votre programme fonctionne pour moi et un paquet peut être vu dans Wireshark.

Je pense que votre port est déjà utilisé.

Vous devez changer de port pour 30000 ou plus, les 1000 ports sont souvent pris par d’autres applications

Vous devriez aussi déboguer en utilisant telnet [ip] [port]