2
* Copyright (C) 2007-2013 Sourcefire, Inc.
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 2 as
8
* published by the Free Software Foundation.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22
#include "clamav-config.h"
27
#include <sys/types.h>
35
#include "matcher-ac.h"
36
#include "matcher-bm.h"
37
#include "filetypes.h"
50
#include "regex/regex.h"
51
#include "filtering.h"
52
#include "perflogging.h"
53
#include "bytecode_priv.h"
54
#include "bytecode_api_impl.h"
56
#ifdef CLI_PERF_LOGGING
58
static inline void PERF_LOG_FILTER(int32_t pos, int32_t length, int8_t trie)
60
cli_perf_log_add(RAW_BYTES_SCANNED, length);
61
cli_perf_log_add(FILTER_BYTES_SCANNED, length - pos);
62
cli_perf_log_count2(TRIE_SCANNED, trie, length - pos);
65
static inline int PERF_LOG_TRIES(int8_t acmode, int8_t bm_called, int32_t length)
68
cli_perf_log_add(BM_SCANNED, length);
70
cli_perf_log_add(AC_SCANNED, length);
75
static inline void PERF_LOG_FILTER(int32_t pos, uint32_t length, int8_t trie) {
81
static inline int PERF_LOG_TRIES(int8_t acmode, int8_t bm_called, int32_t length) {
83
UNUSEDPARAM(bm_called);
90
static inline int matcher_run(const struct cli_matcher *root,
91
const unsigned char *buffer, uint32_t length,
92
const char **virname, struct cli_ac_data *mdata,
94
const struct cli_target_info *tinfo,
96
struct cli_matched_type **ftoffset,
98
struct cli_ac_result **acres,
100
struct cli_bm_off *offdata,
106
struct filter_match_info info;
107
uint32_t orig_length, orig_offset;
108
const unsigned char* orig_buffer;
109
unsigned int viruses_found = 0;
114
if(filter_search_ext(root->filter, buffer, length, &info) == -1) {
115
/* for safety always scan last maxpatlen bytes */
116
pos = length - root->maxpatlen - 1;
117
if (pos < 0) pos = 0;
118
PERF_LOG_FILTER(pos, length, root->type);
120
/* must not cut buffer for 64[4-4]6161, because we must be able to check
122
pos = info.first_match - root->maxpatlen - 1;
123
if (pos < 0) pos = 0;
124
PERF_LOG_FILTER(pos, length, root->type);
127
PERF_LOG_FILTER(0, length, root->type);
130
orig_length = length;
131
orig_buffer = buffer;
132
orig_offset = offset;
136
if (!root->ac_only) {
137
PERF_LOG_TRIES(0, 1, length);
138
if (root->bm_offmode) {
139
/* Don't use prefiltering for BM offset mode, since BM keeps tracks
140
* of offsets itself, and doesn't work if we skip chunks of input
142
ret = cli_bm_scanbuff(orig_buffer, orig_length, virname, NULL, root, orig_offset, tinfo, offdata, viroffset);
144
ret = cli_bm_scanbuff(buffer, length, virname, NULL, root, offset, tinfo, offdata, viroffset);
146
if (ret == CL_VIRUS) {
148
cli_append_virus(ctx, *virname);
156
PERF_LOG_TRIES(acmode, 0, length);
157
ret = cli_ac_scanbuff(buffer, length, virname, NULL, acres, root, mdata, offset, ftype, ftoffset, acmode, ctx);
159
if (ctx && !SCAN_ALL && ret == CL_VIRUS)
160
cli_append_virus(ctx, *virname);
161
if (ctx && SCAN_ALL && viruses_found)
167
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)
170
unsigned int i = 0, j = 0, viruses_found = 0;
171
struct cli_ac_data mdata;
172
struct cli_matcher *groot, *troot = NULL;
173
const char *virname = NULL;
174
const struct cl_engine *engine=ctx->engine;
177
cli_errmsg("cli_scanbuff: engine == NULL\n");
181
groot = engine->root[0]; /* generic signatures */
184
for(i = 1; i < CLI_MTARGETS; i++) {
185
for (j = 0; j < cli_mtargets[i].target_count; ++j) {
186
if(cli_mtargets[i].target[j] == ftype) {
187
troot = ctx->engine->root[i];
197
if(!acdata && (ret = cli_ac_initdata(&mdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
200
ret = matcher_run(troot, buffer, length, &virname, acdata ? (acdata[0]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, NULL, *ctx->fmap, NULL, NULL, ctx);
203
cli_ac_freedata(&mdata);
207
if(ret == CL_VIRUS) {
209
if(ctx && !SCAN_ALL) {
217
if(!acdata && (ret = cli_ac_initdata(&mdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
220
ret = matcher_run(groot, buffer, length, &virname, acdata ? (acdata[1]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, NULL, *ctx->fmap, NULL, NULL, ctx);
223
cli_ac_freedata(&mdata);
232
* offdata[1]: offset value
233
* offdata[2]: max shift
234
* offdata[3]: section number
236
int cli_caloff(const char *offstr, const struct cli_target_info *info, unsigned int target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max)
242
if(!info) { /* decode offset string */
244
cli_errmsg("cli_caloff: offstr == NULL\n");
248
if(!strcmp(offstr, "*")) {
249
offdata[0] = *offset_max = *offset_min = CLI_OFF_ANY;
253
if(strlen(offstr) > 64) {
254
cli_errmsg("cli_caloff: Offset string too long\n");
257
strcpy(offcpy, offstr);
259
if((pt = strchr(offcpy, ','))) {
260
if(!cli_isnumber(pt + 1)) {
261
cli_errmsg("cli_caloff: Invalid offset shift value\n");
264
offdata[2] = atoi(pt + 1);
270
*offset_max = *offset_min = CLI_OFF_NONE;
272
if(!strncmp(offcpy, "EP+", 3) || !strncmp(offcpy, "EP-", 3)) {
274
offdata[0] = CLI_OFF_EP_PLUS;
276
offdata[0] = CLI_OFF_EP_MINUS;
278
if(!cli_isnumber(&offcpy[3])) {
279
cli_errmsg("cli_caloff: Invalid offset value\n");
282
offdata[1] = atoi(&offcpy[3]);
284
} else if(offcpy[0] == 'S') {
285
if(offcpy[1] == 'E') {
286
if(!cli_isnumber(&offcpy[2])) {
287
cli_errmsg("cli_caloff: Invalid section number\n");
290
offdata[0] = CLI_OFF_SE;
291
offdata[3] = atoi(&offcpy[2]);
293
} else if(!strncmp(offstr, "SL+", 3)) {
294
offdata[0] = CLI_OFF_SL_PLUS;
295
if(!cli_isnumber(&offcpy[3])) {
296
cli_errmsg("cli_caloff: Invalid offset value\n");
299
offdata[1] = atoi(&offcpy[3]);
301
} else if(sscanf(offcpy, "S%u+%u", &n, &val) == 2) {
302
offdata[0] = CLI_OFF_SX_PLUS;
306
cli_errmsg("cli_caloff: Invalid offset string\n");
310
} else if(!strncmp(offcpy, "EOF-", 4)) {
311
offdata[0] = CLI_OFF_EOF_MINUS;
312
if(!cli_isnumber(&offcpy[4])) {
313
cli_errmsg("cli_caloff: Invalid offset value\n");
316
offdata[1] = atoi(&offcpy[4]);
317
} else if(!strncmp(offcpy, "VI", 2)) {
319
offdata[0] = CLI_OFF_VERSION;
320
} else if (strchr(offcpy, '$')) {
321
if (sscanf(offcpy, "$%u$", &n) != 1) {
322
cli_errmsg("cli_caloff: Invalid macro($) in offset: %s\n", offcpy);
326
cli_errmsg("cli_caloff: at most 32 macro groups supported\n");
329
offdata[0] = CLI_OFF_MACRO;
332
offdata[0] = CLI_OFF_ABSOLUTE;
333
if(!cli_isnumber(offcpy)) {
334
cli_errmsg("cli_caloff: Invalid offset value\n");
337
*offset_min = offdata[1] = atoi(offcpy);
338
*offset_max = *offset_min + offdata[2];
341
if(offdata[0] != CLI_OFF_ANY && offdata[0] != CLI_OFF_ABSOLUTE &&
342
offdata[0] != CLI_OFF_EOF_MINUS && offdata[0] != CLI_OFF_MACRO) {
343
if(target != 1 && target != 6 && target != 9) {
344
cli_errmsg("cli_caloff: Invalid offset type for target %u\n", target);
350
/* calculate relative offsets */
351
*offset_min = CLI_OFF_NONE;
353
*offset_max = CLI_OFF_NONE;
354
if(info->status == -1)
358
case CLI_OFF_EOF_MINUS:
359
*offset_min = info->fsize - offdata[1];
362
case CLI_OFF_EP_PLUS:
363
*offset_min = info->exeinfo.ep + offdata[1];
366
case CLI_OFF_EP_MINUS:
367
*offset_min = info->exeinfo.ep - offdata[1];
370
case CLI_OFF_SL_PLUS:
371
*offset_min = info->exeinfo.section[info->exeinfo.nsections - 1].raw + offdata[1];
374
case CLI_OFF_SX_PLUS:
375
if(offdata[3] >= info->exeinfo.nsections)
376
*offset_min = CLI_OFF_NONE;
378
*offset_min = info->exeinfo.section[offdata[3]].raw + offdata[1];
382
if(offdata[3] >= info->exeinfo.nsections) {
383
*offset_min = CLI_OFF_NONE;
385
*offset_min = info->exeinfo.section[offdata[3]].raw;
387
*offset_max = *offset_min + info->exeinfo.section[offdata[3]].rsz + offdata[2];
391
case CLI_OFF_VERSION:
393
*offset_min = *offset_max = CLI_OFF_ANY;
396
cli_errmsg("cli_caloff: Not a relative offset (type: %u)\n", offdata[0]);
400
if(offset_max && *offset_max == CLI_OFF_NONE && *offset_min != CLI_OFF_NONE)
401
*offset_max = *offset_min + offdata[2];
407
void cli_targetinfo(struct cli_target_info *info, unsigned int target, fmap_t *map)
409
int (*einfo)(fmap_t *, struct cli_exe_info *) = NULL;
412
memset(info, 0, sizeof(struct cli_target_info));
413
info->fsize = map->len;
414
cli_hashset_init_noalloc(&info->exeinfo.vinfo);
417
einfo = cli_peheader;
419
einfo = cli_elfheader;
421
einfo = cli_machoheader;
424
if(einfo(map, &info->exeinfo))
430
int cli_checkfp(unsigned char *digest, size_t size, cli_ctx *ctx)
434
const char *virname=NULL;
437
uint8_t shash1[SHA1_HASH_SIZE*2+1];
438
uint8_t shash256[SHA256_HASH_SIZE*2+1];
439
int have_sha1, have_sha256, do_dsig_check = 1;
440
stats_section_t sections;
442
if(cli_hm_scan(digest, size, &virname, ctx->engine->hm_fp, CLI_HASH_MD5) == CL_VIRUS) {
443
cli_dbgmsg("cli_checkfp(md5): Found false positive detection (fp sig: %s), size: %d\n", virname, (int)size);
446
else if(cli_hm_scan_wild(digest, &virname, ctx->engine->hm_fp, CLI_HASH_MD5) == CL_VIRUS) {
447
cli_dbgmsg("cli_checkfp(md5): Found false positive detection (fp sig: %s), size: *\n", virname);
451
if(cli_debug_flag || ctx->engine->cb_hash) {
452
for(i = 0; i < 16; i++)
453
sprintf(md5 + i * 2, "%02x", digest[i]);
455
cli_dbgmsg("FP SIGNATURE: %s:%u:%s\n", md5, (unsigned int) size,
456
cli_get_last_virus(ctx) ? cli_get_last_virus(ctx) : "Name");
459
if(cli_get_last_virus(ctx))
460
do_dsig_check = strncmp("W32S.", cli_get_last_virus(ctx), 5);
463
have_sha1 = cli_hm_have_size(ctx->engine->hm_fp, CLI_HASH_SHA1, size)
464
|| cli_hm_have_wild(ctx->engine->hm_fp, CLI_HASH_SHA1)
465
|| (cli_hm_have_size(ctx->engine->hm_fp, CLI_HASH_SHA1, 1) && do_dsig_check);
466
have_sha256 = cli_hm_have_size(ctx->engine->hm_fp, CLI_HASH_SHA256, size)
467
|| cli_hm_have_wild(ctx->engine->hm_fp, CLI_HASH_SHA256);
468
if(have_sha1 || have_sha256) {
469
if((ptr = fmap_need_off_once(map, 0, size))) {
471
cl_sha1(ptr, size, &shash1[SHA1_HASH_SIZE], NULL);
473
if(cli_hm_scan(&shash1[SHA1_HASH_SIZE], size, &virname, ctx->engine->hm_fp, CLI_HASH_SHA1) == CL_VIRUS) {
474
cli_dbgmsg("cli_checkfp(sha1): Found false positive detection (fp sig: %s)\n", virname);
477
if(cli_hm_scan_wild(&shash1[SHA1_HASH_SIZE], &virname, ctx->engine->hm_fp, CLI_HASH_SHA1) == CL_VIRUS) {
478
cli_dbgmsg("cli_checkfp(sha1): Found false positive detection (fp sig: %s)\n", virname);
481
if(do_dsig_check && cli_hm_scan(&shash1[SHA1_HASH_SIZE], 1, &virname, ctx->engine->hm_fp, CLI_HASH_SHA1) == CL_VIRUS) {
482
cli_dbgmsg("cli_checkfp(sha1): Found false positive detection via catalog file\n");
488
cl_sha256(ptr, size, &shash256[SHA256_HASH_SIZE], NULL);
490
if(cli_hm_scan(&shash256[SHA256_HASH_SIZE], size, &virname, ctx->engine->hm_fp, CLI_HASH_SHA256) == CL_VIRUS) {
491
cli_dbgmsg("cli_checkfp(sha256): Found false positive detection (fp sig: %s)\n", virname);
494
if(cli_hm_scan_wild(&shash256[SHA256_HASH_SIZE], &virname, ctx->engine->hm_fp, CLI_HASH_SHA256) == CL_VIRUS) {
495
cli_dbgmsg("cli_checkfp(sha256): Found false positive detection (fp sig: %s)\n", virname);
502
#ifdef HAVE__INTERNAL__SHA_COLLECT
503
if((ctx->options & CL_SCAN_INTERNAL_COLLECT_SHA) && ctx->sha_collect>0) {
504
if((ptr = fmap_need_off_once(map, 0, size))) {
506
cl_sha256(ptr, size, shash256+SHA256_HASH_SIZE, NULL);
508
for(i=0; i<SHA256_HASH_SIZE; i++)
509
sprintf((char *)shash256+i*2, "%02x", shash256[SHA256_HASH_SIZE+i]);
512
cl_sha1(ptr, size, shash1+SHA1_HASH_SIZE);
514
for(i=0; i<SHA1_HASH_SIZE; i++)
515
sprintf((char *)shash1+i*2, "%02x", shash1[SHA1_HASH_SIZE+i]);
517
cli_errmsg("COLLECT:%s:%s:%u:%s:%s\n", shash256, shash1, size, cli_get_last_virus(ctx), ctx->entry_filename);
519
cli_errmsg("can't compute sha\n!");
521
ctx->sha_collect = -1;
525
memset(§ions, 0x00, sizeof(stats_section_t));
526
if(do_dsig_check || ctx->engine->cb_stats_add_sample) {
527
uint32_t flags = (do_dsig_check ? CL_CHECKFP_PE_FLAG_AUTHENTICODE : 0);
528
if (!(ctx->engine->engine_options & ENGINE_OPTIONS_DISABLE_PE_STATS) && !(ctx->engine->dconf->stats & (DCONF_STATS_DISABLED | DCONF_STATS_PE_SECTION_DISABLED)))
529
flags |= CL_CHECKFP_PE_FLAG_STATS;
531
switch(cli_checkfp_pe(ctx, shash1, §ions, flags)) {
533
cli_dbgmsg("cli_checkfp(pe): PE file whitelisted due to valid embedded digital signature\n");
536
if(cli_hm_scan(shash1, 2, &virname, ctx->engine->hm_fp, CLI_HASH_SHA1) == CL_VIRUS) {
537
cli_dbgmsg("cli_checkfp(pe): PE file whitelisted by catalog file\n");
544
if (ctx->engine->cb_hash)
545
ctx->engine->cb_hash(fmap_fd(*ctx->fmap), size, (const unsigned char *)md5, cli_get_last_virus(ctx), ctx->cb_ctx);
547
if (ctx->engine->cb_stats_add_sample)
548
ctx->engine->cb_stats_add_sample(cli_get_last_virus(ctx), digest, size, §ions, ctx->engine->stats_data);
550
if (sections.sections)
551
free(sections.sections);
556
static int matchicon(cli_ctx *ctx, struct cli_exe_info *exeinfo, const char *grp1, const char *grp2)
558
icon_groupset iconset;
562
!ctx->engine->iconcheck ||
563
!ctx->engine->iconcheck->group_counts[0] ||
564
!ctx->engine->iconcheck->group_counts[1] ||
568
if (!(ctx->dconf->pe & PE_CONF_MATCHICON))
571
cli_icongroupset_init(&iconset);
572
cli_icongroupset_add(grp1 ? grp1 : "*", &iconset, 0, ctx);
573
cli_icongroupset_add(grp2 ? grp2 : "*", &iconset, 1, ctx);
574
return cli_scanicon(&iconset, exeinfo->res_addr, ctx, exeinfo->section, exeinfo->nsections, exeinfo->hdr_size);
577
int32_t cli_bcapi_matchicon(struct cli_bc_ctx *ctx , const uint8_t* grp1, int32_t grp1len,
578
const uint8_t* grp2, int32_t grp2len)
581
char group1[128], group2[128];
582
const char **oldvirname;
583
struct cli_exe_info info;
585
if (!ctx->hooks.pedata->ep) {
586
cli_dbgmsg("bytecode: matchicon only works with PE files\n");
589
if ((size_t) grp1len > sizeof(group1)-1 ||
590
(size_t) grp2len > sizeof(group2)-1)
592
oldvirname = ((cli_ctx*)ctx->ctx)->virname;
593
((cli_ctx*)ctx->ctx)->virname = NULL;
594
memcpy(group1, grp1, grp1len);
595
memcpy(group2, grp2, grp2len);
598
memset(&info, 0, sizeof(info));
599
if (ctx->bc->kind == BC_PE_UNPACKER || ctx->bc->kind == BC_PE_ALL) {
600
if(le16_to_host(ctx->hooks.pedata->file_hdr.Characteristics) & 0x2000 ||
601
!ctx->hooks.pedata->dirs[2].Size)
604
info.res_addr = le32_to_host(ctx->hooks.pedata->dirs[2].VirtualAddress);
606
info.res_addr = ctx->resaddr; /* from target_info */
607
info.section = (struct cli_exe_section*)ctx->sections;
608
info.nsections = ctx->hooks.pedata->nsections;
609
info.hdr_size = ctx->hooks.pedata->hdr_size;
610
cli_dbgmsg("bytecode matchicon %s %s\n", group1, group2);
611
ret = matchicon(ctx->ctx, &info, group1[0] ? group1 : NULL,
612
group2[0] ? group2 : NULL);
613
((cli_ctx*)ctx->ctx)->virname = oldvirname;
618
int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode, struct cli_ac_result **acres)
620
int ret = CL_EMEM, empty;
621
fmap_t *map = *ctx->fmap;
623
if((*ctx->fmap = fmap_check_empty(desc, 0, 0, &empty))) {
624
ret = cli_fmap_scandesc(ctx, ftype, ftonly, ftoffset, acmode, acres, NULL);
625
map->dont_cache_flag = (*ctx->fmap)->dont_cache_flag;
634
int cli_lsig_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_ac_data *acdata, struct cli_target_info *target_info, const char *hash)
636
unsigned int i, evalcnt;
638
fmap_t *map = *ctx->fmap;
639
unsigned int viruses_found = 0;
641
for(i = 0; i < root->ac_lsigs; i++) {
644
cli_ac_chkmacro(root, acdata, i);
645
if(cli_ac_chklsig(root->ac_lsigtable[i]->logic, root->ac_lsigtable[i]->logic + strlen(root->ac_lsigtable[i]->logic), acdata->lsigcnt[i], &evalcnt, &evalids, 0) == 1) {
646
if(root->ac_lsigtable[i]->tdb.container && root->ac_lsigtable[i]->tdb.container[0] != ctx->container_type)
648
if(root->ac_lsigtable[i]->tdb.filesize && (root->ac_lsigtable[i]->tdb.filesize[0] > map->len || root->ac_lsigtable[i]->tdb.filesize[1] < map->len))
651
if(root->ac_lsigtable[i]->tdb.ep || root->ac_lsigtable[i]->tdb.nos) {
652
if(!target_info || target_info->status != 1)
654
if(root->ac_lsigtable[i]->tdb.ep && (root->ac_lsigtable[i]->tdb.ep[0] > target_info->exeinfo.ep || root->ac_lsigtable[i]->tdb.ep[1] < target_info->exeinfo.ep))
656
if(root->ac_lsigtable[i]->tdb.nos && (root->ac_lsigtable[i]->tdb.nos[0] > target_info->exeinfo.nsections || root->ac_lsigtable[i]->tdb.nos[1] < target_info->exeinfo.nsections))
660
if(hash && root->ac_lsigtable[i]->tdb.handlertype) {
661
if(memcmp(ctx->handlertype_hash, hash, 16)) {
663
memcpy(ctx->handlertype_hash, hash, 16);
664
if(cli_magic_scandesc_type(ctx, root->ac_lsigtable[i]->tdb.handlertype[0]) == CL_VIRUS) {
677
if(root->ac_lsigtable[i]->tdb.icongrp1 || root->ac_lsigtable[i]->tdb.icongrp2) {
678
if(!target_info || target_info->status != 1)
680
if(matchicon(ctx, &target_info->exeinfo, root->ac_lsigtable[i]->tdb.icongrp1, root->ac_lsigtable[i]->tdb.icongrp2) == CL_VIRUS) {
681
if(!root->ac_lsigtable[i]->bc_idx) {
682
cli_append_virus(ctx, root->ac_lsigtable[i]->virname);
688
} else if(cli_bytecode_runlsig(ctx, target_info, &ctx->engine->bcs, root->ac_lsigtable[i]->bc_idx, acdata->lsigcnt[i], acdata->lsigsuboff_first[i], map) == CL_VIRUS) {
698
if(!root->ac_lsigtable[i]->bc_idx) {
699
cli_append_virus(ctx, root->ac_lsigtable[i]->virname);
706
if(cli_bytecode_runlsig(ctx, target_info, &ctx->engine->bcs, root->ac_lsigtable[i]->bc_idx, acdata->lsigcnt[i], acdata->lsigsuboff_first[i], map) == CL_VIRUS) {
715
if (SCAN_ALL && viruses_found)
720
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)
722
const unsigned char *buff;
723
int ret = CL_CLEAN, type = CL_CLEAN, bytes, compute_hash[CLI_HASH_AVAIL_TYPES];
724
unsigned int i = 0, j = 0, bm_offmode = 0;
725
uint32_t maxpatlen, offset = 0;
726
struct cli_ac_data gdata, tdata;
727
struct cli_bm_off toff;
728
unsigned char digest[CLI_HASH_AVAIL_TYPES][32];
729
struct cli_matcher *groot = NULL, *troot = NULL;
730
struct cli_target_info info;
731
fmap_t *map = *ctx->fmap;
732
struct cli_matcher *hdb, *fp;
733
const char *virname = NULL;
734
uint32_t viroffset = 0;
735
uint32_t viruses_found = 0;
736
void *md5ctx, *sha1ctx, *sha256ctx;
739
cli_errmsg("cli_scandesc: engine == NULL\n");
743
md5ctx = cl_hash_init("md5");
747
sha1ctx = cl_hash_init("sha1");
749
cl_hash_destroy(md5ctx);
753
sha256ctx = cl_hash_init("sha256");
755
cl_hash_destroy(md5ctx);
756
cl_hash_destroy(sha1ctx);
761
groot = ctx->engine->root[0]; /* generic signatures */
764
for(i = 1; i < CLI_MTARGETS; i++) {
765
for (j = 0; j < cli_mtargets[i].target_count; ++j) {
766
if(cli_mtargets[i].target[j] == ftype) {
767
troot = ctx->engine->root[i];
777
cl_hash_destroy(md5ctx);
778
cl_hash_destroy(sha1ctx);
779
cl_hash_destroy(sha256ctx);
783
maxpatlen = troot->maxpatlen;
786
maxpatlen = MAX(troot->maxpatlen, groot->maxpatlen);
788
maxpatlen = groot->maxpatlen;
791
cli_targetinfo(&info, i, map);
794
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))) {
795
if(info.exeinfo.section)
796
free(info.exeinfo.section);
798
cli_hashset_destroy(&info.exeinfo.vinfo);
799
cl_hash_destroy(md5ctx);
800
cl_hash_destroy(sha1ctx);
801
cl_hash_destroy(sha256ctx);
807
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))) {
809
cli_ac_freedata(&gdata);
810
if(info.exeinfo.section)
811
free(info.exeinfo.section);
813
cli_hashset_destroy(&info.exeinfo.vinfo);
814
cl_hash_destroy(md5ctx);
815
cl_hash_destroy(sha1ctx);
816
cl_hash_destroy(sha256ctx);
819
if(troot->bm_offmode) {
820
if(map->len >= CLI_DEFAULT_BM_OFFMODE_FSIZE) {
821
if((ret = cli_bm_initoff(troot, &toff, &info))) {
823
cli_ac_freedata(&gdata);
825
cli_ac_freedata(&tdata);
826
if(info.exeinfo.section)
827
free(info.exeinfo.section);
829
cli_hashset_destroy(&info.exeinfo.vinfo);
830
cl_hash_destroy(md5ctx);
831
cl_hash_destroy(sha1ctx);
832
cl_hash_destroy(sha256ctx);
841
hdb = ctx->engine->hm_hdb;
842
fp = ctx->engine->hm_fp;
846
if(cli_hm_have_size(hdb, CLI_HASH_MD5, map->len) || cli_hm_have_size(fp, CLI_HASH_MD5, map->len)) {
847
compute_hash[CLI_HASH_MD5] = 1;
849
compute_hash[CLI_HASH_MD5] = 0;
852
compute_hash[CLI_HASH_MD5] = 0;
853
memcpy(digest[CLI_HASH_MD5], refhash, 16);
856
if(cli_hm_have_size(hdb, CLI_HASH_SHA1, map->len) || cli_hm_have_wild(hdb, CLI_HASH_SHA1)
857
|| cli_hm_have_size(fp, CLI_HASH_SHA1, map->len) || cli_hm_have_wild(fp, CLI_HASH_SHA1) ) {
858
compute_hash[CLI_HASH_SHA1] = 1;
860
compute_hash[CLI_HASH_SHA1] = 0;
863
if(cli_hm_have_size(hdb, CLI_HASH_SHA256, map->len) || cli_hm_have_wild(hdb, CLI_HASH_SHA256)
864
|| cli_hm_have_size(fp, CLI_HASH_SHA256, map->len) || cli_hm_have_wild(fp, CLI_HASH_SHA256)) {
865
compute_hash[CLI_HASH_SHA256] = 1;
867
compute_hash[CLI_HASH_SHA256] = 0;
871
while(offset < map->len) {
872
bytes = MIN(map->len - offset, SCANBUFF);
873
if(!(buff = fmap_need_off_once(map, offset, bytes)))
876
*ctx->scanned += bytes / CL_COUNT_PRECISION;
881
ret = matcher_run(troot, buff, bytes, &virname, &tdata, offset, &info, ftype, ftoffset, acmode, acres, map, bm_offmode ? &toff : NULL, &viroffset, ctx);
884
/* virname already appended by matcher_run */
887
if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
889
cli_ac_freedata(&gdata);
891
cli_ac_freedata(&tdata);
893
cli_bm_freeoff(&toff);
895
if(info.exeinfo.section)
896
free(info.exeinfo.section);
898
cli_hashset_destroy(&info.exeinfo.vinfo);
899
cl_hash_destroy(md5ctx);
900
cl_hash_destroy(sha1ctx);
901
cl_hash_destroy(sha256ctx);
909
ret = matcher_run(groot, buff, bytes, &virname, &gdata, offset, &info, ftype, ftoffset, acmode, acres, map, NULL, &viroffset, ctx);
912
/* virname already appended by matcher_run */
915
if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
916
cli_ac_freedata(&gdata);
918
cli_ac_freedata(&tdata);
920
cli_bm_freeoff(&toff);
923
if(info.exeinfo.section)
924
free(info.exeinfo.section);
926
cli_hashset_destroy(&info.exeinfo.vinfo);
927
cl_hash_destroy(md5ctx);
928
cl_hash_destroy(sha1ctx);
929
cl_hash_destroy(sha256ctx);
931
} else if((acmode & AC_SCAN_FT) && ret >= CL_TYPENO) {
937
const void *data = buff + maxpatlen * (offset!=0);
938
uint32_t data_len = bytes - maxpatlen * (offset!=0);
940
if(compute_hash[CLI_HASH_MD5])
941
cl_update_hash(md5ctx, (void *)data, data_len);
942
if(compute_hash[CLI_HASH_SHA1])
943
cl_update_hash(sha1ctx, (void *)data, data_len);
944
if(compute_hash[CLI_HASH_SHA256])
945
cl_update_hash(sha256ctx, (void *)data, data_len);
949
if(SCAN_ALL && viroffset) {
957
offset += bytes - maxpatlen;
961
enum CLI_HASH_TYPE hashtype, hashtype2;
963
if(compute_hash[CLI_HASH_MD5]) {
964
cl_finish_hash(md5ctx, digest[CLI_HASH_MD5]);
968
compute_hash[CLI_HASH_MD5] = 1;
969
if(compute_hash[CLI_HASH_SHA1]) {
970
cl_finish_hash(sha1ctx, digest[CLI_HASH_SHA1]);
973
if(compute_hash[CLI_HASH_SHA256]) {
974
cl_finish_hash(sha256ctx, digest[CLI_HASH_SHA256]);
979
for(hashtype = CLI_HASH_MD5; hashtype < CLI_HASH_AVAIL_TYPES; hashtype++) {
980
const char * virname_w = NULL;
983
/* If no hash, skip to next type */
984
if(!compute_hash[hashtype])
988
if((ret = cli_hm_scan(digest[hashtype], map->len, &virname, hdb, hashtype)) == CL_VIRUS) {
991
if(!found || SCAN_ALL) {
992
if ((ret = cli_hm_scan_wild(digest[hashtype], &virname_w, hdb, hashtype)) == CL_VIRUS)
996
/* If found, do immediate hash-only FP check */
998
for(hashtype2 = CLI_HASH_MD5; hashtype2 < CLI_HASH_AVAIL_TYPES; hashtype2++) {
999
if(!compute_hash[hashtype2])
1001
if(cli_hm_scan(digest[hashtype2], map->len, NULL, fp, hashtype2) == CL_VIRUS) {
1006
else if(cli_hm_scan_wild(digest[hashtype2], NULL, fp, hashtype2) == CL_VIRUS) {
1014
/* If matched size-based hash ... */
1017
cli_append_virus(ctx, virname);
1022
/* If matched size-agnostic hash ... */
1025
cli_append_virus(ctx, virname_w);
1033
cl_hash_destroy(md5ctx);
1034
cl_hash_destroy(sha1ctx);
1035
cl_hash_destroy(sha256ctx);
1038
if(ret != CL_VIRUS || SCAN_ALL)
1039
ret = cli_lsig_eval(ctx, troot, &tdata, &info, (const char *)refhash);
1040
if (ret == CL_VIRUS)
1043
cli_ac_freedata(&tdata);
1045
cli_bm_freeoff(&toff);
1049
if(ret != CL_VIRUS || SCAN_ALL)
1050
ret = cli_lsig_eval(ctx, groot, &gdata, &info, (const char *)refhash);
1051
cli_ac_freedata(&gdata);
1054
if(info.exeinfo.section)
1055
free(info.exeinfo.section);
1057
cli_hashset_destroy(&info.exeinfo.vinfo);
1059
if (SCAN_ALL && viruses_found)
1064
return (acmode & AC_SCAN_FT) ? type : CL_CLEAN;
1067
int cli_matchmeta(cli_ctx *ctx, const char *fname, size_t fsizec, size_t fsizer, int encrypted, unsigned int filepos, int res1, void *res2)
1069
const struct cli_cdb *cdb;
1070
unsigned int viruses_found = 0;
1072
cli_dbgmsg("CDBNAME:%s:%lu:%s:%lu:%lu:%d:%u:%u:%p\n",
1073
cli_ftname(ctx->container_type), fsizec, fname, fsizec, fsizer, encrypted, filepos, res1, res2);
1075
if (ctx->engine && ctx->engine->cb_meta)
1076
if (ctx->engine->cb_meta(cli_ftname(ctx->container_type), fsizec, fname, fsizer, encrypted, filepos, ctx->cb_ctx) == CL_VIRUS) {
1077
cli_dbgmsg("inner file blacklisted by callback: %s\n", fname);
1079
cli_append_virus(ctx, "Detected.By.Callback");
1085
if(!ctx->engine || !(cdb = ctx->engine->cdb))
1089
if(cdb->ctype != CL_TYPE_ANY && cdb->ctype != ctx->container_type)
1092
if(cdb->encrypted != 2 && cdb->encrypted != encrypted)
1095
if(cdb->res1 && (cdb->ctype == CL_TYPE_ZIP || cdb->ctype == CL_TYPE_RAR) && cdb->res1 != res1)
1098
#define CDBRANGE(field, val) \
1099
if(field[0] != CLI_OFF_ANY) { \
1100
if(field[0] == field[1] && field[0] != val) \
1102
else if(field[0] != field[1] && ((field[0] && field[0] > val) ||\
1103
(field[1] && field[1] < val))) \
1107
CDBRANGE(cdb->csize, ctx->container_size);
1108
CDBRANGE(cdb->fsizec, fsizec);
1109
CDBRANGE(cdb->fsizer, fsizer);
1110
CDBRANGE(cdb->filepos, filepos);
1112
if(cdb->name.re_magic && (!fname || cli_regexec(&cdb->name, fname, 0, NULL, 0) == REG_NOMATCH))
1115
cli_append_virus(ctx, cdb->virname);
1120
} while((cdb = cdb->next));
1122
if (SCAN_ALL && viruses_found)