本文共 5005 字,大约阅读时间需要 16 分钟。
Raw sockets or packets contain user defined IP headers. Its as simple as that.
Here we shall consider sending a raw tcp packets. A tcp packets has 3 parts : IP header + TCP header + data
The structure of IP Header as given by RFC 791 is :
1 | 0 1 2 3 |
2 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
3 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
4 | |Version| IHL |Type of Service| Total Length | |
5 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
6 | | Identification |Flags| Fragment Offset | |
7 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
8 | | Time to Live | Protocol | Header Checksum | |
9 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
10 | | Source Address | |
11 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
12 | | Destination Address | |
13 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
14 | | Options | Padding | |
15 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
The structure of a TCP header as given by RFC 793 :
1 | 0 1 2 3 |
2 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
3 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
4 | | Source Port | Destination Port | |
5 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
6 | | Sequence Number | |
7 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
8 | | Acknowledgment Number | |
9 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
10 | | Data | |U|A|P|R|S|F| | |
11 | | Offset| Reserved |R|C|S|S|Y|I| Window | |
12 | | | |G|K|H|T|N|N| | |
13 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
14 | | Checksum | Urgent Pointer | |
15 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
16 | | Options | Padding | |
17 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
18 | | data | |
19 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
To create a raw socket :
1 | int s = socket (PF_INET, SOCK_RAW, IPPROTO_TCP); |
Another option to make sure the kernel uses the raw headers :
1 | { |
2 | int one = 1; |
3 | const int *val = &one; |
4 | if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0) |
5 | printf ( "Warning: Cannot set HDRINCL!\n" ); |
6 | } |
Below is an example code which constructs a raw TCP packet :
Code :1 | /* |
2 | Raw Sockets with LINUX |
3 | */ |
4 | #include<stdio.h> |
5 | #include<netinet/tcp.h> //Provides declarations for tcp header |
6 | #include<netinet/ip.h> //Provides declarations for ip header |
7 |
8 | //Checksum calculation function |
9 | unsigned short csum (unsigned short *buf, int nwords) |
10 | { |
11 | unsigned long sum; |
12 | |
13 | for (sum = 0; nwords > 0; nwords--) |
14 | sum += *buf++; |
15 | |
16 | sum = (sum >> 16) + (sum & 0xffff); |
17 | sum += (sum >> 16); |
18 | |
19 | return ~sum; |
20 | } |
21 |
22 | int main ( void ) |
23 | { |
24 | //Create a raw socket |
25 | int s = socket (PF_INET, SOCK_RAW, IPPROTO_TCP); |
26 | //Datagram to represent the packet |
27 | char datagram[4096]; |
28 | //IP header |
29 | struct iphdr *iph = ( struct iphdr *) datagram; |
30 | //TCP header |
31 | struct tcphdr *tcph = ( struct tcphdr *) (datagram + sizeof ( struct ip)); |
32 | struct sockaddr_in sin ; |
33 | |
34 | sin .sin_family = AF_INET; |
35 | sin .sin_port = htons(40); |
36 | sin .sin_addr.s_addr = inet_addr ( "60.61.62.63" ); |
37 | |
38 | memset (datagram, 0, 4096); /* zero out the buffer */ |
39 | |
40 | //Fill in the IP Header |
41 | iph->ihl = 5; |
42 | iph->version = 4; |
43 | iph->tos = 0; |
44 | iph->tot_len = sizeof ( struct ip) + sizeof ( struct tcphdr); |
45 | iph->id = htonl (54321); //Id of this packet |
46 | iph->frag_off = 0; |
47 | iph->ttl = 255; |
48 | iph->protocol = 6; |
49 | iph->check = 0; //Set to 0 before calculating checksum |
50 | iph->saddr = inet_addr ( "1.2.3.4" ); //Spoof the source ip address |
51 | iph->daddr = sin .sin_addr.s_addr; |
52 | |
53 | //TCP Header |
54 | tcph->source = htons (1234); |
55 | tcph->dest = htons (85); |
56 | tcph->seq = random (); |
57 | tcph->ack_seq = 0; |
58 | tcph->doff = 0; /* first and only tcp segment */ |
59 | tcph->syn = 1; |
60 | tcph->window = htonl (65535); /* maximum allowed window size */ |
61 | tcph->check = 0; /* if you set a checksum to zero, your kernel's IP stack |
62 | should fill in the correct checksum during transmission */ |
63 | tcph->urg_ptr = 0; |
64 | //Now the IP checksum |
65 | iph->check = csum ((unsigned short *) datagram, iph->tot_len >> 1); |
66 | |
67 | //IP_HDRINCL to tell the kernel that headers are included in the packet |
68 | { |
69 | int one = 1; |
70 | const int *val = &one; |
71 | if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0) |
72 | printf ( "Warning: Cannot set HDRINCL!\n" ); |
73 | } |
74 | |
75 | while (1) |
76 | { |
77 | //Send the packet |
78 | if (sendto (s, /* our socket */ |
79 | datagram, /* the buffer containing headers and data */ |
80 | iph->tot_len, /* total length of our datagram */ |
81 | 0, /* routing flags, normally always 0 */ |
82 | ( struct sockaddr *) & sin , /* socket addr, just like in */ |
83 | sizeof ( sin )) < 0) /* a normal send() */ |
84 | printf ( "error\n" ); |
85 | else |
86 | printf ( "." ); |
87 | } |
88 | |
89 | return 0; |
90 | } |
Remember to run the above code with root privileges. Raw sockets require root privileges
User wireshark to check the output.
转载地址:http://yylfa.baihongyu.com/