[Pkg-clamav-commits] [SCM] Debian repository for ClamAV branch, debian/unstable, updated. debian/0.95+dfsg-1-6156-g094ec9b
Török Edvin
edwin at clamav.net
Sun Apr 4 01:19:36 UTC 2010
The following commit has been merged in the debian/unstable branch:
commit 461a7bd9025b88594c5239c027c68f65fb1a12f2
Merge: 40103a3004de9ab704bf4824aca2595753bc095d 2a94c08e19303bf4c7394fa11ba41dd337b60913
Author: Török Edvin <edwin at clamav.net>
Date: Tue Feb 9 20:19:56 2010 +0200
Merge branch 'prefiltering_split' into prefiltering3
* prefiltering_split:
move matching code to matcher_run.
matcher-ac: move leaf checks inside IS_FINAL.
Conflicts:
libclamav/matcher.c
diff --combined libclamav/matcher-ac.c
index f01014d,a43f458..21ae45e
--- a/libclamav/matcher-ac.c
+++ b/libclamav/matcher-ac.c
@@@ -1,5 -1,5 +1,5 @@@
/*
- * Copyright (C) 2007-2008 Sourcefire, Inc.
+ * Copyright (C) 2007-2009 Sourcefire, Inc.
*
* Authors: Tomasz Kojm
*
@@@ -26,7 -26,6 +26,7 @@@
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
+#include <sys/stat.h>
#include <assert.h>
#ifdef HAVE_UNISTD_H
@@@ -45,45 -44,12 +45,45 @@@
#include "mpool.h"
+#define AC_SPECIAL_ALT_CHAR 1
+#define AC_SPECIAL_ALT_STR 2
+#define AC_SPECIAL_LINE_MARKER 3
+#define AC_SPECIAL_BOUNDARY 4
+
+#define AC_BOUNDARY_LEFT 1
+#define AC_BOUNDARY_LEFT_NEGATIVE 2
+#define AC_BOUNDARY_RIGHT 4
+#define AC_BOUNDARY_RIGHT_NEGATIVE 8
+#define AC_LINE_MARKER_LEFT 16
+#define AC_LINE_MARKER_LEFT_NEGATIVE 32
+#define AC_LINE_MARKER_RIGHT 64
+#define AC_LINE_MARKER_RIGHT_NEGATIVE 128
+
+static char boundary[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 3, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 1, 3,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
int cli_ac_addpatt(struct cli_matcher *root, struct cli_ac_patt *pattern)
{
struct cli_ac_node *pt, *next;
struct cli_ac_patt *ph;
void *newtable;
- struct cli_ac_alt *a1, *a2;
+ struct cli_ac_special *a1, *a2;
uint8_t i, match;
uint16_t len = MIN(root->ac_maxdepth, pattern->length);
@@@ -164,31 -130,27 +164,31 @@@
while(ph) {
if((ph->length == pattern->length) && (ph->prefix_length == pattern->prefix_length) && (ph->ch[0] == pattern->ch[0]) && (ph->ch[1] == pattern->ch[1])) {
if(!memcmp(ph->pattern, pattern->pattern, ph->length * sizeof(uint16_t)) && !memcmp(ph->prefix, pattern->prefix, ph->prefix_length * sizeof(uint16_t))) {
- if(!ph->alt && !pattern->alt) {
+ if(!ph->special && !pattern->special) {
match = 1;
- } else if(ph->alt == pattern->alt) {
+ } else if(ph->special == pattern->special) {
match = 1;
- for(i = 0; i < ph->alt; i++) {
- a1 = ph->alttable[i];
- a2 = pattern->alttable[i];
+ for(i = 0; i < ph->special; i++) {
+ a1 = ph->special_table[i];
+ a2 = pattern->special_table[i];
if(a1->num != a2->num) {
match = 0;
break;
}
- if(a1->chmode != a2->chmode) {
+ if(a1->negative != a2->negative) {
+ match = 0;
+ break;
+ }
+ if(a1->type != a2->type) {
match = 0;
break;
- } else if(a1->chmode) {
+ } else if(a1->type == AC_SPECIAL_ALT_CHAR) {
if(memcmp(a1->str, a2->str, a1->num)) {
match = 0;
break;
}
- } else {
+ } else if(a1->type == AC_SPECIAL_ALT_STR) {
while(a1 && a2) {
if((a1->len != a2->len) || memcmp(a1->str, a2->str, a1->len))
break;
@@@ -333,7 -295,7 +333,7 @@@ static int ac_maketrans(struct cli_matc
continue;
for(i = 0; i < 256; i++) {
child = node->trans[i];
- if(!child) {
+ if (!child || (!IS_FINAL(child) && IS_LEAF(child))) {
struct cli_ac_node *failtarget = node->fail;
while(IS_LEAF(failtarget) || !failtarget->trans[i])
failtarget = failtarget->fail;
@@@ -387,22 -349,22 +387,22 @@@ int cli_ac_init(struct cli_matcher *roo
}
#ifdef USE_MPOOL
-#define mpool_ac_free_alt(a, b) ac_free_alt(a, b)
-static void ac_free_alt(mpool_t *mempool, struct cli_ac_patt *p)
+#define mpool_ac_free_special(a, b) ac_free_special(a, b)
+static void ac_free_special(mpool_t *mempool, struct cli_ac_patt *p)
#else
-#define mpool_ac_free_alt(a, b) ac_free_alt(b)
-static void ac_free_alt(struct cli_ac_patt *p)
+#define mpool_ac_free_special(a, b) ac_free_special(b)
+static void ac_free_special(struct cli_ac_patt *p)
#endif
{
- uint16_t i;
- struct cli_ac_alt *a1, *a2;
+ unsigned int i;
+ struct cli_ac_special *a1, *a2;
- if(!p->alt)
+ if(!p->special)
return;
- for(i = 0; i < p->alt; i++) {
- a1 = p->alttable[i];
+ for(i = 0; i < p->special; i++) {
+ a1 = p->special_table[i];
while(a1) {
a2 = a1;
a1 = a1->next;
@@@ -411,7 -373,7 +411,7 @@@
mpool_free(mempool, a2);
}
}
- mpool_free(mempool, p->alttable);
+ mpool_free(mempool, p->special_table);
}
void cli_ac_free(struct cli_matcher *root)
@@@ -424,16 -386,15 +424,16 @@@
patt = root->ac_pattable[i];
mpool_free(root->mempool, patt->prefix ? patt->prefix : patt->pattern);
mpool_free(root->mempool, patt->virname);
- if(patt->offset)
- mpool_free(root->mempool, patt->offset);
- if(patt->alt)
- mpool_ac_free_alt(root->mempool, patt);
+ if(patt->special)
+ mpool_ac_free_special(root->mempool, patt);
mpool_free(root->mempool, patt);
}
if(root->ac_pattable)
mpool_free(root->mempool, root->ac_pattable);
+ if(root->ac_reloff)
+ mpool_free(root->mempool, root->ac_reloff);
+
for(i = 0; i < root->ac_nodes; i++) {
if(!IS_LEAF(root->ac_nodetable[i]))
mpool_free(root->mempool, root->ac_nodetable[i]->trans);
@@@ -687,84 -648,61 +687,84 @@@ int cli_ac_chklsig(const char *expr, co
* more than one of them can match at the current position.
*/
-#define AC_MATCH_CHAR(p,b) \
- switch(wc = p & CLI_MATCH_WILDCARD) { \
- case CLI_MATCH_CHAR: \
- if((unsigned char) p != b) \
- match = 0; \
- break; \
- \
- case CLI_MATCH_IGNORE: \
- break; \
- \
- case CLI_MATCH_ALTERNATIVE: \
- match = 0; \
- alt = pattern->alttable[altcnt]; \
- if(alt->chmode) { \
- for(j = 0; j < alt->num; j++) { \
- if(alt->str[j] == b) { \
- match = 1; \
- break; \
- } \
- } \
- } else { \
- while(alt) { \
- if(bp + alt->len <= length) { \
- if(!memcmp(&buffer[bp], alt->str, alt->len)) { \
- match = 1; \
- bp += alt->len - 1; \
- break; \
- } \
- } \
- alt = alt->next; \
- } \
- } \
- altcnt++; \
- break; \
- \
- case CLI_MATCH_NIBBLE_HIGH: \
- if((unsigned char) (p & 0x00f0) != (b & 0xf0)) \
- match = 0; \
- break; \
- \
- case CLI_MATCH_NIBBLE_LOW: \
- if((unsigned char) (p & 0x000f) != (b & 0x0f)) \
- match = 0; \
- break; \
- \
- default: \
- cli_errmsg("ac_findmatch: Unknown wildcard 0x%x\n", wc); \
- match = 0; \
- }
-
-inline static int ac_findmatch(const unsigned char *buffer, uint32_t offset, uint32_t length, const struct cli_ac_patt *pattern, uint32_t *end)
+#define AC_MATCH_CHAR(p,b) \
+ switch(wc = p & CLI_MATCH_WILDCARD) { \
+ case CLI_MATCH_CHAR: \
+ if((unsigned char) p != b) \
+ match = 0; \
+ break; \
+ \
+ case CLI_MATCH_IGNORE: \
+ break; \
+ \
+ case CLI_MATCH_SPECIAL: \
+ special = pattern->special_table[specialcnt]; \
+ match = special->negative; \
+ switch(special->type) { \
+ case AC_SPECIAL_ALT_CHAR: \
+ for(j = 0; j < special->num; j++) { \
+ if(special->str[j] == b) { \
+ match = !special->negative; \
+ break; \
+ } else if(special->str[j] > b) \
+ break; \
+ } \
+ break; \
+ \
+ case AC_SPECIAL_ALT_STR: \
+ while(special) { \
+ if(bp + special->len <= length) { \
+ if(!memcmp(&buffer[bp], special->str, special->len)) { \
+ match = !special->negative; \
+ bp += special->len - 1; \
+ break; \
+ } \
+ } \
+ special = special->next; \
+ } \
+ break; \
+ \
+ case AC_SPECIAL_LINE_MARKER: \
+ if(b == '\n') { \
+ match = !special->negative; \
+ } else if(b == '\r' && (bp + 1 < length && buffer[bp + 1] == '\n')) { \
+ bp++; \
+ match = !special->negative; \
+ } \
+ break; \
+ \
+ case AC_SPECIAL_BOUNDARY: \
+ if(boundary[b]) \
+ match = !special->negative; \
+ break; \
+ \
+ default: \
+ cli_errmsg("ac_findmatch: Unknown special\n"); \
+ match = 0; \
+ } \
+ specialcnt++; \
+ break; \
+ \
+ case CLI_MATCH_NIBBLE_HIGH: \
+ if((unsigned char) (p & 0x00f0) != (b & 0xf0)) \
+ match = 0; \
+ break; \
+ \
+ case CLI_MATCH_NIBBLE_LOW: \
+ if((unsigned char) (p & 0x000f) != (b & 0x0f)) \
+ match = 0; \
+ break; \
+ \
+ default: \
+ cli_errmsg("ac_findmatch: Unknown wildcard 0x%x\n", wc); \
+ match = 0; \
+ }
+
+inline static int ac_findmatch(const unsigned char *buffer, uint32_t offset, uint32_t fileoffset, uint32_t length, const struct cli_ac_patt *pattern, uint32_t *end)
{
uint32_t bp, match;
- uint16_t wc, i, j, altcnt = pattern->alt_pattern;
- struct cli_ac_alt *alt;
+ uint16_t wc, i, j, specialcnt = pattern->special_pattern;
+ struct cli_ac_special *special;
if((offset + pattern->length > length) || (pattern->prefix_length > offset))
@@@ -781,38 -719,6 +781,38 @@@
}
*end = bp;
+ if(pattern->boundary & AC_BOUNDARY_LEFT) {
+ match = !!(pattern->boundary & AC_BOUNDARY_LEFT_NEGATIVE);
+ if(!fileoffset || (offset && (boundary[buffer[offset - 1]] == 1 || boundary[buffer[offset - 1]] == 3)))
+ match = !match;
+ if(!match)
+ return 0;
+ }
+
+ if(pattern->boundary & AC_BOUNDARY_RIGHT) {
+ match = !!(pattern->boundary & AC_BOUNDARY_RIGHT_NEGATIVE);
+ if((length <= SCANBUFF) && (bp == length || boundary[buffer[bp]] >= 2))
+ match = !match;
+ if(!match)
+ return 0;
+ }
+
+ if(pattern->boundary & AC_LINE_MARKER_LEFT) {
+ match = !!(pattern->boundary & AC_LINE_MARKER_LEFT_NEGATIVE);
+ if(!fileoffset || (offset && (buffer[offset - 1] == '\n')))
+ match = !match;
+ if(!match)
+ return 0;
+ }
+
+ if(pattern->boundary & AC_LINE_MARKER_RIGHT) {
+ match = !!(pattern->boundary & AC_LINE_MARKER_RIGHT_NEGATIVE);
+ if((length <= SCANBUFF) && (bp == length || buffer[bp] == '\n' || (buffer[bp] == '\r' && bp + 1 < length && buffer[bp + 1] == '\n')))
+ match = !match;
+ if(!match)
+ return 0;
+ }
+
if(!(pattern->ch[1] & CLI_MATCH_IGNORE)) {
bp += pattern->ch_mindist[1];
for(i = pattern->ch_mindist[1]; i <= pattern->ch_maxdist[1]; i++) {
@@@ -829,7 -735,7 +829,7 @@@
}
if(pattern->prefix) {
- altcnt = 0;
+ specialcnt = 0;
bp = offset - pattern->prefix_length;
match = 1;
for(i = 0; i < pattern->prefix_length; i++) {
@@@ -862,9 -768,9 +862,9 @@@
return 1;
}
-int cli_ac_initdata(struct cli_ac_data *data, uint32_t partsigs, uint32_t lsigs, uint8_t tracklen)
+int cli_ac_initdata(struct cli_ac_data *data, uint32_t partsigs, uint32_t lsigs, uint32_t reloffsigs, uint8_t tracklen)
{
- unsigned int i;
+ unsigned int i, j;
if(!data) {
@@@ -872,26 -778,12 +872,26 @@@
return CL_ENULLARG;
}
- data->partsigs = partsigs;
+ cli_hashset_init_noalloc(&data->vinfo);
+ data->reloffsigs = reloffsigs;
+ if(reloffsigs) {
+ data->offset = (uint32_t *) cli_malloc(reloffsigs * 2 * sizeof(uint32_t));
+ if(!data->offset) {
+ cli_errmsg("cli_ac_init: Can't allocate memory for data->offset\n");
+ return CL_EMEM;
+ }
+ for(i = 0; i < reloffsigs * 2; i += 2)
+ data->offset[i] = CLI_OFF_NONE;
+ }
+
+ data->partsigs = partsigs;
if(partsigs) {
data->offmatrix = (int32_t ***) cli_calloc(partsigs, sizeof(int32_t **));
if(!data->offmatrix) {
cli_errmsg("cli_ac_init: Can't allocate memory for data->offmatrix\n");
+ if(reloffsigs)
+ free(data->offset);
return CL_EMEM;
}
}
@@@ -902,8 -794,6 +902,8 @@@
if(!data->lsigcnt) {
if(partsigs)
free(data->offmatrix);
+ if(reloffsigs)
+ free(data->offset);
cli_errmsg("cli_ac_init: Can't allocate memory for data->lsigcnt\n");
return CL_EMEM;
}
@@@ -912,82 -802,13 +912,82 @@@
free(data->lsigcnt);
if(partsigs)
free(data->offmatrix);
+ if(reloffsigs)
+ free(data->offset);
cli_errmsg("cli_ac_init: Can't allocate memory for data->lsigcnt[0]\n");
return CL_EMEM;
}
for(i = 1; i < lsigs; i++)
data->lsigcnt[i] = data->lsigcnt[0] + 64 * i;
- }
-
+
+ /* subsig offsets */
+ data->lsigsuboff = (uint32_t **) cli_malloc(lsigs * sizeof(uint32_t *));
+ if(!data->lsigsuboff) {
+ free(data->lsigcnt[0]);
+ free(data->lsigcnt);
+ if(partsigs)
+ free(data->offmatrix);
+ if(reloffsigs)
+ free(data->offset);
+ cli_errmsg("cli_ac_init: Can't allocate memory for data->lsigsuboff\n");
+ return CL_EMEM;
+ }
+ data->lsigsuboff[0] = (uint32_t *) cli_calloc(lsigs * 64, sizeof(uint32_t));
+ if(!data->lsigsuboff[0]) {
+ free(data->lsigsuboff);
+ free(data->lsigcnt[0]);
+ free(data->lsigcnt);
+ if(partsigs)
+ free(data->offmatrix);
+ if(reloffsigs)
+ free(data->offset);
+ cli_errmsg("cli_ac_init: Can't allocate memory for data->lsigsuboff[0]\n");
+ return CL_EMEM;
+ }
+ for(j = 0; j < 64; j++)
+ data->lsigsuboff[0][j] = CLI_OFF_NONE;
+ for(i = 1; i < lsigs; i++) {
+ data->lsigsuboff[i] = data->lsigsuboff[0] + 64 * i;
+ for(j = 0; j < 64; j++)
+ data->lsigsuboff[i][j] = CLI_OFF_NONE;
+ }
+ }
+ for (i=0;i<32;i++)
+ data->macro_lastmatch[i] = CLI_OFF_NONE;
+
+ return CL_SUCCESS;
+}
+
+int cli_ac_caloff(const struct cli_matcher *root, struct cli_ac_data *data, fmap_t *map)
+{
+ int ret;
+ unsigned int i;
+ struct cli_ac_patt *patt;
+ struct cli_target_info info;
+
+ if(map) {
+ memset(&info, 0, sizeof(info));
+ info.fsize = map->len;
+ }
+
+ info.exeinfo.vinfo = &data->vinfo;
+
+ for(i = 0; i < root->ac_reloff_num; i++) {
+ patt = root->ac_reloff[i];
+ if(!map) {
+ data->offset[patt->offset_min] = CLI_OFF_NONE;
+ } else if((ret = cli_caloff(NULL, &info, map, root->type, patt->offdata, &data->offset[patt->offset_min], &data->offset[patt->offset_max]))) {
+ cli_errmsg("cli_ac_caloff: Can't calculate relative offset in signature for %s\n", patt->virname);
+ if(info.exeinfo.section)
+ free(info.exeinfo.section);
+ return ret;
+ } else if((data->offset[patt->offset_min] != CLI_OFF_NONE) && (data->offset[patt->offset_min] + patt->length > info.fsize)) {
+ data->offset[patt->offset_min] = CLI_OFF_NONE;
+ }
+ }
+ if(map && info.exeinfo.section)
+ free(info.exeinfo.section);
+
return CL_SUCCESS;
}
@@@ -995,7 -816,6 +995,7 @@@ void cli_ac_freedata(struct cli_ac_dat
{
uint32_t i;
+ cli_hashset_destroy(&data->vinfo);
if(data && data->partsigs) {
for(i = 0; i < data->partsigs; i++) {
@@@ -1011,15 -831,8 +1011,15 @@@
if(data && data->lsigs) {
free(data->lsigcnt[0]);
free(data->lsigcnt);
+ free(data->lsigsuboff[0]);
+ free(data->lsigsuboff);
data->lsigs = 0;
}
+
+ if(data && data->reloffsigs) {
+ free(data->offset);
+ data->reloffsigs = 0;
+ }
}
inline static int ac_addtype(struct cli_matched_type **list, cli_file_t type, off_t offset, const cli_ctx *ctx)
@@@ -1054,63 -867,7 +1054,63 @@@
return CL_SUCCESS;
}
-int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, void **customdata, struct cli_ac_result **res, const struct cli_matcher *root, struct cli_ac_data *mdata, uint32_t offset, cli_file_t ftype, int fd, struct cli_matched_type **ftoffset, unsigned int mode, const cli_ctx *ctx)
+static inline void lsig_sub_matched(const struct cli_matcher *root, struct cli_ac_data *mdata, uint32_t lsigid1, uint32_t lsigid2, uint32_t realoff)
+{
+ if(mdata->lsigsuboff[lsigid1][lsigid2] == CLI_OFF_NONE)
+ mdata->lsigsuboff[lsigid1][lsigid2] = realoff;
+ else if (mdata->lsigcnt[lsigid1][lsigid2] == 1) {
+ /* Check that the previous match had a macro match following it at the
+ * correct distance. This check is only done after the 1st match.*/
+ const struct cli_lsig_tdb *tdb = &root->ac_lsigtable[lsigid1]->tdb;
+ const struct cli_ac_patt *macropt;
+ uint32_t id, last_macro_match, smin, smax, last_macroprev_match;
+ if (!tdb->macro_ptids)
+ return;
+ id = tdb->macro_ptids[lsigid2];
+ if (!id)
+ return;
+ macropt = root->ac_pattable[id];
+ smin = macropt->ch_mindist[0];
+ smax = macropt->ch_maxdist[0];
+ /* start of last macro match */
+ last_macro_match = mdata->macro_lastmatch[macropt->sigid];
+ /* start of previous lsig subsig match */
+ last_macroprev_match = mdata->lsigsuboff[lsigid1][lsigid2];
+ if (last_macro_match != CLI_OFF_NONE)
+ cli_dbgmsg("Checking macro match: %u + (%u - %u) == %u\n",
+ last_macroprev_match, smin, smax, last_macro_match);
+ if (last_macro_match == CLI_OFF_NONE ||
+ last_macroprev_match + smin > last_macro_match ||
+ last_macroprev_match + smax < last_macro_match) {
+ cli_dbgmsg("Canceled false lsig macro match\n");
+ /* Previous match was false, cancel it and make this match the first
+ * one.*/
+ mdata->lsigcnt[lsigid1][lsigid2] = 0;
+ mdata->lsigsuboff[lsigid1][lsigid2] = realoff;
+ } else {
+ /* mark the macro sig itself matched */
+ mdata->lsigcnt[lsigid1][lsigid2+1]++;
+ mdata->lsigsuboff[lsigid1][lsigid2+1] = last_macro_match;
+ }
+ }
+ if (realoff != CLI_OFF_NONE) {
+ mdata->lsigcnt[lsigid1][lsigid2]++;
+ }
+}
+
+void cli_ac_chkmacro(struct cli_matcher *root, struct cli_ac_data *data, unsigned lsigid1)
+{
+ const struct cli_lsig_tdb *tdb = &root->ac_lsigtable[lsigid1]->tdb;
+ unsigned i;
+ /* Loop through all subsigs, and if they are tied to macros check that the
+ * macro matched at a correct distance */
+ for (i=0;i<tdb->subsigs;i++) {
+ lsig_sub_matched(root, data, lsigid1, i, CLI_OFF_NONE);
+ }
+}
+
+
+int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, void **customdata, struct cli_ac_result **res, const struct cli_matcher *root, struct cli_ac_data *mdata, uint32_t offset, cli_file_t ftype, struct cli_matched_type **ftoffset, unsigned int mode, const cli_ctx *ctx)
{
struct cli_ac_node *current;
struct cli_ac_patt *patt, *pt;
@@@ -1118,83 -875,49 +1118,81 @@@
uint16_t j;
int32_t **offmatrix;
uint8_t found;
int type = CL_CLEAN;
struct cli_ac_result *newres;
if(!root->ac_root)
return CL_CLEAN;
- if(!mdata) {
+ if(!mdata && (root->ac_partsigs || root->ac_lsigs || root->ac_reloff_num)) {
cli_errmsg("cli_ac_scanbuff: mdata == NULL\n");
return CL_ENULLARG;
}
current = root->ac_root;
for(i = 0; i < length; i++) {
-
- if(IS_LEAF(current))
- current = current->fail;
-
current = current->trans[buffer[i]];
if(IS_FINAL(current)) {
patt = current->list;
+ if (IS_LEAF(current))
+ current = current->fail;
while(patt) {
bp = i + 1 - patt->depth;
- if(ac_findmatch(buffer, bp, length, patt, &matchend)) {
- pt = patt;
+ if(patt->offdata[0] != CLI_OFF_VERSION && patt->offdata[0] != CLI_OFF_MACRO && !patt->next_same && (patt->offset_min != CLI_OFF_ANY) && (!patt->sigid || patt->partno == 1)) {
+ if(patt->offset_min == CLI_OFF_NONE) {
+ patt = patt->next;
+ continue;
+ }
+ realoff = offset + bp - patt->prefix_length;
+ if(patt->offdata[0] == CLI_OFF_ABSOLUTE) {
+ if(patt->offset_max < realoff || patt->offset_min > realoff) {
+ patt = patt->next;
+ continue;
+ }
+ } else {
+ if(mdata->offset[patt->offset_min] == CLI_OFF_NONE || mdata->offset[patt->offset_max] < realoff || mdata->offset[patt->offset_min] > realoff) {
+ patt = patt->next;
+ continue;
+ }
+ }
+ }
+ pt = patt;
+ if(ac_findmatch(buffer, bp, offset + bp - patt->prefix_length, length, patt, &matchend)) {
while(pt) {
-
if((pt->type && !(mode & AC_SCAN_FT)) || (!pt->type && !(mode & AC_SCAN_VIR))) {
pt = pt->next_same;
continue;
}
-
realoff = offset + bp - pt->prefix_length;
-
- if(pt->offset && (!pt->sigid || pt->partno == 1)) {
- if((fd == -1 && !ftype) || !cli_validatesig(ftype, pt->offset, realoff, &info, fd, pt->virname)) {
+ if(patt->offdata[0] == CLI_OFF_VERSION) {
+ if(!cli_hashset_contains_maybe_noalloc(&mdata->vinfo, realoff)) {
pt = pt->next_same;
continue;
}
+ cli_dbgmsg("cli_ac_scanbuff: VI match for offset %x\n", realoff);
+ } else if (patt->offdata[0] == CLI_OFF_MACRO) {
+ mdata->macro_lastmatch[patt->offdata[1]] = realoff;
+ pt = pt->next_same;
+ continue;
+ } else if(pt->offset_min != CLI_OFF_ANY && (!pt->sigid || pt->partno == 1)) {
+ if(pt->offset_min == CLI_OFF_NONE) {
+ pt = pt->next_same;
+ continue;
+ }
+ if(pt->offdata[0] == CLI_OFF_ABSOLUTE) {
+ if(pt->offset_max < realoff || pt->offset_min > realoff) {
+ pt = pt->next_same;
+ continue;
+ }
+ } else {
+ if(mdata->offset[pt->offset_min] == CLI_OFF_NONE || mdata->offset[pt->offset_max] < realoff || mdata->offset[pt->offset_min] > realoff) {
+ pt = pt->next_same;
+ continue;
+ }
+ }
}
-
if(pt->sigid) { /* it's a partial signature */
if(pt->partno != 1 && (!mdata->offmatrix[pt->sigid - 1] || !mdata->offmatrix[pt->sigid - 1][pt->partno - 2][0])) {
@@@ -1206,6 -929,8 +1204,6 @@@
mdata->offmatrix[pt->sigid - 1] = cli_malloc(pt->parts * sizeof(int32_t *));
if(!mdata->offmatrix[pt->sigid - 1]) {
cli_errmsg("cli_ac_scanbuff: Can't allocate memory for mdata->offmatrix[%u]\n", pt->sigid - 1);
- if(info.exeinfo.section)
- free(info.exeinfo.section);
return CL_EMEM;
}
@@@ -1214,6 -939,8 +1212,6 @@@
cli_errmsg("cli_ac_scanbuff: Can't allocate memory for mdata->offmatrix[%u][0]\n", pt->sigid - 1);
free(mdata->offmatrix[pt->sigid - 1]);
mdata->offmatrix[pt->sigid - 1] = NULL;
- if(info.exeinfo.section)
- free(info.exeinfo.section);
return CL_EMEM;
}
memset(mdata->offmatrix[pt->sigid - 1][0], -1, pt->parts * (CLI_DEFAULT_AC_TRACKLEN + 1) * sizeof(int32_t));
@@@ -1252,17 -979,25 +1250,17 @@@
} else if(found && pt->partno == pt->parts) {
if(pt->type) {
- if(pt->type == CL_TYPE_IGNORED && (!pt->rtype || ftype == pt->rtype)) {
- if(info.exeinfo.section)
- free(info.exeinfo.section);
-
+ if(pt->type == CL_TYPE_IGNORED && (!pt->rtype || ftype == pt->rtype))
return CL_TYPE_IGNORED;
- }
if((pt->type > type || pt->type >= CL_TYPE_SFX || pt->type == CL_TYPE_MSEXE) && (!pt->rtype || ftype == pt->rtype)) {
cli_dbgmsg("Matched signature for file type %s\n", pt->virname);
type = pt->type;
- if(ftoffset && (!*ftoffset || (*ftoffset)->cnt < MAX_EMBEDDED_OBJ || type == CL_TYPE_ZIPSFX) && ((ftype == CL_TYPE_MSEXE && type >= CL_TYPE_SFX) || ((ftype == CL_TYPE_MSEXE || ftype == CL_TYPE_ZIP || ftype == CL_TYPE_MSOLE2) && type == CL_TYPE_MSEXE))) {
+ if(ftoffset && (!*ftoffset || (*ftoffset)->cnt < MAX_EMBEDDED_OBJ || type == CL_TYPE_ZIPSFX) && (type >= CL_TYPE_SFX || ((ftype == CL_TYPE_MSEXE || ftype == CL_TYPE_ZIP || ftype == CL_TYPE_MSOLE2) && type == CL_TYPE_MSEXE))) {
/* FIXME: we don't know which offset of the first part is the correct one */
- for(j = 1; j <= CLI_DEFAULT_AC_TRACKLEN && offmatrix[0][j] != -1; j++) {
- if(ac_addtype(ftoffset, type, offmatrix[pt->parts - 1][j], ctx)) {
- if(info.exeinfo.section)
- free(info.exeinfo.section);
+ for(j = 1; j <= CLI_DEFAULT_AC_TRACKLEN && offmatrix[0][j] != -1; j++)
+ if(ac_addtype(ftoffset, type, offmatrix[pt->parts - 1][j], ctx))
return CL_EMEM;
- }
- }
}
memset(offmatrix[0], -1, pt->parts * (CLI_DEFAULT_AC_TRACKLEN + 1) * sizeof(int32_t));
@@@ -1272,28 -1007,34 +1270,28 @@@
} else { /* !pt->type */
if(pt->lsigid[0]) {
- mdata->lsigcnt[pt->lsigid[1]][pt->lsigid[2]]++;
- pt = pt->next;
+ lsig_sub_matched(root, mdata, pt->lsigid[1], pt->lsigid[2], realoff);
+ pt = pt->next_same;
continue;
}
if(res) {
newres = (struct cli_ac_result *) malloc(sizeof(struct cli_ac_result));
- if(!newres) {
- if(info.exeinfo.section)
- free(info.exeinfo.section);
+ if(!newres)
return CL_EMEM;
newres->virname = pt->virname;
newres->customdata = pt->customdata;
newres->next = *res;
+ newres->offset = realoff;
*res = newres;
- pt = pt->next;
+ pt = pt->next_same;
continue;
} else {
if(virname)
*virname = pt->virname;
if(customdata)
*customdata = pt->customdata;
-
- if(info.exeinfo.section)
- free(info.exeinfo.section);
-
return CL_VIRUS;
}
}
@@@ -1301,42 -1042,54 +1299,42 @@@
} else { /* old type signature */
if(pt->type) {
- if(pt->type == CL_TYPE_IGNORED && (!pt->rtype || ftype == pt->rtype)) {
- if(info.exeinfo.section)
- free(info.exeinfo.section);
-
+ if(pt->type == CL_TYPE_IGNORED && (!pt->rtype || ftype == pt->rtype))
return CL_TYPE_IGNORED;
- }
+
if((pt->type > type || pt->type >= CL_TYPE_SFX || pt->type == CL_TYPE_MSEXE) && (!pt->rtype || ftype == pt->rtype)) {
cli_dbgmsg("Matched signature for file type %s at %u\n", pt->virname, realoff);
type = pt->type;
- if(ftoffset && (!*ftoffset || (*ftoffset)->cnt < MAX_EMBEDDED_OBJ || type == CL_TYPE_ZIPSFX) && ((ftype == CL_TYPE_MSEXE && type >= CL_TYPE_SFX) || ((ftype == CL_TYPE_MSEXE || ftype == CL_TYPE_ZIP || ftype == CL_TYPE_MSOLE2) && type == CL_TYPE_MSEXE))) {
+ if(ftoffset && (!*ftoffset || (*ftoffset)->cnt < MAX_EMBEDDED_OBJ || type == CL_TYPE_ZIPSFX) && (type >= CL_TYPE_SFX || ((ftype == CL_TYPE_MSEXE || ftype == CL_TYPE_ZIP || ftype == CL_TYPE_MSOLE2) && type == CL_TYPE_MSEXE))) {
- if(ac_addtype(ftoffset, type, realoff, ctx)) {
- if(info.exeinfo.section)
- free(info.exeinfo.section);
+ if(ac_addtype(ftoffset, type, realoff, ctx))
return CL_EMEM;
- }
}
}
} else {
if(pt->lsigid[0]) {
- mdata->lsigcnt[pt->lsigid[1]][pt->lsigid[2]]++;
- pt = pt->next;
+ lsig_sub_matched(root, mdata, pt->lsigid[1], pt->lsigid[2], realoff);
+ pt = pt->next_same;
continue;
}
if(res) {
newres = (struct cli_ac_result *) malloc(sizeof(struct cli_ac_result));
- if(!newres) {
- if(info.exeinfo.section)
- free(info.exeinfo.section);
+ if(!newres)
return CL_EMEM;
- }
newres->virname = pt->virname;
newres->customdata = pt->customdata;
+ newres->offset = realoff;
newres->next = *res;
*res = newres;
- pt = pt->next;
+ pt = pt->next_same;
continue;
} else {
if(virname)
*virname = pt->virname;
if(customdata)
*customdata = pt->customdata;
-
- if(info.exeinfo.section)
- free(info.exeinfo.section);
-
return CL_VIRUS;
}
}
@@@ -1349,14 -1102,12 +1347,14 @@@
}
}
return (mode & AC_SCAN_FT) ? type : CL_CLEAN;
}
+static int qcompare(const void *a, const void *b)
+{
+ return *(const unsigned char *)a - *(const unsigned char *)b;
+}
+
/* FIXME: clean up the code */
int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hexsig, uint32_t sigid, uint16_t parts, uint16_t partno, uint16_t rtype, uint16_t type, uint32_t mindist, uint32_t maxdist, const char *offset, const uint32_t *lsigid, unsigned int options)
{
@@@ -1364,7 -1115,7 +1362,7 @@@
char *pt, *pt2, *hex = NULL, *hexcpy = NULL;
uint16_t i, j, ppos = 0, pend, *dec, nzpos = 0;
uint8_t wprefix = 0, zprefix = 1, plen = 0, nzplen = 0;
- struct cli_ac_alt *newalt, *altpt, **newtable;
+ struct cli_ac_special *newspecial, *specialpt, **newtable;
int ret, error = CL_SUCCESS;
@@@ -1499,149 -1250,99 +1497,149 @@@
error = CL_EMALFDB;
break;
}
-
+ newspecial = (struct cli_ac_special *) mpool_calloc(root->mempool, 1, sizeof(struct cli_ac_special));
+ if(!newspecial) {
+ cli_errmsg("cli_ac_addsig: Can't allocate newspecial\n");
+ error = CL_EMEM;
+ break;
+ }
+ if(pt >= hexcpy + 2) {
+ if(pt[-2] == '!') {
+ newspecial->negative = 1;
+ pt[-2] = 0;
+ }
+ }
strcat(hexnew, start);
- strcat(hexnew, "()");
if(!(start = strchr(pt, ')'))) {
+ mpool_free(root->mempool, newspecial);
error = CL_EMALFDB;
break;
}
*start++ = 0;
-
- newalt = (struct cli_ac_alt *) mpool_calloc(root->mempool, 1, sizeof(struct cli_ac_alt));
- if(!newalt) {
- cli_errmsg("cli_ac_addsig: Can't allocate newalt\n");
- error = CL_EMEM;
+ if(!strlen(pt)) {
+ cli_errmsg("cli_ac_addsig: Empty block\n");
+ error = CL_EMALFDB;
break;
}
- new->alt++;
-
- newtable = (struct cli_ac_alt **) mpool_realloc(root->mempool, new->alttable, new->alt * sizeof(struct cli_ac_alt *));
+ if(!strcmp(pt, "B")) {
+ if(!*start) {
+ new->boundary |= AC_BOUNDARY_RIGHT;
+ if(newspecial->negative)
+ new->boundary |= AC_BOUNDARY_RIGHT_NEGATIVE;
+ mpool_free(root->mempool, newspecial);
+ continue;
+ } else if(pt - 1 == hexcpy) {
+ new->boundary |= AC_BOUNDARY_LEFT;
+ if(newspecial->negative)
+ new->boundary |= AC_BOUNDARY_LEFT_NEGATIVE;
+ mpool_free(root->mempool, newspecial);
+ continue;
+ }
+ } else if(!strcmp(pt, "L")) {
+ if(!*start) {
+ new->boundary |= AC_LINE_MARKER_RIGHT;
+ if(newspecial->negative)
+ new->boundary |= AC_LINE_MARKER_RIGHT_NEGATIVE;
+ mpool_free(root->mempool, newspecial);
+ continue;
+ } else if(pt - 1 == hexcpy) {
+ new->boundary |= AC_LINE_MARKER_LEFT;
+ if(newspecial->negative)
+ new->boundary |= AC_LINE_MARKER_LEFT_NEGATIVE;
+ mpool_free(root->mempool, newspecial);
+ continue;
+ }
+ }
+ strcat(hexnew, "()");
+ new->special++;
+ newtable = (struct cli_ac_special **) mpool_realloc(root->mempool, new->special_table, new->special * sizeof(struct cli_ac_special *));
if(!newtable) {
- new->alt--;
- mpool_free(root->mempool, newalt);
- cli_errmsg("cli_ac_addsig: Can't realloc new->alttable\n");
+ new->special--;
+ mpool_free(root->mempool, newspecial);
+ cli_errmsg("cli_ac_addsig: Can't realloc new->special_table\n");
error = CL_EMEM;
break;
}
- newtable[new->alt - 1] = newalt;
- new->alttable = newtable;
-
- for(i = 0; i < strlen(pt); i++)
- if(pt[i] == '|')
- newalt->num++;
-
- if(!newalt->num) {
- error = CL_EMALFDB;
- break;
- } else
- newalt->num++;
-
- if(3 * newalt->num - 1 == (uint16_t) strlen(pt)) {
- newalt->chmode = 1;
- newalt->str = (unsigned char *) mpool_malloc(root->mempool, newalt->num);
- if(!newalt->str) {
- cli_errmsg("cli_ac_addsig: Can't allocate newalt->str\n");
- error = CL_EMEM;
- break;
- }
- }
+ newtable[new->special - 1] = newspecial;
+ new->special_table = newtable;
+
+ if(!strcmp(pt, "B")) {
+ newspecial->type = AC_SPECIAL_BOUNDARY;
+ } else if(!strcmp(pt, "L")) {
+ newspecial->type = AC_SPECIAL_LINE_MARKER;
+ /*
+ } else if(strcmp(pt, "W")) {
+ newspecial->type = AC_SPECIAL_WHITE;
+ */
+ } else {
+ for(i = 0; i < strlen(pt); i++)
+ if(pt[i] == '|')
+ newspecial->num++;
- for(i = 0; i < newalt->num; i++) {
- if(!(h = cli_strtok(pt, i, "|"))) {
+ if(!newspecial->num) {
error = CL_EMALFDB;
break;
+ } else
+ newspecial->num++;
+
+ if(3 * newspecial->num - 1 == (uint16_t) strlen(pt)) {
+ newspecial->type = AC_SPECIAL_ALT_CHAR;
+ newspecial->str = (unsigned char *) mpool_malloc(root->mempool, newspecial->num);
+ if(!newspecial->str) {
+ cli_errmsg("cli_ac_addsig: Can't allocate newspecial->str\n");
+ error = CL_EMEM;
+ break;
+ }
+ } else {
+ newspecial->type = AC_SPECIAL_ALT_STR;
}
- if(!(c = cli_mpool_hex2str(root->mempool, h))) {
- free(h);
- error = CL_EMALFDB;
- break;
- }
+ for(i = 0; i < newspecial->num; i++) {
+ if(!(h = cli_strtok(pt, i, "|"))) {
+ error = CL_EMALFDB;
+ break;
+ }
- if(newalt->chmode) {
- newalt->str[i] = *c;
- mpool_free(root->mempool, c);
- } else {
- if(i) {
- altpt = newalt;
- while(altpt->next)
- altpt = altpt->next;
-
- altpt->next = (struct cli_ac_alt *) mpool_calloc(root->mempool, 1, sizeof(struct cli_ac_alt));
- if(!altpt->next) {
- cli_errmsg("cli_ac_addsig: Can't allocate altpt->next\n");
- error = CL_EMEM;
- free(c);
- free(h);
- break;
- }
+ if(!(c = cli_mpool_hex2str(root->mempool, h))) {
+ free(h);
+ error = CL_EMALFDB;
+ break;
+ }
- altpt->next->str = (unsigned char *) c;
- altpt->next->len = strlen(h) / 2;
+ if(newspecial->type == AC_SPECIAL_ALT_CHAR) {
+ newspecial->str[i] = *c;
+ mpool_free(root->mempool, c);
} else {
- newalt->str = (unsigned char *) c;
- newalt->len = strlen(h) / 2;
+ if(i) {
+ specialpt = newspecial;
+ while(specialpt->next)
+ specialpt = specialpt->next;
+
+ specialpt->next = (struct cli_ac_special *) mpool_calloc(root->mempool, 1, sizeof(struct cli_ac_special));
+ if(!specialpt->next) {
+ cli_errmsg("cli_ac_addsig: Can't allocate specialpt->next\n");
+ error = CL_EMEM;
+ free(c);
+ free(h);
+ break;
+ }
+ specialpt->next->str = (unsigned char *) c;
+ specialpt->next->len = strlen(h) / 2;
+ } else {
+ newspecial->str = (unsigned char *) c;
+ newspecial->len = strlen(h) / 2;
+ }
}
+ free(h);
}
+ if(newspecial->type == AC_SPECIAL_ALT_CHAR)
+ cli_qsort(newspecial->str, newspecial->num, sizeof(unsigned char), qcompare);
- free(h);
+ if(error)
+ break;
}
-
- if(error)
- break;
}
if(start)
@@@ -1651,9 -1352,9 +1649,9 @@@
free(hexcpy);
if(error) {
- if(new->alt) {
+ if(new->special) {
free(hex);
- mpool_ac_free_alt(root->mempool, new);
+ mpool_ac_free_special(root->mempool, new);
}
mpool_free(root->mempool, new);
return error;
@@@ -1662,8 -1363,8 +1660,8 @@@
new->pattern = cli_mpool_hex2ui(root->mempool, hex ? hex : hexsig);
if(new->pattern == NULL) {
- if(new->alt)
- mpool_ac_free_alt(root->mempool, new);
+ if(new->special)
+ mpool_ac_free_special(root->mempool, new);
mpool_free(root->mempool, new);
free(hex);
return CL_EMALFDB;
@@@ -1712,7 -1413,7 +1710,7 @@@
if(plen < root->ac_mindepth) {
cli_errmsg("cli_ac_addsig: Can't find a static subpattern of length %u\n", root->ac_mindepth);
- mpool_ac_free_alt(root->mempool, new);
+ mpool_ac_free_special(root->mempool, new);
mpool_free(root->mempool, new->pattern);
mpool_free(root->mempool, new);
return CL_EMALFDB;
@@@ -1724,17 -1425,17 +1722,17 @@@
new->length -= ppos;
for(i = 0; i < new->prefix_length; i++)
- if((new->prefix[i] & CLI_MATCH_WILDCARD) == CLI_MATCH_ALTERNATIVE)
- new->alt_pattern++;
+ if((new->prefix[i] & CLI_MATCH_WILDCARD) == CLI_MATCH_SPECIAL)
+ new->special_pattern++;
}
if(new->length > root->maxpatlen)
root->maxpatlen = new->length;
- new->virname = cli_mpool_virname(root->mempool, (char *) virname, options & CL_DB_OFFICIAL);
+ new->virname = cli_mpool_virname(root->mempool, virname, options & CL_DB_OFFICIAL);
if(!new->virname) {
mpool_free(root->mempool, new->prefix ? new->prefix : new->pattern);
- mpool_ac_free_alt(root->mempool, new);
+ mpool_ac_free_special(root->mempool, new);
mpool_free(root->mempool, new);
return CL_EMEM;
}
@@@ -1742,34 -1443,26 +1740,34 @@@
if(new->lsigid[0])
root->ac_lsigtable[new->lsigid[1]]->virname = new->virname;
- if(offset) {
- new->offset = cli_mpool_strdup(root->mempool, offset);
- if(!new->offset) {
- mpool_free(root->mempool, new->prefix ? new->prefix : new->pattern);
- mpool_ac_free_alt(root->mempool, new);
- mpool_free(root->mempool, new->virname);
- mpool_free(root->mempool, new);
- return CL_EMEM;
- }
+ ret = cli_caloff(offset, NULL, NULL, root->type, new->offdata, &new->offset_min, &new->offset_max);
+ if(ret != CL_SUCCESS) {
+ mpool_free(root->mempool, new->prefix ? new->prefix : new->pattern);
+ mpool_ac_free_special(root->mempool, new);
+ mpool_free(root->mempool, new->virname);
+ mpool_free(root->mempool, new);
+ return ret;
}
if((ret = cli_ac_addpatt(root, new))) {
mpool_free(root->mempool, new->prefix ? new->prefix : new->pattern);
mpool_free(root->mempool, new->virname);
- mpool_ac_free_alt(root->mempool, new);
- if(new->offset)
- mpool_free(root->mempool, new->offset);
+ mpool_ac_free_special(root->mempool, new);
mpool_free(root->mempool, new);
return ret;
}
+ if(new->offdata[0] != CLI_OFF_ANY && new->offdata[0] != CLI_OFF_ABSOLUTE && new->offdata[0] != CLI_OFF_MACRO) {
+ root->ac_reloff = (struct cli_ac_patt **) mpool_realloc2(root->mempool, root->ac_reloff, (root->ac_reloff_num + 1) * sizeof(struct cli_ac_patt *));
+ if(!root->ac_reloff) {
+ cli_errmsg("cli_ac_addsig: Can't allocate memory for root->ac_reloff\n");
+ return CL_EMEM;
+ }
+ root->ac_reloff[root->ac_reloff_num] = new;
+ new->offset_min = root->ac_reloff_num * 2;
+ new->offset_max = new->offset_min + 1;
+ root->ac_reloff_num++;
+ }
+
return CL_SUCCESS;
}
diff --combined libclamav/matcher.c
index f445782,c061450..ecd925f
--- a/libclamav/matcher.c
+++ b/libclamav/matcher.c
@@@ -1,5 -1,5 +1,5 @@@
/*
- * Copyright (C) 2007-2008 Sourcefire, Inc.
+ * Copyright (C) 2007-2009 Sourcefire, Inc.
*
* Authors: Tomasz Kojm
*
@@@ -44,12 -44,23 +44,28 @@@
#include "str.h"
#include "cltypes.h"
#include "default.h"
+#include "macho.h"
+#include "fmap.h"
+#include "pe_icons.h"
+#include "regex/regex.h"
+ static inline int matcher_run(const struct cli_matcher *root,
+ const unsigned char *buffer, uint32_t length,
+ const char **virname, struct cli_ac_data *mdata,
+ uint32_t offset,
+ cli_file_t ftype,
- int desc,
+ struct cli_matched_type **ftoffset,
- unsigned int acmode)
++ unsigned int acmode,
++ fmap_t *map,
++ struct cli_bm_off *offdata)
+ {
+ int ret;
- if (root->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, root, offset, ftype, desc)) != CL_VIRUS)
- ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, root, mdata, offset, ftype, desc, ftoffset, acmode, NULL);
++ if (root->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, NULL, root, offset, map, offdata)) != CL_VIRUS)
++ ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, root, mdata, offset, ftype, ftoffset, acmode, NULL);
+ return ret;
+ }
+
-int cli_scanbuff(const unsigned char *buffer, uint32_t length, cli_ctx *ctx, cli_file_t ftype, struct cli_ac_data **acdata)
+int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, cli_ctx *ctx, cli_file_t ftype, struct cli_ac_data **acdata)
{
int ret = CL_CLEAN;
unsigned int i;
@@@ -76,11 -87,10 +92,10 @@@
if(troot) {
- if(!acdata && (ret = cli_ac_initdata(&mdata, troot->ac_partsigs, troot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
+ if(!acdata && (ret = cli_ac_initdata(&mdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
return ret;
- if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, NULL, troot, offset, NULL, NULL)) != CL_VIRUS)
- ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, troot, acdata ? (acdata[0]) : (&mdata), offset, ftype, NULL, AC_SCAN_VIR, NULL);
- ret = matcher_run(troot, buffer, length, virname, acdata ? (acdata[0]): (&mdata), 0, ftype, -1, NULL, AC_SCAN_VIR);
++ ret = matcher_run(troot, buffer, length, virname, acdata ? (acdata[0]): (&mdata), offset, ftype, NULL, AC_SCAN_VIR, NULL, NULL);
if(!acdata)
cli_ac_freedata(&mdata);
@@@ -89,11 -99,10 +104,10 @@@
return ret;
}
- if(!acdata && (ret = cli_ac_initdata(&mdata, groot->ac_partsigs, groot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
+ if(!acdata && (ret = cli_ac_initdata(&mdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
return ret;
- if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, NULL, groot, offset, NULL, NULL)) != CL_VIRUS)
- ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, groot, acdata ? (acdata[1]) : (&mdata), offset, ftype, NULL, AC_SCAN_VIR, NULL);
- ret = matcher_run(groot, buffer, length, virname, acdata ? (acdata[1]): (&mdata), 0, ftype, -1, NULL, AC_SCAN_VIR);
++ ret = matcher_run(groot, buffer, length, virname, acdata ? (acdata[1]): (&mdata), offset, ftype, NULL, AC_SCAN_VIR, NULL, NULL);
if(!acdata)
cli_ac_freedata(&mdata);
@@@ -101,285 -110,171 +115,285 @@@
return ret;
}
-off_t cli_caloff(const char *offstr, struct cli_target_info *info, int fd, cli_file_t ftype, int *ret, unsigned int *maxshift)
+/*
+ * offdata[0]: type
+ * offdata[1]: offset value
+ * offdata[2]: max shift
+ * offdata[3]: section number
+ */
+int cli_caloff(const char *offstr, struct cli_target_info *info, fmap_t *map, unsigned int target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max)
{
- int (*einfo)(int, struct cli_exe_info *) = NULL;
+ int (*einfo)(fmap_t *, struct cli_exe_info *) = NULL;
+ char offcpy[65];
unsigned int n, val;
- const char *pt;
- off_t pos, offset;
+ char *pt;
+ if(!info) { /* decode offset string */
+ if(!offstr) {
+ cli_errmsg("cli_caloff: offstr == NULL\n");
+ return CL_ENULLARG;
+ }
- *ret = 0;
+ if(!strcmp(offstr, "*")) {
+ offdata[0] = *offset_max = *offset_min = CLI_OFF_ANY;
+ return CL_SUCCESS;
+ }
- if(!strncmp(offstr, "EP", 2) || offstr[0] == 'S') {
+ if(strlen(offstr) > 64) {
+ cli_errmsg("cli_caloff: Offset string too long\n");
+ return CL_EMALFDB;
+ }
+ strcpy(offcpy, offstr);
- if(info->status == -1) {
- *ret = -1;
- return 0;
+ if((pt = strchr(offcpy, ','))) {
+ if(!cli_isnumber(pt + 1)) {
+ cli_errmsg("cli_caloff: Invalid offset shift value\n");
+ return CL_EMALFDB;
+ }
+ offdata[2] = atoi(pt + 1);
+ *pt = 0;
+ } else {
+ offdata[2] = 0;
+ }
- } else if(!info->status) {
+ *offset_max = *offset_min = CLI_OFF_NONE;
- if(ftype == CL_TYPE_MSEXE)
- einfo = cli_peheader;
- else if(ftype == CL_TYPE_ELF)
- einfo = cli_elfheader;
+ if(!strncmp(offcpy, "EP+", 3) || !strncmp(offcpy, "EP-", 3)) {
+ if(offcpy[2] == '+')
+ offdata[0] = CLI_OFF_EP_PLUS;
+ else
+ offdata[0] = CLI_OFF_EP_MINUS;
- if(einfo) {
- if((pos = lseek(fd, 0, SEEK_CUR)) == -1) {
- cli_dbgmsg("Invalid descriptor\n");
- info->status = *ret = -1;
- return 0;
+ if(!cli_isnumber(&offcpy[3])) {
+ cli_errmsg("cli_caloff: Invalid offset value\n");
+ return CL_EMALFDB;
+ }
+ offdata[1] = atoi(&offcpy[3]);
+
+ } else if(offcpy[0] == 'S') {
+ if(!strncmp(offstr, "SL+", 3)) {
+ offdata[0] = CLI_OFF_SL_PLUS;
+ if(!cli_isnumber(&offcpy[3])) {
+ cli_errmsg("cli_caloff: Invalid offset value\n");
+ return CL_EMALFDB;
}
+ offdata[1] = atoi(&offcpy[3]);
+
+ } else if(sscanf(offcpy, "S%u+%u", &n, &val) == 2) {
+ offdata[0] = CLI_OFF_SX_PLUS;
+ offdata[1] = val;
+ offdata[3] = n;
+ } else {
+ cli_errmsg("cli_caloff: Invalid offset string\n");
+ return CL_EMALFDB;
+ }
- lseek(fd, 0, SEEK_SET);
- if(einfo(fd, &info->exeinfo)) {
- lseek(fd, pos, SEEK_SET);
- info->status = *ret = -1;
- return 0;
- }
- lseek(fd, pos, SEEK_SET);
- info->status = 1;
+ } else if(!strncmp(offcpy, "EOF-", 4)) {
+ offdata[0] = CLI_OFF_EOF_MINUS;
+ if(!cli_isnumber(&offcpy[4])) {
+ cli_errmsg("cli_caloff: Invalid offset value\n");
+ return CL_EMALFDB;
}
+ offdata[1] = atoi(&offcpy[4]);
+ } else if(!strncmp(offcpy, "VI", 2)) {
+ /* versioninfo */
+ offdata[0] = CLI_OFF_VERSION;
+ } else if (strchr(offcpy, '$')) {
+ if (sscanf(offcpy, "$%u$", &n) != 1) {
+ cli_errmsg("cli_caloff: Invalid macro($) in offset: %s\n", offcpy);
+ return CL_EMALFDB;
+ }
+ if (n >= 32) {
+ cli_errmsg("cli_caloff: at most 32 macro groups supported\n");
+ return CL_EMALFDB;
+ }
+ offdata[0] = CLI_OFF_MACRO;
+ offdata[1] = n;
+ } else {
+ offdata[0] = CLI_OFF_ABSOLUTE;
+ if(!cli_isnumber(offcpy)) {
+ cli_errmsg("cli_caloff: Invalid offset value\n");
+ return CL_EMALFDB;
+ }
+ *offset_min = offdata[1] = atoi(offcpy);
+ *offset_max = *offset_min + offdata[2];
}
- }
-
- if((pt = strchr(offstr, ',')))
- *maxshift = atoi(++pt);
-
- if(isdigit(offstr[0])) {
- return atoi(offstr);
-
- } else if(info->status == 1 && (!strncmp(offstr, "EP+", 3) || !strncmp(offstr, "EP-", 3))) {
- if(offstr[2] == '+')
- return info->exeinfo.ep + atoi(offstr + 3);
- else
- return info->exeinfo.ep - atoi(offstr + 3);
-
- } else if(info->status == 1 && offstr[0] == 'S') {
-
- if(!strncmp(offstr, "SL", 2) && info->exeinfo.section[info->exeinfo.nsections - 1].rsz) {
-
- if(sscanf(offstr, "SL+%u", &val) != 1) {
- *ret = -1;
- return 0;
+ if(offdata[0] != CLI_OFF_ANY && offdata[0] != CLI_OFF_ABSOLUTE &&
+ offdata[0] != CLI_OFF_EOF_MINUS && offdata[0] != CLI_OFF_MACRO) {
+ if(target != 1 && target != 6 && target != 9) {
+ cli_errmsg("cli_caloff: Invalid offset type for target %u\n", target);
+ return CL_EMALFDB;
}
+ }
- offset = val + info->exeinfo.section[info->exeinfo.nsections - 1].raw;
+ } else {
+ /* calculate relative offsets */
+ if(info->status == -1) {
+ *offset_min = CLI_OFF_NONE;
+ if(offset_max)
+ *offset_max = CLI_OFF_NONE;
+ return CL_SUCCESS;
+ }
- } else {
+ if((offdata[0] == CLI_OFF_EOF_MINUS)) {
+ if(!info->fsize)
+ info->fsize = map->len;
+ } else if(!info->status) {
+ if(target == 1)
+ einfo = cli_peheader;
+ else if(target == 6)
+ einfo = cli_elfheader;
+ else if(target == 9)
+ einfo = cli_machoheader;
- if(sscanf(offstr, "S%u+%u", &n, &val) != 2) {
- *ret = -1;
- return 0;
+ if(!einfo) {
+ cli_errmsg("cli_caloff: Invalid offset/filetype\n");
+ return CL_EMALFDB;
}
- if(n >= info->exeinfo.nsections || !info->exeinfo.section[n].rsz) {
- *ret = -1;
- return 0;
+ if(einfo(map, &info->exeinfo)) {
+ /* einfo *may* fail */
+ info->status = -1;
+ *offset_min = CLI_OFF_NONE;
+ if(offset_max)
+ *offset_max = CLI_OFF_NONE;
+ return CL_SUCCESS;
}
-
- offset = val + info->exeinfo.section[n].raw;
+ info->status = 1;
}
- return offset;
+ switch(offdata[0]) {
+ case CLI_OFF_EOF_MINUS:
+ *offset_min = info->fsize - offdata[1];
+ break;
+
+ case CLI_OFF_EP_PLUS:
+ *offset_min = info->exeinfo.ep + offdata[1];
+ break;
- } else if(!strncmp(offstr, "EOF-", 4)) {
- struct stat sb;
+ case CLI_OFF_EP_MINUS:
+ *offset_min = info->exeinfo.ep - offdata[1];
+ break;
- if(!info->fsize) {
- if(fstat(fd, &sb) == -1) {
- info->status = *ret = -1;
- return 0;
- }
- info->fsize = sb.st_size;
+ case CLI_OFF_SL_PLUS:
+ *offset_min = info->exeinfo.section[info->exeinfo.nsections - 1].raw + offdata[1];
+ break;
+
+ case CLI_OFF_SX_PLUS:
+ if(offdata[3] >= info->exeinfo.nsections)
+ *offset_min = CLI_OFF_NONE;
+ else
+ *offset_min = info->exeinfo.section[offdata[3]].raw + offdata[1];
+ break;
+ case CLI_OFF_VERSION:
+ *offset_min = *offset_max = CLI_OFF_ANY;
+ break;
+ default:
+ cli_errmsg("cli_caloff: Not a relative offset (type: %u)\n", offdata[0]);
+ return CL_EARG;
}
- return info->fsize - atoi(offstr + 4);
+ if(offset_max) {
+ if(*offset_min != CLI_OFF_NONE)
+ *offset_max = *offset_min + offdata[2];
+ else
+ *offset_max = CLI_OFF_NONE;
+ }
}
- *ret = -1;
- return 0;
+ return CL_SUCCESS;
}
-static int cli_checkfp(int fd, const struct cl_engine *engine)
+int cli_checkfp(int fd, cli_ctx *ctx)
{
unsigned char *digest;
+ char md5[33];
+ unsigned int i;
const char *virname;
+ off_t pos;
+ struct stat sb;
+ const struct cli_bm_patt *patt = NULL;
+
+ if((pos = lseek(fd, 0, SEEK_CUR)) == -1) {
+ cli_errmsg("cli_checkfp(): lseek() failed\n");
+ return 0;
+ }
+
+ lseek(fd, 0, SEEK_SET);
+
+ if(ctx->engine->md5_fp) {
+ if(fstat(fd, &sb) == -1) {
+ cli_errmsg("cli_checkfp(): fstat(%d) failed\n", fd);
+ lseek(fd, pos, SEEK_SET);
+ return 0;
+ }
- if(engine->md5_fp) {
if(!(digest = cli_md5digest(fd))) {
cli_errmsg("cli_checkfp(): Can't generate MD5 checksum\n");
+ lseek(fd, pos, SEEK_SET);
return 0;
}
- if(cli_bm_scanbuff(digest, 16, &virname, engine->md5_fp, 0, 0, -1) == CL_VIRUS) {
- cli_dbgmsg("Eliminated false positive match (fp sig: %s)\n", virname);
+ if(cli_bm_scanbuff(digest, 16, &virname, &patt, ctx->engine->md5_fp, 0, NULL, NULL) == CL_VIRUS && patt->filesize == sb.st_size) {
+ cli_dbgmsg("cli_checkfp(): Found false positive detection (fp sig: %s)\n", virname);
free(digest);
+ lseek(fd, pos, SEEK_SET);
return 1;
}
+
+ for(i = 0; i < 16; i++)
+ sprintf(md5 + i * 2, "%02x", digest[i]);
+ md5[32] = 0;
+ cli_dbgmsg("FP SIGNATURE: %s:%u:%s\n", md5, (unsigned int) sb.st_size, *ctx->virname ? *ctx->virname : "Name");
+
free(digest);
}
+ lseek(fd, pos, SEEK_SET);
return 0;
}
-int cli_validatesig(cli_file_t ftype, const char *offstr, off_t fileoff, struct cli_target_info *info, int desc, const char *virname)
+static int matchicon(cli_ctx *ctx, const char *grp1, const char *grp2)
{
- off_t offset;
- int ret;
- unsigned int maxshift = 0;
-
+ icon_groupset iconset;
- if(offstr && desc != -1) {
- offset = cli_caloff(offstr, info, desc, ftype, &ret, &maxshift);
+ cli_icongroupset_init(&iconset);
+ cli_icongroupset_add(grp1 ? grp1 : "*", &iconset, 0, ctx);
+ cli_icongroupset_add(grp2 ? grp2 : "*", &iconset, 1, ctx);
+ return cli_match_icon(&iconset, ctx);
+}
- if(ret == -1) {
- cli_dbgmsg("cli_validatesig: Can't calculate offset for signature %s\n", virname);
- return 0;
- }
+int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode)
+{
+ int ret = CL_EMEM;
+ fmap_t *map = *ctx->fmap;
- if(maxshift) {
- if((fileoff < offset) || (fileoff > offset + (off_t) maxshift)) {
- /* cli_dbgmsg("Signature offset: %lu, expected: [%lu..%lu] (%s)\n", (unsigned long int) fileoff, (unsigned long int) offset, (unsigned long int) (offset + maxshift), virname); */
- return 0;
- }
- } else if(fileoff != offset) {
- /* cli_dbgmsg("Signature offset: %lu, expected: %lu (%s)\n", (unsigned long int) fileoff, (unsigned long int) offset, virname); */
- return 0;
- }
+ if((*ctx->fmap = fmap(desc, 0, 0))) {
+ ret = cli_fmap_scandesc(ctx, ftype, ftonly, ftoffset, acmode, NULL);
+ funmap(*ctx->fmap);
}
-
- return 1;
+ *ctx->fmap = map;
+ return ret;
}
-int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode)
+
+int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode, unsigned char *refhash)
{
- unsigned char *buffer, *buff, *endbl, *upt;
+ unsigned char *buff;
int ret = CL_CLEAN, type = CL_CLEAN, bytes;
- unsigned int i, evalcnt;
- uint32_t buffersize, length, maxpatlen, shift = 0, offset = 0;
+ unsigned int i, evalcnt, bm_offmode = 0;
+ uint32_t maxpatlen, offset = 0;
uint64_t evalids;
struct cli_ac_data gdata, tdata;
+ struct cli_bm_off toff;
cli_md5_ctx md5ctx;
unsigned char digest[16];
struct cli_matcher *groot = NULL, *troot = NULL;
-
+ fmap_t *map = *ctx->fmap;
+ int (*einfo)(fmap_t *, struct cli_exe_info *) = NULL;
+ struct cli_exe_info exeinfo;
if(!ctx->engine) {
cli_errmsg("cli_scandesc: engine == NULL\n");
@@@ -410,195 -305,140 +424,195 @@@
maxpatlen = groot->maxpatlen;
}
- /* prepare the buffer */
- buffersize = maxpatlen + SCANBUFF;
- if(!(buffer = (unsigned char *) cli_calloc(buffersize, sizeof(unsigned char)))) {
- cli_dbgmsg("cli_scandesc(): unable to cli_calloc(%u)\n", buffersize);
- return CL_EMEM;
- }
-
- if(!ftonly && (ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
- return ret;
+ if(!ftonly)
+ if((ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(groot, &gdata, map)))
+ return ret;
if(troot) {
- if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
+ if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(troot, &tdata, map))) {
+ if(!ftonly)
+ cli_ac_freedata(&gdata);
return ret;
+ }
+ if(troot->bm_offmode) {
+ if(map->len >= CLI_DEFAULT_BM_OFFMODE_FSIZE) {
+ if((ret = cli_bm_initoff(troot, &toff, map))) {
+ if(!ftonly)
+ cli_ac_freedata(&gdata);
+ cli_ac_freedata(&tdata);
+ return ret;
+ }
+ bm_offmode = 1;
+ }
+ }
}
- if(!ftonly && ctx->engine->md5_hdb)
+ if(!refhash && !ftonly && ctx->engine->md5_hdb)
cli_md5_init(&md5ctx);
- buff = buffer;
- buff += maxpatlen; /* pointer to read data block */
- endbl = buff + SCANBUFF - maxpatlen; /* pointer to the last block
- * length of maxpatlen
- */
-
- upt = buff;
- while((bytes = cli_readn(desc, buff + shift, SCANBUFF - shift)) > 0) {
-
+ while(offset < map->len) {
+ bytes = MIN(map->len - offset, SCANBUFF);
+ if(!(buff = fmap_need_off_once(map, offset, bytes)))
+ break;
if(ctx->scanned)
*ctx->scanned += bytes / CL_COUNT_PRECISION;
- length = shift + bytes;
- if(upt == buffer)
- length += maxpatlen;
-
if(troot) {
- if(troot->ac_only || (ret = cli_bm_scanbuff(buff, bytes, ctx->virname, NULL, troot, offset, map, bm_offmode ? &toff : NULL)) != CL_VIRUS)
- ret = cli_ac_scanbuff(buff, bytes, ctx->virname, NULL, NULL, troot, &tdata, offset, ftype, ftoffset, acmode, NULL);
- ret = matcher_run(troot, upt, length, ctx->virname, &tdata, offset, ftype, desc, NULL, acmode);
++ ret = matcher_run(troot, buff, bytes, ctx->virname, &tdata, offset, ftype, ftoffset, acmode, map, bm_offmode ? &toff : NULL);
+
if(ret == CL_VIRUS) {
if(!ftonly)
cli_ac_freedata(&gdata);
cli_ac_freedata(&tdata);
-
- lseek(desc, 0, SEEK_SET);
- if(cli_checkfp(desc, ctx->engine))
- return CL_CLEAN;
- else
- return CL_VIRUS;
+ if(bm_offmode)
+ cli_bm_freeoff(&toff);
+ return CL_VIRUS;
}
}
if(!ftonly) {
- if(groot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, groot, offset, ftype, desc)) != CL_VIRUS)
- ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, groot, &gdata, offset, ftype, desc, ftoffset, acmode, NULL);
-
+ if(groot->ac_only || (ret = cli_bm_scanbuff(buff, bytes, ctx->virname, NULL, groot, offset, map, NULL)) != CL_VIRUS)
+ ret = cli_ac_scanbuff(buff, bytes, ctx->virname, NULL, NULL, groot, &gdata, offset, ftype, ftoffset, acmode, NULL);
if(ret == CL_VIRUS) {
- free(buffer);
cli_ac_freedata(&gdata);
- if(troot)
+ if(troot) {
cli_ac_freedata(&tdata);
- lseek(desc, 0, SEEK_SET);
- if(cli_checkfp(desc, ctx->engine))
- return CL_CLEAN;
- else
- return CL_VIRUS;
-
+ if(bm_offmode)
+ cli_bm_freeoff(&toff);
+ }
+ return CL_VIRUS;
} else if((acmode & AC_SCAN_FT) && ret >= CL_TYPENO) {
if(ret > type)
type = ret;
}
- if(ctx->engine->md5_hdb)
- cli_md5_update(&md5ctx, buff + shift, bytes);
+ if(!refhash && ctx->engine->md5_hdb)
+ cli_md5_update(&md5ctx, buff + maxpatlen * (offset!=0), bytes - maxpatlen * (offset!=0));
}
- if(bytes + shift == SCANBUFF) {
- memmove(buffer, endbl, maxpatlen);
- offset += SCANBUFF;
-
- if(upt == buff) {
- upt = buffer;
- offset -= maxpatlen;
- }
-
- shift = 0;
-
- } else {
- shift += bytes;
- }
+ if(bytes < SCANBUFF) break;
+ offset += bytes - maxpatlen;
}
- free(buffer);
+#define LSIGEVAL(xroot, xdata) \
+ for(i = 0; i < xroot->ac_lsigs; i++) { \
+ evalcnt = 0; \
+ evalids = 0; \
+ cli_ac_chkmacro(xroot, &xdata, i);\
+ if(cli_ac_chklsig(xroot->ac_lsigtable[i]->logic, xroot->ac_lsigtable[i]->logic + strlen(xroot->ac_lsigtable[i]->logic), xdata.lsigcnt[i], &evalcnt, &evalids, 0) == 1) { \
+ if(xroot->ac_lsigtable[i]->tdb.container && xroot->ac_lsigtable[i]->tdb.container[0] != ctx->container_type) \
+ continue; \
+ if(xroot->ac_lsigtable[i]->tdb.filesize && (xroot->ac_lsigtable[i]->tdb.filesize[0] > map->len || xroot->ac_lsigtable[i]->tdb.filesize[1] < map->len)) \
+ continue; \
+ \
+ if(xroot->ac_lsigtable[i]->tdb.ep || xroot->ac_lsigtable[i]->tdb.nos) { \
+ einfo = NULL; \
+ if(xroot->type == 1) \
+ einfo = cli_peheader; \
+ else if(xroot->type == 6) \
+ einfo = cli_elfheader; \
+ else if(xroot->type == 9) \
+ einfo = cli_machoheader; \
+ if(!einfo) \
+ continue; \
+ memset(&exeinfo, 0, sizeof(exeinfo)); \
+ if(einfo(map, &exeinfo)) \
+ continue; \
+ if(exeinfo.section) \
+ free(exeinfo.section); \
+ if(xroot->ac_lsigtable[i]->tdb.ep && (xroot->ac_lsigtable[i]->tdb.ep[0] > exeinfo.ep || xroot->ac_lsigtable[i]->tdb.ep[1] < exeinfo.ep)) \
+ continue; \
+ if(xroot->ac_lsigtable[i]->tdb.nos && (xroot->ac_lsigtable[i]->tdb.nos[0] > exeinfo.nsections || xroot->ac_lsigtable[i]->tdb.nos[1] < exeinfo.nsections)) \
+ continue; \
+ } \
+ if(xroot->ac_lsigtable[i]->tdb.icongrp1 || xroot->ac_lsigtable[i]->tdb.icongrp2) { \
+ if(matchicon(ctx, xroot->ac_lsigtable[i]->tdb.icongrp1, xroot->ac_lsigtable[i]->tdb.icongrp2) == CL_VIRUS) { \
+ ret = CL_VIRUS; \
+ break; \
+ } else { \
+ continue; \
+ } \
+ } \
+ if(!xroot->ac_lsigtable[i]->bc_idx) { \
+ if(ctx->virname) \
+ *ctx->virname = xroot->ac_lsigtable[i]->virname; \
+ ret = CL_VIRUS; \
+ break; \
+ } \
+ if(cli_bytecode_runlsig(ctx, &ctx->engine->bcs, xroot->ac_lsigtable[i]->bc_idx, ctx->virname, xdata.lsigcnt[i], xdata.lsigsuboff[i], map) == CL_VIRUS) { \
+ ret = CL_VIRUS; \
+ break; \
+ } \
+ } \
+ }
if(troot) {
- for(i = 0; i < troot->ac_lsigs; i++) {
- evalcnt = 0;
- evalids = 0;
- if(cli_ac_chklsig(troot->ac_lsigtable[i]->logic, troot->ac_lsigtable[i]->logic + strlen(troot->ac_lsigtable[i]->logic), tdata.lsigcnt[i], &evalcnt, &evalids, 0) == 1) {
- if(ctx->virname)
- *ctx->virname = troot->ac_lsigtable[i]->virname;
- ret = CL_VIRUS;
- break;
- }
- }
+ LSIGEVAL(troot, tdata);
cli_ac_freedata(&tdata);
+ if(bm_offmode)
+ cli_bm_freeoff(&toff);
}
if(groot) {
- if(ret != CL_VIRUS) for(i = 0; i < groot->ac_lsigs; i++) {
- evalcnt = 0;
- evalids = 0;
- if(cli_ac_chklsig(groot->ac_lsigtable[i]->logic, groot->ac_lsigtable[i]->logic + strlen(groot->ac_lsigtable[i]->logic), gdata.lsigcnt[i], &evalcnt, &evalids, 0) == 1) {
- if(ctx->virname)
- *ctx->virname = groot->ac_lsigtable[i]->virname;
- ret = CL_VIRUS;
- break;
- }
- }
+ if(ret != CL_VIRUS)
+ LSIGEVAL(groot, gdata);
cli_ac_freedata(&gdata);
}
- if(ret == CL_VIRUS) {
- lseek(desc, 0, SEEK_SET);
- if(cli_checkfp(desc, ctx->engine))
- return CL_CLEAN;
- else
- return CL_VIRUS;
- }
+ if(ret == CL_VIRUS)
+ return CL_VIRUS;
if(!ftonly && ctx->engine->md5_hdb) {
- cli_md5_final(digest, &md5ctx);
- if(cli_bm_scanbuff(digest, 16, ctx->virname, ctx->engine->md5_hdb, 0, 0, -1) == CL_VIRUS && (cli_bm_scanbuff(digest, 16, NULL, ctx->engine->md5_fp, 0, 0, -1) != CL_VIRUS))
+ const struct cli_bm_patt *patt;
+ if(!refhash) {
+ cli_md5_final(digest, &md5ctx);
+ refhash = digest;
+ }
+ if(cli_bm_scanbuff(refhash, 16, ctx->virname, &patt, ctx->engine->md5_hdb, 0, NULL, NULL) == CL_VIRUS && patt->filesize == map->len && (cli_bm_scanbuff(refhash, 16, NULL, &patt, ctx->engine->md5_fp, 0, NULL, NULL) != CL_VIRUS || patt->filesize != map->len))
return CL_VIRUS;
}
return (acmode & AC_SCAN_FT) ? type : CL_CLEAN;
}
+
+int cli_matchmeta(cli_ctx *ctx, const char *fname, size_t fsizec, size_t fsizer, int encrypted, int filepos, int res1, void *res2)
+{
+ const struct cli_cdb *cdb;
+
+ if(!(cdb = ctx->engine->cdb))
+ return CL_CLEAN;
+
+ do {
+ if(cdb->ctype != CL_TYPE_ANY && cdb->ctype != ctx->container_type)
+ continue;
+
+ if(cdb->encrypted != 2 && cdb->encrypted != encrypted)
+ continue;
+
+ if(cdb->res1 && (cdb->ctype == CL_TYPE_ZIP || cdb->ctype == CL_TYPE_RAR) && cdb->res1 != res1)
+ continue;
+
+#define CDBRANGE(field, val) \
+ if(field[0] != CLI_OFF_ANY) { \
+ if(field[0] == field[1] && field[0] != val) \
+ continue; \
+ else if(field[0] != field[1] && ((field[0] && field[0] > val) ||\
+ (field[1] && field[1] < val))) \
+ continue; \
+ }
+
+ CDBRANGE(cdb->csize, ctx->container_size);
+ CDBRANGE(cdb->fsizec, fsizec);
+ CDBRANGE(cdb->fsizer, fsizer);
+ CDBRANGE(cdb->filepos, filepos);
+
+ if(cdb->name.re_magic && (!fname || cli_regexec(&cdb->name, fname, 0, NULL, 0) == REG_NOMATCH))
+ continue;
+
+ *ctx->virname = cdb->virname;
+ return CL_VIRUS;
+
+ } while((cdb = cdb->next));
+
+ return CL_CLEAN;
+}
--
Debian repository for ClamAV
More information about the Pkg-clamav-commits
mailing list