libclamav: check file sizes for MD5 sigs in all cases

0.96
Tomasz Kojm 16 years ago
parent 862cc2d7f5
commit 6c26e99c59
  1. 5
      ChangeLog
  2. 4
      libclamav/matcher-bm.c
  3. 4
      libclamav/matcher-bm.h
  4. 31
      libclamav/matcher.c
  5. 5
      libclamav/pe.c
  6. 4
      libclamav/phishcheck.c
  7. 7
      libclamav/readdb.c
  8. 2
      libclamav/regex_list.c
  9. 2
      unit_tests/check_matchers.c

@ -1,3 +1,8 @@
Fri Oct 2 21:01:51 CEST 2009 (tk)
----------------------------------
* libclamav: check file sizes for MD5 sigs in all cases
Reported by Edwin
Fri Oct 2 14:35:42 CEST 2009 (tk)
----------------------------------
* libclamav: unify fp checking; output fp signatures in debug mode

@ -245,7 +245,7 @@ void cli_bm_free(struct cli_matcher *root)
}
}
int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, int fd, struct cli_bm_off *offdata)
int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_bm_patt **patt, const struct cli_matcher *root, uint32_t offset, int fd, struct cli_bm_off *offdata)
{
uint32_t i, j, off, off_min, off_max;
uint8_t found, pchain, shift;
@ -370,6 +370,8 @@ int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
}
if(virname)
*virname = p->virname;
if(patt)
*patt = p;
if(info.exeinfo.section)
free(info.exeinfo.section);
return CL_VIRUS;

@ -35,7 +35,7 @@ struct cli_bm_patt {
uint16_t length, prefix_length;
uint16_t cnt;
unsigned char pattern0;
uint32_t boundary;
uint32_t boundary, filesize;
};
struct cli_bm_off {
@ -46,7 +46,7 @@ int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern, const
int cli_bm_init(struct cli_matcher *root);
int cli_bm_initoff(const struct cli_matcher *root, struct cli_bm_off *data, int fd);
void cli_bm_freeoff(struct cli_bm_off *data, const struct cli_matcher *root);
int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, int fd, struct cli_bm_off *offdata);
int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_bm_patt **patt, const struct cli_matcher *root, uint32_t offset, int fd, struct cli_bm_off *offdata);
void cli_bm_free(struct cli_matcher *root);
#endif

