1 /*
2 file2pcap
3 Code by Martin Zeiser
4 Started July 2009
5 */
6
7
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <string.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <time.h>
16 #include <libgen.h>
17 #include <getopt.h>
18
19
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <arpa/inet.h>
23 #include <errno.h>
24
25
26
27
28 #define __FAVOR_BSD
29 #include <netinet/in_systm.h>
30 #include <netinet/in.h>
31 #include <netinet/ip.h>
32 #include <netinet/ip6.h> // struct ip6_hdr
33 #include <netinet/tcp.h>
34
35
36 #include "file2pcap.h"
37 #include "ftp.h"
38 #include "http.h"
39 #include "http2.h"
40 #include "http-gzip.h"
41 #include "smtp.h"
42 #include "pop3.h"
43 #include "imap.h"
44 #include "crc32.h"
45
46 unsigned short srcport, dstport;
47 struct pcap_packet_header ph;
48
49 struct {
50 int PCAPMAGIC;
51 const short major_version;
52 short minor_version;
53 int GMT;
54 int timestamp_granularity;
55 int entire_packet;
56 int assume_ethernet;
57 } pcap_file_header = { 0xA1B2C3D4,2,4,0,0,65535,1};
58
59 FILE *inFile, *outFile;
60
61
62 const int packetLen4 = (sizeof(SRC_ETHER)-1 + sizeof(DST_ETHER)-1 + sizeof(PROTO_ETHER)-1 + sizeof(struct ip) + sizeof(struct tcphdr));
63 const int packetLen6 = (sizeof(SRC_ETHER)-1 + sizeof(DST_ETHER)-1 + sizeof(PROTO_ETHER6)-1 + sizeof(struct ip6_hdr) + sizeof(struct tcphdr));
64
65
66 struct pcap_packet_header ph;
67 unsigned short srcport, dstport;
68 struct handover hoFtp;
69
70
71
72 /***************************************************************************************/
73
74
usage()75 void usage() {
76 char *helptext = "\nfile2pcap - developed by Martin Zeiser(mzeiser@cisco.com)\n"\
77 "Version: " VERSION "\n"\
78 "Takes a file as input and creates a pcap showing that file being transferred between hosts\n"\
79 "\nOptions:\n"\
80 "--block-size size\tspecify the payload size per packet[1 to 1200]\n\n"
81 "--srcemail address\tspecify the sender's email address\n"
82 "--dstemail address\tspecify the recipient's email address\n\n"
83 "-e email encoding\r\n"
84 "\t\t\t0 - base64\n"
85 "\t\t\t1 - quoted printable\n"
86 "\t\t\t2 - UU encoding\n"
87 "\t\t\t[default: base64]\n\n"\
88 "--http-encoder\t\t0 - default transfer\n"
89 "\t\t\t1 - gzip compression\n"
90 "\t\t\t2 - chunked encoding\n"
91 "\t\t\t3 - gzip compression and chunked encoding\n"
92 "-m mode\r\n"
93 "\t\t\th - http GET (download)\r\n"
94 "\t\t\th2 - http2 GET (download)\r\n"
95 "\t\t\tH - http POST (upload)\r\n"
96 "\t\t\ts - smtp\r\n"
97 "\t\t\tp - pop3\r\n"
98 "\t\t\ti - imap\r\n"
99 "\t\t\tf - active ftp\r\n"
100 "\t\t\tF - passive ftp\r\n"
101 "\t\t\t[default: http GET]\n\n"\
102 "-o outfile\t\toutput filename [default: <filename>-<protocol>.pcap]\n"\
103 "-p port[:port]\t\tspecify [source and] destination port\n"
104 "\t\t\t-p 8080 will simulate a connection from a random port to port 8080\n"
105 "\t\t\t-p 1234:80 will simulate a connection from port 1234 to port 80\n"
106 "\t\t\t[default: use IANA assigned port for the protocol]\n\n"
107 "--srcip ip_address\tspecify source IP address\n"
108 "--dstip ip_address\tspecify destination IP address\n\n"
109 "-6\t\t\tUse IPv6 instead of the default IPv4\n";
110 char *usage = "\nUsage:\n"\
111 "\t\t\tfile2pcap [options] infile\n";
112 char *example = "Examples:\n"\
113 "\t\t\tfile2pcap malware.pdf\n"\
114 "\t\t\tfile2pcap -mshp malware.pdf --http-encoder=1\n"\
115 "\t\t\tfile2pcap -mH -p8080 malware.pdf\n"\
116 "\t\t\tfile2pcap -mi malware.pdf -o outfile.pcap\n";
117
118 printf("%s\n", helptext);
119 printf("%s\n", usage);
120 printf("%s\n", example);
121
122 exit(0);
123
124 return;
125 }
126
127 /**********************************************************************************************************/
128
ipChecksum(unsigned short * ptr,int nbytes)129 unsigned short ipChecksum (unsigned short *ptr, int nbytes)
130 {
131 register long sum = 0;
132 register u_short answer;
133 u_short oddbyte;
134
135 while (nbytes > 1)
136 {
137 sum += *ptr++;
138 nbytes -= 2;
139 }
140
141 if (nbytes == 1)
142 {
143 oddbyte = 0;
144 *((u_char *) & oddbyte) = *(u_char *) ptr;
145 sum += oddbyte;
146 }
147
148 sum = (sum >> 16) + (sum & 0xffff);
149 sum += (sum >> 16);
150 answer = ~sum;
151 return (answer);
152 }
153
154
155 /*****************************************************************/
156 // direction: 0 == client to server. 1 == server to client.
157
craftIpv4(char * payload,int payloadSize,char direction,struct handover * ho)158 int craftIpv4(char *payload, int payloadSize, char direction, struct handover *ho) {
159 unsigned int minimalLength;
160 size_t packetLen = sizeof (struct ip) + payloadSize;
161 unsigned char minimalip[(minimalLength = 12 + payloadSize)];
162 char ipv4packet[packetLen];
163 struct ip *iphdr = (struct ip *) ipv4packet;
164
165
166 memset (ipv4packet, 0, packetLen);
167 memset (minimalip, 0, minimalLength);
168
169
170 if(payload!=NULL)
171 memcpy(((unsigned char*)(ipv4packet)) + sizeof (struct ip), payload, payloadSize);
172
173
174 if(direction==TO_SERVER)
175 {
176 *((unsigned long *) ((unsigned char *) minimalip + 0)) = ho->srcIP;
177 *((unsigned long *) ((unsigned char *) minimalip + 4)) = ho->dstIP;
178 }
179 else
180 {
181 *((unsigned long *) ((unsigned char *) minimalip + 0)) = ho->dstIP;
182 *((unsigned long *) ((unsigned char *) minimalip + 4)) = ho->srcIP;
183 }
184
185 *((unsigned char *) ((unsigned char *) minimalip + 8)) = 0;
186 *((unsigned char *) ((unsigned char *) minimalip + 9)) = IPPROTO_TCP;
187 *((unsigned short *) ((unsigned char *) minimalip + 10)) = htons (packetLen - sizeof (struct ip));
188
189 iphdr->ip_v = 4;
190 iphdr->ip_hl = 5;
191
192 iphdr->ip_id = rand() & 0xFFFF;
193
194 if(direction == TO_SERVER)
195 {
196 iphdr->ip_src.s_addr = ho->srcIP;
197 iphdr->ip_dst.s_addr = ho->dstIP;
198 }
199 else
200 {
201 iphdr->ip_src.s_addr = ho->dstIP;
202 iphdr->ip_dst.s_addr = ho->srcIP;
203 }
204 iphdr->ip_p = IPPROTO_TCP;
205 iphdr->ip_ttl = 64;
206 iphdr->ip_len = ntohs(packetLen);
207 iphdr->ip_sum=0;
208 iphdr->ip_sum = ipChecksum ((u_short *) iphdr, sizeof (struct ip));
209
210 memcpy (minimalip + 12, ((unsigned char *) ipv4packet) + sizeof (struct ip), packetLen - sizeof (struct ip));
211
212 write(fileno(outFile), ipv4packet, packetLen);
213
214
215 return 0;
216 }
217
218 /*****************************************************************/
219 // direction: 0 == client to server. 1 == server to client.
220
craftIpv6(char * payload,int payloadSize,char direction,struct handover * ho)221 int craftIpv6(char *payload, int payloadSize, char direction, struct handover *ho) {
222 size_t packetLen = sizeof (struct ip6_hdr) + payloadSize;
223 char ipv6packet[packetLen];
224 uint16_t tcp6_checksum (struct ip6_hdr, struct tcphdr);
225 struct ip6_hdr *iphdr = (struct ip6_hdr*) ipv6packet;
226
227
228 memset (ipv6packet, 0, sizeof(ipv6packet));
229
230
231 if(payload!=NULL)
232 memcpy(((unsigned char*)(ipv6packet)) + sizeof (struct ip6_hdr), payload, payloadSize);
233
234 iphdr->ip6_ctlun.ip6_un1.ip6_un1_hlim=64;
235 iphdr->ip6_ctlun.ip6_un1.ip6_un1_flow=htonl ((6 << 28) | (0 << 20) | 0);
236 iphdr->ip6_ctlun.ip6_un1.ip6_un1_plen=htons(packetLen-sizeof(struct ip6_hdr));
237 iphdr->ip6_ctlun.ip6_un1.ip6_un1_nxt=IPPROTO_TCP;
238
239
240
241
242 if(direction == TO_SERVER)
243 {
244 memcpy(&(iphdr->ip6_src), &ho->srcIP6, sizeof(iphdr->ip6_src));
245 memcpy(&(iphdr->ip6_dst), &ho->dstIP6, sizeof(iphdr->ip6_dst));
246 }
247 else
248 {
249 memcpy(&(iphdr->ip6_src), &ho->dstIP6, sizeof(iphdr->ip6_src));
250 memcpy(&(iphdr->ip6_dst), &ho->srcIP6, sizeof(iphdr->ip6_dst));
251 }
252
253 write(fileno(outFile), ipv6packet, packetLen);
254
255
256 return 0;
257 }
258
259
260
261
262 /*****************************************************************/
263 // direction: 0 == client to server. 1 == server to client.
264
craftTcp(char * payload,int payloadSize,char direction,unsigned char flags,struct handover * ho)265 int craftTcp(char *payload, int payloadSize, char direction, unsigned char flags, struct handover *ho) {
266 size_t packetLen;
267 char packet[(packetLen = sizeof (struct tcphdr) + payloadSize)];
268 struct tcphdr *tcpheader = (struct tcphdr *) ((unsigned char *) packet);
269 unsigned int minimalLength, minimalLength6;
270 unsigned char minimalip[(minimalLength = 12 + sizeof (struct tcphdr) + payloadSize)];
271 unsigned char minimalip6[(minimalLength6 = 40 + packetLen)];
272 struct v6_pseudo_header *v6PseudoHeader = (struct v6_pseudo_header*)minimalip6;
273
274
275
276 memset (packet, 0, packetLen);
277
278 if(payload!=NULL)
279 memcpy(((unsigned char*)(packet)) + sizeof (struct tcphdr), payload, payloadSize);
280
281
282 if(ho->ipV == 4)
283 {
284 if(direction==TO_SERVER)
285 {
286 *((unsigned long *) ((unsigned char *) minimalip + 0)) = ho->srcIP;
287 *((unsigned long *) ((unsigned char *) minimalip + 4)) = ho->dstIP;
288 }
289 else
290 {
291 *((unsigned long *) ((unsigned char *) minimalip + 0)) = ho->dstIP;
292 *((unsigned long *) ((unsigned char *) minimalip + 4)) = ho->srcIP;
293 }
294
295 *((unsigned char *) ((unsigned char *) minimalip + 8)) = 0;
296 *((unsigned char *) ((unsigned char *) minimalip + 9)) = IPPROTO_TCP;
297 *((unsigned short *) ((unsigned char *) minimalip + 10)) = htons (packetLen);
298 }
299 else
300 {
301 memset(v6PseudoHeader, 0, sizeof(*v6PseudoHeader));
302
303 if(direction == TO_SERVER)
304 {
305 memcpy(&(v6PseudoHeader->src), &ho->srcIP6, sizeof(v6PseudoHeader->src));
306 memcpy(&(v6PseudoHeader->dst), &ho->dstIP6, sizeof(v6PseudoHeader->dst));
307 }
308 else
309 {
310 memcpy(&(v6PseudoHeader->src), &ho->dstIP6, sizeof(v6PseudoHeader->src));
311 memcpy(&(v6PseudoHeader->dst), &ho->srcIP6, sizeof(v6PseudoHeader->dst));
312 }
313
314 v6PseudoHeader->length = htonl(packetLen);
315 v6PseudoHeader->next_header = IPPROTO_TCP;
316
317 tcpheader->th_sum = 0;
318 }
319
320
321 if(direction == TO_SERVER)
322 {
323 tcpheader->th_sport = htons(ho->srcPort);
324 tcpheader->th_dport = htons(ho->dstPort);
325 }
326 else
327 {
328 tcpheader->th_sport = htons(ho->dstPort);
329 tcpheader->th_dport = htons(ho->srcPort);
330 }
331
332
333 if(direction==TO_SERVER)
334 {
335 tcpheader->th_seq = htonl(ho->seq);
336 tcpheader->th_ack = htonl(ho->ack_seq);
337 }
338 else
339 {
340 tcpheader->th_seq = htonl(ho->ack_seq);
341 tcpheader->th_ack = htonl(ho->seq);
342 }
343
344 tcpheader->th_off = ((sizeof (struct tcphdr)) / 4);
345
346 tcpheader->th_flags = flags;
347
348 tcpheader->th_win = htons (5840);
349
350 if(ho->ipV == 4)
351 {
352 memcpy (minimalip + 12, ((unsigned char *) packet), packetLen);
353 tcpheader->th_sum = ipChecksum ((u_short *) & minimalip, minimalLength);
354 craftIpv4(packet, packetLen, direction, ho);
355 }
356 else
357 {
358 memcpy (minimalip6 + 40, ((unsigned char *) packet), packetLen);
359 tcpheader->th_sum = ipChecksum((u_short *) & minimalip6, minimalLength6);
360 craftIpv6(packet, packetLen, direction, ho);
361 }
362
363
364 if(direction==TO_SERVER)
365 ho->seq=ho->seq+payloadSize;
366 else
367 ho->ack_seq+=payloadSize;
368
369
370 return 0;
371 }
372
373
374 /**************************************************************************************************************/
375
tcpSendString(struct handover * ho,char * string,char direction)376 int tcpSendString(struct handover *ho, char *string, char direction) {
377 int packetLen=-1, direction2=-1;
378
379 if(direction==TO_SERVER)
380 {
381 direction2 = FROM_SERVER;
382 }
383 else
384 {
385 direction2 = TO_SERVER;
386 }
387
388 if(ho->ipV == 4)
389 packetLen = packetLen4 + strlen(string);
390 else
391 packetLen = packetLen6 + strlen(string);
392
393 ph.time = ho->time;
394 ph.usec = ho->usec;
395
396
397 ph.usec += INTERVAL;
398
399 if((ph.usec + INTERVAL) >= 1000000)
400 {
401 ph.time+=1;
402 ph.usec=0;
403 }
404
405
406 ph.length1 = packetLen;
407 ph.length2 = packetLen;
408
409 write(fileno(ho->outFile), &ph, sizeof(struct pcap_packet_header));
410
411
412 if(direction == TO_SERVER)
413 write(fileno(ho->outFile), ho->toEther, sizeof(ho->toEther)-1);
414 else
415 write(fileno(ho->outFile), ho->fromEther, sizeof(ho->fromEther)-1);
416
417
418 craftTcp(string, strlen(string), direction, TH_ACK|TH_PUSH, ho);
419
420 //and now send the ack
421 ph.usec+=INTERVAL;
422 ph.length1=packetLen-strlen(string);
423 ph.length2=packetLen-strlen(string);
424 write(fileno(ho->outFile), &ph, sizeof(struct pcap_packet_header));
425
426 if(direction == TO_SERVER)
427 write(fileno(ho->outFile), ho->fromEther, sizeof(ho->fromEther)-1);
428 else
429 write(fileno(ho->outFile), ho->toEther, sizeof(ho->toEther)-1);
430
431
432 craftTcp(NULL,0, direction2, TH_ACK, ho);
433
434 ho->time = ph.time;
435 ho->usec = ph.usec;
436
437
438 return strlen(string);
439 }
440
441
442 /**************************************************************************************************************/
443
tcpSendData(struct handover * ho,char * buffer,int length,char direction)444 int tcpSendData(struct handover *ho, char *buffer, int length, char direction) {
445 int packetLen=-1, direction2=-1;
446
447 if(direction==TO_SERVER)
448 {
449 direction2 = FROM_SERVER;
450 }
451 else
452 {
453 direction2 = TO_SERVER;
454 }
455
456 if(ho->ipV == 4)
457 packetLen = packetLen4 + length;
458 else
459 packetLen = packetLen6 + length;
460
461 ph.time = ho->time;
462 ph.usec = ho->usec;
463
464
465 ph.usec += INTERVAL;
466
467 if((ph.usec + INTERVAL) >= 1000000)
468 {
469 ph.time+=1;
470 ph.usec=0;
471 }
472
473
474 ph.length1 = packetLen;
475 ph.length2 = packetLen;
476
477 write(fileno(ho->outFile), &ph, sizeof(struct pcap_packet_header));
478
479
480 if(direction == TO_SERVER)
481 write(fileno(ho->outFile), ho->toEther, sizeof(ho->toEther)-1);
482 else
483 write(fileno(ho->outFile), ho->fromEther, sizeof(ho->fromEther)-1);
484
485
486 craftTcp(buffer, length, direction, TH_ACK|TH_PUSH, ho);
487
488 //and now send the ack
489 ph.usec+=INTERVAL;
490 ph.length1=packetLen-length;
491 ph.length2=packetLen-length;
492 write(fileno(ho->outFile), &ph, sizeof(struct pcap_packet_header));
493
494 if(direction == TO_SERVER)
495 write(fileno(ho->outFile), ho->fromEther, sizeof(ho->fromEther)-1);
496 else
497 write(fileno(ho->outFile), ho->toEther, sizeof(ho->toEther)-1);
498
499
500 craftTcp(NULL,0, direction2, TH_ACK, ho);
501
502 ho->time = ph.time;
503 ho->usec = ph.usec;
504
505
506 return length;
507 }
508
509
510
511
512 /**********************************************************************************************/
513
514
tcpHandshake(struct handover * ho)515 int tcpHandshake(struct handover *ho) {
516 int packetLen;
517
518 if(ho->ipV == 4)
519 packetLen = packetLen4;
520 else
521 packetLen = packetLen6;
522
523 ph.usec += INTERVAL;
524 ph.length1 = packetLen;
525 ph.length2 = packetLen;
526
527
528 ho->seq=rand() & 0xfff;
529 ho->seq+=1;
530 ho->ack_seq=0;
531
532
533 //client to server SYN
534 write(fileno(outFile), &ph, sizeof(struct pcap_packet_header));
535
536 //replace that with a sprintf and a single write
537
538 write(fileno(outFile), ho->toEther, sizeof(ho->toEther)-1);
539
540 craftTcp(NULL, 0, TO_SERVER, TH_SYN, ho); //direction 0 - client to server
541
542 ho->ack_seq=rand() & 0xfff;
543 ho->ack_seq+=1;
544 ho->seq+=1;
545
546 //and now send the SYN/ACK
547 ph.usec+=INTERVAL;
548 write(fileno(outFile), &ph, sizeof(struct pcap_packet_header));
549 write(fileno(outFile), ho->fromEther, sizeof(ho->fromEther)-1);
550 craftTcp(NULL,0, FROM_SERVER, TH_SYN|TH_ACK, ho); //direction 1 - server to client
551
552 ho->ack_seq+=1;
553
554 //client to server ACK
555 ph.usec += INTERVAL;
556 write(fileno(outFile), &ph, sizeof(struct pcap_packet_header));
557 write(fileno(outFile), ho->toEther, sizeof(ho->toEther)-1);
558 craftTcp(NULL, 0, TO_SERVER, TH_ACK, ho); //direction 0 - client to server
559
560
561 ho->time = ph.time;
562 ho->usec = ph.usec;
563
564
565 return 0;
566 }
567
568 /*******************************************************************************************/
569
570
tcpShutdown(struct handover * ho)571 int tcpShutdown(struct handover *ho) {
572 int packetLen;
573
574
575 if(ho->ipV == 4)
576 packetLen = packetLen4;
577 else
578 packetLen = packetLen6;
579
580
581 ph.time = ho->time;
582 ph.usec = ho->usec;
583
584
585 ph.usec += INTERVAL;
586 ph.length1 = packetLen;
587 ph.length2 = packetLen;
588
589
590 //server to client FIN
591 write(fileno(outFile), &ph, sizeof(struct pcap_packet_header));
592 write(fileno(outFile), ho->fromEther, sizeof(ho->fromEther)-1);
593 craftTcp(NULL, 0, FROM_SERVER, TH_ACK|TH_FIN, ho); //direction - server to client
594
595 ho->ack_seq+=1;
596
597 //and now send the ack
598 ph.usec+=INTERVAL;
599 write(fileno(outFile), &ph, sizeof(struct pcap_packet_header));
600 write(fileno(outFile), ho->toEther, sizeof(ho->toEther)-1);
601
602 craftTcp(NULL,0, TO_SERVER, TH_ACK, ho); //direction - client to server
603
604 //client to server FIN
605 ph.usec+=INTERVAL;
606 write(fileno(outFile), &ph, sizeof(struct pcap_packet_header));
607 write(fileno(outFile), ho->toEther, sizeof(ho->toEther)-1);
608 craftTcp(NULL, 0, TO_SERVER, TH_ACK|TH_FIN, ho); //direction - client to server
609
610 ho->seq+=1;
611
612 //and now send the ack
613 ph.usec+=INTERVAL;
614 write(fileno(outFile), &ph, sizeof(struct pcap_packet_header));
615 write(fileno(outFile), ho->fromEther, sizeof(ho->fromEther)-1);
616 craftTcp(NULL,0, FROM_SERVER, TH_ACK, ho); //direction - server to client
617
618
619 // printf("Pcap replay length: %d second(s)\n", ph.time - 0x48f35358 + 1);
620
621 return(0);
622 }
623
624
625 /****************************************************************************************************/
626
openOutFile(struct handover * ho,char * inFileName,char * suffix)627 int openOutFile(struct handover *ho, char *inFileName, char *suffix){
628 char buffer[500];
629
630
631
632 if(strlen(ho->dstFile) == 0)
633 {
634 snprintf(buffer, sizeof(buffer)-1,"%s%s", inFileName, suffix);
635 }
636 else
637 snprintf(buffer, sizeof(buffer)-1, "%s", ho->dstFile);
638
639
640 if((outFile = fopen(buffer, "w"))==NULL)
641 {
642 printf("Failed to open outfile %s\n", buffer);
643 exit(-1);
644 }
645 else
646 ho->outFile = outFile;
647
648 printf("Writing to %s\n", buffer);
649
650 write(fileno(outFile), &pcap_file_header, sizeof(pcap_file_header));
651
652 return 0;
653 }
654
655
656
657 /*************************************************************************************************/
658
ftp(struct handover * ho,char mode)659 int ftp(struct handover *ho, char mode) {
660
661 srcport = rand() & 0x7fff; //0 <-> 32k
662 srcport +=1025;
663 hoFtp.srcPort=srcport;
664
665
666 //initialize the time in the handover struct. The times have to be correct in all streams
667 hoFtp.time = ho->time;
668 hoFtp.usec = ho->usec;
669
670 //snprintf(hoFtp.srcFile, sizeof(hoFtp.srcFile)-1, "%s", ho->srcFile);
671 hoFtp.inFile = ho->inFile;
672 hoFtp.outFile = ho->outFile;
673 hoFtp.blockSize = ho->blockSize;
674
675 //fill all the parameters into the handover struct
676 if(mode == PASSIVE_FTP)
677 {
678 hoFtp.srcIP = ho->srcIP;
679 hoFtp.dstIP = ho->dstIP;
680
681 memcpy(hoFtp.srcIP6, ho->srcIP6, sizeof(hoFtp.srcIP6));
682 memcpy(hoFtp.dstIP6, ho->dstIP6, sizeof(hoFtp.dstIP6));
683
684
685 memcpy(hoFtp.srcEther, DST_ETHER, sizeof(hoFtp.dstEther));
686 memcpy(hoFtp.dstEther, SRC_ETHER, sizeof(hoFtp.srcEther));
687
688 }
689 else
690 {
691 hoFtp.srcPort = htons(20);
692 hoFtp.srcIP = ho->dstIP;
693 hoFtp.dstIP = ho->srcIP;
694
695 memcpy(hoFtp.srcIP6, ho->dstIP6, sizeof(hoFtp.srcIP6));
696 memcpy(hoFtp.dstIP6, ho->srcIP6, sizeof(hoFtp.dstIP6));
697
698
699 memcpy(hoFtp.srcEther, DST_ETHER, sizeof(hoFtp.srcEther));
700 memcpy(hoFtp.dstEther, SRC_ETHER, sizeof(hoFtp.dstEther));
701 }
702
703 //Set the protocol the Ethernet is carrying. IPv4 or IPv6
704 if(hoFtp.ipV == 4)
705 memcpy(hoFtp.protoEther, PROTO_ETHER, 2);
706 else
707 memcpy(hoFtp.protoEther, PROTO_ETHER6, 2);
708
709
710 if(ho->srcFile != NULL)
711 snprintf(hoFtp.srcFile, sizeof(hoFtp.srcFile),"%s", ho->srcFile);
712
713 if(ho->dstFile != NULL)
714 snprintf(hoFtp.dstFile, sizeof(hoFtp.dstFile),"%s", ho->dstFile);
715
716 hoFtp.dstPort = 20;
717
718 if(mode == PASSIVE_FTP)
719 {
720 hoFtp.direction = FROM_SERVER;
721 memcpy(hoFtp.toEther, hoFtp.dstEther, 6);
722 memcpy(hoFtp.toEther+6, hoFtp.srcEther, 6);
723 memcpy(hoFtp.toEther+12, hoFtp.protoEther, 2);
724
725 memcpy(hoFtp.fromEther, hoFtp.srcEther, 6);
726 memcpy(hoFtp.fromEther+6, hoFtp.dstEther, 6);
727 memcpy(hoFtp.fromEther+12, hoFtp.protoEther, 2);
728
729 }
730 else
731 {
732 ho->direction = FROM_SERVER;
733 hoFtp.direction = TO_SERVER;
734
735 memcpy(hoFtp.toEther, hoFtp.srcEther, 6);
736 memcpy(hoFtp.toEther+6, hoFtp.dstEther, 6);
737 memcpy(hoFtp.toEther+12, hoFtp.protoEther, 2);
738
739 memcpy(hoFtp.fromEther, hoFtp.dstEther, 6);
740 memcpy(hoFtp.fromEther+6, hoFtp.srcEther, 6);
741 memcpy(hoFtp.fromEther+12, hoFtp.protoEther, 2);
742 }
743
744
745 tcpHandshake(ho);
746
747 if(mode == ACTIVE_FTP)
748 hoFtp.dstPort = ftpCommandsStartActive(ho);
749 else
750 hoFtp.dstPort = ftpCommandsStartPassive(ho);
751
752 tcpHandshake(&hoFtp);
753 ftpTransferFile(&hoFtp);
754 tcpShutdown(&hoFtp);
755
756 ho->time=hoFtp.time;
757 ho->usec=hoFtp.usec;
758
759 ftpCommandsEnd(ho);
760 tcpShutdown(ho);
761
762 return 0;
763 }
764
765 /***********************************************************************************************/
766
767
768
httpGet(struct handover * ho)769 int httpGet(struct handover *ho) {
770 int ret;
771
772 tcpHandshake(ho);
773
774 if(ho->httpEncoder == ENC_HTTP_GZIP || ho->httpEncoder == ENC_HTTP_GZIP_CHUNKED)
775 compressGzip(ho);
776
777 httpGetRequest(ho);
778 httpGetRequestAcknowledge(ho);
779 ho->direction = FROM_SERVER;
780 httpTransferFile(ho);
781
782 tcpShutdown(ho);
783
784 return 0;
785 }
786
787 /***********************************************************************************************/
788
789
http2Get(struct handover * ho)790 int http2Get(struct handover *ho) {
791
792 tcpHandshake(ho);
793 http2ConnectionUpgrade(ho);
794 http2SwitchingProtocols(ho);
795 http2ClientMagic(ho);
796
797 //send settings from server to client
798 ho->direction = FROM_SERVER;
799 http2Settings(ho);
800
801 //ack server settings and send settings from client to server
802 ho->direction = TO_SERVER;
803 http2SettingsAck(ho);
804 http2Settings(ho);
805
806 //ack client settings
807 ho->direction = FROM_SERVER;
808 http2SettingsAck(ho);
809
810 ho->direction = TO_SERVER;
811 http2ClientGetRequest(ho);
812
813 ho->direction = FROM_SERVER;
814 http2Headers(ho);
815 http2TransferFile(ho);
816 http2DataStreamClose(ho);
817 http2GoAway(ho);
818 tcpShutdown(ho);
819
820 return 0;
821 }
822
823
824 /***********************************************************************************************/
825
826
827
httpPost(struct handover * ho)828 int httpPost(struct handover *ho) {
829
830 tcpHandshake(ho);
831 httpPostRequest(ho);
832 ho->direction = TO_SERVER;
833 httpTransferFile(ho);
834 httpPostFinalBoundary(ho);
835 tcpShutdown(ho);
836
837 return 0;
838 }
839
840
841 /*******************************************************************************************/
842
smtp(struct handover * ho)843 int smtp(struct handover *ho) {
844
845 tcpHandshake(ho);
846 smtpRequest(ho);
847 tcpShutdown(ho);
848
849 return 0;
850 }
851
852 /*********************************************************************************************/
853
pop3(struct handover * ho)854 int pop3(struct handover *ho) {
855
856 tcpHandshake(ho);
857 pop3Request(ho);
858 tcpShutdown(ho);
859
860 return 0;
861 }
862
863
864 /********************************************************************************************/
865
imap(struct handover * ho)866 int imap(struct handover *ho) {
867
868 tcpHandshake(ho);
869 imapRequest(ho);
870 tcpShutdown(ho);
871
872 return 0;
873 }
874
875
876 /********************************************************************************************/
877
878
main(int argc,char ** argv)879 int main(int argc, char **argv) {
880 char *modeString=NULL, *srcFile=NULL, *dstFile=NULL, *portString=NULL, *tok1=NULL, *tok2=NULL, *encoderString=NULL, *httpEncoderString=NULL, *srcEmail=NULL, *dstEmail=NULL;
881 char *srcIP=NULL, *dstIP=NULL;
882 int c, i, option_index=0;
883 struct stat statbuf, statbuf2;
884 struct handover ho;
885 static struct option long_options[] =
886 {
887 {"6", no_argument, 0, '6'},
888 {"block-size", required_argument, 0, 0},
889 // {"chunk-size", required_argument, 0, 0},
890 {"dstemail", required_argument, 0, 0},
891 {"dstip", required_argument, 0, 0},
892 {"email-encoder", required_argument, 0, 'e'},
893 {"http-encoder", required_argument, 0, 0},
894 {"mode", required_argument, 0, 'm'},
895 {"outfile", required_argument, 0, 'o'},
896 {"port", required_argument, 0, 'p'},
897 {"srcemail", required_argument, 0, 0},
898 {"srcip", required_argument, 0, 0},
899 {"verbose", no_argument, 0, 'v'},
900 {0, 0, 0, 0}
901 };
902
903
904
905 if(argc < 2)
906 usage();
907
908
909 memset(ho.srcEmail, 0, sizeof(ho.srcEmail));
910 memset(ho.dstEmail, 0, sizeof(ho.dstEmail));
911
912 //Default is IPv4
913 ho.ipV = 4;
914 ho.verbose=FALSE;
915 ho.blockSize=READ_SIZE;
916 ho.srcIP = inet_addr(SRC_IP4);
917 ho.dstIP = inet_addr(DST_IP4);
918
919 hoFtp.ipV = 4;
920
921 ho.httpEncoder = ENC_HTTP_DEFAULT;
922 snprintf(ho.srcEmail, sizeof(ho.srcEmail)-1, "%s", SRC_EMAIL);
923 snprintf(ho.dstEmail, sizeof(ho.dstEmail)-1, "%s", DST_EMAIL);
924
925 while ((c = getopt_long (argc, argv, "e:m:o:p:v6", long_options, &option_index)) != -1)
926 {
927 if(c == -1)
928 break;
929
930 switch (c)
931 {
932
933 case 0: //long option names
934 // printf("option %s", long_options[option_index].name);
935
936 if (strcmp(long_options[option_index].name, "http-encoder")==0)
937 {
938 httpEncoderString = (char*) strdup(optarg);
939 break;
940 }
941 else if(strcmp(long_options[option_index].name,"block-size")==0)
942 {
943 ho.blockSize = atoi((char*) strdup(optarg));
944 if(ho.blockSize < 0 || ho.blockSize > 1200)
945 {
946 usage();
947 exit(-1);
948 }
949 break;
950 }
951 else if(strcmp(long_options[option_index].name,"srcemail")==0)
952 {
953 srcEmail = (char*) strdup(optarg);
954 break;
955 }
956 else if(strcmp(long_options[option_index].name,"dstemail")==0)
957 {
958 dstEmail = (char*) strdup(optarg);
959 break;
960 }
961 else if(strcmp(long_options[option_index].name,"srcip")==0)
962 {
963 srcIP = (char*) strdup(optarg);
964 break;
965 }
966 else if(strcmp(long_options[option_index].name,"dstip")==0)
967 {
968 dstIP = (char*) strdup(optarg);
969 break;
970 }
971
972 else
973 {
974 printf("Unknown parameter %s with arg %s", long_options[option_index].name, optarg);
975 usage();
976 exit(-1);
977 break;
978 }
979
980 case 'e':
981 encoderString = (char*) strdup(optarg);
982 break;
983
984 case 'm':
985 modeString = (char *) strdup (optarg);
986 break;
987
988 case 'o':
989 dstFile = (char *) strdup(optarg);
990 break;
991
992 case 'p':
993 portString = (char *) strdup(optarg);
994 break;
995
996 case '6':
997 ho.ipV=6;
998 hoFtp.ipV = 6;
999 break;
1000
1001 case 'v':
1002 ho.verbose=TRUE;
1003 break;
1004
1005 default:
1006 usage();
1007 exit(0);
1008 }
1009 }
1010
1011 unlink(TMP_FILE);
1012
1013
1014 if(optind < argc)
1015 {
1016 srcFile = (char*) strdup(argv[optind]);
1017 }
1018
1019
1020 if(srcEmail != NULL)
1021 {
1022 snprintf(ho.srcEmail, sizeof(ho.srcEmail)-1,"%s", srcEmail);
1023 if(ho.verbose==TRUE)
1024 printf("Using custom source email address: %s\n", srcEmail);
1025 }
1026
1027 if(dstEmail != NULL)
1028 {
1029 snprintf(ho.dstEmail, sizeof(ho.dstEmail)-1, "%s", dstEmail);
1030 if(ho.verbose==TRUE)
1031 printf("Using custom destination email address: %s\n", dstEmail);
1032 }
1033
1034
1035
1036 if((srcFile == NULL))
1037 {
1038 printf("Input file not found\n");
1039 exit(-1);
1040 }
1041
1042 //check if the input file is a directory, quit if true
1043 if(stat(srcFile, &statbuf)==0)
1044 {
1045 if(S_ISDIR(statbuf.st_mode))
1046 {
1047 printf("Input has to be a file, not a directory\n");
1048 exit(-1);
1049 }
1050 }
1051 else
1052 {
1053 printf("Input file %s not found\n", srcFile);
1054 exit(-1);
1055 }
1056
1057 if((inFile = fopen(srcFile, "r"))==NULL)
1058 {
1059 printf("Failed to open infile %s\n", srcFile);
1060 exit(-1);
1061 }
1062 else
1063 {
1064 ho.inFile=inFile;
1065 hoFtp.inFile=inFile;
1066 }
1067
1068 ho.inFileSize = statbuf.st_size;
1069
1070 //init the PRNG
1071 srand(time(NULL));
1072
1073 srcport = rand() & 0x7fff; //0 <-> 32k
1074 srcport +=1025;
1075 ho.srcPort=srcport;
1076
1077
1078
1079 ph.time = 0x48f35358;
1080 ph.usec=0;
1081
1082 //initialize the time in the handover struct. The times have to be correct in all streams
1083 ho.time = ph.time;
1084 ho.usec = ph.usec;
1085
1086
1087 if(srcIP != NULL)
1088 {
1089 ho.srcIP = inet_addr(srcIP);
1090 if(ho.verbose==TRUE)
1091 printf("Using custom source IP: %s\n", srcIP);
1092 }
1093
1094 if(dstIP != NULL)
1095 {
1096 ho.dstIP = inet_addr(dstIP);
1097 if(ho.verbose==TRUE)
1098 printf("Using custom destination IP: %s\n", dstIP);
1099 }
1100
1101 inet_pton(AF_INET6, SRC_IP6, &(ho.srcIP6));
1102 inet_pton(AF_INET6, DST_IP6, &(ho.dstIP6));
1103 memcpy(ho.srcEther, SRC_ETHER, sizeof(ho.srcEther));
1104 memcpy(ho.dstEther, DST_ETHER, sizeof(ho.dstEther));
1105
1106 //Set the protocol the Ethernet is carrying. IPv4 or IPv6
1107 if(ho.ipV == 4)
1108 memcpy(ho.protoEther, PROTO_ETHER, 2);
1109 else
1110 memcpy(ho.protoEther, PROTO_ETHER6, 2);
1111
1112
1113 snprintf(ho.srcFile, sizeof(ho.srcFile)-1,"%s", srcFile);
1114
1115 memset(ho.dstFile, 0, sizeof(ho.dstFile));
1116 if(dstFile != NULL)
1117 {
1118 if(stat(dstFile, &statbuf2) ==0)
1119 {
1120 if((statbuf.st_dev == statbuf2.st_dev) && (statbuf.st_ino == statbuf2.st_ino))
1121 {
1122 printf("Output file cannot be input file!\n");
1123 exit(-1);
1124 }
1125 }
1126
1127 snprintf(ho.dstFile, sizeof(ho.dstFile)-1,"%s", dstFile);
1128 }
1129
1130 ho.outFile = NULL;
1131 ho.encoder = ENC_BASE64;
1132 ho.dstPort = 0;
1133
1134
1135 memcpy(ho.toEther, ho.srcEther, 6);
1136 memcpy(ho.toEther+6, ho.dstEther, 6);
1137 memcpy(ho.toEther+12, ho.protoEther, 2);
1138
1139 memcpy(ho.fromEther, ho.dstEther, 6);
1140 memcpy(ho.fromEther+6, ho.srcEther, 6);
1141 memcpy(ho.fromEther+12, ho.protoEther, 2);
1142
1143
1144
1145 if(portString != NULL)
1146 {
1147 if(strstr(portString,":") != NULL)
1148 {
1149 tok1=strtok(portString,":");
1150 ho.srcPort=atoi(tok1);
1151
1152 if(tok1!=NULL)
1153 tok2=strtok(NULL,":");
1154 else
1155 {
1156 usage();
1157 exit(-1);
1158 }
1159
1160 if(tok2!=NULL)
1161 ho.dstPort = atoi(tok2);
1162 else
1163 {
1164 usage();
1165 exit(-1);
1166 }
1167 }
1168 else
1169 {
1170 ho.dstPort=atoi(portString);
1171 }
1172 }
1173
1174
1175
1176
1177 if(encoderString != NULL)
1178 {
1179 switch(atoi(encoderString))
1180 {
1181 case 0:
1182 ho.encoder = ENC_BASE64;
1183 break;
1184 case 1:
1185 ho.encoder = ENC_QUOTED_PRINTABLE;
1186 break;
1187 case 2:
1188 ho.encoder = ENC_UU;
1189 break;
1190
1191 }
1192 }
1193
1194
1195
1196 if(httpEncoderString != NULL)
1197 {
1198 switch(atoi(httpEncoderString))
1199 {
1200 case 0:
1201 ho.httpEncoder = ENC_HTTP_DEFAULT;
1202 break;
1203 case 1:
1204 ho.httpEncoder = ENC_HTTP_GZIP;
1205 break;
1206 case 2:
1207 ho.httpEncoder = ENC_HTTP_CHUNKED;
1208 break;
1209 case 3:
1210 ho.httpEncoder = ENC_HTTP_GZIP_CHUNKED;
1211 break;
1212 default:
1213 usage();
1214 exit(-1);
1215
1216 }
1217 }
1218
1219
1220
1221 if(modeString != NULL)
1222 {
1223 if(strlen(modeString) > 1)
1224 {
1225 if(ho.dstPort != 0)
1226 printf("Specifying a destination port is not possible when using multiple modes. Switching to default destination ports.\n");
1227
1228 ho.dstPort = 0;
1229
1230 if(dstFile != NULL)
1231 {
1232 printf("Specifying an output filename does not work when using multiple modes\n");
1233 usage();
1234 exit(-1);
1235 }
1236 }
1237
1238
1239
1240 for(i=0; i < strlen(modeString); i++)
1241 {
1242 switch (modeString[i])
1243 {
1244 case 'f':
1245 if(ho.dstPort == 0)
1246 ho.dstPort = 21;
1247
1248 openOutFile(&ho, basename(srcFile), "-ftp-active.pcap");
1249 ftp(&ho, ACTIVE_FTP);
1250
1251 fclose(ho.outFile);
1252 ho.dstPort = 0;
1253 break;
1254
1255 case 'F':
1256
1257 if(ho.dstPort == 0)
1258 ho.dstPort = 21;
1259
1260 openOutFile(&ho, basename(srcFile), "-ftp-passive.pcap");
1261 ftp(&ho, PASSIVE_FTP);
1262
1263 fclose(ho.outFile);
1264 ho.dstPort = 0;
1265 break;
1266
1267 case 'h':
1268 if(ho.dstPort == 0)
1269 ho.dstPort = 80;
1270
1271 if(modeString[i+1] == '2')
1272 {
1273 openOutFile(&ho, basename(srcFile), "-http2-get.pcap");
1274 http2Get(&ho);
1275 i++;
1276 }
1277 else
1278 {
1279 openOutFile(&ho, basename(srcFile), "-http-get.pcap");
1280 httpGet(&ho);
1281 }
1282
1283 fclose(ho.outFile);
1284 ho.dstPort = 0;
1285 break;
1286
1287 case 'H':
1288 if(ho.dstPort == 0)
1289 ho.dstPort = 80;
1290 openOutFile(&ho, basename(srcFile), "-http-post.pcap");
1291 httpPost(&ho);
1292 fclose(ho.outFile);
1293 ho.dstPort = 0;
1294 break;
1295
1296
1297 case 's':
1298 if(ho.dstPort == 0)
1299 ho.dstPort = 25;
1300 openOutFile(&ho, basename(srcFile), "-smtp.pcap");
1301 smtp(&ho);
1302 fclose(ho.outFile);
1303 ho.dstPort = 0;
1304 break;
1305
1306 case 'p':
1307 if(ho.dstPort == 0)
1308 ho.dstPort = 110;
1309 openOutFile(&ho, basename(srcFile), "-pop3.pcap");
1310 pop3(&ho);
1311 fclose(ho.outFile);
1312 ho.dstPort = 0;
1313 break;
1314
1315 case 'i':
1316 if(ho.dstPort == 0)
1317 ho.dstPort = 143;
1318 openOutFile(&ho, basename(srcFile), "-imap.pcap");
1319 imap(&ho);
1320 fclose(ho.outFile);
1321 ho.dstPort = 0;
1322 break;
1323
1324 case 'x':
1325 if(ho.dstPort == 0)
1326 ho.dstPort = 80;
1327 openOutFile(&ho, basename(srcFile), "-http2-get.pcap");
1328
1329
1330 http2Get(&ho);
1331 fclose(ho.outFile);
1332 ho.dstPort = 0;
1333 break;
1334
1335
1336
1337
1338 default:
1339 usage();
1340 exit(-1);
1341 break;
1342 }
1343 }
1344 }
1345 else
1346 {
1347 if(ho.dstPort == 0)
1348 ho.dstPort = 80;
1349 openOutFile(&ho, basename(srcFile), "-http-get.pcap");
1350 httpGet(&ho);
1351 fclose(ho.outFile);
1352 }
1353
1354
1355 unlink(TMP_FILE);
1356 exit(0);
1357 }
1358
1359