~ubuntu-branches/ubuntu/saucy/clamav/saucy-backports

« back to all changes in this revision

Viewing changes to libclamav/matcher.c

  • Committer: Package Import Robot
  • Author(s): Scott Kitterman
  • Date: 2014-07-15 01:08:10 UTC
  • mfrom: (0.35.47 sid)
  • Revision ID: package-import@ubuntu.com-20140715010810-ru66ek4fun2iseba
Tags: 0.98.4+dfsg-2~ubuntu13.10.1
No-change backport to saucy (LP: #1341962)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 *  Copyright (C) 2007-2009 Sourcefire, Inc.
 
2
 *  Copyright (C) 2007-2013 Sourcefire, Inc.
3
3
 *
4
4
 *  Authors: Tomasz Kojm
5
5
 *
30
30
#include <unistd.h>
31
31
#endif
32
32
 
 
33
#include <openssl/ssl.h>
 
34
#include <openssl/err.h>
 
35
#include "libclamav/crypto.h"
 
36
 
33
37
#include "clamav.h"
34
38
#include "others.h"
35
39
#include "matcher-ac.h"
36
40
#include "matcher-bm.h"
37
 
#include "md5.h"
38
 
#include "sha1.h"
39
 
#include "sha256.h"
40
41
#include "filetypes.h"
41
42
#include "matcher.h"
42
43
#include "pe.h"
55
56
#include "perflogging.h"
56
57
#include "bytecode_priv.h"
57
58
#include "bytecode_api_impl.h"
58
 
#include "sha256.h"
59
 
#include "sha1.h"
60
59
 
61
60
#ifdef CLI_PERF_LOGGING
62
61
 
159
158
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)
160
159
{
161
160
        int ret = CL_CLEAN;
162
 
        unsigned int i, viruses_found = 0;
 
161
        unsigned int i = 0, j = 0, viruses_found = 0;
163
162
        struct cli_ac_data mdata;
164
163
        struct cli_matcher *groot, *troot = NULL;
165
164
        const char *virname = NULL;
173
172
    groot = engine->root[0]; /* generic signatures */
174
173
 
175
174
    if(ftype) {
176
 
        for(i = 1; i < CLI_MTARGETS; i++) {
177
 
            if(cli_mtargets[i].target == ftype) {
178
 
                troot = engine->root[i];
179
 
                break;
180
 
            }
181
 
        }
 
175
        for(i = 1; i < CLI_MTARGETS; i++) {
 
176
            for (j = 0; j < cli_mtargets[i].target_count; ++j) {
 
177
                if(cli_mtargets[i].target[j] == ftype) {
 
178
                    troot = ctx->engine->root[i];
 
179
                    break;
 
180
                }
 
181
            }
 
182
            if (troot) break;
 
183
        }
182
184
    }
183
185
 
184
186
    if(troot) {
393
395
    return CL_SUCCESS;
394
396
}
395
397
 
396
 
static void targetinfo(struct cli_target_info *info, unsigned int target, fmap_t *map)
 
398
void cli_targetinfo(struct cli_target_info *info, unsigned int target, fmap_t *map)
397
399
{
398
400
        int (*einfo)(fmap_t *, struct cli_exe_info *) = NULL;
399
401
 
418
420
 
419
421
int cli_checkfp(unsigned char *digest, size_t size, cli_ctx *ctx)
420
422
{
421
 
        char md5[33];
422
 
        unsigned int i;
423
 
        const char *virname;
424
 
        SHA1Context sha1;
425
 
        SHA256_CTX sha256;
426
 
        fmap_t *map;
427
 
        const char *ptr;
428
 
        uint8_t shash1[SHA1_HASH_SIZE*2+1];
429
 
        uint8_t shash256[SHA256_HASH_SIZE*2+1];
430
 
        int have_sha1, have_sha256, do_dsig_check = 1;
 
423
    char md5[33];
 
424
    unsigned int i;
 
425
    const char *virname=NULL;
 
426
    fmap_t *map;
 
427
    const char *ptr;
 
428
    uint8_t shash1[SHA1_HASH_SIZE*2+1];
 
429
    uint8_t shash256[SHA256_HASH_SIZE*2+1];
 
430
    int have_sha1, have_sha256, do_dsig_check = 1;
 
431
    stats_section_t sections;
431
432
 
432
433
    if(cli_hm_scan(digest, size, &virname, ctx->engine->hm_fp, CLI_HASH_MD5) == CL_VIRUS) {
433
 
        cli_dbgmsg("cli_checkfp(md5): Found false positive detection (fp sig: %s), size: %d\n", virname, (int)size);
434
 
        return CL_CLEAN;
 
434
        cli_dbgmsg("cli_checkfp(md5): Found false positive detection (fp sig: %s), size: %d\n", virname, (int)size);
 
435
        return CL_CLEAN;
435
436
    }
436
437
    else if(cli_hm_scan_wild(digest, &virname, ctx->engine->hm_fp, CLI_HASH_MD5) == CL_VIRUS) {
437
 
        cli_dbgmsg("cli_checkfp(md5): Found false positive detection (fp sig: %s), size: *\n", virname);
438
 
        return CL_CLEAN;
 
438
        cli_dbgmsg("cli_checkfp(md5): Found false positive detection (fp sig: %s), size: *\n", virname);
 
439
        return CL_CLEAN;
439
440
    }
440
441
 
441
442
    if(cli_debug_flag || ctx->engine->cb_hash) {
442
 
        for(i = 0; i < 16; i++)
443
 
            sprintf(md5 + i * 2, "%02x", digest[i]);
444
 
        md5[32] = 0;
445
 
        cli_dbgmsg("FP SIGNATURE: %s:%u:%s\n", md5, (unsigned int) size,
446
 
                   cli_get_last_virus(ctx) ? cli_get_last_virus(ctx) : "Name");
 
443
        for(i = 0; i < 16; i++)
 
444
            sprintf(md5 + i * 2, "%02x", digest[i]);
 
445
        md5[32] = 0;
 
446
        cli_dbgmsg("FP SIGNATURE: %s:%u:%s\n", md5, (unsigned int) size,
 
447
               cli_get_last_virus(ctx) ? cli_get_last_virus(ctx) : "Name");
447
448
    }
448
449
 
449
450
    if(cli_get_last_virus(ctx))
450
 
        do_dsig_check = strncmp("W32S.", cli_get_last_virus(ctx), 5);
 
451
        do_dsig_check = strncmp("W32S.", cli_get_last_virus(ctx), 5);
451
452
 
452
453
    map = *ctx->fmap;
453
454
    have_sha1 = cli_hm_have_size(ctx->engine->hm_fp, CLI_HASH_SHA1, size)
454
 
         || cli_hm_have_wild(ctx->engine->hm_fp, CLI_HASH_SHA1)
455
 
         || (cli_hm_have_size(ctx->engine->hm_fp, CLI_HASH_SHA1, 1) && do_dsig_check);
 
455
     || cli_hm_have_wild(ctx->engine->hm_fp, CLI_HASH_SHA1)
 
456
     || (cli_hm_have_size(ctx->engine->hm_fp, CLI_HASH_SHA1, 1) && do_dsig_check);
456
457
    have_sha256 = cli_hm_have_size(ctx->engine->hm_fp, CLI_HASH_SHA256, size)
457
 
         || cli_hm_have_wild(ctx->engine->hm_fp, CLI_HASH_SHA256);
 
458
     || cli_hm_have_wild(ctx->engine->hm_fp, CLI_HASH_SHA256);
458
459
    if(have_sha1 || have_sha256) {
459
 
        if((ptr = fmap_need_off_once(map, 0, size))) {
460
 
            if(have_sha1) {
461
 
                SHA1Init(&sha1);
462
 
                SHA1Update(&sha1, ptr, size);
463
 
                SHA1Final(&sha1, &shash1[SHA1_HASH_SIZE]);
464
 
                if(cli_hm_scan(&shash1[SHA1_HASH_SIZE], size, &virname, ctx->engine->hm_fp, CLI_HASH_SHA1) == CL_VIRUS) {
465
 
                    cli_dbgmsg("cli_checkfp(sha1): Found false positive detection (fp sig: %s)\n", virname);
466
 
                    return CL_CLEAN;
467
 
                }
468
 
                if(cli_hm_scan_wild(&shash1[SHA1_HASH_SIZE], &virname, ctx->engine->hm_fp, CLI_HASH_SHA1) == CL_VIRUS) {
469
 
                    cli_dbgmsg("cli_checkfp(sha1): Found false positive detection (fp sig: %s)\n", virname);
470
 
                    return CL_CLEAN;
471
 
                }
472
 
                if(do_dsig_check && cli_hm_scan(&shash1[SHA1_HASH_SIZE], 1, &virname, ctx->engine->hm_fp, CLI_HASH_SHA1) == CL_VIRUS) {
473
 
                    cli_dbgmsg("cli_checkfp(sha1): Found false positive detection via catalog file\n");
474
 
                    return CL_CLEAN;
475
 
                }
476
 
            }
477
 
            if(have_sha256) {
478
 
                sha256_init(&sha256);
479
 
                sha256_update(&sha256, ptr, size);
480
 
                sha256_final(&sha256, &shash256[SHA256_HASH_SIZE]);
481
 
                if(cli_hm_scan(&shash256[SHA256_HASH_SIZE], size, &virname, ctx->engine->hm_fp, CLI_HASH_SHA256) == CL_VIRUS) {
482
 
                    cli_dbgmsg("cli_checkfp(sha256): Found false positive detection (fp sig: %s)\n", virname);
483
 
                    return CL_CLEAN;
484
 
                }
485
 
                if(cli_hm_scan_wild(&shash256[SHA256_HASH_SIZE], &virname, ctx->engine->hm_fp, CLI_HASH_SHA256) == CL_VIRUS) {
486
 
                    cli_dbgmsg("cli_checkfp(sha256): Found false positive detection (fp sig: %s)\n", virname);
487
 
                    return CL_CLEAN;
488
 
                }
489
 
            }
490
 
        }
 
460
        if((ptr = fmap_need_off_once(map, 0, size))) {
 
461
            if(have_sha1) {
 
462
                cl_sha1(ptr, size, &shash1[SHA1_HASH_SIZE], NULL);
 
463
 
 
464
                if(cli_hm_scan(&shash1[SHA1_HASH_SIZE], size, &virname, ctx->engine->hm_fp, CLI_HASH_SHA1) == CL_VIRUS) {
 
465
                    cli_dbgmsg("cli_checkfp(sha1): Found false positive detection (fp sig: %s)\n", virname);
 
466
                    return CL_CLEAN;
 
467
                }
 
468
                if(cli_hm_scan_wild(&shash1[SHA1_HASH_SIZE], &virname, ctx->engine->hm_fp, CLI_HASH_SHA1) == CL_VIRUS) {
 
469
                    cli_dbgmsg("cli_checkfp(sha1): Found false positive detection (fp sig: %s)\n", virname);
 
470
                    return CL_CLEAN;
 
471
                }
 
472
                if(do_dsig_check && cli_hm_scan(&shash1[SHA1_HASH_SIZE], 1, &virname, ctx->engine->hm_fp, CLI_HASH_SHA1) == CL_VIRUS) {
 
473
                    cli_dbgmsg("cli_checkfp(sha1): Found false positive detection via catalog file\n");
 
474
                    return CL_CLEAN;
 
475
                }
 
476
            }
 
477
 
 
478
            if(have_sha256) {
 
479
                cl_sha256(ptr, size, &shash256[SHA256_HASH_SIZE], NULL);
 
480
 
 
481
                if(cli_hm_scan(&shash256[SHA256_HASH_SIZE], size, &virname, ctx->engine->hm_fp, CLI_HASH_SHA256) == CL_VIRUS) {
 
482
                    cli_dbgmsg("cli_checkfp(sha256): Found false positive detection (fp sig: %s)\n", virname);
 
483
                    return CL_CLEAN;
 
484
                }
 
485
                if(cli_hm_scan_wild(&shash256[SHA256_HASH_SIZE], &virname, ctx->engine->hm_fp, CLI_HASH_SHA256) == CL_VIRUS) {
 
486
                    cli_dbgmsg("cli_checkfp(sha256): Found false positive detection (fp sig: %s)\n", virname);
 
487
                    return CL_CLEAN;
 
488
                }
 
489
            }
 
490
        }
491
491
    }
492
492
 
493
493
#ifdef HAVE__INTERNAL__SHA_COLLECT
494
494
    if((ctx->options & CL_SCAN_INTERNAL_COLLECT_SHA) && ctx->sha_collect>0) {
495
495
        if((ptr = fmap_need_off_once(map, 0, size))) {
496
 
            if(!have_sha256) {
497
 
                sha256_init(&sha256);
498
 
                sha256_update(&sha256, ptr, size);
499
 
                sha256_final(&sha256, &shash256[SHA256_HASH_SIZE]);
500
 
            }
 
496
            if(!have_sha256)
 
497
                cl_sha256(ptr, size, shash256+SHA256_HASH_SIZE, NULL);
 
498
 
501
499
            for(i=0; i<SHA256_HASH_SIZE; i++)
502
500
                sprintf((char *)shash256+i*2, "%02x", shash256[SHA256_HASH_SIZE+i]);
503
501
 
504
 
            if(!have_sha1) {
505
 
                SHA1Init(&sha1);
506
 
                SHA1Update(&sha1, ptr, size);
507
 
                SHA1Final(&sha1, &shash1[SHA1_HASH_SIZE]);
508
 
            }
 
502
            if(!have_sha1)
 
503
                cl_sha1(ptr, size, shash1+SHA1_HASH_SIZE);
 
504
 
509
505
            for(i=0; i<SHA1_HASH_SIZE; i++)
510
506
                sprintf((char *)shash1+i*2, "%02x", shash1[SHA1_HASH_SIZE+i]);
511
507
 
512
 
            cli_errmsg("COLLECT:%s:%s:%u:%s:%s\n", shash256, shash1, size, cli_get_last_virus(ctx), ctx->entry_filename);
 
508
            cli_errmsg("COLLECT:%s:%s:%u:%s:%s\n", shash256, shash1, size, cli_get_last_virus(ctx), ctx->entry_filename);
513
509
        } else
514
510
            cli_errmsg("can't compute sha\n!");
 
511
 
515
512
        ctx->sha_collect = -1;
516
513
    }
517
514
#endif
518
515
 
519
 
    if(do_dsig_check) {
520
 
        switch(cli_checkfp_pe(ctx, shash1)) {
521
 
        case CL_CLEAN:
522
 
            cli_dbgmsg("cli_checkfp(pe): PE file whitelisted due to valid embedded digital signature\n");
523
 
            return CL_CLEAN;
524
 
        case CL_VIRUS:
525
 
            if(cli_hm_scan(shash1, 2, &virname, ctx->engine->hm_fp, CLI_HASH_SHA1) == CL_VIRUS) {
526
 
                cli_dbgmsg("cli_checkfp(pe): PE file whitelisted by catalog file\n");
527
 
                return CL_CLEAN;
528
 
            }
529
 
        }
 
516
    memset(&sections, 0x00, sizeof(stats_section_t));
 
517
    if(do_dsig_check || ctx->engine->cb_stats_add_sample) {
 
518
        uint32_t flags = (do_dsig_check ? CL_CHECKFP_PE_FLAG_AUTHENTICODE : 0);
 
519
        if (!(ctx->engine->engine_options & ENGINE_OPTIONS_DISABLE_PE_STATS) && !(ctx->engine->dconf->stats & (DCONF_STATS_DISABLED | DCONF_STATS_PE_SECTION_DISABLED)))
 
520
            flags |= CL_CHECKFP_PE_FLAG_STATS;
 
521
 
 
522
        switch(cli_checkfp_pe(ctx, shash1, &sections, flags)) {
 
523
        case CL_CLEAN:
 
524
            cli_dbgmsg("cli_checkfp(pe): PE file whitelisted due to valid embedded digital signature\n");
 
525
            return CL_CLEAN;
 
526
        case CL_VIRUS:
 
527
            if(cli_hm_scan(shash1, 2, &virname, ctx->engine->hm_fp, CLI_HASH_SHA1) == CL_VIRUS) {
 
528
                cli_dbgmsg("cli_checkfp(pe): PE file whitelisted by catalog file\n");
 
529
 
 
530
                return CL_CLEAN;
 
531
            }
 
532
        }
530
533
    }
 
534
 
531
535
    if (ctx->engine->cb_hash)
532
 
        ctx->engine->cb_hash(fmap_fd(*ctx->fmap), size, md5, cli_get_last_virus(ctx), ctx->cb_ctx);
 
536
        ctx->engine->cb_hash(fmap_fd(*ctx->fmap), size, md5, cli_get_last_virus(ctx), ctx->cb_ctx);
 
537
 
 
538
    if (ctx->engine->cb_stats_add_sample)
 
539
        ctx->engine->cb_stats_add_sample(cli_get_last_virus(ctx), digest, size, &sections, ctx->engine->stats_data);
 
540
 
 
541
    if (sections.sections)
 
542
        free(sections.sections);
533
543
 
534
544
    return CL_VIRUS;
535
545
}
536
546
 
537
547
static int matchicon(cli_ctx *ctx, struct cli_exe_info *exeinfo, const char *grp1, const char *grp2)
538
548
{
539
 
        icon_groupset iconset;
 
549
    icon_groupset iconset;
540
550
 
541
551
    if(!ctx ||
542
552
       !ctx->engine ||
546
556
       !exeinfo->res_addr
547
557
    ) return CL_CLEAN;
548
558
 
 
559
    if (!(ctx->dconf->pe & PE_CONF_MATCHICON))
 
560
        return CL_CLEAN;
 
561
 
549
562
    cli_icongroupset_init(&iconset);
550
563
    cli_icongroupset_add(grp1 ? grp1 : "*", &iconset, 0, ctx);
551
564
    cli_icongroupset_add(grp2 ? grp2 : "*", &iconset, 1, ctx);
697
710
 
698
711
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)
699
712
{
700
 
        const unsigned char *buff;
701
 
        int ret = CL_CLEAN, type = CL_CLEAN, bytes, compute_hash[CLI_HASH_AVAIL_TYPES];
702
 
        unsigned int i = 0, bm_offmode = 0;
703
 
        uint32_t maxpatlen, offset = 0;
704
 
        struct cli_ac_data gdata, tdata;
705
 
        struct cli_bm_off toff;
706
 
        cli_md5_ctx md5ctx;
707
 
        SHA256_CTX sha256ctx;
708
 
        SHA1Context sha1ctx;
709
 
        unsigned char digest[CLI_HASH_AVAIL_TYPES][32];
710
 
        struct cli_matcher *groot = NULL, *troot = NULL;
711
 
        struct cli_target_info info;
712
 
        fmap_t *map = *ctx->fmap;
713
 
        struct cli_matcher *hdb, *fp;
714
 
        const char *virname = NULL;
715
 
        uint32_t viroffset = 0;
716
 
        uint32_t viruses_found = 0;
 
713
    const unsigned char *buff;
 
714
    int ret = CL_CLEAN, type = CL_CLEAN, bytes, compute_hash[CLI_HASH_AVAIL_TYPES];
 
715
    unsigned int i = 0, j = 0, bm_offmode = 0;
 
716
    uint32_t maxpatlen, offset = 0;
 
717
    struct cli_ac_data gdata, tdata;
 
718
    struct cli_bm_off toff;
 
719
    unsigned char digest[CLI_HASH_AVAIL_TYPES][32];
 
720
    struct cli_matcher *groot = NULL, *troot = NULL;
 
721
    struct cli_target_info info;
 
722
    fmap_t *map = *ctx->fmap;
 
723
    struct cli_matcher *hdb, *fp;
 
724
    const char *virname = NULL;
 
725
    uint32_t viroffset = 0;
 
726
    uint32_t viruses_found = 0;
 
727
    void *md5ctx, *sha1ctx, *sha256ctx;
717
728
 
718
729
    if(!ctx->engine) {
719
 
        cli_errmsg("cli_scandesc: engine == NULL\n");
720
 
        return CL_ENULLARG;
 
730
        cli_errmsg("cli_scandesc: engine == NULL\n");
 
731
        return CL_ENULLARG;
 
732
    }
 
733
 
 
734
    md5ctx = cl_hash_init("md5");
 
735
    if (!(md5ctx))
 
736
        return CL_EMEM;
 
737
 
 
738
    sha1ctx = cl_hash_init("sha1");
 
739
    if (!(sha1ctx)) {
 
740
        cl_hash_destroy(md5ctx);
 
741
        return CL_EMEM;
 
742
    }
 
743
 
 
744
    sha256ctx = cl_hash_init("sha256");
 
745
    if (!(sha256ctx)) {
 
746
        cl_hash_destroy(md5ctx);
 
747
        cl_hash_destroy(sha1ctx);
 
748
        return CL_EMEM;
721
749
    }
722
750
 
723
751
    if(!ftonly)
724
 
        groot = ctx->engine->root[0]; /* generic signatures */
 
752
        groot = ctx->engine->root[0]; /* generic signatures */
725
753
 
726
754
    if(ftype) {
727
 
        for(i = 1; i < CLI_MTARGETS; i++) {
728
 
            if(cli_mtargets[i].target == ftype) {
729
 
                troot = ctx->engine->root[i];
730
 
                break;
731
 
            }
732
 
        }
 
755
        for(i = 1; i < CLI_MTARGETS; i++) {
 
756
            for (j = 0; j < cli_mtargets[i].target_count; ++j) {
 
757
                if(cli_mtargets[i].target[j] == ftype) {
 
758
                    troot = ctx->engine->root[i];
 
759
                    break;
 
760
                }
 
761
            }
 
762
            if (troot) break;
 
763
        }
733
764
    }
734
765
 
735
766
    if(ftonly) {
736
 
        if(!troot)
737
 
            return CL_CLEAN;
 
767
        if(!troot) {
 
768
            cl_hash_destroy(md5ctx);
 
769
            cl_hash_destroy(sha1ctx);
 
770
            cl_hash_destroy(sha256ctx);
 
771
            return CL_CLEAN;
 
772
        }
738
773
 
739
 
        maxpatlen = troot->maxpatlen;
 
774
        maxpatlen = troot->maxpatlen;
740
775
    } else {
741
 
        if(troot)
742
 
            maxpatlen = MAX(troot->maxpatlen, groot->maxpatlen);
743
 
        else
744
 
            maxpatlen = groot->maxpatlen;
745
 
    }
746
 
 
747
 
    targetinfo(&info, i, map);
748
 
 
749
 
    if(!ftonly)
750
 
        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))) {
751
 
            if(info.exeinfo.section)
752
 
                free(info.exeinfo.section);
753
 
            cli_hashset_destroy(&info.exeinfo.vinfo);
754
 
            return ret;
755
 
        }
 
776
        if(troot)
 
777
            maxpatlen = MAX(troot->maxpatlen, groot->maxpatlen);
 
778
        else
 
779
            maxpatlen = groot->maxpatlen;
 
780
    }
 
