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, viruses_found = 0; struct cli_ac_data mdata; struct cli_matcher *groot, *troot = NULL; const char *virname = NULL; const struct cl_engine *engine=ctx->engine; if(!engine) { cli_errmsg("cli_scanbuff: engine == NULL\n"); return CL_ENULLARG; } groot = engine->root[0]; /* generic signatures */ if(ftype) { for(i = 1; i < CLI_MTARGETS; i++) { if(cli_mtargets[i].target == ftype) { troot = engine->root[i]; break; } } } if(troot) { if(!acdata && (ret = cli_ac_initdata(&mdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN))) return ret; ret = matcher_run(troot, buffer, length, &virname, acdata ? (acdata[0]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, NULL, *ctx->fmap, NULL, NULL, ctx); if(!acdata) cli_ac_freedata(&mdata); if(ret == CL_EMEM) return ret; if(ret == CL_VIRUS) { viruses_found = 1; if(ctx && !SCAN_ALL) { return ret; } } } virname = NULL; if(!acdata && (ret = cli_ac_initdata(&mdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN))) return ret; ret = matcher_run(groot, buffer, length, &virname, acdata ? (acdata[1]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, NULL, *ctx->fmap, NULL, NULL, ctx); if(!acdata) cli_ac_freedata(&mdata); if(viruses_found) return CL_VIRUS; return ret; }
int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode, struct cli_ac_result **acres, unsigned char *refhash) { const unsigned char *buff; int ret = CL_CLEAN, type = CL_CLEAN, bytes, compute_hash[CLI_HASH_AVAIL_TYPES]; unsigned int i = 0, j = 0, bm_offmode = 0; uint32_t maxpatlen, offset = 0; struct cli_ac_data gdata, tdata; struct cli_bm_off toff; struct cli_pcre_off gpoff, tpoff; unsigned char digest[CLI_HASH_AVAIL_TYPES][32]; struct cli_matcher *groot = NULL, *troot = NULL; struct cli_target_info info; fmap_t *map = *ctx->fmap; struct cli_matcher *hdb, *fp; const char *virname = NULL; uint32_t viruses_found = 0; void *md5ctx, *sha1ctx, *sha256ctx; if(!ctx->engine) { cli_errmsg("cli_scandesc: engine == NULL\n"); return CL_ENULLARG; } md5ctx = cl_hash_init("md5"); if (!(md5ctx)) return CL_EMEM; sha1ctx = cl_hash_init("sha1"); if (!(sha1ctx)) { cl_hash_destroy(md5ctx); return CL_EMEM; } sha256ctx = cl_hash_init("sha256"); if (!(sha256ctx)) { cl_hash_destroy(md5ctx); cl_hash_destroy(sha1ctx); return CL_EMEM; } if(!ftonly) groot = ctx->engine->root[0]; /* generic signatures */ if(ftype) { for(i = 1; i < CLI_MTARGETS; i++) { for (j = 0; j < cli_mtargets[i].target_count; ++j) { if(cli_mtargets[i].target[j] == ftype) { troot = ctx->engine->root[i]; break; } } if (troot) break; } } if(ftonly) { if(!troot) { cl_hash_destroy(md5ctx); cl_hash_destroy(sha1ctx); cl_hash_destroy(sha256ctx); return CL_CLEAN; } maxpatlen = troot->maxpatlen; } else { if(troot) maxpatlen = MAX(troot->maxpatlen, groot->maxpatlen); else maxpatlen = groot->maxpatlen; } cli_targetinfo(&info, i, map); 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, &info))) { if(info.exeinfo.section) free(info.exeinfo.section); cli_hashset_destroy(&info.exeinfo.vinfo); cl_hash_destroy(md5ctx); cl_hash_destroy(sha1ctx); cl_hash_destroy(sha256ctx); return ret; } if((ret = cli_pcre_recaloff(groot, &gpoff, &info, ctx))) { cli_ac_freedata(&gdata); if(info.exeinfo.section) free(info.exeinfo.section); cli_hashset_destroy(&info.exeinfo.vinfo); cl_hash_destroy(md5ctx); cl_hash_destroy(sha1ctx); cl_hash_destroy(sha256ctx); return ret; } } if(troot) { 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, &info))) { if(!ftonly) { cli_ac_freedata(&gdata); cli_pcre_freeoff(&gpoff); } if(info.exeinfo.section) free(info.exeinfo.section); cli_hashset_destroy(&info.exeinfo.vinfo); cl_hash_destroy(md5ctx); cl_hash_destroy(sha1ctx); cl_hash_destroy(sha256ctx); return ret; } if(troot->bm_offmode) { if(map->len >= CLI_DEFAULT_BM_OFFMODE_FSIZE) { if((ret = cli_bm_initoff(troot, &toff, &info))) { if(!ftonly) { cli_ac_freedata(&gdata); cli_pcre_freeoff(&gpoff); } cli_ac_freedata(&tdata); if(info.exeinfo.section) free(info.exeinfo.section); cli_hashset_destroy(&info.exeinfo.vinfo); cl_hash_destroy(md5ctx); cl_hash_destroy(sha1ctx); cl_hash_destroy(sha256ctx); return ret; } bm_offmode = 1; } } if ((ret = cli_pcre_recaloff(troot, &tpoff, &info, ctx))) { if(!ftonly) { cli_ac_freedata(&gdata); cli_pcre_freeoff(&gpoff); } cli_ac_freedata(&tdata); if(bm_offmode) cli_bm_freeoff(&toff); if(info.exeinfo.section) free(info.exeinfo.section); cli_hashset_destroy(&info.exeinfo.vinfo); cl_hash_destroy(md5ctx); cl_hash_destroy(sha1ctx); cl_hash_destroy(sha256ctx); return ret; } } hdb = ctx->engine->hm_hdb; fp = ctx->engine->hm_fp; if(!ftonly && hdb) { if(!refhash) { if(cli_hm_have_size(hdb, CLI_HASH_MD5, map->len) || cli_hm_have_size(fp, CLI_HASH_MD5, map->len) || cli_hm_have_wild(hdb, CLI_HASH_MD5) || cli_hm_have_wild(fp, CLI_HASH_MD5)) { compute_hash[CLI_HASH_MD5] = 1; } else { compute_hash[CLI_HASH_MD5] = 0; } } else { compute_hash[CLI_HASH_MD5] = 0; memcpy(digest[CLI_HASH_MD5], refhash, 16); } if(cli_hm_have_size(hdb, CLI_HASH_SHA1, map->len) || cli_hm_have_wild(hdb, CLI_HASH_SHA1) || cli_hm_have_size(fp, CLI_HASH_SHA1, map->len) || cli_hm_have_wild(fp, CLI_HASH_SHA1) ) { compute_hash[CLI_HASH_SHA1] = 1; } else { compute_hash[CLI_HASH_SHA1] = 0; } if(cli_hm_have_size(hdb, CLI_HASH_SHA256, map->len) || cli_hm_have_wild(hdb, CLI_HASH_SHA256) || cli_hm_have_size(fp, CLI_HASH_SHA256, map->len) || cli_hm_have_wild(fp, CLI_HASH_SHA256)) { compute_hash[CLI_HASH_SHA256] = 1; } else { compute_hash[CLI_HASH_SHA256] = 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; if(troot) { virname = NULL; ret = matcher_run(troot, buff, bytes, &virname, &tdata, offset, &info, ftype, ftoffset, acmode, PCRE_SCAN_FMAP, acres, map, bm_offmode ? &toff : NULL, &tpoff, ctx); if (virname) { /* virname already appended by matcher_run */ viruses_found = 1; } if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) { if(!ftonly) { cli_ac_freedata(&gdata); cli_pcre_freeoff(&gpoff); } cli_ac_freedata(&tdata); if(bm_offmode) cli_bm_freeoff(&toff); cli_pcre_freeoff(&tpoff); if(info.exeinfo.section) free(info.exeinfo.section); cli_hashset_destroy(&info.exeinfo.vinfo); cl_hash_destroy(md5ctx); cl_hash_destroy(sha1ctx); cl_hash_destroy(sha256ctx); return ret; } } if(!ftonly) { virname = NULL; ret = matcher_run(groot, buff, bytes, &virname, &gdata, offset, &info, ftype, ftoffset, acmode, PCRE_SCAN_FMAP, acres, map, NULL, &gpoff, ctx); if (virname) { /* virname already appended by matcher_run */ viruses_found = 1; } if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) { cli_ac_freedata(&gdata); cli_pcre_freeoff(&gpoff); if(troot) { cli_ac_freedata(&tdata); if(bm_offmode) cli_bm_freeoff(&toff); cli_pcre_freeoff(&tpoff); } if(info.exeinfo.section) free(info.exeinfo.section); cli_hashset_destroy(&info.exeinfo.vinfo); cl_hash_destroy(md5ctx); cl_hash_destroy(sha1ctx); cl_hash_destroy(sha256ctx); return ret; } else if((acmode & AC_SCAN_FT) && ret >= CL_TYPENO) { if(ret > type) type = ret; } /* if (bytes <= (maxpatlen * (offset!=0))), it means the last window finished the file hashing * * since the last window is responsible for adding intersection between windows (maxpatlen) */ if(hdb && (bytes > (maxpatlen * (offset!=0)))) { const void *data = buff + maxpatlen * (offset!=0); uint32_t data_len = bytes - maxpatlen * (offset!=0); if(compute_hash[CLI_HASH_MD5]) cl_update_hash(md5ctx, (void *)data, data_len); if(compute_hash[CLI_HASH_SHA1]) cl_update_hash(sha1ctx, (void *)data, data_len); if(compute_hash[CLI_HASH_SHA256]) cl_update_hash(sha256ctx, (void *)data, data_len); } } if(bytes < SCANBUFF) break; offset += bytes - maxpatlen; } if(!ftonly && hdb) { enum CLI_HASH_TYPE hashtype, hashtype2; if(compute_hash[CLI_HASH_MD5]) { cl_finish_hash(md5ctx, digest[CLI_HASH_MD5]); md5ctx = NULL; } if(refhash) compute_hash[CLI_HASH_MD5] = 1; if(compute_hash[CLI_HASH_SHA1]) { cl_finish_hash(sha1ctx, digest[CLI_HASH_SHA1]); sha1ctx = NULL; } if(compute_hash[CLI_HASH_SHA256]) { cl_finish_hash(sha256ctx, digest[CLI_HASH_SHA256]); sha256ctx = NULL; } virname = NULL; for(hashtype = CLI_HASH_MD5; hashtype < CLI_HASH_AVAIL_TYPES; hashtype++) { const char * virname_w = NULL; int found = 0; /* If no hash, skip to next type */ if(!compute_hash[hashtype]) continue; /* Do hash scan */ if((ret = cli_hm_scan(digest[hashtype], map->len, &virname, hdb, hashtype)) == CL_VIRUS) { found += 1; } if(!found || SCAN_ALL) { if ((ret = cli_hm_scan_wild(digest[hashtype], &virname_w, hdb, hashtype)) == CL_VIRUS) found += 2; } /* If found, do immediate hash-only FP check */ if (found && fp) { for(hashtype2 = CLI_HASH_MD5; hashtype2 < CLI_HASH_AVAIL_TYPES; hashtype2++) { if(!compute_hash[hashtype2]) continue; if(cli_hm_scan(digest[hashtype2], map->len, NULL, fp, hashtype2) == CL_VIRUS) { found = 0; ret = CL_CLEAN; break; } else if(cli_hm_scan_wild(digest[hashtype2], NULL, fp, hashtype2) == CL_VIRUS) { found = 0; ret = CL_CLEAN; break; } } } /* If matched size-based hash ... */ if (found % 2) { viruses_found = 1; cli_append_virus(ctx, virname); if (!SCAN_ALL) break; virname = NULL; } /* If matched size-agnostic hash ... */ if (found > 1) { viruses_found = 1; cli_append_virus(ctx, virname_w); if (!SCAN_ALL) break; } } } cl_hash_destroy(md5ctx); cl_hash_destroy(sha1ctx); cl_hash_destroy(sha256ctx); if(troot) { if(ret != CL_VIRUS || SCAN_ALL) ret = cli_exp_eval(ctx, troot, &tdata, &info, (const char *)refhash); if (ret == CL_VIRUS) viruses_found++; cli_ac_freedata(&tdata); if(bm_offmode) cli_bm_freeoff(&toff); cli_pcre_freeoff(&tpoff); } if(groot) { if(ret != CL_VIRUS || SCAN_ALL) ret = cli_exp_eval(ctx, groot, &gdata, &info, (const char *)refhash); cli_ac_freedata(&gdata); cli_pcre_freeoff(&gpoff); } if(info.exeinfo.section) free(info.exeinfo.section); cli_hashset_destroy(&info.exeinfo.vinfo); if (SCAN_ALL && viruses_found) return CL_VIRUS; if(ret == CL_VIRUS) return CL_VIRUS; return (acmode & AC_SCAN_FT) ? type : CL_CLEAN; }
int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode, struct cli_ac_result **acres, unsigned char *refhash) { const unsigned char *buff; int ret = CL_CLEAN, type = CL_CLEAN, bytes, compute_hash[CLI_HASH_AVAIL_TYPES]; unsigned int i = 0, bm_offmode = 0; uint32_t maxpatlen, offset = 0; struct cli_ac_data gdata, tdata; struct cli_bm_off toff; cli_md5_ctx md5ctx; SHA256_CTX sha256ctx; SHA1Context sha1ctx; unsigned char digest[CLI_HASH_AVAIL_TYPES][32]; struct cli_matcher *groot = NULL, *troot = NULL; struct cli_target_info info; fmap_t *map = *ctx->fmap; struct cli_matcher *hdb, *fp; const char *virname = NULL; uint32_t viroffset = 0; uint32_t viruses_found = 0; if(!ctx->engine) { cli_errmsg("cli_scandesc: engine == NULL\n"); return CL_ENULLARG; } if(!ftonly) groot = ctx->engine->root[0]; /* generic signatures */ if(ftype) { for(i = 1; i < CLI_MTARGETS; i++) { if(cli_mtargets[i].target == ftype) { troot = ctx->engine->root[i]; break; } } } if(ftonly) { if(!troot) return CL_CLEAN; maxpatlen = troot->maxpatlen; } else { if(troot) maxpatlen = MAX(troot->maxpatlen, groot->maxpatlen); else maxpatlen = groot->maxpatlen; } targetinfo(&info, i, map); 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, &info))) { if(info.exeinfo.section) free(info.exeinfo.section); cli_hashset_destroy(&info.exeinfo.vinfo); return ret; } if(troot) { 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, &info))) { if(!ftonly) cli_ac_freedata(&gdata); if(info.exeinfo.section) free(info.exeinfo.section); cli_hashset_destroy(&info.exeinfo.vinfo); return ret; } if(troot->bm_offmode) { if(map->len >= CLI_DEFAULT_BM_OFFMODE_FSIZE) { if((ret = cli_bm_initoff(troot, &toff, &info))) { if(!ftonly) cli_ac_freedata(&gdata); cli_ac_freedata(&tdata); if(info.exeinfo.section) free(info.exeinfo.section); cli_hashset_destroy(&info.exeinfo.vinfo); return ret; } bm_offmode = 1; } } } hdb = ctx->engine->hm_hdb; fp = ctx->engine->hm_fp; if(!ftonly && hdb) { if(!refhash) { if(cli_hm_have_size(hdb, CLI_HASH_MD5, map->len) || cli_hm_have_size(fp, CLI_HASH_MD5, map->len)) { cli_md5_init(&md5ctx); compute_hash[CLI_HASH_MD5] = 1; } else compute_hash[CLI_HASH_MD5] = 0; } else { compute_hash[CLI_HASH_MD5] = 0; memcpy(digest[CLI_HASH_MD5], refhash, 16); } if(cli_hm_have_size(hdb, CLI_HASH_SHA1, map->len) || cli_hm_have_wild(hdb, CLI_HASH_SHA1) || cli_hm_have_size(fp, CLI_HASH_SHA1, map->len) || cli_hm_have_wild(fp, CLI_HASH_SHA1) ) { SHA1Init(&sha1ctx); compute_hash[CLI_HASH_SHA1] = 1; } else compute_hash[CLI_HASH_SHA1] = 0; if(cli_hm_have_size(hdb, CLI_HASH_SHA256, map->len) || cli_hm_have_wild(hdb, CLI_HASH_SHA256) || cli_hm_have_size(fp, CLI_HASH_SHA256, map->len) || cli_hm_have_wild(fp, CLI_HASH_SHA256)) { sha256_init(&sha256ctx); compute_hash[CLI_HASH_SHA256] = 1; } else compute_hash[CLI_HASH_SHA256] = 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; if (ctx->engine->cb_progress && map->handle_is_fd && !ctx->engine->cb_progress((ssize_t) map->handle, bytes, ctx->engine->cb_progress_ctx)) return CL_BREAK; if(troot) { virname = NULL; viroffset = 0; ret = matcher_run(troot, buff, bytes, &virname, &tdata, offset, &info, ftype, ftoffset, acmode, acres, map, bm_offmode ? &toff : NULL, &viroffset, ctx); if (virname) { /* virname already appended by matcher_run */ viruses_found = 1; } if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) { if(!ftonly) cli_ac_freedata(&gdata); cli_ac_freedata(&tdata); if(bm_offmode) cli_bm_freeoff(&toff); if(info.exeinfo.section) free(info.exeinfo.section); cli_hashset_destroy(&info.exeinfo.vinfo); return ret; } } if(!ftonly) { virname = NULL; viroffset = 0; ret = matcher_run(groot, buff, bytes, &virname, &gdata, offset, &info, ftype, ftoffset, acmode, acres, map, NULL, &viroffset, ctx); if (virname) { /* virname already appended by matcher_run */ viruses_found = 1; } if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) { cli_ac_freedata(&gdata); if(troot) { cli_ac_freedata(&tdata); if(bm_offmode) cli_bm_freeoff(&toff); } if(info.exeinfo.section) free(info.exeinfo.section); cli_hashset_destroy(&info.exeinfo.vinfo); return ret; } else if((acmode & AC_SCAN_FT) && ret >= CL_TYPENO) { if(ret > type) type = ret; } if(hdb && !SCAN_ALL) { const void *data = buff + maxpatlen * (offset!=0); uint32_t data_len = bytes - maxpatlen * (offset!=0); if(compute_hash[CLI_HASH_MD5]) cli_md5_update(&md5ctx, data, data_len); if(compute_hash[CLI_HASH_SHA1]) SHA1Update(&sha1ctx, data, data_len); if(compute_hash[CLI_HASH_SHA256]) sha256_update(&sha256ctx, data, data_len); } } if(SCAN_ALL && viroffset) { offset = viroffset; continue; } if(bytes < SCANBUFF) break; offset += bytes - maxpatlen; } if(!ftonly && hdb) { enum CLI_HASH_TYPE hashtype, hashtype2; if(compute_hash[CLI_HASH_MD5]) cli_md5_final(digest[CLI_HASH_MD5], &md5ctx); if(refhash) compute_hash[CLI_HASH_MD5] = 1; if(compute_hash[CLI_HASH_SHA1]) SHA1Final(&sha1ctx, digest[CLI_HASH_SHA1]); if(compute_hash[CLI_HASH_SHA256]) sha256_final(&sha256ctx, digest[CLI_HASH_SHA256]); virname = NULL; for(hashtype = CLI_HASH_MD5; hashtype < CLI_HASH_AVAIL_TYPES; hashtype++) { const char * virname_w = NULL; int found = 0; /* If no hash, skip to next type */ if(!compute_hash[hashtype]) continue; /* Do hash scan */ if((ret = cli_hm_scan(digest[hashtype], map->len, &virname, hdb, hashtype)) == CL_VIRUS) { found += 1; } if(!found || SCAN_ALL) { if ((ret = cli_hm_scan_wild(digest[hashtype], &virname_w, hdb, hashtype)) == CL_VIRUS) found += 2; } /* If found, do immediate hash-only FP check */ if (found && fp) { for(hashtype2 = CLI_HASH_MD5; hashtype2 < CLI_HASH_AVAIL_TYPES; hashtype2++) { if(!compute_hash[hashtype2]) continue; if(cli_hm_scan(digest[hashtype2], map->len, NULL, fp, hashtype2) == CL_VIRUS) { found = 0; ret = CL_CLEAN; break; } else if(cli_hm_scan_wild(digest[hashtype2], NULL, fp, hashtype2) == CL_VIRUS) { found = 0; ret = CL_CLEAN; break; } } } /* If matched size-based hash ... */ if (found % 2) { viruses_found = 1; cli_append_virus(ctx, virname); if (!SCAN_ALL) break; virname = NULL; } /* If matched size-agnostic hash ... */ if (found > 1) { viruses_found = 1; cli_append_virus(ctx, virname_w); if (!SCAN_ALL) break; } } } if(troot) { if(ret != CL_VIRUS || SCAN_ALL) ret = cli_lsig_eval(ctx, troot, &tdata, &info, refhash); if (ret == CL_VIRUS) viruses_found++; cli_ac_freedata(&tdata); if(bm_offmode) cli_bm_freeoff(&toff); } if(groot) { if(ret != CL_VIRUS || SCAN_ALL) ret = cli_lsig_eval(ctx, groot, &gdata, &info, refhash); cli_ac_freedata(&gdata); } if(info.exeinfo.section) free(info.exeinfo.section); cli_hashset_destroy(&info.exeinfo.vinfo); if (SCAN_ALL && viruses_found) return CL_VIRUS; if(ret == CL_VIRUS) return CL_VIRUS; return (acmode & AC_SCAN_FT) ? type : CL_CLEAN; }
int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode, struct cli_ac_result **acres, unsigned char *refhash) { //CHR ftype => type == CL_TYPE_TEXT_ASCII ? 0 : type //CHR ftonly => 0 cli_infomsg(NULL,"DEBUG: in cli_fmap_scandesc\n");//CHR const unsigned char *buff; int ret = CL_CLEAN, type = CL_CLEAN, bytes, compute_hash[CLI_HASH_AVAIL_TYPES]; unsigned int i = 0, bm_offmode = 0; uint32_t maxpatlen, offset = 0; struct cli_ac_data gdata, tdata; struct cli_bm_off toff; cli_md5_ctx md5ctx; SHA256_CTX sha256ctx; SHA1Context sha1ctx; unsigned char digest[CLI_HASH_AVAIL_TYPES][32]; struct cli_matcher *groot = NULL, *troot = NULL; struct cli_target_info info; fmap_t *map = *ctx->fmap; struct cli_matcher *hdb, *fp; const char *virname = NULL; uint32_t viroffset = 0; uint32_t viruses_found = 0; if(!ctx->engine) { cli_errmsg("cli_scandesc: engine == NULL\n"); return CL_ENULLARG; } cli_infomsg(NULL,"DEBUG: ftype=%d, ftonly=%d(using generic signatures for groot)\n",ftype,ftonly);//CHR if(!ftonly) groot = ctx->engine->root[0]; /* generic signatures */ //CHR in test.txt case, ftype=0, troot is for sepcific types: from 1 to CLI_MTARGETS if(ftype) { for(i = 1; i < CLI_MTARGETS; i++) { if(cli_mtargets[i].target == ftype) { troot = ctx->engine->root[i]; break; } } } if(ftonly) { if(!troot) return CL_CLEAN; maxpatlen = troot->maxpatlen; } else { if(troot) maxpatlen = MAX(troot->maxpatlen, groot->maxpatlen); else{ maxpatlen = groot->maxpatlen; cli_infomsg(NULL,"DEBUG: no troot, maxpatlen using groot->maxpatlen=%d\n",groot->maxpatlen);//CHR } } targetinfo(&info, i, map); if(!ftonly) // CHR init AC scan structure? 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, &info))) { if(info.exeinfo.section) free(info.exeinfo.section); cli_hashset_destroy(&info.exeinfo.vinfo); return ret; } // not run in this case test.txt if(troot) { 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, &info))) { if(!ftonly) cli_ac_freedata(&gdata); if(info.exeinfo.section) free(info.exeinfo.section); cli_hashset_destroy(&info.exeinfo.vinfo); return ret; } if(troot->bm_offmode) {// CHR offset mode if(map->len >= CLI_DEFAULT_BM_OFFMODE_FSIZE) { if((ret = cli_bm_initoff(troot, &toff, &info))) { if(!ftonly) cli_ac_freedata(&gdata); cli_ac_freedata(&tdata); if(info.exeinfo.section) free(info.exeinfo.section); cli_hashset_destroy(&info.exeinfo.vinfo); return ret; } bm_offmode = 1; } } } hdb = ctx->engine->hm_hdb; fp = ctx->engine->hm_fp; // hdb related if(!ftonly && hdb) { //CHR if have hdb should init mn5 contex if(!refhash) { if(cli_hm_have_size(hdb, CLI_HASH_MD5, map->len) || cli_hm_have_size(fp, CLI_HASH_MD5, map->len)) { cli_md5_init(&md5ctx); compute_hash[CLI_HASH_MD5] = 1; } else compute_hash[CLI_HASH_MD5] = 0; } else { compute_hash[CLI_HASH_MD5] = 0; memcpy(digest[CLI_HASH_MD5], refhash, 16); } if(cli_hm_have_size(hdb, CLI_HASH_SHA1, map->len) || cli_hm_have_size(fp, CLI_HASH_SHA1, map->len)) { SHA1Init(&sha1ctx); compute_hash[CLI_HASH_SHA1] = 1; } else compute_hash[CLI_HASH_SHA1] = 0; if(cli_hm_have_size(hdb, CLI_HASH_SHA256, map->len) || cli_hm_have_size(fp, CLI_HASH_SHA256, map->len)) { sha256_init(&sha256ctx); compute_hash[CLI_HASH_SHA256] = 1; } else compute_hash[CLI_HASH_SHA256] = 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; // CHR not troot for this case if(troot) { cli_infomsg(NULL,"DEBUG: not troot, should not show this msg\n");//CHR virname = NULL; viroffset = 0; // CHR run match ret = matcher_run(troot, buff, bytes, &virname, &tdata, offset, &info, ftype, ftoffset, acmode, acres, map, bm_offmode ? &toff : NULL, &viroffset, ctx); if (virname) { viruses_found++; } if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) { if(!ftonly) cli_ac_freedata(&gdata); cli_ac_freedata(&tdata); if(bm_offmode) cli_bm_freeoff(&toff); if(info.exeinfo.section) free(info.exeinfo.section); cli_hashset_destroy(&info.exeinfo.vinfo); return ret; } } if(!ftonly) { cli_infomsg(NULL,"DEBUG: !ftonly=true, will run matcher_run with groot with generic sigs\n");//CHR virname = NULL; viroffset = 0; ret = matcher_run(groot, buff, bytes, &virname, &gdata, offset, &info, ftype, ftoffset, acmode, acres, map, NULL, &viroffset, ctx); if (virname) { viruses_found++; } if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) { cli_ac_freedata(&gdata); if(troot) { cli_ac_freedata(&tdata); if(bm_offmode) cli_bm_freeoff(&toff); } if(info.exeinfo.section) free(info.exeinfo.section); cli_hashset_destroy(&info.exeinfo.vinfo); return ret; } else if((acmode & AC_SCAN_FT) && ret >= CL_TYPENO) { if(ret > type) type = ret; } if(hdb && !SCAN_ALL) { const void *data = buff + maxpatlen * (offset!=0); uint32_t data_len = bytes - maxpatlen * (offset!=0); if(compute_hash[CLI_HASH_MD5]) cli_md5_update(&md5ctx, data, data_len); if(compute_hash[CLI_HASH_SHA1]) SHA1Update(&sha1ctx, data, data_len); if(compute_hash[CLI_HASH_SHA256]) sha256_update(&sha256ctx, data, data_len); } } if(SCAN_ALL && viroffset) { offset = viroffset; continue; } if(bytes < SCANBUFF) break; offset += bytes - maxpatlen; } if(!ftonly && hdb) { enum CLI_HASH_TYPE hashtype, hashtype2; if(compute_hash[CLI_HASH_MD5]) cli_md5_final(digest[CLI_HASH_MD5], &md5ctx); if(refhash) compute_hash[CLI_HASH_MD5] = 1; if(compute_hash[CLI_HASH_SHA1]) SHA1Final(&sha1ctx, digest[CLI_HASH_SHA1]); if(compute_hash[CLI_HASH_SHA256]) sha256_final(&sha256ctx, digest[CLI_HASH_SHA256]); virname = NULL; for(hashtype = CLI_HASH_MD5; hashtype < CLI_HASH_AVAIL_TYPES; hashtype++) { if(compute_hash[hashtype] && (ret = cli_hm_scan(digest[hashtype], map->len, &virname, hdb, hashtype)) == CL_VIRUS) { if(fp) { for(hashtype2 = CLI_HASH_MD5; hashtype2 < CLI_HASH_AVAIL_TYPES; hashtype2++) { if(compute_hash[hashtype2] && cli_hm_scan(digest[hashtype2], map->len, NULL, fp, hashtype2) == CL_VIRUS) { ret = CL_CLEAN; break; } } } if (ret == CL_VIRUS) { viruses_found++; cli_append_virus(ctx, virname); if (!SCAN_ALL) break; } virname = NULL; } } } if(troot) { if(ret != CL_VIRUS || SCAN_ALL) ret = cli_lsig_eval(ctx, troot, &tdata, &info, refhash); if (ret == CL_VIRUS) viruses_found++; cli_ac_freedata(&tdata); if(bm_offmode) cli_bm_freeoff(&toff); } if(groot) { if(ret != CL_VIRUS || SCAN_ALL) ret = cli_lsig_eval(ctx, groot, &gdata, &info, refhash); cli_ac_freedata(&gdata); } if(info.exeinfo.section) free(info.exeinfo.section); cli_hashset_destroy(&info.exeinfo.vinfo); if (SCAN_ALL && viruses_found) return CL_VIRUS; if(ret == CL_VIRUS) return CL_VIRUS; return (acmode & AC_SCAN_FT) ? type : CL_CLEAN; }