diff -Nru pcapfix-1.1.1/Changelog pcapfix-1.1.3/Changelog --- pcapfix-1.1.1/Changelog 2018-01-02 13:35:14.000000000 +0000 +++ pcapfix-1.1.3/Changelog 2018-09-04 13:36:53.000000000 +0000 @@ -1,6 +1,15 @@ pcapfix Changelog ***************** +1.1.3 - 04.09.2018 +------------------ +* implemtented soft mode (for plausibility checks) + +1.1.2 - 16.07.2018 +------------------ +* fixed cross compiling (thanks to Helmut Grohne) +* increased maximum snap length to 262144 + 1.1.1 - 25.12.2017 ------------------ * added write buffers and support to perform repair diff -Nru pcapfix-1.1.1/debian/changelog pcapfix-1.1.3/debian/changelog --- pcapfix-1.1.1/debian/changelog 2018-04-13 13:43:35.000000000 +0000 +++ pcapfix-1.1.3/debian/changelog 2018-09-05 14:05:55.000000000 +0000 @@ -1,3 +1,18 @@ +pcapfix (1.1.3-1) unstable; urgency=medium + + * New upstream release. + * debian/control: bumped Standards-Version to 4.2.1. + * debian/copyright: updated upstream copyright years. + * debian/README.Debian: updated to explain about a new test. + * debian/source/include-binaries: updated. + * debian/test/: + - Added a new test: test_2018.pcap. + - Changed all suffix from dump to pcap. + * debian/tests/control: updated to use all tests from debian/test directory. + * debian/watch: added GitHub as an additional repository. + + -- Joao Eriberto Mota Filho Wed, 05 Sep 2018 11:05:55 -0300 + pcapfix (1.1.1-1) unstable; urgency=medium * New upstream release. diff -Nru pcapfix-1.1.1/debian/control pcapfix-1.1.3/debian/control --- pcapfix-1.1.1/debian/control 2018-04-13 13:43:35.000000000 +0000 +++ pcapfix-1.1.3/debian/control 2018-09-05 14:05:55.000000000 +0000 @@ -3,7 +3,7 @@ Priority: optional Maintainer: Joao Eriberto Mota Filho Build-Depends: debhelper (>= 11) -Standards-Version: 4.1.4 +Standards-Version: 4.2.1 Homepage: http://f00l.de/pcapfix Vcs-Browser: https://salsa.debian.org/debian/pcapfix Vcs-Git: https://salsa.debian.org/debian/pcapfix.git diff -Nru pcapfix-1.1.1/debian/copyright pcapfix-1.1.3/debian/copyright --- pcapfix-1.1.1/debian/copyright 2018-04-13 13:43:35.000000000 +0000 +++ pcapfix-1.1.3/debian/copyright 2018-09-05 14:05:55.000000000 +0000 @@ -3,7 +3,7 @@ Source: https://f00l.de/pcapfix Files: * -Copyright: 2012-2017 Robert Krause +Copyright: 2012-2018 Robert Krause License: GPL-3+ Files: debian/* diff -Nru pcapfix-1.1.1/debian/README.Debian pcapfix-1.1.3/debian/README.Debian --- pcapfix-1.1.1/debian/README.Debian 2014-08-11 13:10:29.000000000 +0000 +++ pcapfix-1.1.3/debian/README.Debian 2018-09-05 14:05:55.000000000 +0000 @@ -1,14 +1,22 @@ pcapfix for Debian ------------------ -There are three network dumps at /usr/share/doc/pcapfix/examples. -The test.dump is an original and perfect file that works fine. The -file test_damaged.dump was damaged by an ASCII FTP operation. The -last file, test_without_pcap_header.dump, hasn't the pcap header -and can't be read by tcpdump or another program. You can use these -files to test pcapfix. +There are four network dumps at /usr/share/doc/pcapfix/examples: -PS: you must use the "-t 1" option to repair the test_without_pcap_header.dump. + * test.pcap is an original and perfect file that works fine. This file was + created from tcpdump 4.3.0-1 and libpcap 1.3.0-1 on 2013-05-22. + + * test_damaged.pcap was damaged by an ASCII FTP operation. This file was + created from tcpdump 4.3.0-1 and libpcap 1.3.0-1 on 2013-05-22. + + * test_without_pcap_header.pcap hasn't a pcap header and can't be read by + tcpdump or another program based in pcap. This file was created from + tcpdump 4.3.0-1 and libpcap 1.3.0-1 on 2013-05-22. + + * test_2018.pcap is an original and perfect file that works fine. This file + was created from tcpdump 4.9.2-1 and libpcap 1.8.1-3 on 2018-08-21. + +You can use the files listed above to test pcapfix. -- Joao Eriberto Mota Filho Wed, 22 May 2013 16:47:18 -0300; - Updated at Sun, 23 Feb 2014 20:01:00 -03:00. + Updated at Wed, 05 Sep 2018 11:26:00 -03:00. diff -Nru pcapfix-1.1.1/debian/source/include-binaries pcapfix-1.1.3/debian/source/include-binaries --- pcapfix-1.1.1/debian/source/include-binaries 2014-08-31 15:41:31.000000000 +0000 +++ pcapfix-1.1.3/debian/source/include-binaries 2018-09-05 14:05:55.000000000 +0000 @@ -1,3 +1,4 @@ -debian/test/test.dump -debian/test/test_damaged.dump -debian/test/test_without_pcap_header.dump +debian/test/test_2018.pcap +debian/test/test_damaged.pcap +debian/test/test.pcap +debian/test/test_without_pcap_header.pcap Binary files /tmp/tmpMnyOY4/xu89OFubx3/pcapfix-1.1.1/debian/test/test_2018.pcap and /tmp/tmpMnyOY4/5l_mEwztRZ/pcapfix-1.1.3/debian/test/test_2018.pcap differ Binary files /tmp/tmpMnyOY4/xu89OFubx3/pcapfix-1.1.1/debian/test/test_damaged.dump and /tmp/tmpMnyOY4/5l_mEwztRZ/pcapfix-1.1.3/debian/test/test_damaged.dump differ Binary files /tmp/tmpMnyOY4/xu89OFubx3/pcapfix-1.1.1/debian/test/test_damaged.pcap and /tmp/tmpMnyOY4/5l_mEwztRZ/pcapfix-1.1.3/debian/test/test_damaged.pcap differ Binary files /tmp/tmpMnyOY4/xu89OFubx3/pcapfix-1.1.1/debian/test/test.dump and /tmp/tmpMnyOY4/5l_mEwztRZ/pcapfix-1.1.3/debian/test/test.dump differ Binary files /tmp/tmpMnyOY4/xu89OFubx3/pcapfix-1.1.1/debian/test/test.pcap and /tmp/tmpMnyOY4/5l_mEwztRZ/pcapfix-1.1.3/debian/test/test.pcap differ Binary files /tmp/tmpMnyOY4/xu89OFubx3/pcapfix-1.1.1/debian/test/test_without_pcap_header.dump and /tmp/tmpMnyOY4/5l_mEwztRZ/pcapfix-1.1.3/debian/test/test_without_pcap_header.dump differ Binary files /tmp/tmpMnyOY4/xu89OFubx3/pcapfix-1.1.1/debian/test/test_without_pcap_header.pcap and /tmp/tmpMnyOY4/5l_mEwztRZ/pcapfix-1.1.3/debian/test/test_without_pcap_header.pcap differ diff -Nru pcapfix-1.1.1/debian/tests/control pcapfix-1.1.3/debian/tests/control --- pcapfix-1.1.1/debian/tests/control 2018-04-13 13:43:35.000000000 +0000 +++ pcapfix-1.1.3/debian/tests/control 2018-09-05 14:05:55.000000000 +0000 @@ -1,2 +1,7 @@ -Test-Command: pcapfix -Depends: @ +Test-Command: pcapfix debian/test/test_2018.pcap + +Test-Command: pcapfix debian/test/test_damaged.pcap + +Test-Command: pcapfix debian/test/test.pcap + +Test-Command: pcapfix debian/test/test_without_pcap_header.pcap diff -Nru pcapfix-1.1.1/debian/watch pcapfix-1.1.3/debian/watch --- pcapfix-1.1.1/debian/watch 2018-04-13 13:43:35.000000000 +0000 +++ pcapfix-1.1.3/debian/watch 2018-09-05 14:05:55.000000000 +0000 @@ -1,3 +1,5 @@ version=4 opts="pgpsigurlmangle=s/$/.asc/" \ https://f00l.de/pcapfix/pcapfix-(\d\S+)\.tar\.(?:bz2|gz|xz) + +https://github.com/Rup0rt/pcapfix/releases .*/archive/v?(\d\S+)\.tar\.(?:bz2|gz|xz) diff -Nru pcapfix-1.1.1/Makefile pcapfix-1.1.3/Makefile --- pcapfix-1.1.1/Makefile 2018-01-02 13:35:14.000000000 +0000 +++ pcapfix-1.1.3/Makefile 2018-09-04 13:36:53.000000000 +0000 @@ -15,13 +15,13 @@ all: pcap pcapng - gcc $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) pcapfix.c pcap.o pcapng.o -o pcapfix + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) pcapfix.c pcap.o pcapng.o -o pcapfix pcap: pcap.c - gcc $(CPPFLAGS) $(CFLAGS) -c pcap.c -o pcap.o + $(CC) $(CPPFLAGS) $(CFLAGS) -c pcap.c -o pcap.o pcapng: pcapng.c - gcc $(CPPFLAGS) $(CFLAGS) -c pcapng.c -o pcapng.o + $(CC) $(CPPFLAGS) $(CFLAGS) -c pcapng.c -o pcapng.o install: install -pDm755 pcapfix $(DESTDIR)$(BINDIR)/pcapfix @@ -34,4 +34,3 @@ clean: rm -f *.o rm -f pcapfix - diff -Nru pcapfix-1.1.1/pcap.c pcapfix-1.1.3/pcap.c --- pcapfix-1.1.1/pcap.c 2018-01-02 13:35:14.000000000 +0000 +++ pcapfix-1.1.3/pcap.c 2018-09-04 13:36:53.000000000 +0000 @@ -1,6 +1,6 @@ /******************************************************************************* * - * Copyright (c) 2012-2017 Robert Krause (ruport@f00l.de) + * Copyright (c) 2012-2018 Robert Krause (ruport@f00l.de) * * This file is part of Pcapfix. * @@ -26,46 +26,71 @@ * Function: is_plausible * ----------------------- * check if the pcap packet header could be a plausible one by satisfying those conditions: - * - packet size >= 16 bytes AND <= 65535 bytes (included length AND original length) (conditions 1,2,3,4) + * - packet size >= 16 bytes AND <= MAX_SNAPLEN bytes (included length AND original length) (conditions 1,2,3,4) * - included length <= original lenth (condition 5) * - packet timestamp is NOT older OR younger than the prior packets timestamp -+ one day (conditions 6,7) * - usec (microseconds) field <= 1000000 (conditions 8) * - usec (nanoseconds) field <= 1000000000 (conditions 9) * - * hdr: the filled packet header struct to check for plausibility - * prior_ts: the prior packets timestamp (seconds) to check for time relation (condition 6,7) + * global_hdr: the filled pcap header struct to check for snaplen + * hdr: the filled packet header struct to check for plausibility + * prior_ts: the prior packets timestamp (seconds) to check for time relation (condition 6,7) * * returns: 0 success * -X error (condition X failed) * */ -int is_plausible(struct packet_hdr_s hdr, unsigned int prior_ts) { +int is_plausible(struct global_hdr_s global_hdr, struct packet_hdr_s hdr, unsigned int prior_ts) { /* check for minimum packet size * minimum packet size should be 16, but in some cases, e.g. local wlan capture, packet might * even be smaller --> decreased minimum size to 10 */ if (conint(hdr.incl_len) < 10) return(-1); if (conint(hdr.orig_len) < 10) return(-2); - /* check max maximum packet size (0xffff) */ - if (conint(hdr.incl_len) > 65535) return(-3); - if (conint(hdr.orig_len) > 65535) return(-4); + /* check packet limit with header field and max snaplen + in soft mode the packet detection accepts a wider range */ + if (soft_mode) { + /* in soft mode, global pcap snap length is ignored, instead MAX snaplen is used */ + if (conint(hdr.incl_len) > PCAP_MAX_SNAPLEN) return(-3); + } else { + /* in hard mode, global pcap snap length is the limit in plausibility checks */ + if (conint(hdr.incl_len) > conint(global_hdr.snaplen)) return(-3); + } + if (conint(hdr.orig_len) > PCAP_MAX_SNAPLEN) return(-4); /* the included length CAN NOT be larger than the original length */ if (conint(hdr.incl_len) > conint(hdr.orig_len)) return(-5); - /* packet is not older than one day (related to prior packet) */ - if ((prior_ts != 0) && (conint(hdr.ts_sec) > (prior_ts+86400))) return(-6); + /* check packet times (older) */ + if (soft_mode) { + /* in soft mode, packet must be older than prior packet */ + if ((prior_ts != 0) && (conint(hdr.ts_sec) < prior_ts)) return(-6); + } else { + /* in hard mode, packet must not be older than one day (related to prior packet) */ + if ((prior_ts != 0) && (conint(hdr.ts_sec) > (prior_ts+86400))) return(-6); + } - /* packet is not younger than one day (related to prior packet) */ + /* check packet times (younger) */ + /* in hard mode, packet must not be younger than one day (related to prior packet) */ if ((prior_ts >= 86400) && (conint(hdr.ts_sec) < (prior_ts-86400))) return(-7); + /* soft mode does not matter for younger timings, because all packets must be older + than the prior one */ - /* check for nano/microseconds */ - if (nanoseconds == 0) { - /* usec (microseconds) must <= 1000000 */ - if (conint(hdr.ts_usec) > 1000000) return(-8); - } else { - /* usec (nanoseconds) must be <= 1000000000 */ - if (conint(hdr.ts_usec) > 1000000000) return(-9); + /* check for nano/microseconds (hard mode only) */ + if (!soft_mode) { + /* in hard mode */ + if (nanoseconds == 0) { + /* usec (microseconds) must <= 1000000 */ + if (conint(hdr.ts_usec) > 1000000) return(-8); + } else { + /* usec (nanoseconds) must be <= 1000000000 */ + if (conint(hdr.ts_usec) > 1000000000) return(-9); + } + } + + /* output warnings if occured */ + if (!deep_scan && conint(hdr.incl_len) > conint(global_hdr.snaplen) && verbose) { + printf("[!] Packet capture length is larger than maximum size defined in global pcap header: %u > %u\n", conint(hdr.incl_len), conint(global_hdr.snaplen)); } /* all conditions fullfilled ==> everything fine! */ @@ -77,23 +102,24 @@ * ----------------------- * this function takes a buffer and brute forces some possible ascii-corrupted bytes versus plausibility checks * - * buffer: the buffer that might contain the possible pcap packet header - * size: the size of the buffer (double pcap packet header size is a good choice) - * priot_ts: the prior packets timestamp (to check for plausibility) - * hdr: the pointer to the packet header buffer (we use this to return the repaired header) + * buffer: the buffer that might contain the possible pcap packet header + * size: the size of the buffer (double pcap packet header size is a good choice) + * priot_ts: the prior packets timestamp (to check for plausibility) + * global_hdr: the pointer to the pcap header + * hdr: the pointer to the packet header buffer (we use this to return the repaired header) * * returns: >=0 success (return value contains number of ascii corrupted bytes in hdr (we need this data to align the beginning of the packet body later) * -1 error (no valid pcap header found inside buffer) * */ -int check_header(char *buffer, unsigned int size, unsigned int prior_ts, struct packet_hdr_s *hdr) { +int check_header(char *buffer, unsigned int size, unsigned int prior_ts, struct global_hdr_s *global_hdr, struct packet_hdr_s *hdr) { unsigned int i; /* loop variable - first byte in buffer that could be beginning of packet */ int res; /* return value */ char *tmp; /* the temporary buffer that will be used for recursion */ /* does the buffer already contain a valid packet header (without any correction) ?? */ memcpy(hdr, buffer, sizeof(struct packet_hdr_s)); - res = is_plausible(*hdr, prior_ts); + res = is_plausible(*global_hdr, *hdr, prior_ts); if (res == 0) return(0); if (verbose >= 2) printf("[-] Header plausibility check failed with error code %d\n", res); @@ -115,7 +141,7 @@ memcpy(tmp+i, buffer+i+1, size-i-1); /* and invoke the header again without this 0x0D byte */ - res = check_header(tmp, size-1, prior_ts, hdr); + res = check_header(tmp, size-1, prior_ts, global_hdr, hdr); /* free recursion buffer */ free(tmp); @@ -145,12 +171,12 @@ * */ int fix_pcap(FILE *pcap, FILE *pcap_fix) { - struct global_hdr_s global_hdr; /* global header data */ - struct packet_hdr_s packet_hdr; /* packet header data */ - struct packet_hdr_s next_packet_hdr; /* next packet header data to look forward */ + struct global_hdr_s global_hdr; /* global header data */ + struct packet_hdr_s packet_hdr; /* packet header data */ + struct packet_hdr_s next_packet_hdr; /* next packet header data to look forward */ - char hdrbuffer[sizeof(packet_hdr)*2]; /* the buffer that will be used to find a proper packet */ - char buffer[65535]; /* the packet body */ + char hdrbuffer[sizeof(packet_hdr)*2]; /* the buffer that will be used to find a proper packet */ + char buffer[PCAP_MAX_SNAPLEN]; /* the packet body */ // we use a buffer to cache 1mb of writing... this way writing is faster and // we can read and write the file at the same time @@ -257,12 +283,12 @@ } /* check for max packet length */ - if ((conint(global_hdr.snaplen) > 0) && (conint(global_hdr.snaplen) <= 65535)) { /* typically 65535 (no support for huge packets yet) */ + if ((conint(global_hdr.snaplen) > 0) && (conint(global_hdr.snaplen) <= PCAP_MAX_SNAPLEN)) { /* typically 262144 nowadays */ if (verbose) printf("[+] Max packet length: %u\n", conint(global_hdr.snaplen)); } else { hdr_integ++; if (verbose) printf("[-] Max packet length: %u\n", conint(global_hdr.snaplen)); - global_hdr.snaplen = conint(65535); + global_hdr.snaplen = conint(PCAP_MAX_SNAPLEN); } /* check for data link type (http://www.tcpdump.org/linktypes.html) */ @@ -293,7 +319,7 @@ fseeko(pcap, 0, SEEK_SET); /* set important header values to defaults */ - global_hdr.snaplen = conint(65535); + global_hdr.snaplen = conint(PCAP_MAX_SNAPLEN); if (data_link_type != -1) { global_hdr.network = conint(data_link_type); @@ -355,7 +381,7 @@ if (bytes != 1) return -3; /* check if the packet header looks proper */ - res = check_header(hdrbuffer, sizeof(hdrbuffer), last_correct_ts_sec, &packet_hdr); + res = check_header(hdrbuffer, sizeof(hdrbuffer), last_correct_ts_sec, &global_hdr, &packet_hdr); if (res != -1) { /* realign packet body (based on possible-ascii corrupted pcap header) */ @@ -387,7 +413,7 @@ bytes = fread(hdrbuffer, sizeof(hdrbuffer), 1, pcap); /* check if next packets header looks proper */ - if (check_header(hdrbuffer, sizeof(hdrbuffer), conint(packet_hdr.ts_sec), &next_packet_hdr) == -1) { + if (check_header(hdrbuffer, sizeof(hdrbuffer), conint(packet_hdr.ts_sec), &global_hdr, &next_packet_hdr) == -1) { /* the next packets header is corrupted thou we are going to scan through the prior packets body to look for an overlapped packet header * also look inside the next packets header + 16bytes of packet body, because we need to know HERE @@ -398,11 +424,14 @@ fseeko(pcap, nextpos, SEEK_SET); bytes = fread(hdrbuffer, sizeof(hdrbuffer), 1, pcap); + /* check read success */ + if (bytes == 0) break; + /* heavy verbose output :-) */ if (verbose >= 2) printf("[*] Trying Packet #%u at position %" PRIu64 " (%u | %u | %u | %u).\n", (count+1), nextpos, conint(next_packet_hdr.ts_sec), conint(next_packet_hdr.ts_usec), conint(next_packet_hdr.incl_len), conint(next_packet_hdr.orig_len)); /* check the header for plausibility */ - res = check_header(hdrbuffer, sizeof(hdrbuffer), last_correct_ts_sec, &next_packet_hdr); + res = check_header(hdrbuffer, sizeof(hdrbuffer), last_correct_ts_sec, &global_hdr, &next_packet_hdr); if (res != -1) { /* we found a proper header inside the packets body! */ @@ -474,7 +503,7 @@ /* scan from the current position to the maximum packet size and look for a next proper packet header to align the corrupted packet * also do not leave the loop if the first packet has not been found yet AND deep scan mode is activated */ - for (nextpos=pos+16+1; (nextpos <= pos+16+65535) || (count == 1 && deep_scan == 1); nextpos++) { + for (nextpos=pos+16+1; (nextpos <= pos+16+PCAP_MAX_SNAPLEN) || (count == 1 && deep_scan == 1); nextpos++) { /* read the possible next packets header */ fseeko(pcap, nextpos, SEEK_SET); @@ -491,6 +520,16 @@ printf("[*] End of file reached. Aligning last packet.\n"); + /* check last packet for plausiblilty */ + res = check_header(hdrbuffer, sizeof(hdrbuffer), last_correct_ts_sec, &global_hdr, &packet_hdr); + if (res != 0) { + printf("[-] Cannot align last packet, because it is broken.\n"); + count--; + break; + } + + /* check passed */ + /* align the last packet to match EOF */ packet_hdr.incl_len = conint(filesize-(pos+16)); packet_hdr.orig_len = packet_hdr.incl_len; @@ -539,11 +578,11 @@ if (verbose >= 2) printf("[*] Trying Packet #%u at position %" PRIu64 " (%u | %u | %u | %u).\n", (count+1), nextpos, conint(next_packet_hdr.ts_sec), conint(next_packet_hdr.ts_usec), conint(next_packet_hdr.incl_len), conint(next_packet_hdr.orig_len)); /* check if next packets header looks proper */ - res = check_header(hdrbuffer, sizeof(hdrbuffer), last_correct_ts_sec, &next_packet_hdr); + res = check_header(hdrbuffer, sizeof(hdrbuffer), last_correct_ts_sec, &global_hdr, &next_packet_hdr); if (res != -1) { - /* if we found a packet that is below the top 65535 bytes (deep scan) we cut it off and take the second packet as first one */ - if ((nextpos-(pos+16) > 65535) && (count == 1) && (deep_scan == 1)) { + /* if we found a packet that is below the top MAX_SNAPLEN bytes (deep scan) we cut it off and take the second packet as first one */ + if ((nextpos-(pos+16) > PCAP_MAX_SNAPLEN) && (count == 1) && (deep_scan == 1)) { if (verbose >= 1) printf("[+] (DEEP SCAN) FOUND FIRST Packet #%u at position %" PRIu64 " (%u | %u | %u | %u).\n", count, nextpos, conint(next_packet_hdr.ts_sec), conint(next_packet_hdr.ts_usec), conint(next_packet_hdr.incl_len), conint(next_packet_hdr.orig_len)); @@ -586,7 +625,7 @@ bytes = fread(&buffer, conint(packet_hdr.incl_len), 1, pcap); /* final check resulting packet for plausibility */ - res = is_plausible(packet_hdr, last_correct_ts_sec); + res = is_plausible(global_hdr, packet_hdr, last_correct_ts_sec); if (res == 0) { // check if there is enough space in buffer @@ -629,7 +668,7 @@ if (corrupted == -1) break; /* did the counter exceed the maximum packet size? */ - if ((count == 1 && deep_scan == 0) && (nextpos > pos+16+65535)) { + if ((count == 1 && deep_scan == 0) && (nextpos > pos+16+PCAP_MAX_SNAPLEN)) { /* PACKET COULD NOT BE REPAIRED! */ @@ -638,7 +677,7 @@ } /* maximum search range reached? -> skip packet and keep on searching */ - if (deep_scan == 0 && (nextpos > pos+16+65535)) { + if (deep_scan == 0 && (nextpos > pos+16+PCAP_MAX_SNAPLEN)) { if (verbose >= 1) printf("[-] No next packet found within max packet range --> SKIPPING!\n"); /* reset counter because no packet found */ @@ -690,6 +729,11 @@ } } else { + /* check if we found at least one packet */ + if (count == 1) { + /* even the first packet was corrupted and no other packet could be found */ + return(-1); + } /* file has been successfully repaired (corruption fixed) */ diff -Nru pcapfix-1.1.1/pcapfix.1 pcapfix-1.1.3/pcapfix.1 --- pcapfix-1.1.1/pcapfix.1 2018-01-02 13:35:14.000000000 +0000 +++ pcapfix-1.1.3/pcapfix.1 2018-09-04 13:36:53.000000000 +0000 @@ -1,4 +1,4 @@ -.TH PCAPFIX 1 "25 DEC 2017" +.TH PCAPFIX 1 "04 SEPT 2018" .SH "NAME" pcapfix \- repair pcap and pcapng files @@ -18,7 +18,10 @@ \-d, \-\-deep\-scan Force deep scan (default = 0) .br -This option will force pcapfix to scan for any packet inside the whole file (instead of the first 65535 bytes only). +\-s, \-\-soft\-mode +Switch to soft mode packet detection (default = 0) +.br +This option will force pcapfix to scan for any packet inside the whole file (instead of the first 262144 (max snaplen) bytes only). .TP \-n, \-\-pcapng Force File Format to PCAPNG (default = 0) @@ -70,6 +73,13 @@ This option is not necessary for pcapng files because the whole file is arranged in blocks that are 'unlimited' by default. In result pcapfix will always scan the whole pcapng file for further blocks. .TP +\fISoft mode\fP + +There are programs that breach some pcap conventions when writing files. Ignoring those rules do not break the pcap file but they make it difficult for pcapfix to identify the packets in case of broken files. + +By default pcapfix uses hard mode. If you encounter problems when repairing files, try to switch to soft mode (-s). Pcapfix will then try to find the packets in a more tolerant way. + +.TP \fIPCAPNG Format\fP Pcapfix will try to identify the file format to repair (pcap / pcapng) before doing any further checks. If the header itself is corrupted, it will assume the format to be classic pcap. To change this behaviour you can force the tool to do a pcapng-repair by supplying \-n (\-\-pcapng) option. @@ -261,6 +271,13 @@ .SH "HISTORY" .TP 5 +1.1.3 - 04.09.2018 +* implemtented soft mode (for plausibility checks) +.TP +1.1.2 - 16.07.2018 +* fixed cross compiling (thanks to Helmut Grohne) +* increased maximum snap length to 262144 +.TP 1.1.1 - 25.12.2017 * added write buffers and support to perform repair process without creation of a separate output file .br @@ -401,7 +418,7 @@ * this is the first version, everything has changed thou :-) .SH "COPYRIGHT" -Copyright (c) 2012-2017 Robert Krause +Copyright (c) 2012-2018 Robert Krause Pcapfix is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version. diff -Nru pcapfix-1.1.1/pcapfix.c pcapfix-1.1.3/pcapfix.c --- pcapfix-1.1.1/pcapfix.c 2018-01-02 13:35:14.000000000 +0000 +++ pcapfix-1.1.3/pcapfix.c 2018-09-04 13:36:53.000000000 +0000 @@ -1,6 +1,6 @@ /******************************************************************************* * - * Copyright (c) 2012-2017 Robert Krause (ruport@f00l.de) + * Copyright (c) 2012-2018 Robert Krause (ruport@f00l.de) * * This file is part of Pcapfix. * @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License along with * Pcapfix. If not, see http://www.gnu.org/licenses/. * - * Last Modified: 25.12.2017 + * Last Modified: 04.09.2018 * ******************************************************************************* * @@ -44,7 +44,7 @@ #include "pcap.h" #include "pcapng.h" -#define VERSION "1.1.1" /* pcapfix version */ +#define VERSION "1.1.3" /* pcapfix version */ #define BTSNOOP_MAGIC 0x6E737462 /* btsnoop file magic (first 4 bytes) */ #define SNOOP_MAGIC 0x6f6f6e73 /* snoop file magic (first 4 bytes) */ @@ -53,11 +53,13 @@ #define ETHERPEEK_MAGIC 0x7265767f /* EtherPeek/AiroPeek/OmniPeek file magic */ /* configuration variables */ -int deep_scan = 0; /* deep scan option (default: no deep scan) */ -int verbose = 0; /* verbose output option (default: dont be verbose) */ -int swapped = 0; /* pcap file is swapped (big endian) */ -int data_link_type = -1; /* data link type (default: LINKTYPE_ETHERNET) */ -int pcapng = 0; /* file format to assume */ +int deep_scan = 0; /* deep scan option (default: no deep scan) */ +int soft_mode = 0; /* soft mode option (default: no soft mode) */ +int keep_outfile = 0; /* keep output file even if nothing needed fixing (default: don't) */ +int verbose = 0; /* verbose output option (default: dont be verbose) */ +int swapped = 0; /* pcap file is swapped (big endian) */ +int data_link_type = -1; /* data link type (default: LINKTYPE_ETHERNET) */ +int pcapng = 0; /* file format to assume */ /* header placeholder */ unsigned int header_magic; @@ -75,8 +77,10 @@ printf("Usage: %s [OPTIONS] filename\n", progname); printf("OPTIONS:"); printf( "\t-d , --deep-scan \tDeep scan (pcap only)\n"); + printf("\t\t-s , --soft-mode \tSoft mode (packet detection)\n"); printf("\t\t-n , --pcapng \tforce pcapng format\n"); printf("\t\t-o , --outfile \tset output file name\n"); + printf("\t\t-k , --keep-outfile \tdon't delete the output file if nothing needed to be fixed\n"); printf("\t\t-t , --data-link-type \tData link type\n"); printf("\t\t-v , --verbose \tVerbose output\n"); printf("\n"); @@ -176,25 +180,33 @@ /* init getopt_long options struct */ struct option long_options[] = { - {"deep-scan", no_argument, 0, 'd'}, /* --deep-scan == -d */ - {"pcapng", no_argument, 0, 'n'}, /* --pcapng == -n */ - {"outfile", required_argument, 0, 'o'}, /* --outfile == -o */ - {"data-link-type", required_argument, 0, 't'}, /* --data-link-type == -t */ - {"verbose", no_argument, 0, 'v'}, /* --verbose == -v */ + {"deep-scan", no_argument, 0, 'd'}, /* --deep-scan == -d */ + {"soft-mode", no_argument, 0, 's'}, /* --soft-mode == -s */ + {"pcapng", no_argument, 0, 'n'}, /* --pcapng == -n */ + {"outfile", required_argument, 0, 'o'}, /* --outfile == -o */ + {"keep-outfile", no_argument, 0, 'k'}, /* --keep-outfile == -k */ + {"data-link-type", required_argument, 0, 't'}, /* --data-link-type == -t */ + {"verbose", no_argument, 0, 'v'}, /* --verbose == -v */ {0, 0, 0, 0} }; /* print out pcapfix header information */ - printf("pcapfix %s (c) 2012-2014 Robert Krause\n\n", VERSION); + printf("pcapfix %s (c) 2012-2018 Robert Krause\n\n", VERSION); /* scan for options and arguments */ - while ((c = getopt_long(argc, argv, ":t:o:v::d::n::", long_options, &option_index)) != -1) { + while ((c = getopt_long(argc, argv, ":t:ko:v::d::s::n::", long_options, &option_index)) != -1) { switch (c) { case 0: /* getopt_long options evaluation */ break; case 'd': /* deep scan */ deep_scan++; break; + case 's': /* soft mode */ + soft_mode++; + break; + case 'k': /* keep outfile even if nothing needed fixing */ + keep_outfile++; + break; case 'n': /* pcapng format */ pcapng++; break; @@ -409,7 +421,9 @@ fclose(pcap_fix); /* delete output file due to no changes failure */ - if (strcmp(filename, filename_fix) != 0) remove(filename_fix); + if ((strcmp(filename, filename_fix) != 0) && (0 == keep_outfile)) { + remove(filename_fix); + } return(0); @@ -424,11 +438,9 @@ /* delete output file due to failure */ if (strcmp(filename, filename_fix) != 0) remove(filename_fix); - /* deep scan dependent output */ - if (pcapng == 0) { - if (deep_scan == 0) printf("If you are SURE that there are pcap packets inside, try with deep scan option (-d) to find them!\n\n"); - else printf("There is REALLY no pcap packet inside this file!!!\n\n"); - } + /* deep scan / soft mode dependent output */ + if (deep_scan == 0 || soft_mode == 0) printf("If you are SURE that there are pcap packets inside, try with deep scan (-d) (pcap only!) and/or soft mode (-s) to find them!\n\n"); + else printf("There is REALLY no pcap packet inside this file!!!\n\n"); return(res-10); @@ -473,13 +485,13 @@ /* Successful repaired! (res > 0) */ fclose(pcap); - int finalpos = ftello(pcap_fix); + off_t finalpos = ftello(pcap_fix); fclose(pcap_fix); int success = truncate(filename_fix, finalpos); if (success != 0) printf("[-] Truncating result file failed!"); printf("[+] SUCCESS: %d Corruption(s) fixed!\n\n", res); - return(1); + return(0); } else { /* Unknown Error (res < 0); this should NEVER happen! */ diff -Nru pcapfix-1.1.1/pcapfix.h pcapfix-1.1.3/pcapfix.h --- pcapfix-1.1.1/pcapfix.h 2018-01-02 13:35:14.000000000 +0000 +++ pcapfix-1.1.3/pcapfix.h 2018-09-04 13:36:53.000000000 +0000 @@ -1,6 +1,6 @@ /******************************************************************************* * - * Copyright (c) 2012-2017 Robert Krause (ruport@f00l.de) + * Copyright (c) 2012-2018 Robert Krause (ruport@f00l.de) * * This file is part of Pcapfix. * @@ -88,9 +88,10 @@ void print_progress(uint64_t pos, uint64_t filesize); /* global configuration variables */ -extern int deep_scan; /* deep scan option (default: no depp scan) */ -extern int verbose; /* verbose output option (default: dont be verbose) */ -extern int swapped; /* pcap file is swapped (big endian) */ -extern int data_link_type; /* data link type (default: LINKTYPE_ETHERNET) */ +extern int deep_scan; /* deep scan option (default: no depp scan) */ +extern int verbose; /* verbose output option (default: dont be verbose) */ +extern int swapped; /* pcap file is swapped (big endian) */ +extern int data_link_type; /* data link type (default: LINKTYPE_ETHERNET) */ +extern int soft_mode; /* soft plausibility check (default: OFF) */ #endif diff -Nru pcapfix-1.1.1/pcap.h pcapfix-1.1.3/pcap.h --- pcapfix-1.1.1/pcap.h 2018-01-02 13:24:39.000000000 +0000 +++ pcapfix-1.1.3/pcap.h 2018-09-04 13:36:53.000000000 +0000 @@ -1,6 +1,6 @@ /******************************************************************************* * - * Copyright (c) 2012-2014 Robert Krause (ruport@f00l.de) + * Copyright (c) 2012-2018 Robert Krause (ruport@f00l.de) * * This file is part of Pcapfix. * @@ -23,9 +23,10 @@ #define PCAP_MAGIC 0xa1b2c3d4 /* the magic of the pcap global header (non swapped) */ #define PCAP_MAGIC_SWAPPED 0xd4c3b2a1 /* the magic of the pcap global header (swapped) */ #define PCAPNG_MAGIC 0x0a0d0d0a /* the magic of the pcap global header (non swapped) */ -#define PCAP_NSEC_MAGIC 0xa1b23c4d /* the magic of the pcap global header (nanoseconds - non swapped) */ +#define PCAP_NSEC_MAGIC 0xa1b23c4d /* the magic of the pcap global header (nanoseconds - non swapped) */ #define PCAP_EXT_MAGIC 0xa1b2cd34 /* the magic of the extended pcap global header (non swapped) */ #define PCAP_EXT_MAGIC_SWAPPED 0x34cdb2a1 /* the magic of the extended pcap global header (swapped) */ +#define PCAP_MAX_SNAPLEN 262144 /* the maximum snap length, should be 256K instead of 64K nowadays */ /* Global header (http://v2.nat32.com/pcap.htm) */ struct global_hdr_s { @@ -59,36 +60,38 @@ * Function: is_plausible * ----------------------- * check if the pcap packet header could be a plausible one by satisfying those conditions: - * - packet size >= 16 bytes AND <= 65535 bytes (included length AND original length) (conditions 1,2,3,4) + * - packet size >= 16 bytes AND <= MAX_SNAPLEN bytes (included length AND original length) (conditions 1,2,3,4) * - included length <= original lenth (condition 5) * - packet timestamp is NOT older OR younger than the prior packets timestamp -+ one day (conditions 6,7) * - usec (microseconds) field <= 1000000 (conditions 8) * - usec (nanoseconds) field <= 1000000000 (conditions 9) * - * hdr: the filled packet header struct to check for plausibility - * prior_ts: the prior packets timestamp (seconds) to check for time relation (condition 6,7) + * global_hdr: the filled pcap header to check for snaplen + * hdr: the filled packet header struct to check for plausibility + * prior_ts: the prior packets timestamp (seconds) to check for time relation (condition 6,7) * * returns: 0 success * -X error (condition X failed) * */ -int is_plausible(struct packet_hdr_s hdr, unsigned int prior_ts); +int is_plausible(struct global_hdr_s global_hdr, struct packet_hdr_s hdr, unsigned int prior_ts); /* * Function: check_header * ----------------------- * this function takes a buffer and brute forces some possible ascii-corrupted bytes versus plausibility checks * - * buffer: the buffer that might contain the possible pcap packet header - * size: the size of the buffer (double pcap packet header size is a good choice) - * priot_ts: the prior packets timestamp (to check for plausibility) - * hdr: the pointer to the packet header buffer (we use this to return the repaired header) + * buffer: the buffer that might contain the possible pcap packet header + * size: the size of the buffer (double pcap packet header size is a good choice) + * priot_ts: the prior packets timestamp (to check for plausibility) + * global_hdr: the pointer to the pcap buffer + * hdr: the pointer to the packet header buffer (we use this to return the repaired header) * * returns: >=0 success (return value contains number of ascii corrupted bytes in hdr (we need this data to align the beginning of the packet body later) * -1 error (no valid pcap header found inside buffer) * */ -int check_header(char *buffer, unsigned int size, unsigned int prior_ts, struct packet_hdr_s *hdr); +int check_header(char *buffer, unsigned int size, unsigned int prior_ts, struct global_hdr_s *global_hdr, struct packet_hdr_s *hdr); /* * Function: fix_pcap diff -Nru pcapfix-1.1.1/pcapng.c pcapfix-1.1.3/pcapng.c --- pcapfix-1.1.1/pcapng.c 2018-01-02 13:35:14.000000000 +0000 +++ pcapfix-1.1.3/pcapng.c 2018-09-04 13:36:53.000000000 +0000 @@ -1,6 +1,6 @@ /******************************************************************************* * - * Copyright (c) 2012-2017 Robert Krause (ruport@f00l.de) + * Copyright (c) 2012-2018 Robert Krause (ruport@f00l.de) * * This file is part of Pcapfix. * @@ -1483,10 +1483,10 @@ } /* Simple Packet Block Checks: - * - max size <= 65535 */ + * - max size <= MAX_SNAPLEN */ if (bh.block_type == TYPE_SPB) { /* max size check */ - if (bh.total_length > 65536) continue; + if (bh.total_length > PCAPNG_MAX_SNAPLEN) continue; } /* Name Resolution Block Checks: @@ -1670,7 +1670,7 @@ idb.reserved = 0; /* we set snaplen to maximum */ - idb.snaplen = 65535; + idb.snaplen = PCAPNG_MAX_SNAPLEN; /* increase total size by interface desciption block (header) */ size += sizeof(struct interface_description_block); diff -Nru pcapfix-1.1.1/pcapng.h pcapfix-1.1.3/pcapng.h --- pcapfix-1.1.1/pcapng.h 2018-01-02 13:35:14.000000000 +0000 +++ pcapfix-1.1.3/pcapng.h 2018-09-04 13:36:53.000000000 +0000 @@ -1,6 +1,6 @@ /******************************************************************************* * - * Copyright (c) 2012-2017 Robert Krause (ruport@f00l.de) + * Copyright (c) 2012-2018 Robert Krause (ruport@f00l.de) * * This file is part of Pcapfix. * @@ -33,6 +33,8 @@ #define TYPE_ISB 0x00000005 /* Interface Statistics Block */ #define TYPE_EPB 0x00000006 /* Enhanced Packet Block */ +#define PCAPNG_MAX_SNAPLEN 262144 /* maximum snap length */ + /* * Function: fix_pcapng * --------------------- diff -Nru pcapfix-1.1.1/README pcapfix-1.1.3/README --- pcapfix-1.1.1/README 2018-01-02 13:35:14.000000000 +0000 +++ pcapfix-1.1.3/README 2018-09-04 13:36:53.000000000 +0000 @@ -1,4 +1,4 @@ -pcapfix v1.1.1 README +pcapfix v1.1.3 README ********************* Pcapfix is a tool to repair your damaged or corrupted pcap and pcapng files. @@ -30,6 +30,7 @@ ./pcapfix [OPTIONS] filename OPTIONS: -d , --deep-scan Deep Scan (default = 0) (pcap only!) + -s , --soft-mode Soft mode (packet detection) -n , --pcapng Force File Format to PCAPNG -o , --outfile Set output file name -t , --data-link-type Data Link Type (default = 1) @@ -58,6 +59,18 @@ the whole pcapng file for further blocks. +Soft Mode +......... + +There are programs that breach some pcap conventions when writing files. +Ignoring those rules do not break the pcap file but they make it difficult for +pcapfix to identify the packets in case of broken files. + +By default pcapfix uses hard mode. If you encounter problems when repairing +files, try to switch to soft mode (-s). Pcapfix will then try to find the +packets in a more tolerant way. + + PCAPNG Format ............. @@ -168,7 +181,7 @@ COPYRIGHT ========= -Copyright 2012-2017 Robert Krause +Copyright 2012-2018 Robert Krause Pcapfix is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software