e3aaff8e |
/* |
33872a43 |
* Copyright (C) 2007-2009 Sourcefire, Inc. |
4addba22 |
* |
2023340a |
* Authors: Tomasz Kojm |
e3aaff8e |
*
* This program is free software; you can redistribute it and/or modify |
bb34cb31 |
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. |
e3aaff8e |
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software |
48b7b4a7 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA. |
e3aaff8e |
*/
|
6d6e8271 |
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
|
e3aaff8e |
#include <string.h> |
7ec67e94 |
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h> |
b58fdfc2 |
#ifdef HAVE_UNISTD_H |
7ec67e94 |
#include <unistd.h> |
b58fdfc2 |
#endif |
e3aaff8e |
#include "clamav.h"
#include "others.h" |
8000d078 |
#include "matcher-ac.h"
#include "matcher-bm.h"
#include "md5.h" |
888f5794 |
#include "filetypes.h" |
b68d11d2 |
#include "matcher.h" |
7ec67e94 |
#include "pe.h" |
01302683 |
#include "elf.h"
#include "execs.h" |
c3a3be2d |
#include "special.h" |
7770d314 |
#include "scanners.h" |
c9c463fe |
#include "str.h" |
bedc58de |
#include "cltypes.h" |
589d8d8e |
#include "default.h" |
8af7ccd0 |
#include "macho.h" |
048d7677 |
#include "fmap.h" |
0f7ba617 |
#include "pe_icons.h" |
55094a9c |
#include "regex/regex.h" |
02eabc6d |
#include "filtering.h"
#include "perflogging.h" |
1dae00eb |
#include "bytecode_priv.h"
#include "bytecode_api_impl.h" |
02eabc6d |
|
16b28d07 |
#ifdef HAVE__INTERNAL__SHA_COLLECT
#include "sha256.h"
#include "sha1.h"
#endif
|
02eabc6d |
#ifdef CLI_PERF_LOGGING
static inline void PERF_LOG_FILTER(int32_t pos, int32_t length, int8_t trie)
{
cli_perf_log_add(RAW_BYTES_SCANNED, length);
cli_perf_log_add(FILTER_BYTES_SCANNED, length - pos);
cli_perf_log_count2(TRIE_SCANNED, trie, length - pos);
}
static inline int PERF_LOG_TRIES(int8_t acmode, int8_t bm_called, int32_t length)
{
if (bm_called)
cli_perf_log_add(BM_SCANNED, length);
if (acmode)
cli_perf_log_add(AC_SCANNED, length);
return 0;
}
#else
static inline void PERF_LOG_FILTER(int32_t pos, uint32_t length, int8_t trie) {}
static inline int PERF_LOG_TRIES(int8_t acmode, int8_t bm_called, int32_t length) { return 0; }
#endif |
53721687 |
|
2a94c08e |
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, |
294558a5 |
const struct cli_target_info *tinfo, |
2a94c08e |
cli_file_t ftype,
struct cli_matched_type **ftoffset, |
461a7bd9 |
unsigned int acmode, |
ffa9b060 |
struct cli_ac_result **acres, |
461a7bd9 |
fmap_t *map,
struct cli_bm_off *offdata) |
2a94c08e |
{
int ret; |
02eabc6d |
int32_t pos = 0;
struct filter_match_info info; |
7ba110bd |
uint32_t orig_length, orig_offset;
const unsigned char* orig_buffer;
|
02eabc6d |
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);
} |
7ba110bd |
orig_length = length;
orig_buffer = buffer;
orig_offset = offset; |
02eabc6d |
length -= pos;
buffer += pos;
offset += pos; |
7ba110bd |
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 */ |
294558a5 |
ret = cli_bm_scanbuff(orig_buffer, orig_length, virname, NULL, root, orig_offset, tinfo, offdata); |
7ba110bd |
} else { |
294558a5 |
ret = cli_bm_scanbuff(buffer, length, virname, NULL, root, offset, tinfo, offdata); |
7ba110bd |
}
if (ret == CL_VIRUS)
return ret; |
02eabc6d |
} |
7ba110bd |
PERF_LOG_TRIES(acmode, 0, length); |
ffa9b060 |
ret = cli_ac_scanbuff(buffer, length, virname, NULL, acres, root, mdata, offset, ftype, ftoffset, acmode, NULL); |
2a94c08e |
return ret;
} |
53721687 |
|
e06afe8e |
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) |
8000d078 |
{ |
bedc58de |
int ret = CL_CLEAN;
unsigned int i; |
4e9ab8ed |
struct cli_ac_data mdata; |
5612732c |
struct cli_matcher *groot, *troot = NULL; |
2ac2095a |
const char **virname=ctx->virname;
const struct cl_engine *engine=ctx->engine; |
e3aaff8e |
|
5612732c |
if(!engine) {
cli_errmsg("cli_scanbuff: engine == NULL\n");
return CL_ENULLARG;
}
groot = engine->root[0]; /* generic signatures */
if(ftype) { |
4addba22 |
for(i = 1; i < CLI_MTARGETS; i++) {
if(cli_mtargets[i].target == ftype) { |
f46d2cc7 |
troot = engine->root[i]; |
5612732c |
break;
}
}
}
if(troot) {
|
aca9ea82 |
if(!acdata && (ret = cli_ac_initdata(&mdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN))) |
4e9ab8ed |
return ret; |
5612732c |
|
294558a5 |
ret = matcher_run(troot, buffer, length, virname, acdata ? (acdata[0]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, NULL, *ctx->fmap, NULL); |
5612732c |
|
01386195 |
if(!acdata)
cli_ac_freedata(&mdata); |
5612732c |
|
cbb9db19 |
if(ret == CL_VIRUS || ret == CL_EMEM) |
5612732c |
return ret;
}
|
aca9ea82 |
if(!acdata && (ret = cli_ac_initdata(&mdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN))) |
4e9ab8ed |
return ret; |
e3aaff8e |
|
294558a5 |
ret = matcher_run(groot, buffer, length, virname, acdata ? (acdata[1]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, NULL, *ctx->fmap, NULL); |
4e9ab8ed |
|
01386195 |
if(!acdata)
cli_ac_freedata(&mdata); |
8000d078 |
return ret; |
e3aaff8e |
}
|
33872a43 |
/*
* offdata[0]: type
* offdata[1]: offset value
* offdata[2]: max shift
* offdata[3]: section number
*/ |
294558a5 |
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) |
7ec67e94 |
{ |
33872a43 |
char offcpy[65]; |
bda5598b |
unsigned int n, val; |
33872a43 |
char *pt; |
e06afe8e |
|
33872a43 |
if(!info) { /* decode offset string */
if(!offstr) {
cli_errmsg("cli_caloff: offstr == NULL\n");
return CL_ENULLARG;
} |
e06afe8e |
|
33872a43 |
if(!strcmp(offstr, "*")) {
offdata[0] = *offset_max = *offset_min = CLI_OFF_ANY;
return CL_SUCCESS;
} |
e06afe8e |
|
33872a43 |
if(strlen(offstr) > 64) {
cli_errmsg("cli_caloff: Offset string too long\n");
return CL_EMALFDB;
}
strcpy(offcpy, offstr); |
841161e0 |
|
33872a43 |
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;
} |
841161e0 |
|
33872a43 |
*offset_max = *offset_min = CLI_OFF_NONE; |
841161e0 |
|
33872a43 |
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; |
841161e0 |
|
33872a43 |
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; |
841161e0 |
} |
33872a43 |
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;
} |
841161e0 |
|
33872a43 |
} 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; |
841161e0 |
} |
33872a43 |
offdata[1] = atoi(&offcpy[4]); |
d2ba6f98 |
} else if(!strncmp(offcpy, "VI", 2)) {
/* versioninfo */
offdata[0] = CLI_OFF_VERSION; |
ab893605 |
} 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; |
33872a43 |
} 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]; |
841161e0 |
} |
4d1136fe |
|
ab893605 |
if(offdata[0] != CLI_OFF_ANY && offdata[0] != CLI_OFF_ABSOLUTE &&
offdata[0] != CLI_OFF_EOF_MINUS && offdata[0] != CLI_OFF_MACRO) { |
33872a43 |
if(target != 1 && target != 6 && target != 9) {
cli_errmsg("cli_caloff: Invalid offset type for target %u\n", target);
return CL_EMALFDB;
}
} |
7ec67e94 |
|
33872a43 |
} else {
/* calculate relative offsets */
if(info->status == -1) { |
006f5fe6 |
*offset_min = CLI_OFF_NONE;
if(offset_max)
*offset_max = CLI_OFF_NONE; |
33872a43 |
return CL_SUCCESS;
} |
7ec67e94 |
|
33872a43 |
switch(offdata[0]) {
case CLI_OFF_EOF_MINUS:
*offset_min = info->fsize - offdata[1];
break; |
399bd596 |
|
33872a43 |
case CLI_OFF_EP_PLUS:
*offset_min = info->exeinfo.ep + offdata[1];
break; |
7ec67e94 |
|
33872a43 |
case CLI_OFF_EP_MINUS:
*offset_min = info->exeinfo.ep - offdata[1];
break;
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) |
006f5fe6 |
*offset_min = CLI_OFF_NONE; |
33872a43 |
else
*offset_min = info->exeinfo.section[offdata[3]].raw + offdata[1];
break; |
d2ba6f98 |
case CLI_OFF_VERSION:
*offset_min = *offset_max = CLI_OFF_ANY;
break; |
33872a43 |
default:
cli_errmsg("cli_caloff: Not a relative offset (type: %u)\n", offdata[0]);
return CL_EARG; |
841161e0 |
} |
7ec67e94 |
|
fbc33106 |
if(offset_max) {
if(*offset_min != CLI_OFF_NONE)
*offset_max = *offset_min + offdata[2];
else
*offset_max = CLI_OFF_NONE;
} |
7ec67e94 |
}
|
33872a43 |
return CL_SUCCESS; |
7ec67e94 |
}
|
294558a5 |
static void targetinfo(struct cli_target_info *info, unsigned int target, fmap_t *map)
{
int (*einfo)(fmap_t *, struct cli_exe_info *) = NULL;
memset(info, 0, sizeof(struct cli_target_info));
info->fsize = map->len; |
04ec2e19 |
cli_hashset_init_noalloc(&info->exeinfo.vinfo); |
294558a5 |
if(target == 1)
einfo = cli_peheader;
else if(target == 6)
einfo = cli_elfheader;
else if(target == 9)
einfo = cli_machoheader;
else return;
if(einfo(map, &info->exeinfo))
info->status = -1;
else
info->status = 1;
}
|
32b1e04e |
int cli_checkfp(unsigned char *digest, size_t size, cli_ctx *ctx) |
db65451b |
{ |
6416cdef |
char md5[33];
unsigned int i; |
2b459819 |
const char *virname; |
db65451b |
|
2296ab0f |
if(ctx->engine->hm_fp && cli_hm_scan(digest, size, &virname, ctx->engine->hm_fp, CLI_HASH_MD5) == CL_VIRUS) {
cli_dbgmsg("cli_checkfp(): Found false positive detection (fp sig: %s)\n", virname);
return CL_CLEAN;
}
|
32b1e04e |
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) size, *ctx->virname ? *ctx->virname : "Name"); |
16b28d07 |
#ifdef HAVE__INTERNAL__SHA_COLLECT |
3d7547cf |
if((ctx->options & CL_SCAN_INTERNAL_COLLECT_SHA) && ctx->sha_collect>0) { |
16b28d07 |
SHA1Context sha1;
SHA256_CTX sha256;
fmap_t *map = *ctx->fmap;
char *ptr;
uint8_t shash1[SHA1_HASH_SIZE*2+1];
uint8_t shash256[SHA256_HASH_SIZE*2+1];
if((ptr = fmap_need_off_once(map, 0, size))) {
sha256_init(&sha256);
sha256_update(&sha256, ptr, size);
sha256_final(&sha256, &shash256[SHA256_HASH_SIZE]);
for(i=0; i<SHA256_HASH_SIZE; i++)
sprintf((char *)shash256+i*2, "%02x", shash256[SHA256_HASH_SIZE+i]);
SHA1Init(&sha1);
SHA1Update(&sha1, ptr, size);
SHA1Final(&sha1, &shash1[SHA1_HASH_SIZE]);
for(i=0; i<SHA1_HASH_SIZE; i++)
sprintf((char *)shash1+i*2, "%02x", shash1[SHA1_HASH_SIZE+i]);
cli_errmsg("COLLECT:%s:%s:%u:%s:%s\n", shash256, shash1, size, *ctx->virname, ctx->entry_filename);
} else
cli_errmsg("can't compute sha\n!");
ctx->sha_collect = -1;
}
#endif
|
769f37a6 |
if (ctx->engine->cb_hash)
ctx->engine->cb_hash(ctx->fmap[0]->fd, size, md5, ctx->virname ? *ctx->virname : NULL, ctx->cb_ctx); |
edbba730 |
|
32b1e04e |
return CL_VIRUS; |
db65451b |
}
|
453d8180 |
static int matchicon(cli_ctx *ctx, struct cli_exe_info *exeinfo, const char *grp1, const char *grp2) |
0f7ba617 |
{
icon_groupset iconset;
|
453d8180 |
if(!ctx ||
!ctx->engine ||
!ctx->engine->iconcheck ||
!ctx->engine->iconcheck->group_counts[0] ||
!ctx->engine->iconcheck->group_counts[1] ||
!exeinfo->res_addr
) return CL_CLEAN;
|
0f7ba617 |
cli_icongroupset_init(&iconset);
cli_icongroupset_add(grp1 ? grp1 : "*", &iconset, 0, ctx);
cli_icongroupset_add(grp2 ? grp2 : "*", &iconset, 1, ctx); |
453d8180 |
return cli_scanicon(&iconset, exeinfo->res_addr, ctx, exeinfo->section, exeinfo->nsections, exeinfo->hdr_size); |
0f7ba617 |
}
|
1dae00eb |
int32_t cli_bcapi_matchicon(struct cli_bc_ctx *ctx , const uint8_t* grp1, int32_t grp1len,
const uint8_t* grp2, int32_t grp2len)
{ |
7882e721 |
int ret; |
1dae00eb |
char group1[128], group2[128]; |
762d46e8 |
const char **oldvirname; |
7882e721 |
struct cli_exe_info info;
|
762d46e8 |
if (!ctx->hooks.pedata->ep) { |
1dae00eb |
cli_dbgmsg("bytecode: matchicon only works with PE files\n");
return -1;
} |
661e8e3f |
if ((size_t) grp1len > sizeof(group1)-1 ||
(size_t) grp2len > sizeof(group2)-1) |
1dae00eb |
return -1; |
e865b2d8 |
oldvirname = ((cli_ctx*)ctx->ctx)->virname; |
762d46e8 |
((cli_ctx*)ctx->ctx)->virname = NULL; |
1dae00eb |
memcpy(group1, grp1, grp1len);
memcpy(group2, grp2, grp2len);
group1[grp1len] = 0; |
762d46e8 |
group2[grp2len] = 0; |
7882e721 |
memset(&info, 0, sizeof(info)); |
4abbeb3a |
if (ctx->bc->kind == BC_PE_UNPACKER || ctx->bc->kind == BC_PE_ALL) { |
762d46e8 |
if(le16_to_host(ctx->hooks.pedata->file_hdr.Characteristics) & 0x2000 ||
!ctx->hooks.pedata->dirs[2].Size)
info.res_addr = 0;
else
info.res_addr = le32_to_host(ctx->hooks.pedata->dirs[2].VirtualAddress);
} else
info.res_addr = ctx->resaddr; /* from target_info */ |
a8935f90 |
info.section = (struct cli_exe_section*)ctx->sections; |
1dae00eb |
info.nsections = ctx->hooks.pedata->nsections;
info.hdr_size = ctx->hooks.pedata->hdr_size; |
762d46e8 |
cli_dbgmsg("bytecode matchicon %s %s\n", group1, group2);
ret = matchicon(ctx->ctx, &info, group1[0] ? group1 : NULL,
group2[0] ? group2 : NULL); |
e865b2d8 |
((cli_ctx*)ctx->ctx)->virname = oldvirname; |
7882e721 |
return ret; |
1dae00eb |
}
|
453d8180 |
|
ffa9b060 |
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) |
e3aaff8e |
{ |
a0c38197 |
int ret = CL_EMEM, empty; |
49cc1e3c |
fmap_t *map = *ctx->fmap; |
fc8e8ca2 |
|
a0c38197 |
if((*ctx->fmap = fmap_check_empty(desc, 0, 0, &empty))) { |
ffa9b060 |
ret = cli_fmap_scandesc(ctx, ftype, ftonly, ftoffset, acmode, acres, NULL); |
742b3a0e |
map->dont_cache_flag = (*ctx->fmap)->dont_cache_flag; |
49cc1e3c |
funmap(*ctx->fmap); |
fc8e8ca2 |
} |
048d7677 |
*ctx->fmap = map; |
a0c38197 |
if(empty)
return CL_CLEAN; |
048d7677 |
return ret; |
fc8e8ca2 |
} |
cceea458 |
|
b240ee01 |
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) |
60dbee52 |
{
unsigned int i, evalcnt;
uint64_t evalids;
fmap_t *map = *ctx->fmap;
for(i = 0; i < root->ac_lsigs; i++) {
evalcnt = 0;
evalids = 0;
cli_ac_chkmacro(root, acdata, i);
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) {
if(root->ac_lsigtable[i]->tdb.container && root->ac_lsigtable[i]->tdb.container[0] != ctx->container_type)
continue;
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))
continue;
if(root->ac_lsigtable[i]->tdb.ep || root->ac_lsigtable[i]->tdb.nos) { |
2445be8c |
if(!target_info || target_info->status != 1) |
60dbee52 |
continue; |
2445be8c |
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)) |
60dbee52 |
continue; |
2445be8c |
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)) |
60dbee52 |
continue;
} |
2445be8c |
|
b240ee01 |
if(hash && root->ac_lsigtable[i]->tdb.handlertype) {
if(memcmp(ctx->handlertype_hash, hash, 16)) {
ctx->recursion++;
memcpy(ctx->handlertype_hash, hash, 16);
if(cli_magic_scandesc_type(map->fd, ctx, root->ac_lsigtable[i]->tdb.handlertype[0]) == CL_VIRUS) {
ctx->recursion--;
return CL_VIRUS;
} |
a0fff76f |
ctx->recursion--; |
b240ee01 |
continue; |
a0fff76f |
} |
7770d314 |
}
|
60dbee52 |
if(root->ac_lsigtable[i]->tdb.icongrp1 || root->ac_lsigtable[i]->tdb.icongrp2) { |
2445be8c |
if(!target_info || target_info->status != 1)
continue; |
453d8180 |
if(matchicon(ctx, &target_info->exeinfo, root->ac_lsigtable[i]->tdb.icongrp1, root->ac_lsigtable[i]->tdb.icongrp2) == CL_VIRUS) { |
9d10f054 |
if(!root->ac_lsigtable[i]->bc_idx) {
if(ctx->virname)
*ctx->virname = root->ac_lsigtable[i]->virname;
return CL_VIRUS; |
0d710688 |
} else if(cli_bytecode_runlsig(ctx, target_info, &ctx->engine->bcs, root->ac_lsigtable[i]->bc_idx, ctx->virname, acdata->lsigcnt[i], acdata->lsigsuboff_first[i], map) == CL_VIRUS) { |
9d10f054 |
return CL_VIRUS;
} |
60dbee52 |
} |
9d10f054 |
continue; |
60dbee52 |
}
if(!root->ac_lsigtable[i]->bc_idx) {
if(ctx->virname)
*ctx->virname = root->ac_lsigtable[i]->virname;
return CL_VIRUS;
} |
0d710688 |
if(cli_bytecode_runlsig(ctx, target_info, &ctx->engine->bcs, root->ac_lsigtable[i]->bc_idx, ctx->virname, acdata->lsigcnt[i], acdata->lsigsuboff_first[i], map) == CL_VIRUS) { |
60dbee52 |
return CL_VIRUS;
}
}
}
return CL_CLEAN;
} |
cceea458 |
|
ffa9b060 |
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) |
cceea458 |
{
unsigned char *buff; |
c7aeeb46 |
int ret = CL_CLEAN, type = CL_CLEAN, bytes; |
2eafc973 |
unsigned int i = 0, bm_offmode = 0; |
cceea458 |
uint32_t maxpatlen, offset = 0; |
4e9ab8ed |
struct cli_ac_data gdata, tdata; |
006f5fe6 |
struct cli_bm_off toff; |
2a9e6ac8 |
cli_md5_ctx md5ctx; |
335d1663 |
unsigned char digest[16]; |
73218de2 |
struct cli_matcher *groot = NULL, *troot = NULL; |
294558a5 |
struct cli_target_info info; |
49cc1e3c |
fmap_t *map = *ctx->fmap; |
888f5794 |
|
3c91998b |
if(!ctx->engine) { |
5612732c |
cli_errmsg("cli_scandesc: engine == NULL\n"); |
8000d078 |
return CL_ENULLARG; |
4048c4f6 |
}
|
73218de2 |
if(!ftonly)
groot = ctx->engine->root[0]; /* generic signatures */ |
5612732c |
if(ftype) { |
4addba22 |
for(i = 1; i < CLI_MTARGETS; i++) {
if(cli_mtargets[i].target == ftype) { |
f46d2cc7 |
troot = ctx->engine->root[i]; |
5612732c |
break;
}
}
}
|
73218de2 |
if(ftonly) {
if(!troot)
return CL_CLEAN;
maxpatlen = troot->maxpatlen;
} else {
if(troot)
maxpatlen = MAX(troot->maxpatlen, groot->maxpatlen);
else
maxpatlen = groot->maxpatlen;
} |
5612732c |
|
294558a5 |
targetinfo(&info, i, map);
|
33872a43 |
if(!ftonly) |
294558a5 |
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); |
04ec2e19 |
cli_hashset_destroy(&info.exeinfo.vinfo); |
33872a43 |
return ret; |
294558a5 |
} |
e3aaff8e |
|
5612732c |
if(troot) { |
294558a5 |
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))) { |
33872a43 |
if(!ftonly)
cli_ac_freedata(&gdata); |
294558a5 |
if(info.exeinfo.section)
free(info.exeinfo.section); |
04ec2e19 |
cli_hashset_destroy(&info.exeinfo.vinfo); |
4e9ab8ed |
return ret; |
33872a43 |
} |
6d3c5bec |
if(troot->bm_offmode) { |
10aa2df7 |
if(map->len >= CLI_DEFAULT_BM_OFFMODE_FSIZE) { |
294558a5 |
if((ret = cli_bm_initoff(troot, &toff, &info))) { |
10aa2df7 |
if(!ftonly)
cli_ac_freedata(&gdata);
cli_ac_freedata(&tdata); |
294558a5 |
if(info.exeinfo.section)
free(info.exeinfo.section); |
04ec2e19 |
cli_hashset_destroy(&info.exeinfo.vinfo); |
10aa2df7 |
return ret; |
6d3c5bec |
} |
10aa2df7 |
bm_offmode = 1; |
6d3c5bec |
} |
006f5fe6 |
} |
5612732c |
}
|
3faa9783 |
if(!refhash && !ftonly && ctx->engine->hm_hdb) |
2a9e6ac8 |
cli_md5_init(&md5ctx); |
e3aaff8e |
|
084d19aa |
while(offset < map->len) { |
b183aa78 |
bytes = MIN(map->len - offset, SCANBUFF); |
13f6bc58 |
if(!(buff = fmap_need_off_once(map, offset, bytes)))
break; |
3c91998b |
if(ctx->scanned)
*ctx->scanned += bytes / CL_COUNT_PRECISION; |
e3aaff8e |
|
5612732c |
if(troot) { |
294558a5 |
ret = matcher_run(troot, buff, bytes, ctx->virname, &tdata, offset, &info, ftype, ftoffset, acmode, acres, map, bm_offmode ? &toff : NULL); |
83fa5305 |
|
cbb9db19 |
if(ret == CL_VIRUS || ret == CL_EMEM) { |
73218de2 |
if(!ftonly)
cli_ac_freedata(&gdata); |
4e9ab8ed |
cli_ac_freedata(&tdata); |
6d3c5bec |
if(bm_offmode) |
e6f5ac51 |
cli_bm_freeoff(&toff); |
294558a5 |
if(info.exeinfo.section)
free(info.exeinfo.section); |
04ec2e19 |
cli_hashset_destroy(&info.exeinfo.vinfo); |
cbb9db19 |
return ret; |
5612732c |
}
} |
db65451b |
|
73218de2 |
if(!ftonly) { |
294558a5 |
ret = matcher_run(groot, buff, bytes, ctx->virname, &gdata, offset, &info, ftype, ftoffset, acmode, acres, map, NULL);
|
cbb9db19 |
if(ret == CL_VIRUS || ret == CL_EMEM) { |
73218de2 |
cli_ac_freedata(&gdata); |
006f5fe6 |
if(troot) { |
73218de2 |
cli_ac_freedata(&tdata); |
6d3c5bec |
if(bm_offmode) |
e6f5ac51 |
cli_bm_freeoff(&toff); |
006f5fe6 |
} |
294558a5 |
if(info.exeinfo.section)
free(info.exeinfo.section); |
04ec2e19 |
cli_hashset_destroy(&info.exeinfo.vinfo); |
cbb9db19 |
return ret; |
6038397e |
} else if((acmode & AC_SCAN_FT) && ret >= CL_TYPENO) { |
73218de2 |
if(ret > type)
type = ret;
} |
e3aaff8e |
|
3faa9783 |
if(!refhash && ctx->engine->hm_hdb) |
2d5dbc37 |
cli_md5_update(&md5ctx, buff + maxpatlen * (offset!=0), bytes - maxpatlen * (offset!=0)); |
73218de2 |
} |
0710165d |
|
b183aa78 |
if(bytes < SCANBUFF) break; |
13f6bc58 |
offset += bytes - maxpatlen; |
8000d078 |
} |
084ee140 |
|
3faa9783 |
if(!ftonly && ctx->engine->hm_hdb) { |
b240ee01 |
if(!refhash) {
cli_md5_final(digest, &md5ctx);
refhash = digest;
} |
2296ab0f |
if(ctx->engine->hm_hdb && cli_hm_scan(refhash, map->len, ctx->virname, ctx->engine->hm_hdb, CLI_HASH_MD5) == CL_VIRUS && cli_hm_scan(refhash, map->len, NULL, ctx->engine->hm_fp, CLI_HASH_MD5) != CL_VIRUS) |
b240ee01 |
ret = CL_VIRUS;
}
|
c7aeeb46 |
if(troot) { |
b240ee01 |
if(ret != CL_VIRUS)
ret = cli_lsig_eval(ctx, troot, &tdata, &info, refhash); |
4e9ab8ed |
cli_ac_freedata(&tdata); |
6d3c5bec |
if(bm_offmode) |
e6f5ac51 |
cli_bm_freeoff(&toff); |
c7aeeb46 |
}
if(groot) { |
17cfd76f |
if(ret != CL_VIRUS) |
b240ee01 |
ret = cli_lsig_eval(ctx, groot, &gdata, &info, refhash); |
c7aeeb46 |
cli_ac_freedata(&gdata);
}
|
2445be8c |
if(info.exeinfo.section)
free(info.exeinfo.section); |
04ec2e19 |
cli_hashset_destroy(&info.exeinfo.vinfo); |
2445be8c |
|
6416cdef |
if(ret == CL_VIRUS)
return CL_VIRUS; |
fc8e8ca2 |
|
6038397e |
return (acmode & AC_SCAN_FT) ? type : CL_CLEAN; |
fc8e8ca2 |
} |
55094a9c |
|
570b1d00 |
int cli_matchmeta(cli_ctx *ctx, const char *fname, size_t fsizec, size_t fsizer, int encrypted, int filepos, int res1, void *res2) |
55094a9c |
{
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;
|
15f413d1 |
if(cdb->res1 && (cdb->ctype == CL_TYPE_ZIP || cdb->ctype == CL_TYPE_RAR) && cdb->res1 != res1)
continue; |
55094a9c |
|
15f413d1 |
#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; \ |
55094a9c |
}
|
15f413d1 |
CDBRANGE(cdb->csize, ctx->container_size);
CDBRANGE(cdb->fsizec, fsizec);
CDBRANGE(cdb->fsizer, fsizer);
CDBRANGE(cdb->filepos, filepos); |
55094a9c |
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;
} |