]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
afl: add dcerpc entry points
authorVictor Julien <victor@inliniac.net>
Fri, 21 Jul 2017 10:38:49 +0000 (12:38 +0200)
committerVictor Julien <victor@inliniac.net>
Tue, 25 Jul 2017 11:29:05 +0000 (13:29 +0200)
Add for requests and mix of request/responses.

Implement storing the files to disk and rereading them.

src/app-layer-dcerpc.c
src/app-layer-parser.c
src/app-layer-parser.h
src/suricata.c

index 1723621b3a3fb57ab5b6d0e838f84b103ec247de..a7fe13c397c6346371b86f3b294bb2d319abff0c 100644 (file)
@@ -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]);
         }
index 925fea84d69f6d571a5ea8421f5d3b8fe9f36737..b564c06d356ec16eb7eeba78da8a8c8982e272f8 100644 (file)
@@ -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 *****/
index bfd0378914689b4427b0b2c3edc41200a9dd88fb..f7343cde2a90831df0c1d12d832671a7e6474e22 100644 (file)
@@ -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 *****/
index 25a62c56f0e5033c8a3be0204a9145117e3ec5ff..c85c8eb8645c3bc7d6d49fca8145452a9c07d8b4 100644 (file)
@@ -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},