781
 
 
782
    cli_targetinfo(&info, i, map);
 
783
 
 
784
    if(!ftonly) {
 
785
        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))) {
 
786
            if(info.exeinfo.section)
 
787
                free(info.exeinfo.section);
 
788
 
 
789
            cli_hashset_destroy(&info.exeinfo.vinfo);
 
790
            cl_hash_destroy(md5ctx);
 
791
            cl_hash_destroy(sha1ctx);
 
792
            cl_hash_destroy(sha256ctx);
 
793
            return ret;
 
794
        }
 
795
    }
756
796
 
757
797
    if(troot) {
758
 
        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))) {
759
 
            if(!ftonly)
760
 
                cli_ac_freedata(&gdata);
761
 
            if(info.exeinfo.section)
762
 
                free(info.exeinfo.section);
763
 
            cli_hashset_destroy(&info.exeinfo.vinfo);
764
 
            return ret;
765
 
        }
766
 
        if(troot->bm_offmode) {
767
 
            if(map->len >= CLI_DEFAULT_BM_OFFMODE_FSIZE) {
768
 
                if((ret = cli_bm_initoff(troot, &toff, &info))) {
769
 
                    if(!ftonly)
770
 
                        cli_ac_freedata(&gdata);
771
 
                    cli_ac_freedata(&tdata);
772
 
                    if(info.exeinfo.section)
773
 
                        free(info.exeinfo.section);
774
 
                    cli_hashset_destroy(&info.exeinfo.vinfo);
775
 
                    return ret;
776
 
                }
777
 
                bm_offmode = 1;
778
 
            }
779
 
        }
 