@ -76,7 +76,7 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset,
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, troot, offset, -1, NULL)) != CL_VIRUS)
if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, NULL, troot, offset, -1, NULL)) != CL_VIRUS)
ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, troot, acdata ? (acdata[0]) : (&mdata), offset, ftype, NULL, AC_SCAN_VIR, NULL);
if(!acdata)
@ -89,7 +89,7 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset,
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, groot, offset, -1, NULL)) != CL_VIRUS)
if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, NULL, groot, offset, -1, NULL)) != CL_VIRUS)
ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, groot, acdata ? (acdata[1]) : (&mdata), offset, ftype, NULL, AC_SCAN_VIR, NULL);
if(!acdata)
@ -292,6 +292,7 @@ int cli_checkfp(int fd, cli_ctx *ctx)
const char *virname;
off_t pos;
struct stat sb;
const struct cli_bm_patt *patt = NULL;
if((pos = lseek(fd, 0, SEEK_CUR)) == -1) {
@ -302,25 +303,29 @@ int cli_checkfp(int fd, cli_ctx *ctx)
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(!(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, ctx->engine->md5_fp, 0, -1, NULL) == CL_VIRUS) {
if(cli_bm_scanbuff(digest, 16, &virname, &patt, ctx->engine->md5_fp, 0, -1, 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;
}
if(fstat(fd, &sb) != -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");
}
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);
}
@ -425,7 +430,7 @@ int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struc
length += maxpatlen;
if(troot) {
if(troot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, troot, offset, desc, bm_offmode ? &toff : NULL)) != CL_VIRUS)
if(troot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, NULL, troot, offset, desc, bm_offmode ? &toff : NULL)) != CL_VIRUS)
ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, troot, &tdata, offset, ftype, ftoffset, acmode, NULL);
if(ret == CL_VIRUS) {
@ -440,7 +445,7 @@ int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struc
}
if(!ftonly) {
if(groot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, groot, offset, desc, NULL)) != CL_VIRUS)
if(groot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, NULL, groot, offset, desc, NULL)) != CL_VIRUS)
ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, groot, &gdata, offset, ftype, ftoffset, acmode, NULL);
if(ret == CL_VIRUS) {
@ -514,8 +519,10 @@ int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struc
return CL_VIRUS;
if(!ftonly && ctx->engine->md5_hdb) {
const struct cli_bm_patt *patt;
cli_md5_final(digest, &md5ctx);
if(cli_bm_scanbuff(digest, 16, ctx->virname, ctx->engine->md5_hdb, 0, -1, NULL) == CL_VIRUS && (cli_bm_scanbuff(digest, 16, NULL, ctx->engine->md5_fp, 0, -1, NULL) != CL_VIRUS))
fstat(desc, &sb);
if(cli_bm_scanbuff(digest, 16, ctx->virname, &patt, ctx->engine->md5_hdb, 0, -1, NULL) == CL_VIRUS && patt->filesize == sb.st_size && (cli_bm_scanbuff(digest, 16, NULL, &patt, ctx->engine->md5_fp, 0, -1, NULL) != CL_VIRUS || patt->filesize != sb.st_size))
return CL_VIRUS;
}

@ -924,8 +924,9 @@ int cli_scanpe(int desc, cli_ctx *ctx)
for(j = 0; j < md5_sect->soff_len && md5_sect->soff[j] <= exe_sections[i].rsz; j++) {
if(md5_sect->soff[j] == exe_sections[i].rsz) {
unsigned char md5_dig[16];
if(cli_md5sect(desc, &exe_sections[i], md5_dig) && cli_bm_scanbuff(md5_dig, 16, ctx->virname, ctx->engine->md5_mdb, 0, -1, NULL) == CL_VIRUS) {
if(cli_bm_scanbuff(md5_dig, 16, NULL, ctx->engine->md5_fp, 0, -1, NULL) != CL_VIRUS) {
const struct cli_bm_patt *patt;
if(cli_md5sect(desc, &exe_sections[i], md5_dig) && cli_bm_scanbuff(md5_dig, 16, ctx->virname, &patt, ctx->engine->md5_mdb, 0, -1, NULL) == CL_VIRUS && patt->filesize == exe_sections[i].rsz) {
if(cli_bm_scanbuff(md5_dig, 16, NULL, &patt, ctx->engine->md5_fp, 0, -1, NULL) != CL_VIRUS || patt->filesize != fsize) {
free(section_hdr);
free(exe_sections);

@ -1194,13 +1194,13 @@ static int hash_match(const struct regex_matcher *rlist, const char *host, size_
h[64]='\0';
cli_dbgmsg("Looking up hash %s for %s(%u)%s(%u)\n", h, host, (unsigned)hlen, path, (unsigned)plen);
if (prefix_matched) {
if (cli_bm_scanbuff(sha256_dig, 4, &virname, &rlist->hostkey_prefix,0,-1,NULL) == CL_VIRUS) {
if (cli_bm_scanbuff(sha256_dig, 4, &virname, NULL, &rlist->hostkey_prefix,0,-1,NULL) == CL_VIRUS) {
cli_dbgmsg("prefix matched\n");
*prefix_matched = 1;
} else
return CL_SUCCESS;
}
if (cli_bm_scanbuff(sha256_dig, 32, &virname, &rlist->sha256_hashes,0,-1,NULL) == CL_VIRUS) {
if (cli_bm_scanbuff(sha256_dig, 32, &virname, NULL, &rlist->sha256_hashes,0,-1,NULL) == CL_VIRUS) {
cli_dbgmsg("This hash matched: %s\n", h);
switch(*virname) {
case 'W':

@ -406,7 +406,7 @@ static int cli_chkign(const struct cli_matcher *ignored, const char *signame, co
if(!ignored || !signame || !entry)
return 0;
if(cli_bm_scanbuff(signame, strlen(signame), &md5_expected, ignored, 0, -1, NULL) == CL_VIRUS) {
if(cli_bm_scanbuff(signame, strlen(signame), &md5_expected, NULL, ignored, 0, -1, NULL) == CL_VIRUS) {
if(md5_expected) {
cli_md5_init(&md5ctx);
cli_md5_update(&md5ctx, entry, strlen(entry));
@ -1289,7 +1289,6 @@ static int cli_loadmd5(FILE *fs, struct cl_engine *engine, unsigned int *signo,
const char *pt;
int ret = CL_SUCCESS;
unsigned int size_field = 1, md5_field = 0, line = 0, sigs = 0, tokens_count;
uint32_t size;
struct cli_bm_patt *new;
struct cli_matcher *db = NULL;
@ -1343,7 +1342,7 @@ static int cli_loadmd5(FILE *fs, struct cl_engine *engine, unsigned int *signo,
}
new->length = 16;
size = atoi(tokens[size_field]);
new->filesize = atoi(tokens[size_field]);
new->virname = cli_mpool_virname(engine->mempool, (char *) tokens[2], options & CL_DB_OFFICIAL);
if(!new->virname) {
@ -1375,7 +1374,7 @@ static int cli_loadmd5(FILE *fs, struct cl_engine *engine, unsigned int *signo,
if(!db->md5_sizes_hs.capacity) {
cli_hashset_init(&db->md5_sizes_hs, 65536, 80);
}
cli_hashset_addkey(&db->md5_sizes_hs, size);
cli_hashset_addkey(&db->md5_sizes_hs, new->filesize);
}
sigs++;

@ -455,7 +455,7 @@ static int add_hash(struct regex_matcher *matcher, char* pattern, const char fl,
if (fl != 'W' && pat->length == 32 &&
cli_hashset_contains(&matcher->sha256_pfx_set, cli_readint32(pat->pattern)) &&
cli_bm_scanbuff(pat->pattern, 32, &vname, &matcher->sha256_hashes,0,-1,NULL) == CL_VIRUS) {
cli_bm_scanbuff(pat->pattern, 32, &vname, NULL, &matcher->sha256_hashes,0,-1,NULL) == CL_VIRUS) {
if (*vname == 'W') {
/* hash is whitelisted in local.gdb */
cli_dbgmsg("Skipping hash %s\n", pattern);

@ -116,7 +116,7 @@ START_TEST (test_bm_scanbuff) {
ret = cli_parse_add(root, "Sig3", "babedead", 0, 0, "*", 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, -1,NULL);
ret = cli_bm_scanbuff("blah\xde\xad\xbe\xef", 12, &virname, NULL, root, 0, -1, NULL);
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);

Loading…
Cancel
Save