gpt4 book ai didi

c - 在 c 中使用 sendto() 发送自定义 tcp 数据包?

转载 作者:可可西里 更新时间:2023-11-01 02:50:23 44 4
gpt4 key购买 nike

准确地说,我已经创建了这个简单的 TCP 程序来通过网络将一个简单的 TCP 数据包发送到目标机器,但不知何故,我真的不知道我做错了什么,但它似乎没有发送任何数据包到目的主机。我也无法在我的 wireshark 中找到它。

rawtcp.c:

//---cat rawtcp.c---
// Run as root or SUID 0, just datagram no data/payload

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <netinet/tcp.h>

// 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 <source hostname/IP> <source port> <target hostname/IP> <target port>\n", argv[0]);
exit(-1);
}

sd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
if(sd < 0)
{
perror("socket() error");
exit(-1);
} else
printf("socket()-SOCK_RAW and tcp protocol is OK.\n");

// The source is redundant, may be used later if needed
// Address family
sin.sin_family = AF_INET;
din.sin_family = AF_INET;

// Source port, can be any, modify as needed
sin.sin_port = htons(atoi(argv[2]));
din.sin_port = htons(atoi(argv[4]));

// Source IP, can be any, modify as needed
sin.sin_addr.s_addr = inet_addr(argv[1]);
din.sin_addr.s_addr = inet_addr(argv[3]);

// IP structure
ip->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 < 20; count++)
{
if(sendto(sd, buffer, ip->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;
}

编译时,它编译得很好。当我运行程序时,它应该是 ./rawtcp 192.168.1.152 1000 192.168.1.151 1000 它说:

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

但是当将 wireshark 过滤为 tcp.port == 1000 时,它永远不会显示(注意:源 ip 是 192.168.1.152,目标 ip 是 192.168.1.151)。但是如果我做一个简单的 hping3 -p 1000 192.168.1.151 它工作得很好,我也可以在 wireshark 中看到它。

如果您能告诉我我的代码中哪里做错了,我将不胜感激:)

最佳答案

首先,您缺少 <arpa/inet.h> header ,它提供了 inet_addr您正在使用的功能。由于隐式函数声明,您的程序仍应在 C89 下编译而无需此,但依赖它是不好的做法,它可能会导致细微的错误。

一个问题是您滥用了 #pragma pack .

在你声明你的结构之前,你应该做 #pragma pack(push, 1) ,这两者都将 struct packing alignment 设置为 1,并将先前的 packing alignment 状态推送到堆栈。完成声明结构后,您可以执行 #pragma pack(pop)在任何以下声明中将结构包装重置为正常。对于您的程序,省略 #pragma pack(pop)在你的声明之后应该仍然有效,但最好重新设置它,以防你声明任何其他你不想被紧密打包的结构,或者你之后包含任何其他头文件。

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

struct b {
/* ... */
};
#pragma pack(pop)

你的 struct ipheader 的另一个问题是你有两个 8 位 iph_flags和一个 16 位 iph_offset ,而 IP header 中的标志字段应为 3 位,偏移字段应为 13 位(两者加起来为 16 位)。这意味着您的 header 中有额外的 8 位,不应该存在。由于您无论如何都要用零填充这两个字段,因此您可以通过删除 iph_flags 来解决此问题完全从你的结构中,只保留一个 16 位 iph_offset字段,用0填充,实际上跨越了IP头中3位和13位字段的空间。

通过这些修复,您的程序对我有效,并且可以在 Wireshark 中看到一个数据包。

关于c - 在 c 中使用 sendto() 发送自定义 tcp 数据包?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48338190/

44 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com