798
        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))) {
 
799
            if(!ftonly)
 
800
                cli_ac_freedata(&gdata);
 
801
            if(info.exeinfo.section)
 
802
                free(info.exeinfo.section);
 
803
 
 
804
            cli_hashset_destroy(&info.exeinfo.vinfo);
 
805
            cl_hash_destroy(md5ctx);
 
806
            cl_hash_destroy(sha1ctx);
 
807
            cl_hash_destroy(sha256ctx);
 
808
            return ret;
 
809
        }
 
810
        if(troot->bm_offmode) {
 
811
            if(map->len >= CLI_DEFAULT_BM_OFFMODE_FSIZE) {
 
812
                if((ret = cli_bm_initoff(troot, &toff, &info))) {
 
813
                    if(!ftonly)
 
814
                        cli_ac_freedata(&gdata);
 
815
 
 
816
                    cli_ac_freedata(&tdata);
 
817
                    if(info.exeinfo.section)
 
818
                        free(info.exeinfo.section);
 
819
 
 
820
                    cli_hashset_destroy(&info.exeinfo.vinfo);
 
821
                    cl_hash_destroy(md5ctx);
 
822
                    cl_hash_destroy(sha1ctx);
 
823
                    cl_hash_destroy(sha256ctx);
 
824
                    return ret;
 
825
                }
 
826
 
 
827
                bm_offmode = 1;
 
828
            }
 
829
        }
