From: Victor Julien Date: Fri, 21 Jul 2017 10:38:49 +0000 (+0200) Subject: afl: add dcerpc entry points X-Git-Tag: suricata-4.0.0~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=31daf435794c93a3908079ef9fcb099e62afe18c;p=thirdparty%2Fsuricata.git afl: add dcerpc entry points Add for requests and mix of request/responses. Implement storing the files to disk and rereading them. --- diff --git a/src/app-layer-dcerpc.c b/src/app-layer-dcerpc.c index 1723621b3a..a7fe13c397 100644 --- a/src/app-layer-dcerpc.c +++ b/src/app-layer-dcerpc.c @@ -1170,13 +1170,13 @@ static uint32_t DCERPCParseREQUEST(DCERPC *dcerpc, uint8_t *input, uint32_t inpu /** \internal * \retval stub_len or 0 in case of error */ -static uint32_t StubDataParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_len) +static uint32_t StubDataParser(DCERPC *dcerpc, const uint8_t *input, uint32_t input_len) { SCEnter(); uint8_t **stub_data_buffer = NULL; uint32_t *stub_data_buffer_len = NULL; uint8_t *stub_data_fresh = NULL; - uint16_t stub_len = 0; + uint32_t stub_len = 0; void *ptmp; /* request PDU. Retrieve the request stub buffer */ @@ -1192,7 +1192,7 @@ static uint32_t StubDataParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_le stub_data_fresh = &dcerpc->dcerpcresponse.stub_data_fresh; } - stub_len = (dcerpc->padleft < input_len) ? dcerpc->padleft : input_len; + stub_len = MIN(dcerpc->padleft, input_len); if (stub_len == 0) { SCLogError(SC_ERR_DCERPC, "stub_len is NULL. We shouldn't be seeing " "this. In case you are, there is something gravely wrong " @@ -1246,7 +1246,7 @@ static uint32_t StubDataParser(DCERPC *dcerpc, uint8_t *input, uint32_t input_le #ifdef DEBUG if (SCLogDebugEnabled()) { - int i = 0; + uint32_t i = 0; for (i = 0; i < stub_len; i++) { SCLogDebug("0x%02x ", input[i]); } diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index 925fea84d6..b564c06d35 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -1473,6 +1473,10 @@ void AppLayerParserStatePrintDetails(AppLayerParserState *pstate) #ifdef AFLFUZZ_APPLAYER int AppLayerParserRequestFromFile(uint8_t ipproto, AppProto alproto, char *filename) { + struct timeval ts; + memset(&ts, 0, sizeof(ts)); + gettimeofday(&ts, NULL); + int result = 1; Flow *f = NULL; TcpSession ssn; @@ -1495,7 +1499,8 @@ int AppLayerParserRequestFromFile(uint8_t ipproto, AppProto alproto, char *filen f->protomap = FlowGetProtoMapping(f->proto); f->alproto = alproto; - uint8_t buffer[64]; + uint8_t buffer[65536]; + uint32_t cnt = 0; #ifdef AFLFUZZ_PERSISTANT_MODE while (__AFL_LOOP(1000)) { @@ -1513,10 +1518,16 @@ int AppLayerParserRequestFromFile(uint8_t ipproto, AppProto alproto, char *filen if (size < sizeof(buffer)) done = 1; + char outfilename[256]; + snprintf(outfilename, sizeof(outfilename), "dump/%u-%u.%u", + (unsigned int)ts.tv_sec, (unsigned int)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); //SCLogInfo("result %u done %d start %d", (uint)result, done, start); uint8_t flags = STREAM_TOSERVER; - if (start--) { flags |= STREAM_START; } @@ -1527,6 +1538,8 @@ int AppLayerParserRequestFromFile(uint8_t ipproto, AppProto alproto, char *filen (void)AppLayerParserParse(NULL, alp_tctx, f, alproto, flags, buffer, size); + cnt++; + if (done) break; } @@ -1537,6 +1550,79 @@ int AppLayerParserRequestFromFile(uint8_t ipproto, AppProto alproto, char *filen } #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", + (unsigned int)ts.tv_sec, (unsigned int)ts.tv_usec, x); + unlink(rmfilename); + } + + result = 0; + +end: + if (alp_tctx != NULL) + AppLayerParserThreadCtxFree(alp_tctx); + if (f != NULL) { + FlowFree(f); + } + return result; +} + +/* load a serie of files generated by DecoderParseDataFromFile() in + * the same order as it was produced. */ +int AppLayerParserRequestFromFileSerie(uint8_t ipproto, AppProto alproto, char *fileprefix) +{ + uint32_t cnt = 0; + int start = 1; + int result = 1; + Flow *f = NULL; + TcpSession ssn; + AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); + + memset(&ssn, 0, sizeof(ssn)); + + f = SCCalloc(1, sizeof(Flow)); + if (f == NULL) + goto end; + FLOW_INITIALIZE(f); + + f->flags |= FLOW_IPV4; + f->src.addr_data32[0] = 0x01020304; + f->dst.addr_data32[0] = 0x05060708; + f->sp = 10000; + f->dp = 80; + f->protoctx = &ssn; + f->proto = ipproto; + f->protomap = FlowGetProtoMapping(f->proto); + f->alproto = alproto; + + uint8_t buffer[65536]; + + 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); + + uint8_t flags = STREAM_TOSERVER; + if (start--) { + flags |= STREAM_START; + } + + (void)AppLayerParserParse(NULL, alp_tctx, f, alproto, flags, + buffer, size); + + fclose(fp); + cnt++; + + snprintf(filename, sizeof(filename), "dump/%s.%u", fileprefix, cnt); + } + result = 0; end: @@ -1550,6 +1636,10 @@ end: int AppLayerParserFromFile(uint8_t ipproto, AppProto alproto, char *filename) { + struct timeval ts; + memset(&ts, 0, sizeof(ts)); + gettimeofday(&ts, NULL); + int result = 1; Flow *f = NULL; TcpSession ssn; @@ -1572,7 +1662,8 @@ int AppLayerParserFromFile(uint8_t ipproto, AppProto alproto, char *filename) f->protomap = FlowGetProtoMapping(f->proto); f->alproto = alproto; - uint8_t buffer[64]; + uint8_t buffer[65536]; + uint32_t cnt = 0; #ifdef AFLFUZZ_PERSISTANT_MODE while (__AFL_LOOP(1000)) { @@ -1591,6 +1682,13 @@ int AppLayerParserFromFile(uint8_t ipproto, AppProto alproto, char *filename) if (size < sizeof(buffer)) done = 1; + char outfilename[256]; + snprintf(outfilename, sizeof(outfilename), "dump/%u-%u.%u", + (unsigned int)ts.tv_sec, (unsigned int)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); //SCLogInfo("result %u done %d start %d", (uint)result, done, start); uint8_t flags = 0; @@ -1612,6 +1710,9 @@ int AppLayerParserFromFile(uint8_t ipproto, AppProto alproto, char *filename) (void)AppLayerParserParse(NULL, alp_tctx, f, alproto, flags, buffer, size); + + cnt++; + if (done) break; } @@ -1622,7 +1723,88 @@ int AppLayerParserFromFile(uint8_t ipproto, AppProto alproto, char *filename) } #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", + (unsigned int)ts.tv_sec, (unsigned int)ts.tv_usec, x); + unlink(rmfilename); + } + + result = 0; +end: + if (alp_tctx != NULL) + AppLayerParserThreadCtxFree(alp_tctx); + if (f != NULL) { + FlowFree(f); + } + return result; +} + +/* load a serie of files generated by DecoderParseDataFromFile() in + * the same order as it was produced. */ +int AppLayerParserFromFileSerie(uint8_t ipproto, AppProto alproto, char *fileprefix) +{ + uint32_t cnt = 0; + int start = 1; + int result = 1; + Flow *f = NULL; + TcpSession ssn; + AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); + + memset(&ssn, 0, sizeof(ssn)); + + f = SCCalloc(1, sizeof(Flow)); + if (f == NULL) + goto end; + FLOW_INITIALIZE(f); + + f->flags |= FLOW_IPV4; + f->src.addr_data32[0] = 0x01020304; + f->dst.addr_data32[0] = 0x05060708; + f->sp = 10000; + f->dp = 80; + f->protoctx = &ssn; + f->proto = ipproto; + f->protomap = FlowGetProtoMapping(f->proto); + f->alproto = alproto; + + uint8_t buffer[65536]; + int flip = 0; + 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); + + uint8_t flags = 0; + if (flip) { + flags = STREAM_TOCLIENT; + flip = 0; + } else { + flags = STREAM_TOSERVER; + flip = 1; + } + + if (start--) { + flags |= STREAM_START; + } + + (void)AppLayerParserParse(NULL, alp_tctx, f, alproto, flags, + buffer, size); + + fclose(fp); + cnt++; + + snprintf(filename, sizeof(filename), "dump/%s.%u", fileprefix, cnt); + } + result = 0; + end: if (alp_tctx != NULL) AppLayerParserThreadCtxFree(alp_tctx); @@ -1631,6 +1813,7 @@ end: } return result; } + #endif /* AFLFUZZ_APPLAYER */ /***** Unittests *****/ diff --git a/src/app-layer-parser.h b/src/app-layer-parser.h index bfd0378914..f7343cde2a 100644 --- a/src/app-layer-parser.h +++ b/src/app-layer-parser.h @@ -252,7 +252,9 @@ void AppLayerParserStatePrintDetails(AppLayerParserState *pstate); #ifdef AFLFUZZ_APPLAYER int AppLayerParserRequestFromFile(uint8_t ipproto, AppProto alproto, char *filename); +int AppLayerParserRequestFromFileSerie(uint8_t ipproto, AppProto alproto, char *prefix); int AppLayerParserFromFile(uint8_t ipproto, AppProto alproto, char *filename); +int AppLayerParserFromFileSerie(uint8_t ipproto, AppProto alproto, char *prefix); #endif /***** Unittests *****/ diff --git a/src/suricata.c b/src/suricata.c index 25a62c56f0..c85c8eb864 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -1341,7 +1341,28 @@ static void ParseCommandLineAFL(const char *opt_name, char *opt_arg) AppLayerParserSetup(); RegisterSMBParsers(); exit(AppLayerParserFromFile(IPPROTO_TCP, ALPROTO_SMB, opt_arg)); - + } else if(strstr(opt_name, "afl-dcerpc-request") != NULL) { + //printf("arg: //%s\n", opt_arg); + MpmTableSetup(); + SpmTableSetup(); + AppLayerProtoDetectSetup(); + AppLayerParserSetup(); + RegisterDCERPCParsers(); + if (strcmp(opt_name, "afl-dcerpc-request") == 0) + exit(AppLayerParserRequestFromFile(IPPROTO_TCP, ALPROTO_DCERPC, opt_arg)); + else + exit(AppLayerParserRequestFromFileSerie(IPPROTO_TCP, ALPROTO_DCERPC, opt_arg)); + } else if(strstr(opt_name, "afl-dcerpc") != NULL) { + //printf("arg: //%s\n", opt_arg); + MpmTableSetup(); + SpmTableSetup(); + AppLayerProtoDetectSetup(); + AppLayerParserSetup(); + RegisterDCERPCParsers(); + if (strcmp(opt_name, "afl-dcerpc") == 0) + exit(AppLayerParserFromFile(IPPROTO_TCP, ALPROTO_DCERPC, opt_arg)); + else + exit(AppLayerParserFromFileSerie(IPPROTO_TCP, ALPROTO_DCERPC, opt_arg)); } else if(strcmp(opt_name, "afl-modbus-request") == 0) { //printf("arg: //%s\n", opt_arg); AppLayerParserSetup(); @@ -1496,6 +1517,10 @@ static TmEcode ParseCommandLine(int argc, char** argv, SCInstance *suri) {"afl-mime", required_argument, 0 , 0}, {"afl-dnp3-request", required_argument, 0, 0}, {"afl-dnp3", required_argument, 0, 0}, + {"afl-dcerpc", required_argument, 0, 0}, + {"afl-dcerpc-serie", required_argument, 0, 0}, + {"afl-dcerpc-request", required_argument, 0, 0}, + {"afl-dcerpc-request-serie", required_argument, 0, 0}, /* Other AFL options. */ {"afl-rules", required_argument, 0 , 0},