... | ... |
@@ -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); |