780
830
    }
781
831
 
782
832
    hdb = ctx->engine->hm_hdb;
783
833
    fp = ctx->engine->hm_fp;
784
834
 
785
835
    if(!ftonly && hdb) {
786
 
        if(!refhash) {
787
 
            if(cli_hm_have_size(hdb, CLI_HASH_MD5, map->len) || cli_hm_have_size(fp, CLI_HASH_MD5, map->len)) {
788
 
                cli_md5_init(&md5ctx);
789
 
                compute_hash[CLI_HASH_MD5] = 1;
790
 
            } else
791
 
                compute_hash[CLI_HASH_MD5] = 0;
792
 
        } else {
793
 
            compute_hash[CLI_HASH_MD5] = 0;
794
 
            memcpy(digest[CLI_HASH_MD5], refhash, 16);
795
 
        }
796
 
 
797
 
        if(cli_hm_have_size(hdb, CLI_HASH_SHA1, map->len) || cli_hm_have_wild(hdb, CLI_HASH_SHA1)
798
 
                || cli_hm_have_size(fp, CLI_HASH_SHA1, map->len) || cli_hm_have_wild(fp, CLI_HASH_SHA1) ) {
799
 
            SHA1Init(&sha1ctx);
800
 
            compute_hash[CLI_HASH_SHA1] = 1;
801
 
        } else
802
 
            compute_hash[CLI_HASH_SHA1] = 0;
803
 
 
804
 
        if(cli_hm_have_size(hdb, CLI_HASH_SHA256, map->len) || cli_hm_have_wild(hdb, CLI_HASH_SHA256)
805
 
                || cli_hm_have_size(fp, CLI_HASH_SHA256, map->len) || cli_hm_have_wild(fp, CLI_HASH_SHA256)) {
806
 
            sha256_init(&sha256ctx);
807
 
            compute_hash[CLI_HASH_SHA256] = 1;
808
 
        } else
809
 
            compute_hash[CLI_HASH_SHA256] = 0;
 
836
        if(!refhash) {
 
837
            if(cli_hm_have_size(hdb, CLI_HASH_MD5, map->len) || cli_hm_have_size(fp, CLI_HASH_MD5, map->len)) {
 
838
                compute_hash[CLI_HASH_MD5] = 1;
 
839
            } else {
 
840
                compute_hash[CLI_HASH_MD5] = 0;
 
841
            }
 
842
        } else {
 
843
            compute_hash[CLI_HASH_MD5] = 0;
 
844
            memcpy(digest[CLI_HASH_MD5], refhash, 16);
 
845
        }
 
846
 
 
847
        if(cli_hm_have_size(hdb, CLI_HASH_SHA1, map->len) || cli_hm_have_wild(hdb, CLI_HASH_SHA1)
 
848
            || cli_hm_have_size(fp, CLI_HASH_SHA1, map->len) || cli_hm_have_wild(fp, CLI_HASH_SHA1) ) {
 
849
            compute_hash[CLI_HASH_SHA1] = 1;
 
850
        } else {
 
851
            compute_hash[CLI_HASH_SHA1] = 0;
 
852
        }
 
853
 
 
854
        if(cli_hm_have_size(hdb, CLI_HASH_SHA256, map->len) || cli_hm_have_wild(hdb, CLI_HASH_SHA256)
 
855
            || cli_hm_have_size(fp, CLI_HASH_SHA256, map->len) || cli_hm_have_wild(fp, CLI_HASH_SHA256)) {
 
856
            compute_hash[CLI_HASH_SHA256] = 1;
 
857
        } else {
 
858
            compute_hash[CLI_HASH_SHA256] = 0;
 
859
        }
810
860
    }
