static int hash_match(const struct regex_matcher *rlist, const char *host, size_t hlen, const char *path, size_t plen, int *prefix_matched) { const char *virname; #if 0 char s[1024]; strncpy(s, host, hlen); strncpy(s+hlen, path, plen); s[hlen+plen] = '\0'; cli_dbgmsg("hash lookup for: %s\n",s); #endif UNUSEDPARAM(prefix_matched); if(rlist->sha256_hashes.bm_patterns) { const char hexchars[] = "0123456789ABCDEF"; unsigned char h[65]; unsigned char sha256_dig[32]; unsigned i; void *sha256; sha256 = cl_hash_init("sha256"); if (!(sha256)) return CL_EMEM; cl_update_hash(sha256, (void *)host, hlen); cl_update_hash(sha256, (void *)path, plen); cl_finish_hash(sha256, sha256_dig); for(i=0;i<32;i++) { h[2*i] = hexchars[sha256_dig[i]>>4]; h[2*i+1] = hexchars[sha256_dig[i]&0xf]; } h[64]='\0'; cli_dbgmsg("Looking up hash %s for %s(%u)%s(%u)\n", h, host, (unsigned)hlen, path, (unsigned)plen); #if 0 if (prefix_matched) { if (cli_bm_scanbuff(sha256_dig, 4, &virname, NULL, &rlist->hostkey_prefix,0,NULL,NULL,NULL) == CL_VIRUS) { cli_dbgmsg("prefix matched\n"); *prefix_matched = 1; } else return CL_SUCCESS; } #endif if (cli_bm_scanbuff(sha256_dig, 32, &virname, NULL, &rlist->sha256_hashes,0,NULL,NULL,NULL) == CL_VIRUS) { cli_dbgmsg("This hash matched: %s\n", h); switch(*virname) { case 'W': cli_dbgmsg("Hash is whitelisted, skipping\n"); break; case '1': return CL_PHISH_HASH1; case '2': return CL_PHISH_HASH2; default: return CL_PHISH_HASH0; } } } return CL_SUCCESS; }
END_TEST START_TEST (test_bm_scanbuff_allscan) { struct cli_matcher *root; const char *virname = NULL; int ret; root = ctx.engine->root[0]; fail_unless(root != NULL, "root == NULL"); #ifdef USE_MPOOL root->mempool = mpool_create(); #endif ret = cli_bm_init(root); fail_unless(ret == CL_SUCCESS, "cli_bm_init() failed"); ret = cli_parse_add(root, "Sig1", "deadbabe", 0, 0, 0, "*", 0, NULL, 0); fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed"); ret = cli_parse_add(root, "Sig2", "deadbeef", 0, 0, 0, "*", 0, NULL, 0); fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed"); ret = cli_parse_add(root, "Sig3", "babedead", 0, 0, 0, "*", 0, NULL, 0); fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed"); ret = cli_bm_scanbuff((const unsigned char*)"blah\xde\xad\xbe\xef", 12, &virname, NULL, root, 0, NULL, NULL, NULL); fail_unless(ret == CL_VIRUS, "cli_bm_scanbuff() failed"); fail_unless(!strncmp(virname, "Sig2", 4), "Incorrect signature matched in cli_bm_scanbuff()\n"); }
END_TEST START_TEST (test_bm_scanbuff) { struct cli_matcher *root; const char *virname = NULL; int ret; root = (struct cli_matcher *) cli_calloc(1, sizeof(struct cli_matcher)); fail_unless(root != NULL, "root == NULL"); #ifdef USE_MPOOL root->mempool = mpool_create(); #endif ret = cli_bm_init(root); fail_unless(ret == CL_SUCCESS, "cli_bm_init() failed"); ret = cli_parse_add(root, "Sig1", "deadbabe", 0, 0, NULL, 0, NULL, 0); fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed"); ret = cli_parse_add(root, "Sig2", "deadbeef", 0, 0, NULL, 0, NULL, 0); fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed"); ret = cli_parse_add(root, "Sig3", "babedead", 0, 0, NULL, 0, NULL, 0); fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed"); ret = cli_bm_scanbuff("blah\xde\xad\xbe\xef", 12, &virname, root, 0, 0, -1); fail_unless(ret == CL_VIRUS, "cli_bm_scanbuff() failed"); fail_unless(!strncmp(virname, "Sig2", 4), "Incorrect signature matched in cli_bm_scanbuff()\n"); cli_bm_free(root); #ifdef USE_MPOOL mpool_destroy(root->mempool); #endif free(root); }
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, const struct cli_target_info *tinfo, cli_file_t ftype, struct cli_matched_type **ftoffset, unsigned int acmode, unsigned int pcremode, struct cli_ac_result **acres, fmap_t *map, struct cli_bm_off *offdata, struct cli_pcre_off *poffdata, cli_ctx *ctx) { int ret, saved_ret = CL_CLEAN; int32_t pos = 0; struct filter_match_info info; uint32_t orig_length, orig_offset; const unsigned char* orig_buffer; unsigned int viruses_found = 0; if (root->filter) { if(filter_search_ext(root->filter, buffer, length, &info) == -1) { /* for safety always scan last maxpatlen bytes */ pos = length - root->maxpatlen - 1; if (pos < 0) pos = 0; PERF_LOG_FILTER(pos, length, root->type); } else { /* must not cut buffer for 64[4-4]6161, because we must be able to check * 64! */ pos = info.first_match - root->maxpatlen - 1; if (pos < 0) pos = 0; PERF_LOG_FILTER(pos, length, root->type); } } else { PERF_LOG_FILTER(0, length, root->type); } orig_length = length; orig_buffer = buffer; orig_offset = offset; length -= pos; buffer += pos; offset += pos; if (!root->ac_only) { PERF_LOG_TRIES(0, 1, length); if (root->bm_offmode) { /* Don't use prefiltering for BM offset mode, since BM keeps tracks * of offsets itself, and doesn't work if we skip chunks of input * data */ ret = cli_bm_scanbuff(orig_buffer, orig_length, virname, NULL, root, orig_offset, tinfo, offdata, ctx); } else { ret = cli_bm_scanbuff(buffer, length, virname, NULL, root, offset, tinfo, offdata, ctx); } if (ret != CL_CLEAN) { if (ret != CL_VIRUS) return ret; /* else (ret == CL_VIRUS) */ if (SCAN_ALL) viruses_found = 1; else { cli_append_virus(ctx, *virname); return ret; } } } PERF_LOG_TRIES(acmode, 0, length); ret = cli_ac_scanbuff(buffer, length, virname, NULL, acres, root, mdata, offset, ftype, ftoffset, acmode, ctx); if (ret != CL_CLEAN) { if (ret == CL_VIRUS) { if (SCAN_ALL) viruses_found = 1; else { cli_append_virus(ctx, *virname); return ret; } } else if (ret > CL_TYPENO && acmode & AC_SCAN_VIR) saved_ret = ret; else return ret; } /* due to logical triggered, pcres cannot be evaluated until after full subsig matching */ /* cannot save pcre execution state without possible evasion; must scan entire buffer */ /* however, scanning the whole buffer may require the whole buffer being loaded into memory */ #if HAVE_PCRE if (root->pcre_metas) { int rc; uint64_t maxfilesize; if (map && (pcremode == PCRE_SCAN_FMAP)) { if (offset+length >= map->len) { /* check that scanned map does not exceed pcre maxfilesize limit */ maxfilesize = (uint64_t)cl_engine_get_num(ctx->engine, CL_ENGINE_PCRE_MAX_FILESIZE, &rc); if (rc != CL_SUCCESS) return rc; if (maxfilesize && (map->len > maxfilesize)) { cli_dbgmsg("matcher_run: pcre max filesize (map) exceeded (limit: %llu, needed: %llu)\n", (long long unsigned)maxfilesize, (long long unsigned)map->len); return CL_EMAXSIZE; } cli_dbgmsg("matcher_run: performing regex matching on full map: %u+%u(%u) >= %zu\n", offset, length, offset+length, map->len); buffer = fmap_need_off_once(map, 0, map->len); if (!buffer) return CL_EMEM; /* scan the full buffer */ ret = cli_pcre_scanbuf(buffer, map->len, virname, acres, root, mdata, poffdata, ctx); } } else if (pcremode == PCRE_SCAN_BUFF) { /* check that scanned buffer does not exceed pcre maxfilesize limit */ maxfilesize = (uint64_t)cl_engine_get_num(ctx->engine, CL_ENGINE_PCRE_MAX_FILESIZE, &rc); if (rc != CL_SUCCESS) return rc; if (maxfilesize && (length > maxfilesize)) { cli_dbgmsg("matcher_run: pcre max filesize (buf) exceeded (limit: %llu, needed: %u)\n", (long long unsigned)maxfilesize, length); return CL_EMAXSIZE; } cli_dbgmsg("matcher_run: performing regex matching on buffer with no map: %u+%u(%u)\n", offset, length, offset+length); /* scan the specified buffer */ ret = cli_pcre_scanbuf(buffer, length, virname, acres, root, mdata, poffdata, ctx); } } #endif /* HAVE_PCRE */ /* end experimental fragment */ if (ctx && !SCAN_ALL && ret == CL_VIRUS) cli_append_virus(ctx, *virname); if (ctx && SCAN_ALL && viruses_found) return CL_VIRUS; if (saved_ret && ret == CL_CLEAN) return saved_ret; return ret; }
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, const struct cli_target_info *tinfo, cli_file_t ftype, struct cli_matched_type **ftoffset, unsigned int acmode, struct cli_ac_result **acres, fmap_t *map, struct cli_bm_off *offdata, uint32_t *viroffset, cli_ctx *ctx) { int ret; int32_t pos = 0; struct filter_match_info info; uint32_t orig_length, orig_offset; const unsigned char* orig_buffer; unsigned int viruses_found = 0; if (root->filter) { if(filter_search_ext(root->filter, buffer, length, &info) == -1) { /* for safety always scan last maxpatlen bytes */ pos = length - root->maxpatlen - 1; if (pos < 0) pos = 0; PERF_LOG_FILTER(pos, length, root->type); } else { /* must not cut buffer for 64[4-4]6161, because we must be able to check * 64! */ pos = info.first_match - root->maxpatlen - 1; if (pos < 0) pos = 0; PERF_LOG_FILTER(pos, length, root->type); } } else { PERF_LOG_FILTER(0, length, root->type); } orig_length = length; orig_buffer = buffer; orig_offset = offset; length -= pos; buffer += pos; offset += pos; if (!root->ac_only) { PERF_LOG_TRIES(0, 1, length); if (root->bm_offmode) { /* Don't use prefiltering for BM offset mode, since BM keeps tracks * of offsets itself, and doesn't work if we skip chunks of input * data */ ret = cli_bm_scanbuff(orig_buffer, orig_length, virname, NULL, root, orig_offset, tinfo, offdata, viroffset); } else { ret = cli_bm_scanbuff(buffer, length, virname, NULL, root, offset, tinfo, offdata, viroffset); } if (ret == CL_VIRUS) { if (ctx) { cli_append_virus(ctx, *virname); if (SCAN_ALL) viruses_found++; else return ret; } } } PERF_LOG_TRIES(acmode, 0, length); ret = cli_ac_scanbuff(buffer, length, virname, NULL, acres, root, mdata, offset, ftype, ftoffset, acmode, ctx); if (ctx && !SCAN_ALL && ret == CL_VIRUS) cli_append_virus(ctx, *virname); if (ctx && SCAN_ALL && viruses_found) return CL_VIRUS; return ret; }
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, const struct cli_target_info *tinfo, cli_file_t ftype, struct cli_matched_type **ftoffset, unsigned int acmode, struct cli_ac_result **acres, fmap_t *map, struct cli_bm_off *offdata, uint32_t *viroffset, cli_ctx *ctx) { cli_infomsg(NULL,"DEBUG: in matcher_run\n");//CHR int ret; int32_t pos = 0; struct filter_match_info info; uint32_t orig_length, orig_offset; const unsigned char* orig_buffer; unsigned int viruses_found = 0; if (root->filter) { cli_infomsg(NULL,"DEBUG: has filter\n");//CHR // CHR function filter_search_ext will do pre-matchon prefix for a given pattern if(filter_search_ext(root->filter, buffer, length, &info) == -1) { cli_infomsg(NULL,"DEBUG: filter and in if\n");//CHR /* for safety always scan last maxpatlen bytes */ pos = length - root->maxpatlen - 1; if (pos < 0) pos = 0; PERF_LOG_FILTER(pos, length, root->type); } else { // CHR FSM match cli_infomsg(NULL,"DEBUG: filter and in else\n");//CHR /* must not cut buffer for 64[4-4]6161, because we must be able to check * 64! */ //CHR if first_match is far more beyond max pattern length //CHR we need to move forward a little bit to speed up the following scan pos = info.first_match - root->maxpatlen - 1; cli_infomsg(NULL,"DEBUG: pos=%d\n",pos);//CHR if (pos < 0) pos = 0; PERF_LOG_FILTER(pos, length, root->type); } } else { PERF_LOG_FILTER(0, length, root->type); } orig_length = length; orig_buffer = buffer; orig_offset = offset; //CHR pos is 0 in this case length -= pos; buffer += pos; offset += pos; if (!root->ac_only) { cli_infomsg(NULL,"DEBUG: !ac_only, bm scan first\n");//CHR PERF_LOG_TRIES(0, 1, length); if (root->bm_offmode) { /* Don't use prefiltering for BM offset mode, since BM keeps tracks * of offsets itself, and doesn't work if we skip chunks of input * data */ cli_infomsg(NULL,"DEBUG: scan in bm_offmode=1 mode\n"); //CHR ret = cli_bm_scanbuff(orig_buffer, orig_length, virname, NULL, root, orig_offset, tinfo, offdata, viroffset); } else { cli_infomsg(NULL,"DEBUG: scan in bm_offmode=0 mode\n"); //CHR cli_infomsg(NULL,"DEBUG: pass into cli_bm_scanbuff with length=%d,offset=%d\n",length,offset);//CHR ret = cli_bm_scanbuff(buffer, length, virname, NULL, root, offset, tinfo, offdata, viroffset); } if (ret == CL_VIRUS) { cli_infomsg(NULL,"DEBUG: bm scan find virus, won't do ac scan\n");//CHR if (ctx) { cli_append_virus(ctx, *virname); if (SCAN_ALL) viruses_found++; else return ret; } } } PERF_LOG_TRIES(acmode, 0, length); cli_infomsg(NULL,"DEBUG: ac scan\n");//CHR ret = cli_ac_scanbuff(buffer, length, virname, NULL, acres, root, mdata, offset, ftype, ftoffset, acmode, NULL); if (ctx && ret == CL_VIRUS) cli_append_virus(ctx, *virname); if (ctx && SCAN_ALL && viruses_found) return CL_VIRUS; return ret; }