diff --git a/src/Makefile.am b/src/Makefile.am index 48f5dd0ee0..ada1afc6a4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -46,6 +46,7 @@ conf-yaml-loader.c conf-yaml-loader.h \ counters.c counters.h \ data-queue.c data-queue.h \ decode.c decode.h \ +decode-afl.c \ decode-erspan.c decode-erspan.h \ decode-ethernet.c decode-ethernet.h \ decode-events.c decode-events.h \ diff --git a/src/decode-afl.c b/src/decode-afl.c new file mode 100644 index 0000000000..59fd6fe13c --- /dev/null +++ b/src/decode-afl.c @@ -0,0 +1,149 @@ +/* Copyright (C) 2007-2017 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "suricata-common.h" +#include "suricata.h" +#include "conf.h" +#include "decode.h" +#include "util-debug.h" +#include "util-mem.h" +#include "app-layer-detect-proto.h" +#include "app-layer.h" +#include "tm-threads.h" +#include "util-error.h" +#include "util-print.h" +#include "tmqh-packetpool.h" +#include "util-profiling.h" +#include "pkt-var.h" +#include "util-mpm-ac.h" + +#include "output.h" +#include "output-flow.h" + +#include "defrag.h" +#include "flow.h" + +#ifdef AFLFUZZ_DECODER + +/* stateful processing of data as packets. Because AFL in case of a + * crash will only safe the last input, we dump all the inputs to a + * directory 'dump' with a unique timestamp for the serie and an + * incrementing 'id' so that we can 'replay' it in + * DecoderParseDataFromFileSerie(). + */ +int DecoderParseDataFromFile(char *filename, DecoderFunc Decoder) { + uint8_t buffer[65536]; + + struct timeval ts; + memset(&ts, 0, sizeof(ts)); + gettimeofday(&ts, NULL); + + uint32_t cnt = 0; + + DefragInit(); + FlowInitConfig(FLOW_QUIET); + + ThreadVars tv; + memset(&tv, 0, sizeof(tv)); + DecodeThreadVars *dtv = DecodeThreadVarsAlloc(&tv); + DecodeRegisterPerfCounters(dtv, &tv); + StatsSetupPrivate(&tv); + +#ifdef AFLFUZZ_PERSISTANT_MODE + while (__AFL_LOOP(1000)) { + /* reset state */ + memset(buffer, 0, sizeof(buffer)); +#endif /* AFLFUZZ_PERSISTANT_MODE */ + + + FILE *fp = fopen(filename, "r"); + BUG_ON(fp == NULL); + + size_t size = fread(&buffer, 1, sizeof(buffer), fp); + char outfilename[256]; + snprintf(outfilename, sizeof(outfilename), "dump/%u-%u.%u", (uint)ts.tv_sec, (uint)ts.tv_usec, cnt); + FILE *out_fp = fopen(outfilename, "w"); + BUG_ON(out_fp == NULL); + (void)fwrite(buffer, size, 1, out_fp); + fclose(out_fp); + + Packet *p = PacketGetFromAlloc(); + if (p != NULL) { + (void) Decoder (&tv, dtv, p, buffer, size, NULL); + PacketFree(p); + } + fclose(fp); + cnt++; + +#ifdef AFLFUZZ_PERSISTANT_MODE + } +#endif /* AFLFUZZ_PERSISTANT_MODE */ + + /* if we get here there was no crash, so we can remove our files */ + uint32_t x = 0; + for (x = 0; x < cnt; x++) { + char rmfilename[256]; + snprintf(rmfilename, sizeof(rmfilename), "dump/%u-%u.%u", (uint)ts.tv_sec, (uint)ts.tv_usec, x); + unlink(rmfilename); + } + + DecodeThreadVarsFree(&tv, dtv); + FlowShutdown(); + DefragDestroy(); + return 0; +} + +/* load a serie of files generated by DecoderParseDataFromFile() in + * the same order as it was produced. */ +int DecoderParseDataFromFileSerie(char *fileprefix, DecoderFunc Decoder) +{ + uint8_t buffer[65536]; + uint32_t cnt = 0; + + DefragInit(); + FlowInitConfig(FLOW_QUIET); + ThreadVars tv; + memset(&tv, 0, sizeof(tv)); + DecodeThreadVars *dtv = DecodeThreadVarsAlloc(&tv); + DecodeRegisterPerfCounters(dtv, &tv); + StatsSetupPrivate(&tv); + + char filename[256]; + snprintf(filename, sizeof(filename), "dump/%s.%u", fileprefix, cnt); + FILE *fp; + while ((fp = fopen(filename, "r")) != NULL) + { + memset(buffer, 0, sizeof(buffer)); + + size_t size = fread(&buffer, 1, sizeof(buffer), fp); + + Packet *p = PacketGetFromAlloc(); + if (p != NULL) { + (void) Decoder (&tv, dtv, p, buffer, size, NULL); + PacketFree(p); + } + fclose(fp); + cnt++; + snprintf(filename, sizeof(filename), "dump/%s.%u", fileprefix, cnt); + } + DecodeThreadVarsFree(&tv, dtv); + FlowShutdown(); + DefragDestroy(); + return 0; +} +#endif /* AFLFUZZ_DECODER */ + diff --git a/src/decode.c b/src/decode.c index 58fa61b338..4b064c8300 100644 --- a/src/decode.c +++ b/src/decode.c @@ -600,55 +600,6 @@ void CaptureStatsSetup(ThreadVars *tv, CaptureStats *s) s->counter_ips_replaced = StatsRegisterCounter("ips.replaced", tv); } -#ifdef AFLFUZZ_DECODER -int DecoderParseDataFromFile(char *filename, DecoderFunc Decoder) { - uint8_t buffer[65536]; - int result = 1; - -#ifdef AFLFUZZ_PERSISTANT_MODE - while (__AFL_LOOP(1000)) { - /* reset state */ - memset(buffer, 0, sizeof(buffer)); -#endif /* AFLFUZZ_PERSISTANT_MODE */ - - FILE *fp = fopen(filename, "r"); - BUG_ON(fp == NULL); - - ThreadVars tv; - memset(&tv, 0, sizeof(tv)); - DecodeThreadVars *dtv = DecodeThreadVarsAlloc(&tv); - DecodeRegisterPerfCounters(dtv, &tv); - StatsSetupPrivate(&tv); - - while (1) { - int done = 0; - size_t size = fread(&buffer, 1, sizeof(buffer), fp); - if (size < sizeof(buffer)) - done = 1; - - Packet *p = PacketGetFromAlloc(); - if (p != NULL) { - (void) Decoder (&tv, dtv, p, buffer, size, NULL); - PacketFree(p); - } - - if (done) - break; - } - DecodeThreadVarsFree(&tv, dtv); - - fclose(fp); - -#ifdef AFLFUZZ_PERSISTANT_MODE - } -#endif /* AFLFUZZ_PERSISTANT_MODE */ - - result = 0; - return result; - -} -#endif /* AFLFUZZ_DECODER */ - /** * @} */ diff --git a/src/decode.h b/src/decode.h index 85b4faf560..dcf7e2e120 100644 --- a/src/decode.h +++ b/src/decode.h @@ -958,6 +958,7 @@ typedef int (*DecoderFunc)(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq); int DecoderParseDataFromFile(char *filename, DecoderFunc Decoder); +int DecoderParseDataFromFileSerie(char *fileprefix, DecoderFunc Decoder); #endif /** \brief Set the No payload inspection Flag for the packet. diff --git a/src/suricata.c b/src/suricata.c index 7f16679525..92d7280880 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -1261,7 +1261,11 @@ static TmEcode ParseCommandLine(int argc, char** argv, SCInstance *suri) {"afl-rules", required_argument, 0 , 0}, {"afl-mime", required_argument, 0 , 0}, {"afl-decoder-ppp", required_argument, 0 , 0}, + {"afl-decoder-ppp-serie", required_argument, 0 , 0}, {"afl-decoder-ipv4", required_argument, 0 , 0}, + {"afl-decoder-ipv4-serie", required_argument, 0 , 0}, + {"afl-decoder-ipv6", required_argument, 0 , 0}, + {"afl-decoder-ipv6-serie", required_argument, 0 , 0}, {"afl-der", required_argument, 0, 0}, #ifdef BUILD_UNIX_SOCKET @@ -1565,24 +1569,33 @@ static TmEcode ParseCommandLine(int argc, char** argv, SCInstance *suri) exit(MimeParserDataFromFile(optarg)); #endif #ifdef AFLFUZZ_DECODER - } else if(strcmp((long_opts[option_index]).name, "afl-decoder-ppp") == 0) { + } else if(strstr((long_opts[option_index]).name, "afl-decoder-ppp") != NULL) { StatsInit(); MpmTableSetup(); SpmTableSetup(); AppLayerProtoDetectSetup(); - DefragInit(); - FlowInitConfig(FLOW_QUIET); - //printf("arg: //%s\n", optarg); - exit(DecoderParseDataFromFile(optarg, DecodePPP)); - } else if(strcmp((long_opts[option_index]).name, "afl-decoder-ipv4") == 0) { + if (strcmp((long_opts[option_index]).name, "afl-decoder-ppp") == 0) + exit(DecoderParseDataFromFile(optarg, DecodePPP)); + else + exit(DecoderParseDataFromFileSerie(optarg, DecodePPP)); + } else if(strstr((long_opts[option_index]).name, "afl-decoder-ipv4") != NULL) { StatsInit(); MpmTableSetup(); SpmTableSetup(); AppLayerProtoDetectSetup(); - DefragInit(); - FlowInitConfig(FLOW_QUIET); - //printf("arg: //%s\n", optarg); - exit(DecoderParseDataFromFile(optarg, DecodeIPV4)); + if (strcmp((long_opts[option_index]).name, "afl-decoder-ipv4") == 0) + exit(DecoderParseDataFromFile(optarg, DecodeIPV4)); + else + exit(DecoderParseDataFromFileSerie(optarg, DecodeIPV4)); + } else if(strstr((long_opts[option_index]).name, "afl-decoder-ipv6") != NULL) { + StatsInit(); + MpmTableSetup(); + SpmTableSetup(); + AppLayerProtoDetectSetup(); + if (strcmp((long_opts[option_index]).name, "afl-decoder-ipv6") == 0) + exit(DecoderParseDataFromFile(optarg, DecodeIPV6)); + else + exit(DecoderParseDataFromFileSerie(optarg, DecodeIPV6)); #endif #ifdef AFLFUZZ_DER } else if(strcmp((long_opts[option_index]).name, "afl-der") == 0) {