811
861
 
812
862
    while(offset < map->len) {
813
 
        bytes = MIN(map->len - offset, SCANBUFF);
814
 
        if(!(buff = fmap_need_off_once(map, offset, bytes)))
815
 
            break;
816
 
        if(ctx->scanned)
817
 
            *ctx->scanned += bytes / CL_COUNT_PRECISION;
818
 
 
819
 
        if(troot) {
 
863
        bytes = MIN(map->len - offset, SCANBUFF);
 
864
        if(!(buff = fmap_need_off_once(map, offset, bytes)))
 
865
            break;
 
866
        if(ctx->scanned)
 
867
            *ctx->scanned += bytes / CL_COUNT_PRECISION;
 
868
 
 
869
        if(troot) {
 
870
                virname = NULL;
 
871
                viroffset = 0;
 
872
                ret = matcher_run(troot, buff, bytes, &virname, &tdata, offset, &info, ftype, ftoffset, acmode, acres, map, bm_offmode ? &toff : NULL, &viroffset, ctx);
 
873
 
 
874
            if (virname) {
 
875
                /* virname already appended by matcher_run */
 
876
                viruses_found = 1;
 
877
            }
 
878
            if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
 
879
                if(!ftonly)
 
880
                    cli_ac_freedata(&gdata);
 
881
 
 
882
                cli_ac_freedata(&tdata);
 
883
                if(bm_offmode)
 
884
                    cli_bm_freeoff(&toff);
 
885
 
 
886
                if(info.exeinfo.section)
 
887
                    free(info.exeinfo.section);
 
888
 
 
889
                cli_hashset_destroy(&info.exeinfo.vinfo);
 
890
                cl_hash_destroy(md5ctx);
 
891
                cl_hash_destroy(sha1ctx);
 
892
                cl_hash_destroy(sha256ctx);
 
893
                return ret;
 
894
            }
 
895
        }
 
896
 
 
897
        if(!ftonly) {
820
898
            virname = NULL;
821
899
            viroffset = 0;
822
 
            ret = matcher_run(troot, buff, bytes, &virname, &tdata, offset, &info, ftype, ftoffset, acmode, acres, map, bm_offmode ? &toff : NULL, &viroffset, ctx);
823
 
 
824
 
            if (virname) {
825
 
                /* virname already appended by matcher_run */
826
 
                viruses_found = 1;
827
 
            }
828
 
            if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
829
 
                if(!ftonly)
830
 
                    cli_ac_freedata(&gdata);
831
 
                cli_ac_freedata(&tdata);
832
 
                if(bm_offmode)
833
 
                    cli_bm_freeoff(&toff);
834
 
                if(info.exeinfo.section)
835
 
                    free(info.exeinfo.section);
836
 
                cli_hashset_destroy(&info.exeinfo.vinfo);
837
 
                return ret;
838
 
            }
839
 
        }
