Browse code

sigtool/pcre: pcre subsig id and exe support in sigtool

Kevin Lin authored on 2014/09/12 01:27:52
Showing 4 changed files
... ...
@@ -35,6 +35,9 @@
35 35
 #include "mpool.h"
36 36
 #include "regex_pcre.h"
37 37
 
38
+cli_events_t *p_sigevents = NULL;
39
+unsigned int p_sigid;
40
+
38 41
 int cli_pcre_addpatt(struct cli_matcher *root, const char *trigger, const char *pattern, const char *cflags, const char *offset, const uint32_t *lsigid)
39 42
 {
40 43
     struct cli_pcre_meta **newmetatable = NULL, *pm = NULL;
... ...
@@ -52,16 +55,22 @@ int cli_pcre_addpatt(struct cli_matcher *root, const char *trigger, const char *
52 52
     /* validate the lsig trigger */
53 53
     rssigs = cli_ac_chklsig(trigger, trigger + strlen(trigger), NULL, NULL, NULL, 1);
54 54
     if((strcmp(trigger, PCRE_BYPASS)) && (rssigs == -1)) {
55
-        cli_errmsg("cli_pcre_addpatt: regex subsig %d is missing a valid logical trigger\n", lsigid[1]);
55
+        cli_errmsg("cli_pcre_addpatt: regex subsig /%s/ is missing a valid logical trigger\n", pattern);
56 56
         return CL_EMALFDB;
57 57
     }
58
-    if (rssigs > lsigid[1]) {
59
-        cli_errmsg("cli_pcre_addpatt: regex subsig %d logical trigger refers to subsequent subsig %d\n", lsigid[1], rssigs);
60
-        return CL_EMALFDB;
58
+
59
+    if (lsigid) {
60
+        if (rssigs > lsigid[1]) {
61
+            cli_errmsg("cli_pcre_addpatt: regex subsig %d logical trigger refers to subsequent subsig %d\n", lsigid[1], rssigs);
62
+            return CL_EMALFDB;
63
+        }
64
+        if (rssigs == lsigid[1]) {
65
+            cli_errmsg("cli_pcre_addpatt: regex subsig %d logical trigger is self-referential\n", lsigid[1]);
66
+            return CL_EMALFDB;
67
+        }
61 68
     }
62
-    if (rssigs == lsigid[1]) {
63
-        cli_errmsg("cli_pcre_addpatt: regex subsig %d logical trigger is self-referential\n", lsigid[1]);
64
-        return CL_EMALFDB;
69
+    else {
70
+        cli_dbgmsg("cli_pcre_addpatt: regex subsig is missing lsigid data\n");
65 71
     }
66 72
 
67 73
     /* allocating entries */
... ...
@@ -87,8 +96,15 @@ int cli_pcre_addpatt(struct cli_matcher *root, const char *trigger, const char *
87 87
         return CL_EMEM;
88 88
     }
89 89
 
90
-    pm->lsigid[0] = lsigid[0];
91
-    pm->lsigid[1] = lsigid[1];
90
+    if (lsigid) {
91
+        pm->lsigid[0] = 1;
92
+        pm->lsigid[1] = lsigid[0];
93
+        pm->lsigid[2] = lsigid[1];
94
+    }
95
+    else {
96
+        /* sigtool */
97
+        pm->lsigid[0] = 0;
98
+    }
92 99
 
93 100
     /* offset parsing and usage, similar to cli_ac_addsig */
94 101
     /* type-specific offsets and type-specific scanning handled during scan (cli_target_info stuff?) */
... ...
@@ -150,8 +166,12 @@ int cli_pcre_addpatt(struct cli_matcher *root, const char *trigger, const char *
150 150
         return CL_EMEM;
151 151
     }
152 152
 
153
-    cli_dbgmsg("cli_pcre_addpatt: Adding /%s/ triggered on (%s) as subsig %d for lsigid %d\n",
154
-               pm->pdata.expression, pm->trigger, pm->lsigid[1], pm->lsigid[0]);
153
+    if (pm->lsigid[0])
154
+        cli_dbgmsg("cli_pcre_addpatt: Adding /%s/ triggered on (%s) as subsig %d for lsigid %d\n",
155
+                   pm->pdata.expression, pm->trigger, pm->lsigid[2], pm->lsigid[1]);
156
+    else
157
+        cli_dbgmsg("cli_pcre_addpatt: Adding /%s/ triggered on (%s) [no lsigid]\n",
158
+                   pm->pdata.expression, pm->trigger);
155 159
 
156 160
     newmetatable[pcre_count-1] = pm;
157 161
     root->pcre_metatable = newmetatable;
... ...
@@ -235,7 +255,7 @@ int cli_pcre_recaloff(struct cli_matcher *root, struct cli_pcre_off *data, struc
235 235
         else {
236 236
             ret = cli_caloff(NULL, info, root->type, pm->offdata, &data->offset[i], &endoff);
237 237
             if (ret != CL_SUCCESS) {
238
-                cli_errmsg("cli_pcre_recaloff: cannot calculate relative offset in signature for sig[%u,%u]\n", pm->lsigid[0], pm->lsigid[1]);
238
+                cli_errmsg("cli_pcre_recaloff: cannot recalculate relative offset for signature\n");
239 239
                 free(data->shift);
240 240
                 free(data->offset);
241 241
                 return ret;
... ...
@@ -323,10 +343,11 @@ static inline void lsig_sub_matched(const struct cli_matcher *root, struct cli_a
323 323
     }
324 324
 }
325 325
 
326
-int cli_pcre_scanbuf(const unsigned char *buffer, uint32_t length, const struct cli_matcher *root, struct cli_ac_data *mdata, const struct cli_pcre_off *data, cli_ctx *ctx)
326
+int cli_pcre_scanbuf(const unsigned char *buffer, uint32_t length, const struct cli_matcher *root, struct cli_ac_data *mdata, struct cli_ac_result **res, const struct cli_pcre_off *data, cli_ctx *ctx)
327 327
 {
328 328
     struct cli_pcre_meta **metatable = root->pcre_metatable, *pm = NULL;
329 329
     struct cli_pcre_data *pd;
330
+    struct cli_ac_result *newres;
330 331
     uint32_t adjbuffer, adjshift, adjlength;
331 332
     unsigned int i, evalcnt;
332 333
     uint64_t evalids;
... ...
@@ -341,10 +362,15 @@ int cli_pcre_scanbuf(const unsigned char *buffer, uint32_t length, const struct
341 341
         pm = root->pcre_metatable[i];
342 342
         pd = &(pm->pdata);
343 343
 
344
-        /* check the evaluation of the trigger */
345
-        cli_dbgmsg("cli_pcre_scanbuf: checking %s; running regex /%s/\n", pm->trigger, pd->expression);
346
-        if ((strcmp(pm->trigger, PCRE_BYPASS)) && (cli_ac_chklsig(pm->trigger, pm->trigger + strlen(pm->trigger), mdata->lsigcnt[pm->lsigid[0]], &evalcnt, &evalids, 0) != 1))
347
-            continue;
344
+        /* check the evaluation of the trigger - TODO: fix me */
345
+        if (pm->lsigid[0]) {
346
+            cli_dbgmsg("cli_pcre_scanbuf: checking %s; running regex /%s/\n", pm->trigger, pd->expression);
347
+            if ((strcmp(pm->trigger, PCRE_BYPASS)) && (cli_ac_chklsig(pm->trigger, pm->trigger + strlen(pm->trigger), mdata->lsigcnt[pm->lsigid[1]], &evalcnt, &evalids, 0) != 1))
348
+                continue;
349
+        }
350
+        else {
351
+            cli_dbgmsg("cli_pcre_scanbuf: skipping %s check due to unintialized lsigid\n", pm->trigger);
352
+        }
348 353
 
349 354
         global = (pm->flags & CLI_PCRE_GLOBAL);       /* search for all matches */
350 355
         encompass = (pm->flags & CLI_PCRE_ENCOMPASS); /* encompass search to offset->offset+maxshift */
... ...
@@ -403,6 +429,7 @@ int cli_pcre_scanbuf(const unsigned char *buffer, uint32_t length, const struct
403 403
 
404 404
         /* if the global flag is set, loop through the scanning - TODO: how does this affect really big files? */
405 405
         do {
406
+            /* TODO: performance metrics */
406 407
             rc = cli_pcre_match(pd, buffer+adjbuffer, adjlength, offset, 0, ovector, OVECCOUNT);
407 408
             cli_dbgmsg("cli_pcre_scanbuf: running regex /%s/ returns %d\n", pd->expression, rc);
408 409
 
... ...
@@ -417,10 +444,29 @@ int cli_pcre_scanbuf(const unsigned char *buffer, uint32_t length, const struct
417 417
                     }
418 418
                 }
419 419
 
420
-                cli_dbgmsg("cli_pcre_scanbuf: assigning lsigcnt[%d][%d], located @ %d\n",
421
-                           pm->lsigid[0], pm->lsigid[1], adjbuffer+ovector[0]);
420
+                /* for logical signature evaluation */
421
+                if (pm->lsigid[0]) {
422
+                    cli_dbgmsg("cli_pcre_scanbuf: assigning lsigcnt[%d][%d], located @ %d\n",
423
+                               pm->lsigid[1], pm->lsigid[2], adjbuffer+ovector[0]);
422 424
 
423
-                lsig_sub_matched(root, mdata, pm->lsigid[0], pm->lsigid[1], adjbuffer+ovector[0], 0);
425
+                    lsig_sub_matched(root, mdata, pm->lsigid[1], pm->lsigid[2], adjbuffer+ovector[0], 0);
426
+                }
427
+                else
428
+                    cli_dbgmsg("cli_pcre_scanbuf: located regex match @ %d\n", adjbuffer+ovector[0]);
429
+
430
+                /* for raw match data */
431
+                if(res) {
432
+                    newres = (struct cli_ac_result *) malloc(sizeof(struct cli_ac_result));
433
+                    if(!newres) {
434
+                        cli_errmsg("cli_pcre_scanbuff: Can't allocate memory for newres %u\n", sizeof(struct cli_ac_result));
435
+                        return CL_EMEM;
436
+                    }
437
+                    newres->virname = NULL;    /* get value? */
438
+                    newres->customdata = NULL; /* get value? */
439
+                    newres->next = *res;
440
+                    newres->offset = adjbuffer+ovector[0];
441
+                    *res = newres;
442
+                }
424 443
             }
425 444
 
426 445
             /* move off to the end of the match for next match; offset is relative to adjbuffer
... ...
@@ -442,7 +488,7 @@ int cli_pcre_scanbuf(const unsigned char *buffer, uint32_t length, const struct
442 442
     return CL_SUCCESS;
443 443
 }
444 444
 
445
-int cli_pcre_ucondscanbuf(const unsigned char *buffer, uint32_t length, const struct cli_matcher *root, struct cli_ac_data *mdata, struct cli_pcre_off *data, cli_ctx *ctx)
445
+int cli_pcre_ucondscanbuf(const unsigned char *buffer, uint32_t length, const struct cli_matcher *root, struct cli_ac_data *mdata, struct cli_ac_result **res, struct cli_pcre_off *data, cli_ctx *ctx)
446 446
 {
447 447
     /* TODO: copy cli_pcre_scanbuf - trigger */
448 448
     return CL_SUCCESS;
... ...
@@ -42,7 +42,7 @@
42 42
 
43 43
 struct cli_pcre_meta {
44 44
     char *trigger;
45
-    uint32_t lsigid[2];
45
+    uint32_t lsigid[3]; /* 0=valid, 1=lsigid, 2=subsigid */
46 46
     struct cli_pcre_data pdata;
47 47
     /* clamav offset data */
48 48
     uint32_t offdata[4];
... ...
@@ -60,8 +60,8 @@ int cli_pcre_addpatt(struct cli_matcher *root, const char *trigger,  const char
60 60
 int cli_pcre_build(struct cli_matcher *root, long long unsigned match_limit, long long unsigned recmatch_limit);
61 61
 int cli_pcre_recaloff(struct cli_matcher *root, struct cli_pcre_off *data, struct cli_target_info *info);
62 62
 void cli_pcre_freeoff(struct cli_pcre_off *data);
63
-int cli_pcre_scanbuf(const unsigned char *buffer, uint32_t length, const struct cli_matcher *root, struct cli_ac_data *mdata, const struct cli_pcre_off *data, cli_ctx *ctx);
64
-int cli_pcre_ucondscanbuf(const unsigned char *buffer, uint32_t length, const struct cli_matcher *root, struct cli_ac_data *mdata,  struct cli_pcre_off *data, cli_ctx *ctx);
63
+int cli_pcre_scanbuf(const unsigned char *buffer, uint32_t length, const struct cli_matcher *root, struct cli_ac_data *mdata,  struct cli_ac_result **res, const struct cli_pcre_off *data, cli_ctx *ctx);
64
+int cli_pcre_ucondscanbuf(const unsigned char *buffer, uint32_t length, const struct cli_matcher *root, struct cli_ac_data *mdata,  struct cli_ac_result **res, struct cli_pcre_off *data, cli_ctx *ctx);
65 65
 void cli_pcre_freemeta(struct cli_pcre_meta *pm);
66 66
 void cli_pcre_freetable(struct cli_matcher *root);
67 67
 #endif /* HAVE_PCRE */
... ...
@@ -985,7 +985,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
985 985
             }
986 986
 
987 987
             /* scan the full buffer */
988
-            ret = cli_pcre_scanbuf(buff, map->len, groot, &gdata, &poff, ctx);
988
+            ret = cli_pcre_scanbuf(buff, map->len, groot, &gdata, acres, &poff, ctx);
989 989
             if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
990 990
                 cli_ac_freedata(&gdata);
991 991
                 cli_ac_freedata(&tdata);
... ...
@@ -1027,7 +1027,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
1027 1027
             }
1028 1028
 
1029 1029
             /* scan the full buffer */
1030
-            ret = cli_pcre_scanbuf(buff, map->len, troot, &tdata, &poff, ctx);
1030
+            ret = cli_pcre_scanbuf(buff, map->len, troot, &tdata, acres, &poff, ctx);
1031 1031
             if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
1032 1032
                 if(!ftonly)
1033 1033
                     cli_ac_freedata(&gdata);
... ...
@@ -373,7 +373,7 @@ static char *getdsig(const char *host, const char *user, const unsigned char *da
373 373
 	    closesocket(sockd);
374 374
 	    return NULL;
375 375
 	} else {
376
-	    mprintf("Signature received (length = %lu)\n", strlen(buff) - 10);
376
+	    mprintf("Signature received (length = %zu)\n", strlen(buff) - 10);
377 377
 	}
378 378
     } else {
379 379
 	mprintf("!getdsig: Communication error with remote server\n");
... ...
@@ -1977,6 +1977,8 @@ static void matchsig(const char *sig, const char *offset, int fd)
1977 1977
 	cli_ctx ctx;
1978 1978
 	int ret;
1979 1979
 
1980
+    mprintf("SUBSIG: %s\n", sig);
1981
+
1980 1982
     if(!(engine = cl_engine_new())) {
1981 1983
 	mprintf("!matchsig: Can't create new engine\n");
1982 1984
 	return;
... ...
@@ -2271,14 +2273,81 @@ static char *decodehexspecial(const char *hex, unsigned int *dlen)
2271 2271
 
2272 2272
 static int decodehex(const char *hexsig)
2273 2273
 {
2274
-	char *pt, *hexcpy, *start, *n, *decoded;
2274
+	char *pt, *hexcpy, *start, *n, *decoded, *wild;
2275 2275
 	int asterisk = 0;
2276 2276
 	unsigned int i, j, hexlen, dlen, parts = 0, bw;
2277 2277
 	int mindist = 0, maxdist = 0, error = 0;
2278 2278
 
2279 2279
 
2280 2280
     hexlen = strlen(hexsig);
2281
-    if(strchr(hexsig, '{') || strchr(hexsig, '[')) {
2281
+    if ((wild = strchr(hexsig, '/'))) {
2282
+	/* ^offset:trigger-logic/regex/options$ */
2283
+	char *trigger, *regex, *regex_end, *cflags;
2284
+	size_t tlen = wild-hexsig, rlen, clen;
2285
+
2286
+	/* check for trigger */
2287
+	if (!tlen) {
2288
+	    mprintf("!pcre without logical trigger\n");
2289
+	    return -1;
2290
+	}
2291
+
2292
+	/* locate end of regex for options start, locate options length */
2293
+	if ((regex_end = strchr(wild+1, '/')) == NULL) {
2294
+	    mprintf("!missing regex expression terminator /\n");
2295
+	    return -1;
2296
+	}
2297
+	rlen = regex_end-wild-1;
2298
+	clen = hexlen-tlen-rlen-2; /* 2 from regex boundaries '/' */
2299
+
2300
+	/* get the trigger statement */
2301
+	trigger = cli_calloc(tlen+1, sizeof(char));
2302
+	if (!trigger) {
2303
+	    mprintf("!cannot allocate memory for trigger string\n");
2304
+	    return -1;
2305
+	}
2306
+	strncpy(trigger, hexsig, tlen);
2307
+	trigger[tlen] = '\0';
2308
+
2309
+	/* get the regex expression */
2310
+	regex = cli_calloc(rlen+1, sizeof(char));
2311
+	if (!regex) {
2312
+	    mprintf("!cannot allocate memory for regex expression\n");
2313
+	    return -1;
2314
+	}
2315
+	strncpy(regex, hexsig+tlen+1, rlen);
2316
+	regex[rlen] = '\0';
2317
+
2318
+	/* get the compile flags */
2319
+	if (clen) {
2320
+	    cflags = cli_calloc(clen+1, sizeof(char));
2321
+	    if (!cflags) {
2322
+		cli_errmsg("!cannot allocate memory for compile flags\n");
2323
+		return -1;
2324
+	    }
2325
+	    strncpy(cflags, hexsig+tlen+rlen+2, clen);
2326
+	    cflags[clen] = '\0';
2327
+	}
2328
+	else {
2329
+	    cflags = NULL;
2330
+	}
2331
+
2332
+	/* print components of regex subsig */
2333
+	mprintf("     +-> TRIGGER: %s\n", trigger);
2334
+	mprintf("     +-> REGEX: %s\n", regex);
2335
+	mprintf("     +-> CFLAGS: %s\n", cflags);
2336
+
2337
+	free(trigger);
2338
+	free(regex);
2339
+	if (cflags)
2340
+	    free(cflags);
2341
+#if HAVE_PCRE
2342
+	return 0;
2343
+#else
2344
+	mprintf("!PCRE subsig cannot be loaded without PCRE support\n");
2345
+	return -1;
2346
+#endif
2347
+    }
2348
+    else if(strchr(hexsig, '{') || strchr(hexsig, '[')) {
2282 2349
 	if(!(hexcpy = strdup(hexsig)))
2283 2350
 	    return -1;
2284 2351
 
... ...
@@ -2474,8 +2543,8 @@ static int decodesig(char *sig, int fd)
2474 2474
 		mprintf(" +-> OFFSET: ANY\n");
2475 2475
 	    }
2476 2476
 	    if(fd == -1) {
2477
-		mprintf(" +-> DECODED SUBSIGNATURE:\n");
2478
-		decodehex(pt ? pt : tokens[3 + i]);
2477
+                mprintf(" +-> DECODED SUBSIGNATURE:\n");
2478
+                decodehex(pt ? pt : tokens[3 + i]);
2479 2479
 	    } else {
2480 2480
 		mprintf(" +-> ");
2481 2481
 		matchsig(pt ? pt : tokens[3 + i], pt ? tokens[3 + i] : NULL, fd);