840
 
 
841
 
        if(!ftonly) {
842
 
            virname = NULL;
843
 
            viroffset = 0;
844
 
            ret = matcher_run(groot, buff, bytes, &virname, &gdata, offset, &info, ftype, ftoffset, acmode, acres, map, NULL, &viroffset, ctx);
 
900
            ret = matcher_run(groot, buff, bytes, &virname, &gdata, offset, &info, ftype, ftoffset, acmode, acres, map, NULL, &viroffset, ctx);
845
901
 
846
902
            if (virname) {
847
 
                /* virname already appended by matcher_run */
848
 
                viruses_found = 1;
849
 
            }
850
 
            if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
851
 
                cli_ac_freedata(&gdata);
852
 
                if(troot) {
853
 
                    cli_ac_freedata(&tdata);
854
 
                    if(bm_offmode)
855
 
                        cli_bm_freeoff(&toff);
856
 
                }
857
 
                if(info.exeinfo.section)
858
 
                    free(info.exeinfo.section);
859
 
                cli_hashset_destroy(&info.exeinfo.vinfo);
860
 
                return ret;
861
 
            } else if((acmode & AC_SCAN_FT) && ret >= CL_TYPENO) {
862
 
                if(ret > type)
863
 
                    type = ret;
864
 
            }
865
 
 
866
 
            if(hdb && !SCAN_ALL) {
867
 
                const void *data = buff + maxpatlen * (offset!=0);
868
 
                uint32_t data_len = bytes - maxpatlen * (offset!=0);
869
 
 
870
 
                if(compute_hash[CLI_HASH_MD5])
871
 
                    cli_md5_update(&md5ctx, data, data_len);
872
 
                if(compute_hash[CLI_HASH_SHA1])
873
 
                    SHA1Update(&sha1ctx, data, data_len);
874
 
                if(compute_hash[CLI_HASH_SHA256])
875
 
                    sha256_update(&sha256ctx, data, data_len);
876
 
            }
877
 
        }
878
 
 
879
 
        if(SCAN_ALL && viroffset) {
880
 
            offset = viroffset;
881
 
            continue;
882
 
        }
883
 
        if(bytes < SCANBUFF) break;
884
 
        offset += bytes - maxpatlen;
 
903
                /* virname already appended by matcher_run */
 
904
                viruses_found = 1;
 
905
            }
 
906
            if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
 
907
                cli_ac_freedata(&gdata);
 
908
                if(troot) {
 
909
                    cli_ac_freedata(&tdata);
 
910
                    if(bm_offmode)
 
911
                        cli_bm_freeoff(&toff);
 
912
                }
 
913
 
 
914
                if(info.exeinfo.section)
 
915
                    free(info.exeinfo.section);
 
916
 
 
917
                cli_hashset_destroy(&info.exeinfo.vinfo);
 
918
                return ret;
 
919
            } else if((acmode & AC_SCAN_FT) && ret >= CL_TYPENO) {
 
920
                if(ret > type)
 
921
                    type = ret;
 
922
            }
 
923
 
 
924
            if(hdb && !SCAN_ALL) {
 
925
                const void *data = buff + maxpatlen * (offset!=0);
 
926
                uint32_t data_len = bytes - maxpatlen * (offset!=0);
 
927
 
 
928
                if(compute_hash[CLI_HASH_MD5])
 
929
                    cl_update_hash(md5ctx, data, data_len);
 
930
                if(compute_hash[CLI_HASH_SHA1])
 
931
                    cl_update_hash(sha1ctx, data, data_len);
 
932
                if(compute_hash[CLI_HASH_SHA256])
 
933
                    cl_update_hash(sha256ctx, data, data_len);
 
934
            }
 
935
        }
 
936
 
 
937
        if(SCAN_ALL && viroffset) {
 
938
            offset = viroffset;
 
939
            continue;
 
940
        }
 
941
 
 
942
        if(bytes < SCANBUFF)
 
943
            break;
 
944
 
 
945
        offset += bytes - maxpatlen;
885
946
    }
886
947
 
887
948
    if(!ftonly && hdb) {
888
 
        enum CLI_HASH_TYPE hashtype, hashtype2;
889
 
 
890
 
        if(compute_hash[CLI_HASH_MD5])
891
 
            cli_md5_final(digest[CLI_HASH_MD5], &md5ctx);
892
 
        if(refhash)
893
 
            compute_hash[CLI_HASH_MD5] = 1;
894
 
        if(compute_hash[CLI_HASH_SHA1])
895
 
            SHA1Final(&sha1ctx, digest[CLI_HASH_SHA1]);
896
 
        if(compute_hash[CLI_HASH_SHA256])
897
 
            sha256_final(&sha256ctx, digest[CLI_HASH_SHA256]);
898
 
 
899
 
        virname = NULL;
900
 
        for(hashtype = CLI_HASH_MD5; hashtype < CLI_HASH_AVAIL_TYPES; hashtype++) {
901
 
            const char * virname_w = NULL;
902
 
            int found = 0;
903
 
 
904
 
            /* If no hash, skip to next type */
905
 
            if(!compute_hash[hashtype])
906
 
                continue;
907
 
 
908
 
            /* Do hash scan */
909
 
            if((ret = cli_hm_scan(digest[hashtype], map->len, &virname, hdb, hashtype)) == CL_VIRUS) {
910
 
                found += 1;
911
 
            }
912
 
            if(!found || SCAN_ALL) {
913
 
                if ((ret = cli_hm_scan_wild(digest[hashtype], &virname_w, hdb, hashtype)) == CL_VIRUS)
914
 
                    found += 2;
915
 
            }
916
 
 
917
 
            /* If found, do immediate hash-only FP check */
918
 
            if (found && fp) {
919
 
                for(hashtype2 = CLI_HASH_MD5; hashtype2 < CLI_HASH_AVAIL_TYPES; hashtype2++) {
920
 
                    if(!compute_hash[hashtype2])
921
 
                        continue;
922
 
                    if(cli_hm_scan(digest[hashtype2], map->len, NULL, fp, hashtype2) == CL_VIRUS) {
923
 
                        found = 0;
924
 
                        ret = CL_CLEAN;
925
 
                        break;
926
 
                    }
927
 
                    else if(cli_hm_scan_wild(digest[hashtype2], NULL, fp, hashtype2) == CL_VIRUS) {
928
 
                        found = 0;
929
 
                        ret = CL_CLEAN;
930
 
                        break;
931
 
                    }
932
 
                }
933
 
            }
934
 
 
935
 
            /* If matched size-based hash ... */
936
 
            if (found % 2) {
937
 
                viruses_found = 1;
938
 
                cli_append_virus(ctx, virname);
939
 
                if (!SCAN_ALL)
940
 
                    break;
941
 
                virname = NULL;
942
 
            }
943
 
            /* If matched size-agnostic hash ... */
944
 
            if (found > 1) {
945
 
                viruses_found = 1;
946
 
                cli_append_virus(ctx, virname_w);
947
 
                if (!SCAN_ALL)
948
 
                    break;
949
 
            }
950
 
        }
 
949
        enum CLI_HASH_TYPE hashtype, hashtype2;
 
950
 
 
951
        if(compute_hash[CLI_HASH_MD5]) {
 
952
            cl_finish_hash(md5ctx, digest[CLI_HASH_MD5]);
 
953
            md5ctx = NULL;
 
954
        }
 
955
        if(refhash)
 
956
            compute_hash[CLI_HASH_MD5] = 1;
 
957
        if(compute_hash[CLI_HASH_SHA1]) {
 
958
            cl_finish_hash(sha1ctx, digest[CLI_HASH_SHA1]);
 
959
            sha1ctx = NULL;
 
960
        }
 
961
        if(compute_hash[CLI_HASH_SHA256]) {
 
962
            cl_finish_hash(sha256ctx, digest[CLI_HASH_SHA256]);
 
963
            sha256ctx = NULL;
 
964
        }
 
965
 
 
966
        virname = NULL;
 
967
        for(hashtype = CLI_HASH_MD5; hashtype < CLI_HASH_AVAIL_TYPES; hashtype++) {
 
968
            const char * virname_w = NULL;
 
969
            int found = 0;
 
970
 
 
971
            /* If no hash, skip to next type */
 
972
            if(!compute_hash[hashtype])
 
973
                continue;
 
974
 
 
975
            /* Do hash scan */
 
976
            if((ret = cli_hm_scan(digest[hashtype], map->len, &virname, hdb, hashtype)) == CL_VIRUS) {
 
977
                found += 1;
 
978
            }
 
979
            if(!found || SCAN_ALL) {
 
980
                if ((ret = cli_hm_scan_wild(digest[hashtype], &virname_w, hdb, hashtype)) == CL_VIRUS)
 
981
                    found += 2;
 
982
            }
 
983
 
 
984
            /* If found, do immediate hash-only FP check */
 
985
            if (found && fp) {
 
986
                for(hashtype2 = CLI_HASH_MD5; hashtype2 < CLI_HASH_AVAIL_TYPES; hashtype2++) {
 
987
                    if(!compute_hash[hashtype2])
 
988
                        continue;
 
989
                    if(cli_hm_scan(digest[hashtype2], map->len, NULL, fp, hashtype2) == CL_VIRUS) {
 
990
                        found = 0;
 
991
                        ret = CL_CLEAN;
 
992
                        break;
 
993
                    }
 
994
                    else if(cli_hm_scan_wild(digest[hashtype2], NULL, fp, hashtype2) == CL_VIRUS) {
 
995
                        found = 0;
 
996
                        ret = CL_CLEAN;
 
997
                        break;
 
998
                    }
 
999
                }
 
1000
            }
 
1001
 
 
1002
            /* If matched size-based hash ... */
 
1003
            if (found % 2) {
 
1004
                viruses_found = 1;
 
1005
                cli_append_virus(ctx, virname);
 
1006
                if (!SCAN_ALL)
 
1007
                    break;
 
1008
                virname = NULL;
 
1009
            }
 
1010
            /* If matched size-agnostic hash ... */
 
1011
            if (found > 1) {
 
1012
                viruses_found = 1;
 
1013
                cli_append_virus(ctx, virname_w);
 
1014
 
 
1015
                if (!SCAN_ALL)
 
1016
                    break;
 
1017
            }
 
1018
        }
951
1019
    }
952
1020
 
 
1021
    cl_hash_destroy(md5ctx);
 
1022
    cl_hash_destroy(sha1ctx);
 
1023
    cl_hash_destroy(sha256ctx);
 
1024
 
953
1025
    if(troot) {
954
 
        if(ret != CL_VIRUS || SCAN_ALL)
955
 
            ret = cli_lsig_eval(ctx, troot, &tdata, &info, refhash);
956
 
        if (ret == CL_VIRUS)
957
 
            viruses_found++;
958
 
        cli_ac_freedata(&tdata);
959
 
        if(bm_offmode)
960
 
            cli_bm_freeoff(&toff);
 
1026
        if(ret != CL_VIRUS || SCAN_ALL)
 
1027
            ret = cli_lsig_eval(ctx, troot, &tdata, &info, refhash);
 
1028
        if (ret == CL_VIRUS)
 
1029
            viruses_found++;
 
1030
 
 
1031
        cli_ac_freedata(&tdata);
 
1032
        if(bm_offmode)
 
1033
            cli_bm_freeoff(&toff);
961
1034
    }
962
1035
 
963
1036
    if(groot) {
964
 
        if(ret != CL_VIRUS || SCAN_ALL)
965
 
            ret = cli_lsig_eval(ctx, groot, &gdata, &info, refhash);
966
 
        cli_ac_freedata(&gdata);
 
1037
        if(ret != CL_VIRUS || SCAN_ALL)
 
1038
            ret = cli_lsig_eval(ctx, groot, &gdata, &info, refhash);
 
1039
        cli_ac_freedata(&gdata);
967
1040
    }
968
1041
 
969
1042
    if(info.exeinfo.section)
970
 
        free(info.exeinfo.section);
 
1043
        free(info.exeinfo.section);
 
1044
 
971
1045
    cli_hashset_destroy(&info.exeinfo.vinfo);
972
1046
 
973
1047
    if (SCAN_ALL && viruses_found)
974
 
        return CL_VIRUS;
 
1048
        return CL_VIRUS;
975
1049
    if(ret == CL_VIRUS)
976
 
        return CL_VIRUS;
 
1050
        return CL_VIRUS;
977
1051
 
978
1052
    return (acmode & AC_SCAN_FT) ? type : CL_CLEAN;
979
1053
}