示例#1
0
static void fmap_aging(fmap_t *m) {
#ifdef ANONYMOUS_MAP
    if(!m->aging) return;
    if(m->paged * m->pgsz > UNPAGE_THRSHLD_HI) { /* we alloc'd too much */
	unsigned int i, avail = 0, freeme[2048], maxavail = MIN(sizeof(freeme)/sizeof(*freeme), m->paged - UNPAGE_THRSHLD_LO / m->pgsz) - 1;

	for(i=0; i<m->pages; i++) {
	    uint32_t s = fmap_bitmap[i];
	    if((s & (FM_MASK_PAGED | FM_MASK_LOCKED)) == FM_MASK_PAGED ) {
		/* page is paged and not locked: dec age */
		if(s & FM_MASK_COUNT) fmap_bitmap[i]--;
		/* and make it available for unpaging */

		if(!avail) {
		    freeme[0] = i;
		    avail++;
		} else {
		    /* Insert sort onto a stack'd array - same performance as quickselect */
		    unsigned int insert_to = MIN(maxavail, avail) - 1, age = fmap_bitmap[i] & FM_MASK_COUNT;
		    if(avail <= maxavail || (fmap_bitmap[freeme[maxavail]] & FM_MASK_COUNT) > age) {
			while((fmap_bitmap[freeme[insert_to]] & FM_MASK_COUNT) > age) {
			    freeme[insert_to + 1] = freeme[insert_to];
			    if(!insert_to--) break;
			}
			freeme[insert_to + 1] = i;
			if(avail <= maxavail) avail++;
		    }
		}
	    }
	}
	if(avail) { /* at least one page is paged and not locked */
	    char *lastpage = NULL;
	    char *firstpage = NULL;
	    for(i=0; i<avail; i++) {
		char *pptr = (char *)m + freeme[i] * m->pgsz + m->hdrsz;
		/* we mark the page as seen */
		fmap_bitmap[freeme[i]] = FM_MASK_SEEN;
		/* and we mmap the page over so the kernel knows there's nothing good in there */
		/* reduce number of mmap calls: if pages are adjacent only do 1 mmap call */
		if (lastpage && pptr == lastpage) {
			lastpage = pptr + m->pgsz;
			continue;
		}
		if (!lastpage) {
			firstpage = pptr;
			lastpage = pptr + m->pgsz;
			continue;
		}
		fmap_lock;
		if(mmap(firstpage, lastpage - firstpage, PROT_READ | PROT_WRITE, MAP_FIXED|MAP_PRIVATE|ANONYMOUS_MAP, -1, 0) == MAP_FAILED)
		    cli_dbgmsg("fmap_aging: kernel hates you\n");
		fmap_unlock;
		firstpage = pptr;
		lastpage = pptr + m->pgsz;
	    }
	    if (lastpage) {
		fmap_lock;
		if(mmap(firstpage, lastpage - firstpage, PROT_READ | PROT_WRITE, MAP_FIXED|MAP_PRIVATE|ANONYMOUS_MAP, -1, 0) == MAP_FAILED)
		    cli_dbgmsg("fmap_aging: kernel hates you\n");
		fmap_unlock;
	    }
	    m->paged -= avail;
	}
    }
#endif
}
示例#2
0
/* Read 64-bit program headers */
static int cli_elf_ph64(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo,
    struct elf_file_hdr64 *file_hdr, uint8_t conv)
{
	struct elf_program_hdr64 *program_hdr = NULL;
	uint16_t phnum, phentsize;
	uint64_t entry, fentry = 0, phoff;
	uint32_t i;
	uint8_t err;

    /* Program headers and Entry */
    phnum = file_hdr->e_phnum;
    cli_dbgmsg("ELF: Number of program headers: %d\n", phnum);
    if(phnum > 128) {
        cli_dbgmsg("ELF: Suspicious number of program headers\n");
        if(ctx && DETECT_BROKEN) {
            cli_append_virus(ctx, "Heuristics.Broken.Executable");
            return CL_VIRUS;
        }
        return CL_EFORMAT;
    }
    entry = file_hdr->e_entry;

    if(phnum && entry) {
        phentsize = file_hdr->e_phentsize;
        /* Sanity check */
        if (phentsize != sizeof(struct elf_program_hdr64)) {
            cli_dbgmsg("ELF: phentsize != sizeof(struct elf_program_hdr64)\n");
            if(ctx && DETECT_BROKEN) {
                cli_append_virus(ctx, "Heuristics.Broken.Executable");
                return CL_VIRUS;
            }
            return CL_EFORMAT;
        }

        phoff = file_hdr->e_phoff;
        if(ctx) {
            cli_dbgmsg("ELF: Program header table offset: " STDu64 "\n", phoff);
        }

        if(phnum) {
            program_hdr = (struct elf_program_hdr64 *) cli_calloc(phnum, sizeof(struct elf_program_hdr64));
            if(!program_hdr) {
                cli_errmsg("ELF: Can't allocate memory for program headers\n");
                return CL_EMEM;
            }
            if(ctx) {
                cli_dbgmsg("------------------------------------\n");
            }
        }

        for(i = 0; i < phnum; i++) {
            err = 0;
            if(fmap_readn(map, &program_hdr[i], phoff, sizeof(struct elf_program_hdr64)) != sizeof(struct elf_program_hdr64))
                err = 1;
            phoff += sizeof(struct elf_program_hdr64);

            if(err) {
                cli_dbgmsg("ELF: Can't read segment #%d\n", i);
                if(ctx) {
                    cli_dbgmsg("ELF: Possibly broken ELF file\n");
                }
                free(program_hdr);
                if(ctx && DETECT_BROKEN) {
                    cli_append_virus(ctx, "Heuristics.Broken.Executable");
                    return CL_VIRUS;
                }
                return CL_BREAK;
            }

            if(ctx) {
                cli_dbgmsg("ELF: Segment #%d\n", i);
                cli_dbgmsg("ELF: Segment type: 0x%x\n", EC32(program_hdr[i].p_type, conv));
                cli_dbgmsg("ELF: Segment offset: 0x" STDx64 "\n", EC64(program_hdr[i].p_offset, conv));
                cli_dbgmsg("ELF: Segment virtual address: 0x" STDx64 "\n", EC64(program_hdr[i].p_vaddr, conv));
                cli_dbgmsg("ELF: Segment real size: 0x" STDx64 "\n", EC64(program_hdr[i].p_filesz, conv));
                cli_dbgmsg("ELF: Segment virtual size: 0x" STDx64 "\n", EC64(program_hdr[i].p_memsz, conv));
                cli_dbgmsg("------------------------------------\n");
            }
        }

        fentry = cli_rawaddr64(entry, program_hdr, phnum, conv, &err);
        free(program_hdr);
        if(err) {
            cli_dbgmsg("ELF: Can't calculate file offset of entry point\n");
            if(ctx && DETECT_BROKEN) {
                cli_append_virus(ctx, "Heuristics.Broken.Executable");
                return CL_VIRUS;
            }
            return CL_EFORMAT;
        }
        if(ctx) {
            cli_dbgmsg("ELF: Entry point address: 0x%.16" PRIx64 "\n", entry);
            cli_dbgmsg("ELF: Entry point offset: 0x%.16" PRIx64 " (" STDi64 ")\n", fentry, fentry);
        }
    }

    if(elfinfo) {
        elfinfo->ep = fentry;
    }

    return CL_CLEAN;
}
示例#3
0
/* Print section type and selected flags to the log */
static void cli_elf_sectionlog(uint32_t sh_type, uint32_t sh_flags)
{
    switch(sh_type) {
        case 0x6: /* SHT_DYNAMIC */
            cli_dbgmsg("ELF: Section type: Dynamic linking information\n");
            break;
        case 0xb: /* SHT_DYNSYM */
            cli_dbgmsg("ELF: Section type: Symbols for dynamic linking\n");
            break;
        case 0xf: /* SHT_FINI_ARRAY */
            cli_dbgmsg("ELF: Section type: Array of pointers to termination functions\n");
            break;
        case 0x5: /* SHT_HASH */
            cli_dbgmsg("ELF: Section type: Symbol hash table\n");
            break;
        case 0xe: /* SHT_INIT_ARRAY */
            cli_dbgmsg("ELF: Section type: Array of pointers to initialization functions\n");
            break;
        case 0x8: /* SHT_NOBITS */
            cli_dbgmsg("ELF: Section type: Empty section (NOBITS)\n");
            break;
        case 0x7: /* SHT_NOTE */
            cli_dbgmsg("ELF: Section type: Note section\n");
            break;
        case 0x0: /* SHT_NULL */
            cli_dbgmsg("ELF: Section type: Null (no associated section)\n");
            break;
        case 0x10: /* SHT_PREINIT_ARRAY */
            cli_dbgmsg("ELF: Section type: Array of pointers to preinit functions\n");
            break;
        case 0x1: /* SHT_PROGBITS */
            cli_dbgmsg("ELF: Section type: Program information\n");
            break;
        case 0x9: /* SHT_REL */
            cli_dbgmsg("ELF: Section type: Relocation entries w/o explicit addends\n");
            break;
        case 0x4: /* SHT_RELA */
            cli_dbgmsg("ELF: Section type: Relocation entries with explicit addends\n");
            break;
        case 0x3: /* SHT_STRTAB */
            cli_dbgmsg("ELF: Section type: String table\n");
            break;
        case 0x2: /* SHT_SYMTAB */
            cli_dbgmsg("ELF: Section type: Symbol table\n");
            break;
        case 0x6ffffffd: /* SHT_GNU_verdef */
            cli_dbgmsg("ELF: Section type: Provided symbol versions\n");
            break;
        case 0x6ffffffe: /* SHT_GNU_verneed */
            cli_dbgmsg("ELF: Section type: Required symbol versions\n");
            break;
        case 0x6fffffff: /* SHT_GNU_versym */
            cli_dbgmsg("ELF: Section type: Symbol Version Table\n");
            break;
        default :
            cli_dbgmsg("ELF: Section type: Unknown\n");
    }

    if(sh_flags & ELF_SHF_WRITE)
        cli_dbgmsg("ELF: Section contains writable data\n");

    if(sh_flags & ELF_SHF_ALLOC)
        cli_dbgmsg("ELF: Section occupies memory\n");

    if(sh_flags & ELF_SHF_EXECINSTR)
        cli_dbgmsg("ELF: Section contains executable code\n");
}
示例#4
0
static int ooxml_content_cb(int fd, cli_ctx *ctx)
{
    int ret = CL_SUCCESS, tmp, toval = 0, state;
    int core=0, extn=0, cust=0, dsig=0;
    int mcore=0, mextn=0, mcust=0;
    const xmlChar *name, *value, *CT, *PN;
    xmlTextReaderPtr reader = NULL;
    uint32_t loff;

    unsigned long sav_scansize = ctx->scansize;
    unsigned int sav_scannedfiles = ctx->scannedfiles;

    cli_dbgmsg("in ooxml_content_cb\n");

    /* perform engine limit checks in temporary tracking session */
    ret = ooxml_updatelimits(fd, ctx);
    if (ret != CL_CLEAN)
        return ret;

    /* apply a reader to the document */
    reader = xmlReaderForFd(fd, "[Content_Types].xml", NULL, CLAMAV_MIN_XMLREADER_FLAGS);
    if (reader == NULL) {
        cli_dbgmsg("ooxml_content_cb: xmlReaderForFd error for ""[Content_Types].xml""\n");
        cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_XML_READER_FD");

        ctx->scansize = sav_scansize;
        ctx->scannedfiles = sav_scannedfiles;
        return CL_SUCCESS; // libxml2 failed!
    }

    /* locate core-properties, extended-properties, and custom-properties (optional) */
    while ((state = xmlTextReaderRead(reader)) == 1) {
        if (cli_json_timeout_cycle_check(ctx, &toval) != CL_SUCCESS) {
            ret = CL_ETIMEOUT;
            goto ooxml_content_exit;
        }

        name = xmlTextReaderConstLocalName(reader);
        if (name == NULL) continue;

        if (strcmp((const char *)name, "Override")) continue;

        if (xmlTextReaderHasAttributes(reader) != 1) continue;

        CT = PN = NULL;
        while (xmlTextReaderMoveToNextAttribute(reader) == 1) {
            name = xmlTextReaderConstLocalName(reader);
            value = xmlTextReaderConstValue(reader);
            if (name == NULL || value == NULL) continue;

            if (!xmlStrcmp(name, (const xmlChar *)"ContentType")) {
                CT = value;
            }
            else if (!xmlStrcmp(name, (const xmlChar *)"PartName")) {
                PN = value;
            }

            cli_dbgmsg("%s: %s\n", name, value);
        }

        if (!CT && !PN) continue;

        if (!xmlStrcmp(CT, (const xmlChar *)"application/vnd.openxmlformats-package.core-properties+xml")) {
            /* default: /docProps/core.xml*/
            tmp = unzip_search_single(ctx, (const char *)(PN+1), xmlStrlen(PN)-1, &loff);
            if (tmp == CL_ETIMEOUT) {
                ret = tmp;
            }
            else if (tmp != CL_VIRUS) {
                cli_dbgmsg("cli_process_ooxml: failed to find core properties file \"%s\"!\n", PN);
                mcore++;
            }
            else {
                cli_dbgmsg("ooxml_content_cb: found core properties file \"%s\" @ %x\n", PN, loff);
                if (!core) {
                    tmp = unzip_single_internal(ctx, loff, ooxml_core_cb);
                    if (tmp == CL_ETIMEOUT || tmp == CL_EMEM) {
                        ret = tmp;
                    }
                }
                core++;
            }
        }
        else if (!xmlStrcmp(CT, (const xmlChar *)"application/vnd.openxmlformats-officedocument.extended-properties+xml")) {
            /* default: /docProps/app.xml */
            tmp = unzip_search_single(ctx, (const char *)(PN+1), xmlStrlen(PN)-1, &loff);
            if (tmp == CL_ETIMEOUT) {
                ret = tmp;
            }
            else if (tmp != CL_VIRUS) {
                cli_dbgmsg("cli_process_ooxml: failed to find extended properties file \"%s\"!\n", PN);
                mextn++;
            }
            else {
                cli_dbgmsg("ooxml_content_cb: found extended properties file \"%s\" @ %x\n", PN, loff);
                if (!extn) {
                    tmp = unzip_single_internal(ctx, loff, ooxml_extn_cb);
                    if (tmp == CL_ETIMEOUT || tmp == CL_EMEM) {
                        ret = tmp;
                    }
                }
                extn++;
            }
        }
        else if (!xmlStrcmp(CT, (const xmlChar *)"application/vnd.openxmlformats-officedocument.custom-properties+xml")) {
            /* default: /docProps/custom.xml */
            tmp = unzip_search_single(ctx, (const char *)(PN+1), xmlStrlen(PN)-1, &loff);
            if (tmp == CL_ETIMEOUT) {
                ret = tmp;
            }
            else if (tmp != CL_VIRUS) {
                cli_dbgmsg("cli_process_ooxml: failed to find custom properties file \"%s\"!\n", PN);
                mcust++;
            }
            else {
                cli_dbgmsg("ooxml_content_cb: found custom properties file \"%s\" @ %x\n", PN, loff);
                /* custom properties are not parsed */
                cust++;
            }
        }
        else if (!xmlStrcmp(CT, (const xmlChar *)"application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml")) {
            dsig++;
        }

        if (ret != CL_SUCCESS)
            goto ooxml_content_exit;
    }

 ooxml_content_exit:
    if (core) {
        cli_jsonint(ctx->wrkproperty, "CorePropertiesFileCount", core);
        if (core > 1)
            cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_MULTIPLE_CORE_PROPFILES");
    }
    else if (!mcore)
        cli_dbgmsg("cli_process_ooxml: file does not contain core properties file\n");
    if (mcore) {
        cli_jsonint(ctx->wrkproperty, "CorePropertiesMissingFileCount", mcore);
        cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_MISSING_CORE_PROPFILES");
    }

    if (extn) {
        cli_jsonint(ctx->wrkproperty, "ExtendedPropertiesFileCount", extn);
        if (extn > 1)
            cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_MULTIPLE_EXTN_PROPFILES");
    }
    else if (!mextn)
        cli_dbgmsg("cli_process_ooxml: file does not contain extended properties file\n");
    if (mextn) {
        cli_jsonint(ctx->wrkproperty, "ExtendedPropertiesMissingFileCount", mextn);
        cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_MISSING_EXTN_PROPFILES");
    }

    if (cust) {
        cli_jsonint(ctx->wrkproperty, "CustomPropertiesFileCount", cust);
        if (cust > 1)
            cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_MULTIPLE_CUSTOM_PROPFILES");
    }
    else if (!mcust)
        cli_dbgmsg("cli_process_ooxml: file does not contain custom properties file\n");
    if (mcust) {
        cli_jsonint(ctx->wrkproperty, "CustomPropertiesMissingFileCount", mcust);
        cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_MISSING_CUST_PROPFILES");
    }

    if (dsig) {
        cli_jsonint(ctx->wrkproperty, "DigitalSignaturesCount", dsig);
    }

    /* restore the engine tracking limits; resets session limit tracking */
    ctx->scansize = sav_scansize;
    ctx->scannedfiles = sav_scannedfiles;

    xmlTextReaderClose(reader);
    xmlFreeTextReader(reader);
    return ret;
}
示例#5
0
/* return count of valid strings found, 0 on error */
static int
vba_read_project_strings(int fd, int big_endian)
{
    unsigned char *buf = NULL;
    uint16_t buflen = 0;
    uint16_t length = 0;
    int ret = 0, getnewlength = 1;

    for(;;) {
        off_t offset;
        char *name;

        /* if no initial name length, exit */
        if(getnewlength && !read_uint16(fd, &length, big_endian)) {
            ret = 0;
            break;
        }
        getnewlength = 0;

        /* if too short, break */
        if (length < 6) {
            if (lseek(fd, -2, SEEK_CUR) == -1) {
                cli_dbgmsg("vba_read_project_strings: call to lseek() has failed\n");
                ret = 0;
            }
            break;
        }
        /* ensure buffer is large enough */
        if(length > buflen) {
            unsigned char *newbuf = (unsigned char *)cli_realloc(buf, length);
            if(newbuf == NULL) {
                ret = 0;
                break;
            }
            buflen = length;
            buf = newbuf;
        }

        /* save current offset */
        offset = lseek(fd, 0, SEEK_CUR);
        if (offset == -1) {
            cli_dbgmsg("vba_read_project_strings: call to lseek() has failed\n");
            ret = 0;
            break;
        }

        /* if read name failed, break */
        if(cli_readn(fd, buf, length) != (int)length) {
            cli_dbgmsg("read name failed - rewinding\n");
            if (lseek(fd, offset, SEEK_SET) == -1) {
                cli_dbgmsg("call to lseek() in read name failed\n");
                ret = 0;
            }
            break;
        }
        name = get_unicode_name((const char *)buf, length, big_endian);
        cli_dbgmsg("length: %d, name: %s\n", length, (name) ? name : "[null]");

        /* if invalid name, break */
        if((name == NULL) || (memcmp("*\\", name, 2) != 0) ||
           (strchr("ghcd", name[2]) == NULL)) {
            /* Not a valid string, rewind */
            if (lseek(fd, -(length+2), SEEK_CUR) == -1) {
                cli_dbgmsg("call to lseek() after get_unicode_name has failed\n");
                ret = 0;
            }
            free(name);
            break;
        }
        free(name);

        /* can't get length, break */
        if(!read_uint16(fd, &length, big_endian)) {
            break;
        }

        ret++;

        /* continue on reasonable length value */
        if ((length != 0) && (length != 65535)) {
            continue;
        }

        /* determine offset and run middle test */
        offset = lseek(fd, 10, SEEK_CUR);
        if (offset == -1) {
            cli_dbgmsg("call to lseek() has failed\n");
            ret = 0;
            break;
        }
        cli_dbgmsg("offset: %lu\n", (unsigned long)offset);
        vba56_test_middle(fd);
        getnewlength = 1;
    }

    free(buf);
    return ret;
}
示例#6
0
int cli_pcre_build(struct cli_matcher *root, long long unsigned match_limit, long long unsigned recmatch_limit, const struct cli_dconf *dconf)
{
    unsigned int i;
    int ret;
    struct cli_pcre_meta *pm = NULL;
    int disable_all = 0;

    if (dconf && !(dconf->pcre & PCRE_CONF_SUPPORT))
        disable_all = 1;

    for (i = 0; i < root->pcre_metas; ++i) {
        pm = root->pcre_metatable[i];
        if (!pm) {
            cli_errmsg("cli_pcre_build: metadata for pcre %d is missing\n", i);
            return CL_ENULLARG;
        }

        /* for safety, disable all pcre */
        if (disable_all) {
            pm->flags |= CLI_PCRE_DISABLED;
            continue;
        }

        if (pm->flags & CLI_PCRE_DISABLED) {
            cli_dbgmsg("cli_pcre_build: Skip compiling regex: %s (disabled)\n", pm->pdata.expression);
            continue;
        }

        /* disable global */
        if (dconf && !(dconf->pcre & PCRE_CONF_GLOBAL)) {
            cli_dbgmsg("cli_pcre_build: disabling global option for regex /%s/\n", pm->pdata.expression);
            pm->flags &= ~(CLI_PCRE_GLOBAL);
        }

        /* options override through metadata manipulation */
#if USING_PCRE2
        //pm->pdata.options |= PCRE2_NEVER_UTF; /* disables (?UTF*) potential security vuln */
        //pm->pdata.options |= PCRE2_UCP;
        //pm->pdata.options |= PCRE2_AUTO_CALLOUT; /* used with CALLOUT(-BACK) function */
#else
        //pm->pdata.options |= PCRE_NEVER_UTF; /* implemented in 8.33, disables (?UTF*) potential security vuln */
        //pm->pdata.options |= PCRE_UCP;/* implemented in 8.20 */
        //pm->pdata.options |= PCRE_AUTO_CALLOUT; /* used with CALLOUT(-BACK) function */
#endif

        if (dconf && (dconf->pcre & PCRE_CONF_OPTIONS)) {
            /* compile the regex, no options override *wink* */
            pm_dbgmsg("cli_pcre_build: Compiling regex: /%s/\n", pm->pdata.expression);
            ret = cli_pcre_compile(&(pm->pdata), match_limit, recmatch_limit, 0, 0);
        }
        else {
            /* compile the regex, options overridden and disabled */
            pm_dbgmsg("cli_pcre_build: Compiling regex: /%s/ (without options)\n", pm->pdata.expression);
            ret = cli_pcre_compile(&(pm->pdata), match_limit, recmatch_limit, 0, 1);
        }
        if (ret != CL_SUCCESS) {
            cli_errmsg("cli_pcre_build: failed to build pcre regex\n");
            pm->flags |= CLI_PCRE_DISABLED; /* disable the pcre, currently will terminate execution */
            return ret;
        }
    }

    return CL_SUCCESS;
}
示例#7
0
void cli_detect_swizz_str(const unsigned char *str, uint32_t len, struct swizz_stats *stats, int blob)
{
	unsigned char stri[4096];
        uint32_t i, j = 0;
	int bad = 0;
	int lastalnum = 0;
	uint8_t ngrams[17576];
	uint16_t all=0;
	uint16_t ngram_cnts[3];
	uint16_t words = 0;
	int ret;

	stats->entries++;
	for(i=0;i<len-1 && j < sizeof(stri)-2;i += 2) {
		unsigned char c = str[i];
		if (str[i+1] || !c) {
			bad++;
			continue;
		}
		if (!isalnum(c)) {
			if (!lastalnum)
				continue;
			lastalnum = 0;
			c = ' ';
		} else {
			lastalnum = 1;
			if (isdigit(c))
				continue;
		}
		stri[j++] = tolower(c);
	}
	stri[j++] = '\0';
	if ((!blob && (bad >= 8)) || j < 4)
		return;
	memset(ngrams, 0, sizeof(ngrams));
	memset(ngram_cnts, 0, sizeof(ngram_cnts));
	for(i=0;i<j-2;i++) {
		if (stri[i] != ' ' && stri[i+1] != ' ' && stri[i+2] != ' ') {
			uint16_t idx = (stri[i] - 'a')*676 + (stri[i+1] - 'a')*26 + (stri[i+2] - 'a');
			if (idx < sizeof(ngrams)) {
				ngrams[idx]++;
				stats->gngrams[idx]++;
			}
		} else if (stri[i] == ' ')
			words++;
	}
	for(i=0;i<sizeof(ngrams);i++) {
		uint8_t v = ngrams[i];
		if (v > 3) v = 3;
		if (v) {
			ngram_cnts[v-1]++;
			all++;
		}
	}
	if (!all)
		return;
	cli_dbgmsg("cli_detect_swizz_str: %u, %u, %u\n",ngram_cnts[0],ngram_cnts[1],ngram_cnts[2]);
	/* normalize */
	for(i=0;i<sizeof(ngram_cnts)/sizeof(ngram_cnts[0]);i++) {
		uint32_t v = ngram_cnts[i];
		ngram_cnts[i] = (v<<10)/all;
	}
	ret = swizz_j48(ngram_cnts) ? CL_VIRUS : CL_CLEAN;
	if (words < 3) ret = CL_CLEAN;
	cli_dbgmsg("cli_detect_swizz_str: %s, %u words\n", ret == CL_VIRUS ? "suspicious" : "ok", words);
	if (ret == CL_VIRUS) {
		stats->suspicious += j;
		cli_dbgmsg("cli_detect_swizz_str: %s\n", stri);
	}
	stats->total += j;
}
示例#8
0
static int asn1_get_x509(fmap_t *map, const void **asn1data, unsigned int *size, crtmgr *master, crtmgr *other) {
    struct cli_asn1 crt, tbs, obj;
    unsigned int avail, tbssize, issuersize;
    cli_crt_hashtype hashtype1, hashtype2;
    cli_crt x509;
    const uint8_t *tbsdata;
    const void *next, *issuer;

    if(cli_crt_init(&x509))
	return 1;

    do {
	if(asn1_expect_objtype(map, *asn1data, size, &crt, 0x30)) /* SEQUENCE */
	    break;
	*asn1data = crt.next;

	tbsdata = crt.content;
	if(asn1_expect_objtype(map, crt.content, &crt.size, &tbs, 0x30)) /* SEQUENCE - TBSCertificate */
	    break;
	tbssize = (uint8_t *)tbs.next - tbsdata;

	if(asn1_expect_objtype(map, tbs.content, &tbs.size, &obj, 0xa0)) /* [0] */
	    break;
	avail = obj.size;
	next = obj.next;
	if(asn1_expect_obj(map, &obj.content, &avail, 0x02, 1, "\x02")) /* version 3 only */
	    break;
	if(avail) {
	    cli_dbgmsg("asn1_get_x509: found unexpected extra data in version\n");
	    break;
	}

	if(asn1_expect_objtype(map, next, &tbs.size, &obj, 0x02)) /* serialNumber */
	    break;
	if(map_sha1(map, obj.content, obj.size, x509.serial))
	    break;

	if(asn1_expect_rsa(map, &obj.next, &tbs.size, &hashtype1)) /* algo = sha1WithRSAEncryption | md5WithRSAEncryption */
	    break;

	if(asn1_expect_objtype(map, obj.next, &tbs.size, &obj, 0x30)) /* issuer */
	    break;
	issuer = obj.content;
	issuersize = obj.size;

	if(asn1_expect_objtype(map, obj.next, &tbs.size, &obj, 0x30)) /* validity */
	    break;
	avail = obj.size;
	next = obj.content;

	if(asn1_get_time(map, &next, &avail, &x509.not_before)) /* notBefore */
	    break;
	if(asn1_get_time(map, &next, &avail, &x509.not_after)) /* notAfter */
	    break;
	if(x509.not_before >= x509.not_after) {
	    cli_dbgmsg("asn1_get_x509: bad validity\n");
	    break;
	}
	if(avail) {
	    cli_dbgmsg("asn1_get_x509: found unexpected extra data in validity\n");
	    break;
	}

	if(asn1_expect_objtype(map, obj.next, &tbs.size, &obj, 0x30)) /* subject */
	    break;
	if(map_sha1(map, obj.content, obj.size, x509.subject))
	    break;
	if(asn1_get_rsa_pubkey(map, &obj.next, &tbs.size, &x509))
	    break;

	avail = 0;
	while(tbs.size) {
	    if(asn1_get_obj(map, obj.next, &tbs.size, &obj)) {
		tbs.size = 1;
		break;
	    }
	    if(obj.type <= 0xa0 + avail || obj.type > 0xa3) {
		cli_dbgmsg("asn1_get_x509: found type %02x in extensions, expecting a1, a2 or a3\n", obj.type);
		tbs.size = 1;
		break;
	    }
	    avail = obj.type - 0xa0;
	    if(obj.type == 0xa3) {
		struct cli_asn1 exts;
		int have_ext_key = 0;
		if(asn1_expect_objtype(map, obj.content, &obj.size, &exts, 0x30)) {
		    tbs.size = 1;
		    break;
		}
		if(obj.size) {
		    cli_dbgmsg("asn1_get_x509: found unexpected extra data in extensions\n");
		    break;
		}
		while(exts.size) {
		    struct cli_asn1 ext, id, value;
		    if(asn1_expect_objtype(map, exts.content, &exts.size, &ext, 0x30)) {
			exts.size = 1;
			break;
		    }
		    exts.content = ext.next;
		    if(asn1_expect_objtype(map, ext.content, &ext.size, &id, 0x06)) {
			exts.size = 1;
			break;
		    }
		    if(asn1_get_obj(map, id.next, &ext.size, &value)) {
			exts.size = 1;
			break;
		    }
		    if(value.type == 0x01) {
			/* critical flag */
			if(value.size != 1) {
			    cli_dbgmsg("asn1_get_x509: found boolean with wrong length\n");
			    exts.size = 1;
			    break;
			}
			if(asn1_get_obj(map, value.next, &ext.size, &value)) {
			    exts.size = 1;
			    break;
			}
		    }
		    if(value.type != 0x04) {
			cli_dbgmsg("asn1_get_x509: bad extension value type %u\n", value.type);
			exts.size = 1;
			break;
		    }
		    if(ext.size) {
			cli_dbgmsg("asn1_get_x509: extra data in extension\n");
			exts.size = 1;
			break;
		    }
		    if(id.size != 3)
			continue;

		    if(!fmap_need_ptr_once(map, id.content, 3)) {
			exts.size = 1;
			break;
		    }
		    if(!memcmp("\x55\x1d\x0f", id.content, 3)) {
			/* KeyUsage 2.5.29.15 */
			const uint8_t *keyusage = value.content;
			uint8_t usage;
			if(value.size < 4 || value.size > 5) {
			    cli_dbgmsg("asn1_get_x509: bad KeyUsage\n");
			    exts.size = 1;
			    break;
			}
			if(!fmap_need_ptr_once(map, value.content, value.size)) {
			    exts.size = 1;
			    break;
			}
			if(keyusage[0] != 0x03 || keyusage[1] != value.size - 2 || keyusage[2] > 7) {
			    cli_dbgmsg("asn1_get_x509: bad KeyUsage\n");
			    exts.size = 1;
			    break;
			}
			usage = keyusage[3];
			if(value.size == 4)
			    usage &= ~((1 << keyusage[2])-1);
			x509.certSign = ((usage & 4) != 0);
			continue;
		    }
		    if(!memcmp("\x55\x1d\x25", id.content, 3)) {
			/* ExtKeyUsage 2.5.29.37 */
			struct cli_asn1 keypurp;
			have_ext_key = 1;
			if(asn1_expect_objtype(map, value.content, &value.size, &keypurp, 0x30)) {
			    exts.size = 1;
			    break;
			}
			if(value.size) {
			    cli_dbgmsg("asn1_get_x509: extra data in ExtKeyUsage\n");
			    exts.size = 1;
			    break;
			}
			ext.next = keypurp.content;
			while(keypurp.size) {
			    if(asn1_expect_objtype(map, ext.next, &keypurp.size, &ext, 0x06)) {
				exts.size = 1;
				break;
			    }
			    if(ext.size != 8)
				continue;
			    if(!fmap_need_ptr_once(map, ext.content, 8)) {
				exts.size = 1;
				break;
			    }
			    if(!memcmp("\x2b\x06\x01\x05\x05\x07\x03\x03", ext.content, 8)) /* id_kp_codeSigning */
				x509.codeSign = 1;
			    else if(!memcmp("\x2b\x06\x01\x05\x05\x07\x03\x08", ext.content, 8)) /* id_kp_timeStamping */
				x509.timeSign = 1;
			}
			continue;
		    }
		    if(!memcmp("\x55\x1d\x13", id.content, 3)) {
			/* Basic Constraints 2.5.29.19 */
			struct cli_asn1 constr;
			if(asn1_expect_objtype(map, value.content, &value.size, &constr, 0x30)) {
			    exts.size = 1;
			    break;
			}
			if(!constr.size)
			    x509.certSign = 0;
			else {
			    if(asn1_expect_objtype(map, constr.content, &constr.size, &ext, 0x01)) {
				exts.size = 1;
				break;
			    }
			    if(ext.size != 1) {
				cli_dbgmsg("asn1_get_x509: wrong bool size in basic constraint %u\n", ext.size);
				exts.size = 1;
				break;
			    }
			    if(!fmap_need_ptr_once(map, ext.content, 1)) {
				exts.size = 1;
				break;
			    }
			    x509.certSign = (((uint8_t *)(ext.content))[0] != 0);
			}
		    }
		}
		if(exts.size) {
		    tbs.size = 1;
		    break;
		}
		if(!have_ext_key)
		    x509.codeSign = x509.timeSign = 1;
	    }
	}
	if(tbs.size)
	    break;


	if(crtmgr_lookup(master, &x509) || crtmgr_lookup(other, &x509)) {
	    cli_dbgmsg("asn1_get_x509: certificate already exists\n");
	    cli_crt_clear(&x509);
	    return 0;
	}

	if(map_sha1(map, issuer, issuersize, x509.issuer))
	    break;

	if(asn1_expect_rsa(map, &tbs.next, &crt.size, &hashtype2)) /* signature algo = sha1WithRSAEncryption | md5WithRSAEncryption */
	    break;

	if(hashtype1 != hashtype2) {
	    cli_dbgmsg("asn1_get_x509: found conflicting rsa hash types\n");
	    break;
	}
	x509.hashtype = hashtype1;

	if(asn1_expect_objtype(map, tbs.next, &crt.size, &obj, 0x03)) /* signature */
	    break;
	if(obj.size > 513) {
	    cli_dbgmsg("asn1_get_x509: signature too long\n");
	    break;
	}
	if(!fmap_need_ptr_once(map, obj.content, obj.size)) {
	    cli_dbgmsg("asn1_get_x509: cannot read signature\n");
	    break;
	}
	if(mp_read_unsigned_bin(&x509.sig, obj.content, obj.size)) {
	    cli_dbgmsg("asn1_get_x509: cannot convert signature to big number\n");
	    break;
	}
	if(crt.size) {
	    cli_dbgmsg("asn1_get_x509: found unexpected extra data in signature\n");
	    break;
	}

	if((x509.hashtype == CLI_SHA1RSA && map_sha1(map, tbsdata, tbssize, x509.tbshash)) || (x509.hashtype == CLI_MD5RSA && (map_md5(map, tbsdata, tbssize, x509.tbshash))))
	    break;

	if(crtmgr_add(other, &x509))
	    break;
	cli_crt_clear(&x509);
	return 0;
    } while(0);
    cli_crt_clear(&x509);
    return 1;
}
示例#9
0
static int asn1_parse_mscat(fmap_t *map, size_t offset, unsigned int size, crtmgr *cmgr, int embedded, const void **hashes, unsigned int *hashes_size, struct cl_engine *engine) {
    struct cli_asn1 asn1, deep, deeper;
    uint8_t sha1[SHA1_HASH_SIZE], issuer[SHA1_HASH_SIZE], md[SHA1_HASH_SIZE], serial[SHA1_HASH_SIZE];
    const uint8_t *message, *attrs;
    unsigned int dsize, message_size, attrs_size;
    cli_crt_hashtype hashtype;
    cli_crt *x509;
    void *ctx;
    int result;
    int isBlacklisted = 0;

    cli_dbgmsg("in asn1_parse_mscat\n");

    do {
	if(!(message = fmap_need_off_once(map, offset, 1))) {
	    cli_dbgmsg("asn1_parse_mscat: failed to read pkcs#7 entry\n");
	    break;
	}

	if(asn1_expect_objtype(map, message, &size, &asn1, 0x30)) /* SEQUENCE */
	    break;
	/* if(size) { */
	/*     cli_dbgmsg("asn1_parse_mscat: found extra data after pkcs#7 %u\n", size); */
	/*     break; */
	/* } */
	size = asn1.size;
	if(asn1_expect_obj(map, &asn1.content, &size, 0x06, lenof(OID_signedData), OID_signedData)) /* OBJECT 1.2.840.113549.1.7.2 - contentType = signedData */
	    break;
	if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0xa0)) /* [0] - content */
	    break;
	if(size) {
	    cli_dbgmsg("asn1_parse_mscat: found extra data in pkcs#7\n");
	    break;
	}
	size = asn1.size;
	if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x30)) /* SEQUENCE */
	    break;
	if(size) {
	    cli_dbgmsg("asn1_parse_mscat: found extra data in signedData\n");
	    break;
	}
	size = asn1.size;
	if(asn1_expect_obj(map, &asn1.content, &size, 0x02, 1, "\x01")) /* INTEGER - VERSION 1 */
	    break;

	if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x31)) /* SET OF DigestAlgorithmIdentifier */
	    break;

	if(asn1_expect_algo(map, &asn1.content, &asn1.size, lenof(OID_sha1), OID_sha1)) /* DigestAlgorithmIdentifier[0] == sha1 */
	    break;
	if(asn1.size) {
	    cli_dbgmsg("asn1_parse_mscat: only one digestAlgorithmIdentifier is allowed\n");
	    break;
	}

	if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0x30)) /* SEQUENCE - contentInfo */
	    break;
	/* Here there is either a PKCS #7 ContentType Object Identifier for Certificate Trust List (szOID_CTL)
	 * or a single SPC_INDIRECT_DATA_OBJID */
	if(
	   (!embedded && asn1_expect_obj(map, &asn1.content, &asn1.size, 0x06, lenof(OID_szOID_CTL), OID_szOID_CTL)) ||
	   (embedded && asn1_expect_obj(map, &asn1.content, &asn1.size, 0x06, lenof(OID_SPC_INDIRECT_DATA_OBJID), OID_SPC_INDIRECT_DATA_OBJID))
	   )
	    break;

	if(asn1_expect_objtype(map, asn1.content, &asn1.size, &deep, 0xa0))
	    break;
	if(asn1.size) {
	    cli_dbgmsg("asn1_parse_mscat: found extra data in contentInfo\n");
	    break;
	}
	dsize = deep.size;
	if(asn1_expect_objtype(map, deep.content, &dsize, &deep, 0x30))
	    break;
	if(dsize) {
	    cli_dbgmsg("asn1_parse_mscat: found extra data in content\n");
	    break;
	}
	*hashes = deep.content;
	*hashes_size = deep.size;

	if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0xa0)) /* certificates */
	    break;

	dsize = asn1.size;
	if(dsize) {
	    crtmgr newcerts;
	    crtmgr_init(&newcerts);
	    while(dsize) {
		if(asn1_get_x509(map, &asn1.content, &dsize, cmgr, &newcerts)) {
		    dsize = 1;
		    break;
		}
	    }
	    if(dsize)
		break;
	    if(newcerts.crts) {
		x509 = newcerts.crts;
		cli_dbgmsg("asn1_parse_mscat: %u new certificates collected\n", newcerts.items);
		while(x509) {
		    cli_crt *parent = crtmgr_verify_crt(cmgr, x509);

            /* Dump the cert if requested before anything happens to it */
            if (engine->dconf->pe & PE_CONF_DUMPCERT) {
                char issuer[SHA1_HASH_SIZE*2+1], subject[SHA1_HASH_SIZE*2+1], serial[SHA1_HASH_SIZE*2+1];
                char mod[1024], exp[1024];
                int j=1024;

                fp_toradix_n(&x509->n, mod, 16, j);
                fp_toradix_n(&x509->e, exp, 16, j);
                for (j=0; j < SHA1_HASH_SIZE; j++) {
                    sprintf(&issuer[j*2], "%02x", x509->issuer[j]);
                    sprintf(&subject[j*2], "%02x", x509->subject[j]);
                    sprintf(&serial[j*2], "%02x", x509->serial[j]);
                }

                cli_dbgmsg_internal("cert subject:%s serial:%s pubkey:%s i:%s %lu->%lu %s %s %s\n", subject, serial, mod, issuer, (unsigned long)x509->not_before, (unsigned long)x509->not_after, x509->certSign ? "cert" : "", x509->codeSign ? "code" : "", x509->timeSign ? "time" : "");
            }

		    if(parent) {
                if (parent->isBlacklisted) {
                    isBlacklisted = 1;
                    cli_dbgmsg("asn1_parse_mscat: Authenticode certificate %s is revoked. Flagging sample as virus.\n", (parent->name ? parent->name : "(no name)"));
                }

			x509->codeSign &= parent->codeSign;
			x509->timeSign &= parent->timeSign;
            if(crtmgr_add(cmgr, x509))
                break;
            crtmgr_del(&newcerts, x509);
			x509 = newcerts.crts;
			continue;
		    }
		    x509 = x509->next;
		}
		if(x509)
		    break;
		if(newcerts.items)
		    cli_dbgmsg("asn1_parse_mscat: %u certificates did not verify\n", newcerts.items);
		crtmgr_free(&newcerts);
	    }
	}

	if(asn1_get_obj(map, asn1.next, &size, &asn1))
	    break;
	if(asn1.type == 0xa1 && asn1_get_obj(map, asn1.next, &size, &asn1)) /* crls - unused shouldn't be present */
	    break;
	if(asn1.type != 0x31) { /* signerInfos */
	    cli_dbgmsg("asn1_parse_mscat: unexpected type %02x for signerInfos\n", asn1.type);
	    break;
	}
	if(size) {
	    cli_dbgmsg("asn1_parse_mscat: unexpected extra data after signerInfos\n");
	    break;
	}
	size = asn1.size;
	if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x30))
	    break;
	if(size) {
	    cli_dbgmsg("asn1_parse_mscat: only one signerInfo shall be present\n");
	    break;
	}
	size = asn1.size;
	if(asn1_expect_obj(map, &asn1.content, &size, 0x02, 1, "\x01")) /* Version = 1 */
	    break;
	if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x30)) /* issuerAndSerialNumber */
	    break;
	dsize = asn1.size;
	if(asn1_expect_objtype(map, asn1.content, &dsize, &deep, 0x30)) /* issuer */
	    break;
	if(map_sha1(map, deep.content, deep.size, issuer))
	    break;

	if(asn1_expect_objtype(map, deep.next, &dsize, &deep, 0x02)) /* serial */
	    break;
	if(map_sha1(map, deep.content, deep.size, serial))
	    break;
	if(dsize) {
	    cli_dbgmsg("asn1_parse_mscat: extra data inside issuerAndSerialNumber\n");
	    break;
	}
	if(asn1_expect_algo(map, &asn1.next, &size, lenof(OID_sha1), OID_sha1)) /* digestAlgorithm == sha1 */
	    break;

	attrs = asn1.next;
	if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0xa0)) /* authenticatedAttributes */
	    break;
	attrs_size = (uint8_t *)(asn1.next) - attrs;
	if(attrs_size < 2) {
	    cli_dbgmsg("asn1_parse_mscat: authenticatedAttributes size is too small\n");
	    break;
	}

	dsize = asn1.size;
	deep.next = asn1.content;
	result = 0;
	while(dsize) {
	    struct cli_asn1 cobj;
	    int content;
	    if(asn1_expect_objtype(map, deep.next, &dsize, &deep, 0x30)) { /* attribute */
		dsize = 1;
		break;
	    }
	    if(asn1_expect_objtype(map, deep.content, &deep.size, &deeper, 0x06)) { /* attribute type */
		dsize = 1;
		break;
	    }
	    if(deeper.size != lenof(OID_contentType))
		continue;
	    if(!fmap_need_ptr_once(map, deeper.content, lenof(OID_contentType))) {
		cli_dbgmsg("asn1_parse_mscat: failed to read authenticated attribute\n");
		dsize = 1;
		break;
	    }
	    if(!memcmp(deeper.content, OID_contentType, lenof(OID_contentType)))
		content = 0; /* contentType */
	    else if(!memcmp(deeper.content, OID_messageDigest, lenof(OID_messageDigest)))
		content = 1; /* messageDigest */
	    else
		continue;
	    if(asn1_expect_objtype(map, deeper.next, &deep.size, &deeper, 0x31)) { /* set - contents */
		dsize = 1;
		break;
	    }
	    if(deep.size) {
		cli_dbgmsg("asn1_parse_mscat: extra data in authenticated attributes\n");
		dsize = 1;
		break;
	    }

	    if(result & (1<<content)) {
		cli_dbgmsg("asn1_parse_mscat: contentType or messageDigest appear twice\n");
		dsize = 1;
		break;
	    }

	    if(content == 0) { /* contentType */
		if(
		   (!embedded && asn1_expect_obj(map, &deeper.content, &deeper.size, 0x06, lenof(OID_szOID_CTL), OID_szOID_CTL)) || /* cat file */
		   (embedded && asn1_expect_obj(map, &deeper.content, &deeper.size, 0x06, lenof(OID_SPC_INDIRECT_DATA_OBJID), OID_SPC_INDIRECT_DATA_OBJID)) /* embedded cat */
		  ) {
		    dsize = 1;
		    break;
		}
		result |= 1;
	    } else { /* messageDigest */
		if(asn1_expect_objtype(map, deeper.content, &deeper.size, &cobj, 0x04)) {
		    dsize = 1;
		    break;
		}
		if(cobj.size != SHA1_HASH_SIZE) {
		    cli_dbgmsg("asn1_parse_mscat: messageDigest attribute has got the wrong size (%u)\n", cobj.size);
		    dsize = 1;
		    break;
		}
		if(!fmap_need_ptr_once(map, cobj.content, SHA1_HASH_SIZE)) {
		    cli_dbgmsg("asn1_parse_mscat: failed to read authenticated attribute\n");
		    dsize = 1;
		    break;
		}
		memcpy(md, cobj.content, SHA1_HASH_SIZE);
		result |= 2;
	    }
	    if(deeper.size) {
		cli_dbgmsg("asn1_parse_mscat: extra data in authenticated attribute\n");
		dsize = 1;
		break;
	    }
	}
	if(dsize)
	    break;
	if(result != 3) {
	    cli_dbgmsg("asn1_parse_mscat: contentType or messageDigest are missing\n");
	    break;
	}

	if(asn1_expect_algo(map, &asn1.next, &size, lenof(OID_rsaEncryption), OID_rsaEncryption)) /* digestEncryptionAlgorithm == sha1 */
	    break;

	if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0x04)) /* encryptedDigest */
	    break;
	if(asn1.size > 513) {
	    cli_dbgmsg("asn1_parse_mscat: encryptedDigest too long\n");
	    break;
	}
	if(map_sha1(map, *hashes, *hashes_size, sha1))
	    break;
	if(memcmp(sha1, md, sizeof(sha1))) {
	    cli_dbgmsg("asn1_parse_mscat: messageDigest mismatch\n");
	    break;
	}

	if(!fmap_need_ptr_once(map, attrs, attrs_size)) {
	    cli_dbgmsg("asn1_parse_mscat: failed to read authenticatedAttributes\n");
	    break;
	}

    ctx = cl_hash_init("sha1");
    if (!(ctx))
        break;

	cl_update_hash(ctx, "\x31", 1);
	cl_update_hash(ctx, (void *)(attrs + 1), attrs_size - 1);
	cl_finish_hash(ctx, sha1);

	if(!fmap_need_ptr_once(map, asn1.content, asn1.size)) {
	    cli_dbgmsg("asn1_parse_mscat: failed to read encryptedDigest\n");
	    break;
	}
	if(!(x509 = crtmgr_verify_pkcs7(cmgr, issuer, serial, asn1.content, asn1.size, CLI_SHA1RSA, sha1, VRFY_CODE))) {
	    cli_dbgmsg("asn1_parse_mscat: pkcs7 signature verification failed\n");
	    break;
	}
	message = asn1.content;
	message_size = asn1.size;

	if(!size) {
	    cli_dbgmsg("asn1_parse_mscat: countersignature is missing\n");
	    break;
	}

	if(size && asn1_expect_objtype(map, asn1.next, &size, &asn1, 0xa1)) /* unauthenticatedAttributes */
	    break;

	if(size) {
	    cli_dbgmsg("asn1_parse_mscat: extra data inside signerInfo\n");
	    break;
	}

	size = asn1.size;
	if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x30))
	    break;
	if(size) {
	    cli_dbgmsg("asn1_parse_mscat: extra data inside unauthenticatedAttributes\n");
	    break;
	}

	size = asn1.size;
	/* 1.2.840.113549.1.9.6 - counterSignature */
	if(asn1_expect_obj(map, &asn1.content, &size, 0x06, lenof(OID_countersignature), OID_countersignature))
	    break;
	if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x31))
	    break;
	if(size) {
	    cli_dbgmsg("asn1_parse_mscat: extra data inside counterSignature\n");
	    break;
	}

	size = asn1.size;
	if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x30))
	    break;
	if(size) {
	    cli_dbgmsg("asn1_parse_mscat: extra data inside unauthenticatedAttributes\n");
	    break;
	}

	size = asn1.size;
	if(asn1_expect_obj(map, &asn1.content, &size, 0x02, 1, "\x01")) /* Version = 1*/
	    break;

	if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x30)) /* issuerAndSerialNumber */
	    break;

	if(asn1_expect_objtype(map, asn1.content, &asn1.size, &deep, 0x30)) /* issuer */
	    break;
	if(map_sha1(map, deep.content, deep.size, issuer))
	    break;

	if(asn1_expect_objtype(map, deep.next, &asn1.size, &deep, 0x02)) /* serial */
	    break;
	if(map_sha1(map, deep.content, deep.size, serial))
	    break;

	if(asn1.size) {
	    cli_dbgmsg("asn1_parse_mscat: extra data inside countersignature issuer\n");
	    break;
	}

	if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0x30)) /* digestAlgorithm */
	    break;
	if(asn1_expect_objtype(map, asn1.content, &asn1.size, &deep, 0x06))
	    break;
	if(deep.size != lenof(OID_sha1) && deep.size != lenof(OID_md5)) {
	    cli_dbgmsg("asn1_parse_mscat: wrong digestAlgorithm size\n");
	    break;
	}
	if(!fmap_need_ptr_once(map, deep.content, deep.size)) {
	    cli_dbgmsg("asn1_parse_mscat: failed to read digestAlgorithm OID\n");
	    break;
	}
	if(deep.size == lenof(OID_sha1) && !memcmp(deep.content, OID_sha1, lenof(OID_sha1))) {
	    hashtype = CLI_SHA1RSA;
	    if(map_sha1(map, message, message_size, md))
		break;
	} else if(deep.size == lenof(OID_md5) && !memcmp(deep.content, OID_md5, lenof(OID_md5))) {
	    hashtype = CLI_MD5RSA;
	    if(map_md5(map, message, message_size, md))
		break;
	} else {
	    cli_dbgmsg("asn1_parse_mscat: unknown digest oid in countersignature\n");
	    break;
	}
	if(asn1.size && asn1_expect_obj(map, &deep.next, &asn1.size, 0x05, 0, NULL))
	    break;
	if(asn1.size) {
	    cli_dbgmsg("asn1_parse_mscat: extra data in countersignature oid\n");
	    break;
	}

	attrs = asn1.next;
	if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0xa0)) /* authenticatedAttributes */
	    break;
	attrs_size = (uint8_t *)(asn1.next) - attrs;
	if(attrs_size < 2) {
	    cli_dbgmsg("asn1_parse_mscat: countersignature authenticatedAttributes are too small\n");
	    break;
	}
	result = 0;
	dsize = asn1.size;
	deep.next = asn1.content;
	while(dsize) {
	    int content;
	    if(asn1_expect_objtype(map, deep.next, &dsize, &deep, 0x30)) { /* attribute */
		dsize = 1;
		break;
	    }
	    if(asn1_expect_objtype(map, deep.content, &deep.size, &deeper, 0x06)) { /* attribute type */
		dsize = 1;
		break;
	    }
	    if(deeper.size != lenof(OID_contentType)) /* lenof(contentType) = lenof(messageDigest) = lenof(signingTime) = 9 */
		continue;

	    if(!fmap_need_ptr_once(map, deeper.content, lenof(OID_contentType))) {
		dsize = 1;
		break;
	    }
	    if(!memcmp(deeper.content, OID_contentType, lenof(OID_contentType)))
		content = 0; /* contentType */
	    else if(!memcmp(deeper.content, OID_messageDigest, lenof(OID_messageDigest)))
		content = 1; /* messageDigest */
	    else if(!memcmp(deeper.content, OID_signingTime, lenof(OID_signingTime)))
		content = 2; /* signingTime */
	    else
		continue;
	    if(result & (1<<content)) {
		cli_dbgmsg("asn1_parse_mscat: duplicate field in countersignature\n");
		dsize = 1;
		break;
	    }
	    result |= (1<<content);
	    if(asn1_expect_objtype(map, deeper.next, &deep.size, &deeper, 0x31)) { /* attribute type */
		dsize = 1;
		break;
	    }
	    if(deep.size) {
		cli_dbgmsg("asn1_parse_mscat: extra data in countersignature value\n");
		dsize = 1;
		break;
	    }
	    deep.size = deeper.size;
	    switch(content) {
	    case 0:  /* contentType = pkcs7-data */
		if(asn1_expect_obj(map, &deeper.content, &deep.size, 0x06, lenof(OID_pkcs7_data), OID_pkcs7_data))
		    deep.size = 1;
		else if(deep.size)
		    cli_dbgmsg("asn1_parse_mscat: extra data in countersignature content-type\n");
		break;
	    case 1:  /* messageDigest */
		if(asn1_expect_obj(map, &deeper.content, &deep.size, 0x04, (hashtype == CLI_SHA1RSA) ? SHA1_HASH_SIZE : 16, md)) {
		    deep.size = 1;
		    cli_dbgmsg("asn1_parse_mscat: countersignature hash mismatch\n");
		} else if(deep.size)
		    cli_dbgmsg("asn1_parse_mscat: extra data in countersignature message-digest\n");
		break;
	    case 2:  /* signingTime */
		{
		    time_t sigdate; /* FIXME shall i use it?! */
		    if(asn1_get_time(map, &deeper.content, &deep.size, &sigdate))
			deep.size = 1;
		    else if(deep.size)
			cli_dbgmsg("asn1_parse_mscat: extra data in countersignature signing-time\n");
		    else if(sigdate < x509->not_before || sigdate > x509->not_after) {
			cli_dbgmsg("asn1_parse_mscat: countersignature timestamp outside cert validity\n");
			deep.size = 1;
		    }
		    break;
		}
	    }
	    if(deep.size) {
		dsize = 1;
		break;
	    }
	}
	if(dsize)
	    break;
	if(result != 7) {
	    cli_dbgmsg("asn1_parse_mscat: some important attributes are missing in countersignature\n");
	    break;
	}

	if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0x30)) /* digestEncryptionAlgorithm == sha1 */
	    break;
	if(asn1_expect_objtype(map, asn1.content, &asn1.size, &deep, 0x06)) /* digestEncryptionAlgorithm == sha1 */
	    break;
	if(deep.size != lenof(OID_rsaEncryption)) { /* lenof(OID_rsaEncryption) = lenof(OID_sha1WithRSAEncryption) = 9 */
	    cli_dbgmsg("asn1_parse_mscat: wrong digestEncryptionAlgorithm size in countersignature\n");
	    break;
	}
	if(!fmap_need_ptr_once(map, deep.content, lenof(OID_rsaEncryption))) {
	    cli_dbgmsg("asn1_parse_mscat: cannot read digestEncryptionAlgorithm in countersignature\n");
	    break;
	}
	/* rsaEncryption or sha1withRSAEncryption */
	if(memcmp(deep.content, OID_rsaEncryption, lenof(OID_rsaEncryption)) && memcmp(deep.content, OID_sha1WithRSAEncryption, lenof(OID_sha1WithRSAEncryption))) {
	    cli_dbgmsg("asn1_parse_mscat: digestEncryptionAlgorithm in countersignature is not sha1\n");
	    break;
	}
	if(asn1.size && asn1_expect_obj(map, &deep.next, &asn1.size, 0x05, 0, NULL))
	    break;
	if(asn1.size) {
	    cli_dbgmsg("asn1_parse_mscat: extra data in digestEncryptionAlgorithm in countersignature\n");
	    break;
	}

	if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0x04)) /* encryptedDigest */
	    break;
	if(asn1.size > 513) {
	    cli_dbgmsg("asn1_parse_mscat: countersignature encryptedDigest too long\n");
	    break;
	}
	if(size) {
	    cli_dbgmsg("asn1_parse_mscat: extra data inside countersignature\n");
	    break;
	}
	if(!fmap_need_ptr_once(map, attrs, attrs_size)) {
	    cli_dbgmsg("asn1_parse_mscat: failed to read authenticatedAttributes\n");
	    break;
	}

	if(hashtype == CLI_SHA1RSA) {
        ctx = cl_hash_init("sha1");
        if (!(ctx))
            break;

        cl_update_hash(ctx, "\x31", 1);
        cl_update_hash(ctx, (void *)(attrs + 1), attrs_size - 1);
        cl_finish_hash(ctx, sha1);
	} else {
        ctx = cl_hash_init("md5");
        if (!(ctx))
            break;

        cl_update_hash(ctx, "\x31", 1);
        cl_update_hash(ctx, (void *)(attrs + 1), attrs_size - 1);
        cl_finish_hash(ctx, sha1);
	}

	if(!fmap_need_ptr_once(map, asn1.content, asn1.size)) {
	    cli_dbgmsg("asn1_parse_mscat: failed to read countersignature encryptedDigest\n");
	    break;
	}
	if(!crtmgr_verify_pkcs7(cmgr, issuer, serial, asn1.content, asn1.size, hashtype, sha1, VRFY_TIME)) {
	    cli_dbgmsg("asn1_parse_mscat: pkcs7 countersignature verification failed\n");
	    break;
	}

	cli_dbgmsg("asn1_parse_mscat: catalog successfully parsed\n");
    if (isBlacklisted) {
        return 1;
    }
	return 0;
    } while(0);

    cli_dbgmsg("asn1_parse_mscat: failed to parse catalog\n");
    return 1;
}
示例#10
0
static int asn1_get_time(fmap_t *map, const void **asn1data, unsigned int *size, time_t *tm) {
    struct cli_asn1 obj;
    int ret = asn1_get_obj(map, *asn1data, size, &obj);
    unsigned int len;
    char *ptr;
    struct tm t;
    int n;

    if(ret)
	return ret;

    if(obj.type == 0x17) /* UTCTime - YYMMDDHHMMSSZ */
	len = 13;
    else if(obj.type == 0x18) /* GeneralizedTime - YYYYMMDDHHMMSSZ */
	len = 15;
    else {
	cli_dbgmsg("asn1_get_time: expected UTCTime or GeneralizedTime, got %02x\n", obj.type);
	return 1;
    }

    if(!fmap_need_ptr_once(map, obj.content, len)) {
	cli_dbgmsg("asn1_get_time: failed to read content\n");
	return 1;
    }

    memset(&t, 0, sizeof(t));
    ptr = (char *)obj.content;
    if(obj.type == 0x18) {
	t.tm_year = asn1_getnum(ptr) * 100;
	if(t.tm_year < 0)
	    return 1;
	n = asn1_getnum(ptr);
	if(n<0)
	    return 1;
	t.tm_year += n;
	ptr+=4;
    } else {
	n = asn1_getnum(ptr);
	if(n<0)
	    return 1;
	if(n>=50)
	    t.tm_year = 1900 + n;
	else
	    t.tm_year = 2000 + n;
	ptr += 2;
    }
    t.tm_year -= 1900;
    n = asn1_getnum(ptr);
    if(n<1 || n>12) {
	cli_dbgmsg("asn1_get_time: invalid month %u\n", n);
	return 1;
    }
    t.tm_mon = n - 1;
    ptr+=2;

    n = asn1_getnum(ptr);
    if(n<1 || n>31) {
	cli_dbgmsg("asn1_get_time: invalid day %u\n", n);
	return 1;
    }
    t.tm_mday = n;
    ptr+=2;

    n = asn1_getnum(ptr);
    if(n<0 || n>23) {
	cli_dbgmsg("asn1_get_time: invalid hour %u\n", n);
	return 1;
    }
    t.tm_hour = n;
    ptr+=2;

    n = asn1_getnum(ptr);
    if(n<0 || n>59) {
	cli_dbgmsg("asn1_get_time: invalid minute %u\n", n);
	return 1;
    }
    t.tm_min = n;
    ptr+=2;

    n = asn1_getnum(ptr);
    if(n<0 || n>59) {
	cli_dbgmsg("asn1_get_time: invalid second %u\n", n);
	return 1;
    }
    t.tm_sec = n;
    ptr+=2;

    if(*ptr != 'Z') {
	cli_dbgmsg("asn1_get_time: expected UTC time 'Z', got '%c'\n", *ptr);
	return 1;
    }

    *tm = mktime(&t);
    *asn1data = obj.next;
    return 0;
}
示例#11
0
static int asn1_get_rsa_pubkey(fmap_t *map, const void **asn1data, unsigned int *size, cli_crt *x509) {
    struct cli_asn1 obj;
    unsigned int avail, avail2;

    if(asn1_expect_objtype(map, *asn1data, size, &obj, 0x30)) /* subjectPublicKeyInfo */
	return 1;
    *asn1data = obj.next;

    avail = obj.size;
    if(asn1_expect_algo(map, &obj.content, &avail, lenof(OID_rsaEncryption), OID_rsaEncryption)) /* rsaEncryption */
       return 1;

    if(asn1_expect_objtype(map, obj.content, &avail, &obj, 0x03)) /* BIT STRING - subjectPublicKey */
	return 1;
    if(avail) {
	cli_dbgmsg("asn1_get_rsa_pubkey: found unexpected extra data in subjectPublicKeyInfo\n");
	return 1;
    }
    /* if(obj.size != 141 && obj.size != 271) /\* encoded len of 1024 and 2048 bit public keys *\/ */
    /*	return 1; */

    if(!fmap_need_ptr_once(map, obj.content, 1)) {
	cli_dbgmsg("asn1_get_rsa_pubkey: cannot read public key content\n");
	return 1;
    }
    if(((uint8_t *)obj.content)[0] != 0) { /* no byte fragments */
	cli_dbgmsg("asn1_get_rsa_pubkey: unexpected byte frags in public key\n");
	return 1;
    }

    avail = obj.size - 1;
    obj.content = ((uint8_t *)obj.content) + 1;
    if(asn1_expect_objtype(map, obj.content, &avail, &obj, 0x30)) /* SEQUENCE */
	return 1;
    if(avail) {
	cli_dbgmsg("asn1_get_rsa_pubkey: found unexpected extra data in public key content\n");
	return 1;
    }

    avail = obj.size;
    if(asn1_expect_objtype(map, obj.content, &avail, &obj, 0x02)) /* INTEGER - mod */
	return 1;
    if(obj.size < 1024/8 || obj.size > 4096/8+1) {
	cli_dbgmsg("asn1_get_rsa_pubkey: modulus has got an unsupported length (%u)\n",	 obj.size * 8);
	return 1;
    }
    avail2 = obj.size;
    if(!fmap_need_ptr_once(map, obj.content, avail2)) {
	cli_dbgmsg("asn1_get_rsa_pubkey: cannot read n\n");
	return 1;
    }
    if(mp_read_unsigned_bin(&x509->n, obj.content, avail2)) {
	cli_dbgmsg("asn1_get_rsa_pubkey: cannot convert n to big number\n");
	return 1;
    }

    if(asn1_expect_objtype(map, obj.next, &avail, &obj, 0x02)) /* INTEGER - exp */
	return 1;
    if(avail) {
	cli_dbgmsg("asn1_get_rsa_pubkey: found unexpected extra data after exp\n");
	return 1;
    }
    if(obj.size < 1 || obj.size > avail2) {
	cli_dbgmsg("asn1_get_rsa_pubkey: exponent has got an unsupported length (%u)\n",  obj.size * 8);
	return 1;
    }
    if(!fmap_need_ptr_once(map, obj.content, obj.size)) {
	cli_dbgmsg("asn1_get_rsa_pubkey: cannot read e\n");
	return 1;
    }
    if(mp_read_unsigned_bin(&x509->e, obj.content, obj.size)) {
	cli_dbgmsg("asn1_get_rsa_pubkey: cannot convert e to big number\n");
	return 1;
    }
    return 0;
}
示例#12
0
int asn1_load_mscat(fmap_t *map, struct cl_engine *engine) {
    struct cli_asn1 c;
    unsigned int size;
    struct cli_matcher *db;
    int i;

    if(asn1_parse_mscat(map, 0, map->len, &engine->cmgr, 0, &c.next, &size, engine))
        return 1;

    if(asn1_expect_objtype(map, c.next, &size, &c, 0x30))
	return 1;
    if(asn1_expect_obj(map, &c.content, &c.size, 0x06, lenof(OID_szOID_CATALOG_LIST), OID_szOID_CATALOG_LIST))
	return 1;
    if(c.size) {
	cli_dbgmsg("asn1_load_mscat: found extra data in szOID_CATALOG_LIST content\n");
	return 1;
    }
    if(asn1_expect_objtype(map, c.next, &size, &c, 0x4)) /* List ID */
	return 1;
    if(asn1_expect_objtype(map, c.next, &size, &c, 0x17)) /* Effective date - WTF?! */
	return 1;
    if(asn1_expect_algo(map, &c.next, &size, lenof(OID_szOID_CATALOG_LIST_MEMBER), OID_szOID_CATALOG_LIST_MEMBER)) /* szOID_CATALOG_LIST_MEMBER */
	return 1;
    if(asn1_expect_objtype(map, c.next, &size, &c, 0x30)) /* hashes here */
	return 1;
    /* [0] is next but we don't care as it's really descriptives stuff */

    size = c.size;
    c.next = c.content;
    while(size) {
	struct cli_asn1 tag;
	if(asn1_expect_objtype(map, c.next, &size, &c, 0x30))
	    return 1;
	if(asn1_expect_objtype(map, c.content, &c.size, &tag, 0x04)) /* TAG NAME */
	    return 1;
	if(asn1_expect_objtype(map, tag.next, &c.size, &tag, 0x31)) /* set */
	    return 1;
	if(c.size) {
	    cli_dbgmsg("asn1_load_mscat: found extra data in tag\n");
	    return 1;
	}
	while(tag.size) {
	    struct cli_asn1 tagval1, tagval2, tagval3;
	    int hashtype;

	    if(asn1_expect_objtype(map, tag.content, &tag.size, &tagval1, 0x30))
		return 1;
	    tag.content = tagval1.next;

	    if(asn1_expect_objtype(map, tagval1.content, &tagval1.size, &tagval2, 0x06))
		return 1;
	    if(tagval2.size != lenof(OID_SPC_INDIRECT_DATA_OBJID))
		continue;

	    if(!fmap_need_ptr_once(map, tagval2.content, lenof(OID_SPC_INDIRECT_DATA_OBJID))) {
		cli_dbgmsg("asn1_load_mscat: cannot read SPC_INDIRECT_DATA\n");
		return 1;
	    }
	    if(memcmp(tagval2.content, OID_SPC_INDIRECT_DATA_OBJID, lenof(OID_SPC_INDIRECT_DATA_OBJID)))
		continue; /* stuff like CAT_NAMEVALUE_OBJID(1.3.6.1.4.1.311.12.2.1) and CAT_MEMBERINFO_OBJID(.2).. */

	    if(asn1_expect_objtype(map, tagval2.next, &tagval1.size, &tagval2, 0x31))
		return 1;
	    if(tagval1.size) {
		cli_dbgmsg("asn1_load_mscat: found extra data in tag value\n");
		return 1;
	    }

	    if(asn1_expect_objtype(map, tagval2.content, &tagval2.size, &tagval1, 0x30))
		return 1;
	    if(tagval2.size) {
		cli_dbgmsg("asn1_load_mscat: found extra data in SPC_INDIRECT_DATA_OBJID tag\n");
		return 1;
	    }

	    if(asn1_expect_objtype(map, tagval1.content, &tagval1.size, &tagval2, 0x30))
		return 1;

	    if(asn1_expect_objtype(map, tagval2.content, &tagval2.size, &tagval3, 0x06)) /* shall have an obj 1.3.6.1.4.1.311.2.1.15 or 1.3.6.1.4.1.311.2.1.25 inside */
		return 1;
	    if(tagval3.size != lenof(OID_SPC_PE_IMAGE_DATA_OBJID)) { /* lenof(OID_SPC_PE_IMAGE_DATA_OBJID) = lenof(OID_SPC_CAB_DATA_OBJID) = 10*/
		cli_dbgmsg("asn1_load_mscat: bad hash type size\n");
		return 1;
	    }
	    if(!fmap_need_ptr_once(map, tagval3.content, lenof(OID_SPC_PE_IMAGE_DATA_OBJID))) {
		cli_dbgmsg("asn1_load_mscat: cannot read hash type\n");
		return 1;
	    }
	    if(!memcmp(tagval3.content, OID_SPC_PE_IMAGE_DATA_OBJID, lenof(OID_SPC_PE_IMAGE_DATA_OBJID)))
		hashtype = 2;
	    else if(!memcmp(tagval3.content, OID_SPC_CAB_DATA_OBJID, lenof(OID_SPC_CAB_DATA_OBJID)))
		hashtype = 1;
	    else {
		cli_dbgmsg("asn1_load_mscat: unexpected hash type\n");
		return 1;
	    }

	    if(asn1_expect_objtype(map, tagval2.next, &tagval1.size, &tagval2, 0x30))
		return 1;
	    if(tagval1.size) {
		cli_dbgmsg("asn1_load_mscat: found extra data after hash\n");
		return 1;
	    }

	    if(asn1_expect_algo(map, &tagval2.content, &tagval2.size, lenof(OID_sha1), OID_sha1)) /* objid 1.3.14.3.2.26 - sha1 */
		return 1;

	    if(asn1_expect_objtype(map, tagval2.content, &tagval2.size, &tagval3, 0x04))
		return 1;
	    if(tagval2.size) {
		cli_dbgmsg("asn1_load_mscat: found extra data in hash\n");
		return 1;
	    }
	    if(tagval3.size != SHA1_HASH_SIZE) {
		cli_dbgmsg("asn1_load_mscat: bad hash size %u\n", tagval3.size);
		return 1;
	    }
	    if(!fmap_need_ptr_once(map, tagval3.content, SHA1_HASH_SIZE)) {
		cli_dbgmsg("asn1_load_mscat: cannot read hash\n");
		return 1;
	    }

	    if(cli_debug_flag) {
		char sha1[SHA1_HASH_SIZE*2+1];
		for(i=0;i<SHA1_HASH_SIZE;i++)
		    sprintf(&sha1[i*2], "%02x", ((uint8_t *)(tagval3.content))[i]);
		cli_dbgmsg("asn1_load_mscat: got hash %s (%s)\n", sha1, (hashtype == 2) ? "PE" : "CAB");
	    }
	    if(!engine->hm_fp) {
		if(!(engine->hm_fp = mpool_calloc(engine->mempool, 1, sizeof(*db)))) {
		    tag.size = 1;;
		    return 1;
		}
#ifdef USE_MPOOL
		engine->hm_fp->mempool = engine->mempool;
#endif
	    }
	    if(hm_addhash_bin(engine->hm_fp, tagval3.content, CLI_HASH_SHA1, hashtype, NULL)) {
		cli_warnmsg("asn1_load_mscat: failed to add hash\n");
		return 1;
	    }
	}
    }

    return 0;
}
示例#13
0
int cli_scancpio_old(int fd, cli_ctx *ctx)
{
	struct cpio_hdr_old hdr_old;
	char name[513];
	unsigned int file = 0, trailer = 0;
	uint32_t filesize, namesize, hdr_namesize;
	int ret, conv;
	off_t pos;


    while(read(fd, &hdr_old, sizeof(hdr_old)) == sizeof(hdr_old)) {
	if(!hdr_old.magic && trailer)
	    return CL_SUCCESS;

	if(hdr_old.magic == 070707) {
	    conv = 0;
	} else if(hdr_old.magic == 0143561) {
	    conv = 1;
	} else {
	    cli_dbgmsg("cli_scancpio_old: Invalid magic number\n");
	    return CL_EFORMAT;
	}

	cli_dbgmsg("CPIO: -- File %u --\n", ++file);

	if(hdr_old.namesize) {
	    hdr_namesize = EC16(hdr_old.namesize, conv);
	    namesize = MIN(sizeof(name), hdr_namesize);
	    if(read(fd, name, namesize) != namesize) {
		cli_dbgmsg("cli_scancpio_old: Can't read file name\n");
		return CL_EFORMAT;
	    }
	    name[namesize - 1] = 0;
	    sanitname(name);
	    cli_dbgmsg("CPIO: Name: %s\n", name);
	    if(!strcmp(name, "TRAILER!!!"))
		trailer = 1;

	    if(namesize < hdr_namesize) {
		if(hdr_namesize % 2)
		    hdr_namesize++;
		lseek(fd, hdr_namesize - namesize, SEEK_CUR);
	    } else if(hdr_namesize % 2)
		lseek(fd, 1, SEEK_CUR);
	}
	filesize = (uint32_t) (EC16(hdr_old.filesize[0], conv) << 16 | EC16(hdr_old.filesize[1], conv));
	cli_dbgmsg("CPIO: Filesize: %u\n", filesize);
	if(!filesize)
	    continue;

	if(cli_matchmeta(ctx, name, filesize, filesize, 0, file, 0, NULL) == CL_VIRUS)
	    return CL_VIRUS;

	pos = lseek(fd, 0, SEEK_CUR);

	if((EC16(hdr_old.mode, conv) & 0170000) != 0100000) {
	    cli_dbgmsg("CPIO: Not a regular file, skipping\n");
	} else {
	    ret = cli_checklimits("cli_scancpio_old", ctx, filesize, 0, 0);
	    if(ret == CL_EMAXFILES) {
		return ret;
	    } else if(ret == CL_SUCCESS) {
		ret = cli_dumpscan(fd, 0, filesize, ctx);
		if(ret == CL_VIRUS)
		    return ret;
	    }
	}
	if(filesize % 2)
	    filesize++;

	lseek(fd, pos + filesize, SEEK_SET);
    }

    return CL_CLEAN;
}
示例#14
0
int cli_scancpio_newc(int fd, cli_ctx *ctx, int crc)
{
	struct cpio_hdr_newc hdr_newc;
	char name[513], buff[9];
	unsigned int file = 0, trailer = 0;
	uint32_t filesize, namesize, hdr_namesize, pad;
	int ret;
	off_t pos;


    while(read(fd, &hdr_newc, sizeof(hdr_newc)) == sizeof(hdr_newc)) {

	if(!hdr_newc.magic[0] && trailer)
	    return CL_SUCCESS;

	if((!crc && strncmp(hdr_newc.magic, "070701", 6)) || (crc && strncmp(hdr_newc.magic, "070702", 6))) {
	    cli_dbgmsg("cli_scancpio_newc: Invalid magic string\n");
	    return CL_EFORMAT;
	}

	cli_dbgmsg("CPIO: -- File %u --\n", ++file);

	strncpy(buff, hdr_newc.namesize, 8);
	buff[8] = 0;
	if(sscanf(buff, "%x", &hdr_namesize) != 1) {
	    cli_dbgmsg("cli_scancpio_newc: Can't convert name size\n");
	    return CL_EFORMAT;
	}
	if(hdr_namesize) {
	    namesize = MIN(sizeof(name), hdr_namesize);
	    if(read(fd, name, namesize) != namesize) {
		cli_dbgmsg("cli_scancpio_newc: Can't read file name\n");
		return CL_EFORMAT;
	    }
	    name[namesize - 1] = 0;
	    sanitname(name);
	    cli_dbgmsg("CPIO: Name: %s\n", name);
	    if(!strcmp(name, "TRAILER!!!"))
		trailer = 1;

	    pad = (4 - (sizeof(hdr_newc) + hdr_namesize) % 4) % 4;
	    if(namesize < hdr_namesize) {
		if(pad)
		    hdr_namesize += pad;
		lseek(fd, hdr_namesize - namesize, SEEK_CUR);
	    } else if(pad)
		lseek(fd, pad, SEEK_CUR);
	}

	strncpy(buff, hdr_newc.filesize, 8);
	buff[8] = 0;
	if(sscanf(buff, "%x", &filesize) != 1) {
	    cli_dbgmsg("cli_scancpio_newc: Can't convert file size\n");
	    return CL_EFORMAT;
	}
	cli_dbgmsg("CPIO: Filesize: %u\n", filesize);
	if(!filesize)
	    continue;

	if(cli_matchmeta(ctx, name, filesize, filesize, 0, file, 0, NULL) == CL_VIRUS)
	    return CL_VIRUS;

	pos = lseek(fd, 0, SEEK_CUR);

	ret = cli_checklimits("cli_scancpio_newc", ctx, filesize, 0, 0);
	if(ret == CL_EMAXFILES) {
	    return ret;
	} else if(ret == CL_SUCCESS) {
	    ret = cli_dumpscan(fd, 0, filesize, ctx);
	    if(ret == CL_VIRUS)
		return ret;
	}

	if((pad = filesize % 4))
	    filesize += (4 - pad);

	lseek(fd, pos + filesize, SEEK_SET);
    }

    return CL_CLEAN;
}
示例#15
0
/* Return converted endian-fixed header, or error code */
static int cli_elf_fileheader(cli_ctx *ctx, fmap_t *map, union elf_file_hdr *file_hdr,
    uint8_t *do_convert, uint8_t *is64)
{
	uint8_t format64, conv;

    /* Load enough for smaller header first */
    if(fmap_readn(map, file_hdr, 0, sizeof(struct elf_file_hdr32)) != sizeof(struct elf_file_hdr32)) {
	/* Not an ELF file? */
	cli_dbgmsg("ELF: Can't read file header\n");
	return CL_BREAK;
    }

    if(memcmp(file_hdr->hdr64.e_ident, "\x7f\x45\x4c\x46", 4)) {
	cli_dbgmsg("ELF: Not an ELF file\n");
	return CL_BREAK;
    }

    switch(file_hdr->hdr64.e_ident[4]) {
	case 1:
	    cli_dbgmsg("ELF: ELF class 1 (32-bit)\n");
	    format64 = 0;
	    break;
        case 2:
	    cli_dbgmsg("ELF: ELF class 2 (64-bit)\n");
	    format64 = 1;
	    break;
        default:
	    cli_dbgmsg("ELF: Unknown ELF class (%u)\n", file_hdr->hdr64.e_ident[4]);
	    if (ctx)
	      cli_append_virus(ctx, "Heuristics.Broken.Executable");
	    return CL_VIRUS;
    }

    /* Need to know to endian convert */
    if(file_hdr->hdr64.e_ident[5] == 1) {
#if WORDS_BIGENDIAN == 0
	if(ctx)
            cli_dbgmsg("ELF: File is little-endian - conversion not required\n");
	conv = 0;
#else
	if(ctx)
            cli_dbgmsg("ELF: File is little-endian - data conversion enabled\n");
	conv = 1;
#endif
    } else {
#if WORDS_BIGENDIAN == 0
	if(ctx)
            cli_dbgmsg("ELF: File is big-endian - data conversion enabled\n");
	conv = 1;
#else
	if(ctx)
            cli_dbgmsg("ELF: File is big-endian - conversion not required\n");
	conv = 0;
#endif
    }

    *do_convert = conv;
    *is64 = format64;

    /* Solve bit-size and conversion pronto */
    file_hdr->hdr64.e_type = EC16(file_hdr->hdr64.e_type, conv);
    file_hdr->hdr64.e_machine = EC16(file_hdr->hdr64.e_machine, conv);
    file_hdr->hdr64.e_version = EC32(file_hdr->hdr64.e_version, conv);

    if(format64) {
	/* Read rest of 64-bit header */
	if(fmap_readn(map, file_hdr->hdr32.pad, sizeof(struct elf_file_hdr32), ELF_HDR_SIZEDIFF)
                != ELF_HDR_SIZEDIFF) {
	    /* Not an ELF file? */
	    cli_dbgmsg("ELF: Can't read file header\n");
	    return CL_BREAK;
	}
	/* Now endian convert, if needed */
	if(conv) {
	    file_hdr->hdr64.e_entry = EC64(file_hdr->hdr64.e_entry, conv);
            file_hdr->hdr64.e_phoff = EC64(file_hdr->hdr64.e_phoff, conv);
            file_hdr->hdr64.e_shoff = EC64(file_hdr->hdr64.e_shoff, conv);
	    file_hdr->hdr64.e_flags = EC32(file_hdr->hdr64.e_flags, conv);
	    file_hdr->hdr64.e_ehsize = EC16(file_hdr->hdr64.e_ehsize, conv);
	    file_hdr->hdr64.e_phentsize = EC16(file_hdr->hdr64.e_phentsize, conv);
	    file_hdr->hdr64.e_phnum = EC16(file_hdr->hdr64.e_phnum, conv);
	    file_hdr->hdr64.e_shentsize = EC16(file_hdr->hdr64.e_shentsize, conv);
	    file_hdr->hdr64.e_shnum = EC16(file_hdr->hdr64.e_shnum, conv);
	    file_hdr->hdr64.e_shstrndx = EC16(file_hdr->hdr64.e_shstrndx, conv);
	}
    }
    else {
	/* Convert 32-bit structure, if needed */
	if(conv) {
	    file_hdr->hdr32.hdr.e_entry = EC32(file_hdr->hdr32.hdr.e_entry, conv);
            file_hdr->hdr32.hdr.e_phoff = EC32(file_hdr->hdr32.hdr.e_phoff, conv);
            file_hdr->hdr32.hdr.e_shoff = EC32(file_hdr->hdr32.hdr.e_shoff, conv);
	    file_hdr->hdr32.hdr.e_flags = EC32(file_hdr->hdr32.hdr.e_flags, conv);
	    file_hdr->hdr32.hdr.e_ehsize = EC16(file_hdr->hdr32.hdr.e_ehsize, conv);
	    file_hdr->hdr32.hdr.e_phentsize = EC16(file_hdr->hdr32.hdr.e_phentsize, conv);
	    file_hdr->hdr32.hdr.e_phnum = EC16(file_hdr->hdr32.hdr.e_phnum, conv);
	    file_hdr->hdr32.hdr.e_shentsize = EC16(file_hdr->hdr32.hdr.e_shentsize, conv);
	    file_hdr->hdr32.hdr.e_shnum = EC16(file_hdr->hdr32.hdr.e_shnum, conv);
	    file_hdr->hdr32.hdr.e_shstrndx = EC16(file_hdr->hdr32.hdr.e_shstrndx, conv);
        }
        /* Wipe pad for safety */
        memset(file_hdr->hdr32.pad, 0, ELF_HDR_SIZEDIFF);
    }

    return CL_CLEAN;
}
示例#16
0
static int yylex(YYSTYPE *lvalp, yyscan_t  scanner)
{
	const size_t len = scanner->insize;
	const unsigned char *in = (const unsigned char*)scanner->in;
	unsigned char lookahead;
	enum char_class cClass;

	scanner->yytext = NULL;
	scanner->yylen = 0;
	if(scanner->pos == scanner->lastpos) {
		if(scanner->last_state == scanner->state) {
			cli_dbgmsg(MODULE "infloop detected, skipping character\n");
			scanner->pos++;
		}
		/* its not necesarely an infloop if it changed
		 * state, and it shouldn't infloop between states */
	}
	scanner->lastpos = scanner->pos;
	scanner->last_state = scanner->state;
	while(scanner->pos < scanner->insize) {
		switch(scanner->state) {
			case Initial:
				textbuf_clean(&scanner->buf);
				cClass = ctype[in[scanner->pos++]];
				switch(cClass) {
					case Whitespace:
						/* eat whitespace */
						continue;
					case Slash:
						if(scanner->pos < len) {
							lookahead = in[scanner->pos];
							switch(lookahead) {
								case '*':
									scanner->state = MultilineComment;
									scanner->pos++;
									continue;
								case '/':
									scanner->state = SinglelineComment;
									scanner->pos++;
									continue;
							}
						}
						--scanner->pos;
						return parseOperator(lvalp, scanner);
					case Operator:
						--scanner->pos;
						return parseOperator(lvalp, scanner);
					case DQuote:
						return parseDQString(lvalp, scanner);
					case SQuote:
						return parseSQString(lvalp, scanner);
					case Digit:
						--scanner->pos;
						return parseNumber(lvalp, scanner);
					case IdStart:
						--scanner->pos;
						return parseId(lvalp,scanner);
					CASE_SPECIAL_CHAR(BracketOpen, "[");
					CASE_SPECIAL_CHAR(BracketClose, "]");
					CASE_SPECIAL_CHAR(Comma, ",");
					CASE_SPECIAL_CHAR(CurlyOpen, "{");
					CASE_SPECIAL_CHAR(CurlyClose, "}");
					CASE_SPECIAL_CHAR(ParOpen, "(");
					CASE_SPECIAL_CHAR(ParClose, ")");
					CASE_SPECIAL_CHAR(Dot, ".");
					CASE_SPECIAL_CHAR(SemiColon, ";");
					case Nop:
					       continue;
				}
				break;
			case DoubleQString:
				return parseString(lvalp, scanner, '"', DoubleQString);
			case SingleQString:
				return parseString(lvalp, scanner, '\'', SingleQString);
			case Identifier:
				return parseId(lvalp, scanner);
			case MultilineComment:
				while(scanner->pos+1 < scanner->insize) {
					if(in[scanner->pos] == '*' && in[scanner->pos+1] == '/') {
						scanner->state = Initial;
						scanner->pos++;
						break;
					}
					scanner->pos++;
				}
				scanner->pos++;
				break;
			case Number:
				return parseNumber(lvalp, scanner);
			case SinglelineComment:
				while(scanner->pos < scanner->insize) {
					/* htmlnorm converts \n to space, so
					 * stop on space too */
					if(in[scanner->pos] == '\n' || in[scanner->pos] == ' ')
						break;
					scanner->pos++;
				}
				scanner->state = Initial;
				break;
			default:
				assert(0 && "Not reached");
		}
	}
	return 0;
}
示例#17
0
int cli_pcre_addpatt(struct cli_matcher *root, const char *virname, const char *trigger, const char *pattern, const char *cflags, const char *offset, const uint32_t *lsigid, unsigned int options)
{
    struct cli_pcre_meta **newmetatable = NULL, *pm = NULL;
    uint32_t pcre_count;
    const char *opt;
    int ret = CL_SUCCESS, rssigs;

    if (!root || !trigger || !pattern || !offset) {
        cli_errmsg("cli_pcre_addpatt: NULL root or NULL trigger or NULL pattern or NULL offset\n");
        return CL_ENULLARG;
    }

    /* TODO: trigger and regex checking (backreference limitations?) (control pattern limitations?) */
    /* cli_ac_chklsig will fail a empty trigger; empty patterns can cause an infinite loop */
    if (*trigger == '\0' || *pattern == '\0') {
        cli_errmsg("cli_pcre_addpatt: trigger or pattern cannot be an empty string\n");
        return CL_EMALFDB;
    }
    if (cflags && *cflags == '\0') {
        cflags = NULL;
    }

    if (lsigid)
        pm_dbgmsg("cli_pcre_addpatt: Adding /%s/%s%s triggered on (%s) as subsig %d for lsigid %d\n", 
                  pattern, cflags ? " with flags " : "", cflags ? cflags : "", trigger, lsigid[1], lsigid[0]);
    else
        pm_dbgmsg("cli_pcre_addpatt: Adding /%s/%s%s triggered on (%s) [no lsigid]\n",
                  pattern, cflags ? " with flags " : "", cflags ? cflags : "", trigger);

#ifdef PCRE_BYPASS
    /* check for trigger bypass */
    if (strcmp(trigger, PCRE_BYPASS)) {
#endif
        /* validate the lsig trigger */
        rssigs = cli_ac_chklsig(trigger, trigger + strlen(trigger), NULL, NULL, NULL, 1);
        if(rssigs == -1) {
            cli_errmsg("cli_pcre_addpatt: regex subsig /%s/ is missing a valid logical trigger\n", pattern);
            return CL_EMALFDB;
        }

        if (lsigid) {
            if (rssigs > lsigid[1]) {
                cli_errmsg("cli_pcre_addpatt: regex subsig %d logical trigger refers to subsequent subsig %d\n", lsigid[1], rssigs);
                return CL_EMALFDB;
            }
            if (rssigs == lsigid[1]) {
                cli_errmsg("cli_pcre_addpatt: regex subsig %d logical trigger is self-referential\n", lsigid[1]);
                return CL_EMALFDB;
            }
        }
        else {
            cli_dbgmsg("cli_pcre_addpatt: regex subsig is missing lsigid data\n");
        }
#ifdef PCRE_BYPASS
    }
#endif

    /* allocating entries */
    pm = (struct cli_pcre_meta *)mpool_calloc(root->mempool, 1, sizeof(*pm));
    if (!pm) {
        cli_errmsg("cli_pcre_addpatt: Unable to allocate memory for new pcre meta\n");
        return CL_EMEM;
    }

    pm->trigger = cli_mpool_strdup(root->mempool, trigger);
    if (!pm->trigger) {
        cli_errmsg("cli_pcre_addpatt: Unable to allocate memory for trigger string\n");
        cli_pcre_freemeta(root, pm);
        mpool_free(root->mempool, pm);
        return CL_EMEM;
    }

    pm->virname = (char *)cli_mpool_virname(root->mempool, virname, options & CL_DB_OFFICIAL);
    if(!pm->virname) {
        cli_errmsg("cli_pcre_addpatt: Unable to allocate memory for virname or NULL virname\n");
        cli_pcre_freemeta(root, pm);
        mpool_free(root->mempool, pm);
        return CL_EMEM;
    }

    if (lsigid) {
        root->ac_lsigtable[lsigid[0]]->virname = pm->virname;

        pm->lsigid[0] = 1;
        pm->lsigid[1] = lsigid[0];
        pm->lsigid[2] = lsigid[1];
    }
    else {
        /* sigtool */
        pm->lsigid[0] = 0;
    }

    pm->pdata.expression = strdup(pattern);
    if (!pm->pdata.expression) {
        cli_errmsg("cli_pcre_addpatt: Unable to allocate memory for expression\n");
        cli_pcre_freemeta(root, pm);
        mpool_free(root->mempool, pm);
        return CL_EMEM;
    }

    /* offset parsing and usage, similar to cli_ac_addsig */
    /* relative and type-specific offsets handled during scan */
    ret = cli_caloff(offset, NULL, root->type, pm->offdata, &(pm->offset_min), &(pm->offset_max));
    if (ret != CL_SUCCESS) {
        cli_errmsg("cli_pcre_addpatt: cannot calculate offset data: %s for pattern: %s\n", offset, pattern);
        cli_pcre_freemeta(root, pm);
        mpool_free(root->mempool, pm);
        return ret;
    }
    if(pm->offdata[0] != CLI_OFF_ANY) {
        if(pm->offdata[0] == CLI_OFF_ABSOLUTE)
            root->pcre_absoff_num++;
        else
            root->pcre_reloff_num++;
    }

    /* parse and add options, also totally not from snort */
    if (cflags) {
        opt = cflags;

        /* cli_pcre_addoptions handles pcre specific options */
        while (cli_pcre_addoptions(&(pm->pdata), &opt, 0) != CL_SUCCESS) {
            /* handle matcher specific options here */
            switch (*opt) {
            case 'g':  pm->flags |= CLI_PCRE_GLOBAL;            break;
            case 'r':  pm->flags |= CLI_PCRE_ROLLING;           break;
            case 'e':  pm->flags |= CLI_PCRE_ENCOMPASS;         break;
            default:
                cli_errmsg("cli_pcre_addpatt: unknown/extra pcre option encountered %c\n", *opt);
                cli_pcre_freemeta(root, pm);
                mpool_free(root->mempool, pm);
                return CL_EMALFDB;
            }
            opt++;
        }

        if (pm->flags) {
            pm_dbgmsg("Matcher:  %s%s%s\n",
                      pm->flags & CLI_PCRE_GLOBAL ? "CLAMAV_GLOBAL " : "",
                      pm->flags & CLI_PCRE_ROLLING ? "CLAMAV_ROLLING " : "",
                      pm->flags & CLI_PCRE_ENCOMPASS ? "CLAMAV_ENCOMPASS " : "");
        }
        else
            pm_dbgmsg("Matcher:  NONE\n");

        if (pm->pdata.options) {
#if USING_PCRE2
            pm_dbgmsg("Compiler: %s%s%s%s%s%s%s\n",
                      pm->pdata.options & PCRE2_CASELESS ? "PCRE2_CASELESS " : "",
                      pm->pdata.options & PCRE2_DOTALL ? "PCRE2_DOTALL " : "",
                      pm->pdata.options & PCRE2_MULTILINE ? "PCRE2_MULTILINE " : "",
                      pm->pdata.options & PCRE2_EXTENDED ? "PCRE2_EXTENDED " : "",

                      pm->pdata.options & PCRE2_ANCHORED ? "PCRE2_ANCHORED " : "",
                      pm->pdata.options & PCRE2_DOLLAR_ENDONLY ? "PCRE2_DOLLAR_ENDONLY " : "",
                      pm->pdata.options & PCRE2_UNGREEDY ? "PCRE2_UNGREEDY " : "");
#else
            pm_dbgmsg("Compiler: %s%s%s%s%s%s%s\n",
                      pm->pdata.options & PCRE_CASELESS ? "PCRE_CASELESS " : "",
                      pm->pdata.options & PCRE_DOTALL ? "PCRE_DOTALL " : "",
                      pm->pdata.options & PCRE_MULTILINE ? "PCRE_MULTILINE " : "",
                      pm->pdata.options & PCRE_EXTENDED ? "PCRE_EXTENDED " : "",

                      pm->pdata.options & PCRE_ANCHORED ? "PCRE_ANCHORED " : "",
                      pm->pdata.options & PCRE_DOLLAR_ENDONLY ? "PCRE_DOLLAR_ENDONLY " : "",
                      pm->pdata.options & PCRE_UNGREEDY ? "PCRE_UNGREEDY " : "");
#endif
        }
        else
            pm_dbgmsg("Compiler: NONE\n");
    }

    /* add metadata to the performance tracker */
    if (options & CL_DB_PCRE_STATS)
        pcre_perf_events_init(pm, virname);

    /* add pcre data to root after reallocation */
    pcre_count = root->pcre_metas+1;
    newmetatable = (struct cli_pcre_meta **)mpool_realloc(root->mempool, root->pcre_metatable,
                                         pcre_count * sizeof(struct cli_pcre_meta *));
    if (!newmetatable) {
        cli_errmsg("cli_pcre_addpatt: Unable to allocate memory for new pcre meta table\n");
        cli_pcre_freemeta(root, pm);
        mpool_free(root->mempool, pm);
        return CL_EMEM;
    }

    newmetatable[pcre_count-1] = pm;
    root->pcre_metatable = newmetatable;

    root->pcre_metas = pcre_count;

    return CL_SUCCESS;
}
示例#18
0
static void run_decoders(struct parser_state *state)
{
  size_t i;
  const char* name;
  struct tokens *tokens = &state->tokens;

  for(i = 0; i < tokens->cnt; i++) {
	  const char *cstring = TOKEN_GET(&tokens->data[i], cstring);
	  struct decode_result res;
	  res.pos_begin = res.pos_end = 0;
	  res.append = 0;
	  if(tokens->data[i].type == TOK_FUNCTION && i+13 < tokens->cnt) {
		  name = NULL;
		  ++i;
		  if(tokens->data[i].type == TOK_IDENTIFIER_NAME) {
			  cstring = TOKEN_GET(&tokens->data[i], cstring);
			  name = cstring;
			  ++i;
		  }
		  if(match_parameters(&tokens->data[i], de_packer_3, sizeof(de_packer_3)/sizeof(de_packer_3[0])) != -1
		     || match_parameters(&tokens->data[i], de_packer_2, sizeof(de_packer_2)/sizeof(de_packer_2[0])) != -1)  {
			  /* find function decl. end */
			  handle_de(tokens->data, i, tokens->cnt, name, &res);
		  }
	  } else if(i+2 < tokens->cnt && tokens->data[i].type == TOK_IDENTIFIER_NAME &&
		    cstring &&
		    !strcmp("dF", cstring) && tokens->data[i+1].type == TOK_PAR_OPEN) {
		  /* TODO: also match signature of dF function (possibly
		   * declared using unescape */

		  handle_df(tokens->data, i+2, &res);
	  } else if(i+2 < tokens->cnt && tokens->data[i].type == TOK_IDENTIFIER_NAME &&
			  cstring &&
			  !strcmp("eval", cstring) && tokens->data[i+1].type == TOK_PAR_OPEN) {
		  handle_eval(tokens, i+2, &res);
	  }
	if(res.pos_end > res.pos_begin) {
		struct tokens parent_tokens;
		if(res.pos_end < tokens->cnt && tokens->data[res.pos_end].type == TOK_SEMICOLON)
			res.pos_end++;
		parent_tokens = state->tokens;/* save current tokens */
		/* initialize embedded context */
		memset(&state->tokens, 0, sizeof(state->tokens));
		if(++state->rec > 16)
			cli_dbgmsg(MODULE "recursion limit reached\n");
		else {
			cli_js_process_buffer(state, res.txtbuf.data, res.txtbuf.pos);
			--state->rec;
		}
		free(res.txtbuf.data);
		/* state->tokens still refers to the embedded/nested context
		 * here */
		if(!res.append) {
			replace_token_range(&parent_tokens, res.pos_begin, res.pos_end, &state->tokens);
		} else {
			/* delete tokens */
			replace_token_range(&parent_tokens, res.pos_begin, res.pos_end, NULL);
			append_tokens(&parent_tokens, &state->tokens);
		}
		/* end of embedded context, restore tokens state */
		free(state->tokens.data);
		state->tokens = parent_tokens;
	}
	  state_update_scope(state, &state->tokens.data[i]);
  }
}
示例#19
0
int cli_pcre_scanbuf(const unsigned char *buffer, uint32_t length, const char **virname, struct cli_ac_result **res, const struct cli_matcher *root, struct cli_ac_data *mdata, const struct cli_pcre_off *data, cli_ctx *ctx)
{
    struct cli_pcre_meta **metatable = root->pcre_metatable, *pm = NULL;
    struct cli_pcre_data *pd;
    struct cli_pcre_results p_res;
    struct cli_ac_result *newres;
    uint32_t adjbuffer, adjshift, adjlength;
    unsigned int i, evalcnt = 0;
    uint64_t maxfilesize, evalids = 0;
    uint32_t global, encompass, rolling;
    int rc, offset, ret = CL_SUCCESS, options=0;
    uint8_t viruses_found = 0;

    if ((root->pcre_metas == 0) || (!root->pcre_metatable) || (ctx && ctx->dconf && !(ctx->dconf->pcre & PCRE_CONF_SUPPORT)))
        return CL_SUCCESS;

    memset(&p_res, 0, sizeof(p_res));

    for (i = 0; i < root->pcre_metas; ++i) {
        pm = root->pcre_metatable[i];
        pd = &(pm->pdata);

        /* skip checking and running disabled pcres */
        if (pm->flags & CLI_PCRE_DISABLED) {
            cli_dbgmsg("cli_pcre_scanbuf: skipping disabled regex /%s/\n", pd->expression);
            continue;
        }

        /* skip checking and running CLI_OFF_NONE pcres */
        if (data && data->offset[i] == CLI_OFF_NONE) {
            pm_dbgmsg("cli_pcre_scanbuf: skipping CLI_OFF_NONE regex /%s/\n", pd->expression);
            continue;
        }

        /* evaluate trigger */
        if (pm->lsigid[0]) {
            cli_dbgmsg("cli_pcre_scanbuf: checking %s; running regex /%s/\n", pm->trigger, pd->expression);
#ifdef PCRE_BYPASS
            if (strcmp(pm->trigger, PCRE_BYPASS))
#endif
                if (cli_ac_chklsig(pm->trigger, pm->trigger + strlen(pm->trigger), mdata->lsigcnt[pm->lsigid[1]], &evalcnt, &evalids, 0) != 1)
                    continue;
        }
        else {
            cli_dbgmsg("cli_pcre_scanbuf: skipping %s check due to uninitialized lsigid\n", pm->trigger);
            /* fall-through to unconditional execution - sigtool-only */
        }

        global = (pm->flags & CLI_PCRE_GLOBAL);       /* globally search for all matches (within bounds) */
        encompass = (pm->flags & CLI_PCRE_ENCOMPASS); /* encompass search to offset->offset+maxshift */
        rolling = (pm->flags & CLI_PCRE_ROLLING);     /* rolling search (unanchored) */
        offset = pd->search_offset;                   /* this is usually 0 */

        cli_dbgmsg("cli_pcre_scanbuf: triggered %s; running regex /%s/%s%s\n", pm->trigger, pd->expression, 
                   global ? " (global)":"", rolling ? " (rolling)":"");

        /* adjust the buffer sent to cli_pcre_match for offset and maxshift */
        if (!data) {
            if (cli_pcre_qoff(pm, length, &adjbuffer, &adjshift) != CL_SUCCESS)
                continue;
        }
        else {
            adjbuffer = data->offset[i];
            adjshift = data->shift[i];
        }

        /* check for need to anchoring */
        if (!rolling && !adjshift && (adjbuffer != CLI_OFF_ANY))
#if USING_PCRE2
            options |= PCRE2_ANCHORED;
#else
            options |= PCRE_ANCHORED;
#endif
        else
            options = 0;

        if (adjbuffer == CLI_OFF_ANY)
            adjbuffer = 0;

        /* check the offset bounds */
        if (adjbuffer < length) {
            /* handle encompass flag */
            if (encompass && adjshift != 0 && adjshift != CLI_OFF_NONE) {
                    if (adjbuffer+adjshift > length)
                        adjlength = length - adjbuffer;
                    else
                        adjlength = adjshift;
            }
            else {
                /* NOTE - if using non-encompass method 2, alter shift universally */
                /* TODO - limitations on non-encompassed buffers? */
                adjlength = length - adjbuffer;
            }
        }
        else {
            /* starting offset is outside bounds of file, skip pcre execution silently */
            pm_dbgmsg("cli_pcre_scanbuf: starting offset is outside bounds of file %u >= %u\n", adjbuffer, length);
            continue;
        }

        pm_dbgmsg("cli_pcre_scanbuf: passed buffer adjusted to %u +%u(%u)[%u]%s\n", adjbuffer, adjlength, adjbuffer+adjlength, adjshift, encompass ? " (encompass)":"");

        /* if the global flag is set, loop through the scanning */
        do {
            /* reset the match results */
            if ((ret = cli_pcre_results_reset(&p_res, pd)) != CL_SUCCESS)
                break;

            /* performance metrics */
            cli_event_time_start(p_sigevents, pm->sigtime_id);
            rc = cli_pcre_match(pd, buffer+adjbuffer, adjlength, offset, options, &p_res);
            cli_event_time_stop(p_sigevents, pm->sigtime_id);
            /* if debug, generate a match report */
            if (cli_debug_flag)
                cli_pcre_report(pd, buffer+adjbuffer, adjlength, rc, &p_res);

            /* matched, rc shouldn't be >0 unless a full match occurs */
            if (rc > 0) {
                cli_dbgmsg("cli_pcre_scanbuf: located regex match @ %d\n", adjbuffer+p_res.match[0]);

                /* check if we've gone over offset+shift */
                if (!encompass && adjshift) {
                    if (p_res.match[0] > adjshift) {
                        /* ignore matched offset (outside of maxshift) */
                        cli_dbgmsg("cli_pcre_scanbuf: match found outside of maxshift @%u\n", adjbuffer+p_res.match[0]);
                        break;
                    }
                }

                /* track the detection count */
                cli_event_count(p_sigevents, pm->sigmatch_id);

                /* for logical signature evaluation */
                if (pm->lsigid[0]) {
                    pm_dbgmsg("cli_pcre_scanbuf: assigning lsigcnt[%d][%d], located @ %d\n",
                              pm->lsigid[1], pm->lsigid[2], adjbuffer+p_res.match[0]);

                    ret = lsig_sub_matched(root, mdata, pm->lsigid[1], pm->lsigid[2], adjbuffer+p_res.match[0], 0);
                    if (ret != CL_SUCCESS)
                        break;
                } else {
                    /* for raw match data - sigtool only */
                    if(res) {
                        newres = (struct cli_ac_result *)cli_calloc(1, sizeof(struct cli_ac_result));
                        if(!newres) {
                            cli_errmsg("cli_pcre_scanbuff: Can't allocate memory for new result\n");
                            ret = CL_EMEM;
                            break;
                        }
                        newres->virname = pm->virname;
                        newres->customdata = NULL; /* get value? */
                        newres->next = *res;
                        newres->offset = adjbuffer+p_res.match[0];
                        *res = newres;
                    } else {
                        if (ctx && SCAN_ALL) {
                            viruses_found = 1;
                            cli_append_virus(ctx, (const char *)pm->virname);
                        }
                        if (virname)
                            *virname = pm->virname;
                        if (!ctx || !SCAN_ALL) {
                            ret = CL_VIRUS;
                            break;
                        }
                    }
                }
            }

            /* move off to the end of the match for next match; offset is relative to adjbuffer
             * NOTE: misses matches starting within the last match; TODO: start from start of last match? */
            offset = p_res.match[1];
        } while (global && rc > 0 && offset < adjlength);

        /* handle error code */
        if (rc < 0 && p_res.err != CL_SUCCESS)
            ret = p_res.err;

        /* jumps out of main loop from 'global' loop */
        if (ret != CL_SUCCESS)
            break;
    }
示例#20
0
int cli_chm_open(const char *dirname, chm_metadata_t *metadata, cli_ctx *ctx)
{
	STATBUF statbuf;
	int retval;

	cli_dbgmsg("in cli_chm_open\n");
	
	if ((retval = chm_init_metadata(metadata)) != CL_SUCCESS) {
		return retval;
	}

	metadata->map = *ctx->fmap;
	if(metadata->map->len < CHM_ITSF_MIN_LEN)
		return CL_ESTAT;
	metadata->m_length = metadata->map->len;

	if (!itsf_read_header(metadata)) {
		goto abort;
	}
	itsf_print_header(&metadata->itsf_hdr);

	if (!itsp_read_header(metadata, metadata->itsf_hdr.dir_offset)) {
		goto abort;
	}
	itsp_print_header(&metadata->itsp_hdr);

	metadata->chunk_offset = metadata->itsf_hdr.dir_offset+CHM_ITSP_LEN;
	
	/* TODO: need to check this first calculation,
		currently have no files of this type */
	if (metadata->itsp_hdr.index_head > 0) {
		metadata->chunk_offset += metadata->itsp_hdr.index_head * metadata->itsp_hdr.block_len;
	}

	metadata->num_chunks = metadata->itsp_hdr.index_tail - metadata->itsp_hdr.index_head + 1;
	
	/* Versions before 3 didn't have a data_offset */
	/* TODO: need to check this calculation,
		 currently have no files of this type */
	if (metadata->itsf_hdr.version < 3) {
		metadata->itsf_hdr.data_offset = metadata->itsf_hdr.dir_offset + CHM_ITSP_LEN +
				(metadata->itsp_hdr.block_len*metadata->itsp_hdr.num_blocks);
	}
	
	while (metadata->num_chunks) {
		if (read_chunk(metadata) != CL_SUCCESS) {
			cli_dbgmsg("read_chunk failed\n");
			goto abort;
		}
		if (read_control_entries(metadata) == FALSE) {
			goto abort;
		}
		metadata->num_chunks--;
		metadata->chunk_offset += metadata->itsp_hdr.block_len;
	}

	if (!metadata->sys_content.length || !metadata->sys_control.length || !metadata->sys_reset.length) {
		cli_dbgmsg("sys file missing\n");
		goto abort;
	}
	
	metadata->ufd = chm_decompress_stream(metadata, dirname, ctx);
	if (metadata->ufd == -1) {
		goto abort;
	}
	
	metadata->chunk_entries = 0;
	metadata->chunk_data = NULL;
	metadata->chunk_offset = metadata->itsf_hdr.dir_offset+CHM_ITSP_LEN;
	metadata->num_chunks = metadata->itsp_hdr.index_tail - metadata->itsp_hdr.index_head + 1;

	return CL_SUCCESS;

abort:
	return CL_EFORMAT;
}
示例#21
0
uint32_t cli_bcapi_debug_print_str(struct cli_bc_ctx *ctx, const uint8_t *str, uint32_t len)
{
    cli_event_fastdata(EV, BCEV_DBG_STR, str, strlen((const char*)str));
    cli_dbgmsg("bytecode debug: %s\n", str);
    return 0;
}
示例#22
0
static void itsp_print_header(chm_itsp_header_t *itsp_hdr)
{
	if (!itsp_hdr) {
		return;
	}
	
	cli_dbgmsg("---- ITSP ----\n");
	cli_dbgmsg("Signature:\t%c%c%c%c\n", itsp_hdr->signature[0],
		itsp_hdr->signature[1],itsp_hdr->signature[2],itsp_hdr->signature[3]);
	cli_dbgmsg("Version:\t%d\n", itsp_hdr->version);
	cli_dbgmsg("Block len:\t%u\n", itsp_hdr->block_len);
	cli_dbgmsg("Block idx int:\t%d\n", itsp_hdr->blockidx_intvl);
	cli_dbgmsg("Index depth:\t%d\n", itsp_hdr->index_depth);
	cli_dbgmsg("Index root:\t%d\n", itsp_hdr->index_root);
	cli_dbgmsg("Index head:\t%u\n", itsp_hdr->index_head);
	cli_dbgmsg("Index tail:\t%u\n", itsp_hdr->index_tail);
	cli_dbgmsg("Num Blocks:\t%u\n", itsp_hdr->num_blocks);
	cli_dbgmsg("Lang ID:\t%u\n\n", itsp_hdr->lang_id);
}
示例#23
0
static int
vba_read_project_strings(int fd, int big_endian)
{
	unsigned char *buf = NULL;
	uint16_t buflen = 0;
	int ret = 0;

	for(;;) {
		off_t offset;
		uint16_t length;
		char *name;

		if(!read_uint16(fd, &length, big_endian))
			break;

		if (length < 6) {
			lseek(fd, -2, SEEK_CUR);
			break;
		}
		if(length > buflen) {
			unsigned char *newbuf = (unsigned char *)cli_realloc(buf, length);
			if(newbuf == NULL) {
				if(buf)
					free(buf);
				return 0;
			}
			buflen = length;
			buf = newbuf;
		}

		offset = lseek(fd, 0, SEEK_CUR);

		if(cli_readn(fd, buf, length) != (int)length) {
			cli_dbgmsg("read name failed - rewinding\n");
			lseek(fd, offset, SEEK_SET);
			break;
		}
		name = get_unicode_name((const char *)buf, length, big_endian);
		cli_dbgmsg("length: %d, name: %s\n", length, (name) ? name : "[null]");

		if((name == NULL) || (memcmp("*\\", name, 2) != 0) ||
		   (strchr("ghcd", name[2]) == NULL)) {
			/* Not a string */
			lseek(fd, -(length+2), SEEK_CUR);
			if(name)
				free(name);
			break;
		}
		free(name);

		if(!read_uint16(fd, &length, big_endian)) {
			if(buf)
				free(buf);
			break;
		}

		ret++;

		if ((length != 0) && (length != 65535)) {
			lseek(fd, -2, SEEK_CUR);
			continue;
		}
		offset = lseek(fd, 10, SEEK_CUR);
		cli_dbgmsg("offset: %lu\n", (unsigned long)offset);
		vba56_test_middle(fd);
	}
	if(buf)
		free(buf);
	return ret;
}
示例#24
0
static int chm_decompress_stream(int fd, chm_metadata_t *metadata, const char *dirname, cli_ctx *ctx)
{
	lzx_content_t lzx_content;
	lzx_reset_table_t lzx_reset_table;
	lzx_control_t lzx_control;
	int window_bits, length, tmpfd, retval=-1;
	struct lzx_stream * stream;
	char filename[1024];
	struct cab_file file;
	
	snprintf(filename, 1024, "%s"PATHSEP"clamav-unchm.bin", dirname);
	tmpfd = open(filename, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU);
	if (tmpfd<0) {
		cli_dbgmsg("open failed for %s\n", filename);
		return -1;
	}

	if (!metadata->sys_control.length || !metadata->sys_content.length ||!metadata->sys_reset.length) {
		cli_dbgmsg("Control file missing\n");
		goto abort;
	}

	if (!read_sys_control(metadata, &lzx_control)) {
		goto abort;
	}
	if (!read_sys_content(metadata, &lzx_content)) {
		goto abort;
	}
	if (!read_sys_reset_table(metadata, &lzx_reset_table)) {
		goto abort;
	}
	
	switch (lzx_control.window_size) {
		case 0x008000:
			window_bits = 15;
			break;
		case 0x010000:
			window_bits = 16;
			break;
		case 0x020000:
			window_bits = 17;
			break;
		case 0x040000:
			window_bits = 18;
			break;
		case 0x080000:
			window_bits = 19;
			break;
		case 0x100000:
			window_bits = 20;
			break;
		case 0x200000:
			window_bits = 21;
			break;
		default:
			cli_dbgmsg("bad control window size: 0x%x\n", lzx_control.window_size);
			goto abort;
	}
	
	if (lzx_control.reset_interval % LZX_FRAME_SIZE) {
		cli_dbgmsg("bad reset_interval: 0x%x\n", lzx_control.window_size);
		goto abort;
	}
	
	length = lzx_reset_table.uncom_len;
	length += lzx_control.reset_interval;
	length &= -lzx_control.reset_interval;
	
	cli_dbgmsg("Compressed offset: %lu\n", (unsigned long int) lzx_content.offset);
	if ((uint64_t) lseek(fd, lzx_content.offset, SEEK_SET) != lzx_content.offset) {
		goto abort;
	}

	memset(&file, 0, sizeof(struct cab_file));
	file.max_size = ctx->engine->maxfilesize;
	stream = lzx_init(fd, tmpfd, window_bits,
			lzx_control.reset_interval / LZX_FRAME_SIZE,
			4096, length, &file, NULL);
	if (!stream) {
		cli_dbgmsg("lzx_init failed\n");
		goto abort;
	}
	
	lzx_decompress(stream, length);
	lzx_free(stream);
	
#ifndef _WIN32
	/* Delete the file */
	if(cli_unlink(filename))
		retval = -1;
	else
#endif
		retval = tmpfd;
	
abort:
	if ((retval == -1) && (tmpfd >= 0)) {
		close(tmpfd);
	}
	return retval;
}
示例#25
0
vba_project_t *
cli_vba_readdir(const char *dir, struct uniq *U, uint32_t which)
{
	unsigned char *buf;
	const unsigned char vba56_signature[] = { 0xcc, 0x61 };
	uint16_t record_count, buflen, ffff, byte_count;
	uint32_t offset;
	int i, j, fd, big_endian = FALSE;
	vba_project_t *vba_project;
	struct vba56_header v56h;
	off_t seekback;
	char fullname[1024], *hash;

	cli_dbgmsg("in cli_vba_readdir()\n");

	if(dir == NULL)
		return NULL;

	/*
	 * _VBA_PROJECT files are embedded within office documents (OLE2)
	 */
	
	if (!uniq_get(U, "_vba_project", 12, &hash))
		return NULL;
	snprintf(fullname, sizeof(fullname), "%s"PATHSEP"%s_%u", dir, hash, which);
	fullname[sizeof(fullname)-1] = '\0';
	fd = open(fullname, O_RDONLY|O_BINARY);

	if(fd == -1)
		return NULL;

	if(cli_readn(fd, &v56h, sizeof(struct vba56_header)) != sizeof(struct vba56_header)) {
		close(fd);
		return NULL;
	}
	if (memcmp(v56h.magic, vba56_signature, sizeof(v56h.magic)) != 0) {
		close(fd);
		return NULL;
	}

	i = vba_read_project_strings(fd, TRUE);
	if ((seekback = lseek(fd, 0, SEEK_CUR)) == -1) {
		cli_dbgmsg("vba_readdir: lseek() failed. Unable to guess VBA type\n");
		close(fd);
		return NULL;
	}
	if (lseek(fd, sizeof(struct vba56_header), SEEK_SET) == -1) {
		cli_dbgmsg("vba_readdir: lseek() failed. Unable to guess VBA type\n");
		close(fd);
		return NULL;
	}
	j = vba_read_project_strings(fd, FALSE);
	if(!i && !j) {
		close(fd);
		cli_dbgmsg("vba_readdir: Unable to guess VBA type\n");
		return NULL;
	}
	if (i > j) {
		big_endian = TRUE;
		if (lseek(fd, seekback, SEEK_SET) == -1) {
			cli_dbgmsg("vba_readdir: call to lseek() while guessing big-endian has failed\n");
			close(fd);
			return NULL;
		}
		cli_dbgmsg("vba_readdir: Guessing big-endian\n");
	} else {
		cli_dbgmsg("vba_readdir: Guessing little-endian\n");
	}

	/* junk some more stuff */
	do
		if (cli_readn(fd, &ffff, 2) != 2) {
			close(fd);
			return NULL;
		}
	while(ffff != 0xFFFF);

	/* check for alignment error */
	if(!seekandread(fd, -3, SEEK_CUR, &ffff, sizeof(uint16_t))) {
		close(fd);
		return NULL;
	}
	if (ffff != 0xFFFF) {
		if (lseek(fd, 1, SEEK_CUR) == -1) {
            cli_dbgmsg("call to lseek() while checking alignment error has failed\n");
            close(fd);
            return NULL;
        }
    }

	if(!read_uint16(fd, &ffff, big_endian)) {
		close(fd);
		return NULL;
	}

	if(ffff != 0xFFFF) {
		if (lseek(fd, ffff, SEEK_CUR) == -1) {
            cli_dbgmsg("call to lseek() while checking alignment error has failed\n");
            close(fd);
            return NULL;
        }
    }

	if(!read_uint16(fd, &ffff, big_endian)) {
		close(fd);
		return NULL;
	}

	if(ffff == 0xFFFF)
		ffff = 0;

	if (lseek(fd, ffff + 100, SEEK_CUR) == -1) {
        cli_dbgmsg("call to lseek() failed\n");
        close(fd);
        return NULL;
    }

	if(!read_uint16(fd, &record_count, big_endian)) {
		close(fd);
		return NULL;
	}
	cli_dbgmsg("vba_readdir: VBA Record count %d\n", record_count);
	if (record_count == 0) {
		/* No macros, assume clean */
		close(fd);
		return NULL;
	}
	if (record_count > MAX_VBA_COUNT) {
		/* Almost certainly an error */
		cli_dbgmsg("vba_readdir: VBA Record count too big\n");
		close(fd);
		return NULL;
	}

	vba_project = create_vba_project(record_count, dir, U);
	if(vba_project == NULL) {
		close(fd);
		return NULL;
	}
	buf = NULL;
	buflen = 0;
	for(i = 0; i < record_count; i++) {
		uint16_t length;
		char *ptr;

		vba_project->colls[i] = 0;
		if(!read_uint16(fd, &length, big_endian))
			break;

		if (length == 0) {
			cli_dbgmsg("vba_readdir: zero name length\n");
			break;
		}
		if(length > buflen) {
			unsigned char *newbuf = (unsigned char *)cli_realloc(buf, length);
			if(newbuf == NULL)
				break;
			buflen = length;
			buf = newbuf;
		}
		if (cli_readn(fd, buf, length) != length) {
			cli_dbgmsg("vba_readdir: read name failed\n");
			break;
		}
		ptr = get_unicode_name((const char *)buf, length, big_endian);
		if(ptr == NULL) break;
		if (!(vba_project->colls[i]=uniq_get(U, ptr, strlen(ptr), &hash))) {
			cli_dbgmsg("vba_readdir: cannot find project %s (%s)\n", ptr, hash);
			free(ptr);
			break;
		}
		cli_dbgmsg("vba_readdir: project name: %s (%s)\n", ptr, hash);
		free(ptr);
		vba_project->name[i] = hash;
		if(!read_uint16(fd, &length, big_endian))
			break;
		lseek(fd, length, SEEK_CUR);

		if(!read_uint16(fd, &ffff, big_endian))
			break;
		if (ffff == 0xFFFF) {
			lseek(fd, 2, SEEK_CUR);
			if(!read_uint16(fd, &ffff, big_endian))
				break;
			lseek(fd, ffff + 8, SEEK_CUR);
		} else
			lseek(fd, ffff + 10, SEEK_CUR);

		if(!read_uint16(fd, &byte_count, big_endian))
			break;
		lseek(fd, (8 * byte_count) + 5, SEEK_CUR);
		if(!read_uint32(fd, &offset, big_endian))
			break;
		cli_dbgmsg("vba_readdir: offset: %u\n", (unsigned int)offset);
		vba_project->offset[i] = offset;
		lseek(fd, 2, SEEK_CUR);
	}

	if(buf)
		free(buf);

	close(fd);

	if(i < record_count) {
		free(vba_project->name);
		free(vba_project->colls);
		free(vba_project->dir);
		free(vba_project->offset);
		free(vba_project);
		return NULL;
	}

	return vba_project;
}
示例#26
0
int cli_chm_open(int fd, const char *dirname, chm_metadata_t *metadata, cli_ctx *ctx)
{
	struct stat statbuf;
	int retval;

	cli_dbgmsg("in cli_chm_open\n");
	
	if ((retval = chm_init_metadata(metadata)) != CL_SUCCESS) {
		return retval;
	}

	if (fstat(fd, &statbuf) == 0) {
		if (statbuf.st_size < CHM_ITSF_MIN_LEN) {
			return CL_ESTAT;
		}
		metadata->m_length = statbuf.st_size;
		metadata->map = fmap(fd, 0, metadata->m_length);
		if (!metadata->map) {
			return CL_EMAP;
		}
	} else {
	    char err[128];
	    cli_warnmsg("fstat() failed: %s\n", cli_strerror(errno, err, sizeof(err)));
	    return CL_ESTAT;
	}

	if (!itsf_read_header(metadata)) {
		goto abort;
	}
	itsf_print_header(&metadata->itsf_hdr);

	if (!itsp_read_header(metadata, metadata->itsf_hdr.dir_offset)) {
		goto abort;
	}
	itsp_print_header(&metadata->itsp_hdr);

	metadata->chunk_offset = metadata->itsf_hdr.dir_offset+CHM_ITSP_LEN;
	
	/* TODO: need to check this first calculation,
		currently have no files of this type */
	if (metadata->itsp_hdr.index_head > 0) {
		metadata->chunk_offset += metadata->itsp_hdr.index_head * metadata->itsp_hdr.block_len;
	}

	metadata->num_chunks = metadata->itsp_hdr.index_tail - metadata->itsp_hdr.index_head + 1;
	
	/* Versions before 3 didn't have a data_offset */
	/* TODO: need to check this calculation,
		 currently have no files of this type */
	if (metadata->itsf_hdr.version < 3) {
		metadata->itsf_hdr.data_offset = metadata->itsf_hdr.dir_offset + CHM_ITSP_LEN +
				(metadata->itsp_hdr.block_len*metadata->itsp_hdr.num_blocks);
	}
	
	while (metadata->num_chunks) {
		if (read_chunk(metadata) != CL_SUCCESS) {
			cli_dbgmsg("read_chunk failed\n");
			goto abort;
		}
		if (read_control_entries(metadata) == FALSE) {
			goto abort;
		}
		metadata->num_chunks--;
		metadata->chunk_offset += metadata->itsp_hdr.block_len;
	}

	if (!metadata->sys_content.length || !metadata->sys_control.length || !metadata->sys_reset.length) {
		cli_dbgmsg("sys file missing\n");
		goto abort;
	}
	
	metadata->ufd = chm_decompress_stream(fd, metadata, dirname, ctx);
	if (metadata->ufd == -1) {
		goto abort;
	}
	
	metadata->chunk_entries = 0;
	metadata->chunk_data = NULL;
	metadata->chunk_offset = metadata->itsf_hdr.dir_offset+CHM_ITSP_LEN;
	metadata->num_chunks = metadata->itsp_hdr.index_tail - metadata->itsp_hdr.index_head + 1;

	return CL_SUCCESS;

abort:
	funmap(metadata->map);
	return CL_EFORMAT;
}
示例#27
0
/* 64-bit version of section header parsing */
static int cli_elf_sh64(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo,
    struct elf_file_hdr64 *file_hdr, uint8_t conv)
{
	struct elf_section_hdr64 *section_hdr = NULL;
	uint16_t shnum, shentsize;
	uint32_t i;
	uint64_t shoff;

    shnum = file_hdr->e_shnum;
    cli_dbgmsg("ELF: Number of sections: %d\n", shnum);
    if(ctx && (shnum > 2048)) {
	cli_dbgmsg("ELF: Number of sections > 2048, skipping\n");
	return CL_BREAK;
    }
    else if(elfinfo && (shnum > 256)) {
	cli_dbgmsg("ELF: Suspicious number of sections\n");
	return CL_BREAK;
    }
    if(elfinfo) {
        elfinfo->nsections = shnum;
    }

    shentsize = file_hdr->e_shentsize;
    /* Sanity check */
    if(shentsize != sizeof(struct elf_section_hdr64)) {
	cli_dbgmsg("ELF: shentsize != sizeof(struct elf_section_hdr64)\n");
        if(ctx && DETECT_BROKEN) {
	    cli_append_virus(ctx, "Heuristics.Broken.Executable");
	    return CL_VIRUS;
        }
	return CL_EFORMAT;
    }

    if(elfinfo && !shnum) {
        return CL_CLEAN;
    }

    shoff = file_hdr->e_shoff;
    if(ctx)
        cli_dbgmsg("ELF: Section header table offset: " STDu64 "\n", shoff);

    if(elfinfo) {
        elfinfo->section = (struct cli_exe_section *)cli_calloc(shnum, sizeof(struct cli_exe_section));
        if(!elfinfo->section) {
            cli_dbgmsg("ELF: Can't allocate memory for section headers\n");
            return CL_EMEM;
        }
    }

    if(shnum) {
	section_hdr = (struct elf_section_hdr64 *) cli_calloc(shnum, shentsize);
	if(!section_hdr) {
	    cli_errmsg("ELF: Can't allocate memory for section headers\n");
	    if(elfinfo) {
                free(elfinfo->section);
                elfinfo->section = NULL;
	    }
	    return CL_EMEM;
	}
	if(ctx) {
            cli_dbgmsg("------------------------------------\n");
	}
    }

    /* Loop over section headers */
    for(i = 0; i < shnum; i++) {
        uint32_t sh_type, sh_flags;

	if(fmap_readn(map, &section_hdr[i], shoff, sizeof(struct elf_section_hdr64)) != sizeof(struct elf_section_hdr64)) {
            cli_dbgmsg("ELF: Can't read section header\n");
            if(ctx) {
                cli_dbgmsg("ELF: Possibly broken ELF file\n");
            }
            free(section_hdr);
            if(elfinfo) {
                free(elfinfo->section);
                elfinfo->section = NULL;
	    }
            if(ctx && DETECT_BROKEN) {
                cli_append_virus(ctx, "Heuristics.Broken.Executable");
		return CL_VIRUS;
            }
            return CL_BREAK;
        }

	shoff += sizeof(struct elf_section_hdr64);

        if(elfinfo) {
            elfinfo->section[i].rva = EC64(section_hdr[i].sh_addr, conv);
            elfinfo->section[i].raw = EC64(section_hdr[i].sh_offset, conv);
            elfinfo->section[i].rsz = EC64(section_hdr[i].sh_size, conv);
        }
        if(ctx) {
	    cli_dbgmsg("ELF: Section %u\n", i);
	    cli_dbgmsg("ELF: Section offset: " STDu64 "\n", EC64(section_hdr[i].sh_offset, conv));
	    cli_dbgmsg("ELF: Section size: " STDu64 "\n", EC64(section_hdr[i].sh_size, conv));

            sh_type = EC32(section_hdr[i].sh_type, conv);
            sh_flags = (uint32_t)(EC64(section_hdr[i].sh_flags, conv) & ELF_SHF_MASK);
            cli_elf_sectionlog(sh_type, sh_flags);

	    cli_dbgmsg("------------------------------------\n");
        }
    }

    free(section_hdr);
    return CL_CLEAN;
}
示例#28
0
void submit_post(const char *host, const char *port, const char *method, const char *url, const char *postdata, uint32_t timeout)
{
    int sockfd, n;
    unsigned int i;
    char *buf, *encoded=NULL;
    size_t bufsz;
    ssize_t recvsz;
    char chunkedlen[21];
    fd_set readfds;
    struct timeval tv;
    char *acceptable_methods[] = {
        "GET",
        "PUT",
        "POST",
        NULL
    };

    for (i=0; acceptable_methods[i] != NULL; i++)
        if (!strcmp(method, acceptable_methods[i]))
            break;

    if (acceptable_methods[i] == NULL)
        return;

    bufsz = strlen(method);
    bufsz += sizeof("   HTTP/1.1") + 2; /* Yes. Three blank spaces. +1 for the \n */
    bufsz += strlen(url);
    bufsz += sizeof("Host: \r\n");
    bufsz += strlen(host);
    bufsz += sizeof("Connection: Close\r\n");
    bufsz += 4; /* +4 for \r\n\r\n */

    if (!strcmp(method, "POST") || !strcmp(method, "PUT")) {
        encoded = encode_data(postdata);
        if (!(encoded))
            return;
        snprintf(chunkedlen, sizeof(chunkedlen), "%zu", strlen(encoded));
        bufsz += sizeof("Content-Type: application/x-www-form-urlencoded\r\n");
        bufsz += sizeof("Content-Length: \r\n");
        bufsz += strlen(chunkedlen);
        bufsz += strlen(encoded);
    }

    buf = cli_calloc(1, bufsz);
    if (!(buf)) {
        if ((encoded))
            free(encoded);

        return;
    }

    snprintf(buf, bufsz, "%s %s HTTP/1.1\r\n", method, url);
    snprintf(buf+strlen(buf), bufsz-strlen(buf), "Host: %s\r\n", host);
    snprintf(buf+strlen(buf), bufsz-strlen(buf), "Connection: Close\r\n");

    if (!strcmp(method, "POST") || !strcmp(method, "PUT")) {
        snprintf(buf+strlen(buf), bufsz-strlen(buf), "Content-Type: application/x-www-form-urlencoded\r\n");
        snprintf(buf+strlen(buf), bufsz-strlen(buf), "Content-Length: %s\r\n", chunkedlen);
        snprintf(buf+strlen(buf), bufsz-strlen(buf), "\r\n");
        snprintf(buf+strlen(buf), bufsz-strlen(buf), "%s", encoded);
        free(encoded);
    }
#if defined(_WIN32)
	sockfd = connect_host(host, port, timeout, 0);
#else
    sockfd = connect_host(host, port, timeout, 1);
#endif
    if (sockfd < 0) {
        free(buf);
        return;
    }

    cli_dbgmsg("stats - Connected to %s:%s\n", host, port);

    if ((size_t)send(sockfd, buf, strlen(buf), 0) != (size_t)strlen(buf)) {
        closesocket(sockfd);
        free(buf);
        return;
    }

    cli_dbgmsg("stats - Sending %s\n", buf);

    while (1) {
        FD_ZERO(&readfds);
        FD_SET(sockfd, &readfds);

        /*
         * Check to make sure the stats submitted okay (so that we don't kill the HTTP request
         * while it's being processed). Give a ten-second timeout so we don't have a major
         * impact on scanning.
         */
        tv.tv_sec = timeout;
        tv.tv_usec = 0;
        if ((n = select(sockfd+1, &readfds, NULL, NULL, &tv)) <= 0)
            break;

        if (FD_ISSET(sockfd, &readfds)) {
            memset(buf, 0x00, bufsz);
            if ((recvsz = recv(sockfd, buf, bufsz-1, 0) <= 0))
                break;

            buf[bufsz-1] = '\0';

            cli_dbgmsg("stats - received: %s\n", buf);

            if (strstr(buf, "STATOK")) {
                cli_dbgmsg("stats - Data received okay\n");
                break;
            }
        }
    }

    closesocket(sockfd);
    free(buf);
}
示例#29
0
/* Scan function for ELF */
int cli_scanelf(cli_ctx *ctx)
{
	union elf_file_hdr file_hdr;
	fmap_t *map = *ctx->fmap;
	int ret;
	uint8_t conv = 0, is64 = 0;

    cli_dbgmsg("in cli_scanelf\n");

    /* Load header to determine size and class */
    ret = cli_elf_fileheader(ctx, map, &file_hdr, &conv, &is64);
    if(ret == CL_BREAK) {
	return CL_CLEAN; /* here, break means "exit but report clean" */
    }
    else if(ret != CL_CLEAN) {
	return ret;
    }

    /* Log File type and machine type */
    switch(file_hdr.hdr64.e_type) {
	case 0x0: /* ET_NONE */
	    cli_dbgmsg("ELF: File type: None\n");
	    break;
	case 0x1: /* ET_REL */
	    cli_dbgmsg("ELF: File type: Relocatable\n");
	    break;
	case 0x2: /* ET_EXEC */
	    cli_dbgmsg("ELF: File type: Executable\n");
	    break;
	case 0x3: /* ET_DYN */
	    cli_dbgmsg("ELF: File type: Core\n");
	    break;
	case 0x4: /* ET_CORE */
	    cli_dbgmsg("ELF: File type: Core\n");
	    break;
	default:
	    cli_dbgmsg("ELF: File type: Unknown (%d)\n", file_hdr.hdr64.e_type);
    }

    switch(file_hdr.hdr64.e_machine) {
	/* Due to a huge list, we only include the most popular machines here */
	case 0: /* EM_NONE */
	    cli_dbgmsg("ELF: Machine type: None\n");
	    break;
	case 2: /* EM_SPARC */
	    cli_dbgmsg("ELF: Machine type: SPARC\n");
	    break;
	case 3: /* EM_386 */
	    cli_dbgmsg("ELF: Machine type: Intel 80386\n");
	    break;
	case 4: /* EM_68K */
	    cli_dbgmsg("ELF: Machine type: Motorola 68000\n");
	    break;
	case 8: /* EM_MIPS */
	    cli_dbgmsg("ELF: Machine type: MIPS RS3000\n");
	    break;
	case 9: /* EM_S370 */
	    cli_dbgmsg("ELF: Machine type: IBM System/370\n");
	    break;
	case 15: /* EM_PARISC */
	    cli_dbgmsg("ELF: Machine type: HPPA\n");
	    break;
	case 20: /* EM_PPC */
	    cli_dbgmsg("ELF: Machine type: PowerPC\n");
	    break;
	case 21: /* EM_PPC64 */
	    cli_dbgmsg("ELF: Machine type: PowerPC 64-bit\n");
	    break;
	case 22: /* EM_S390 */
	    cli_dbgmsg("ELF: Machine type: IBM S390\n");
	    break;
	case 40: /* EM_ARM */
	    cli_dbgmsg("ELF: Machine type: ARM\n");
	    break;
	case 41: /* EM_FAKE_ALPHA */
	    cli_dbgmsg("ELF: Machine type: Digital Alpha\n");
	    break;
	case 43: /* EM_SPARCV9 */
	    cli_dbgmsg("ELF: Machine type: SPARC v9 64-bit\n");
	    break;
	case 50: /* EM_IA_64 */
	    cli_dbgmsg("ELF: Machine type: IA64\n");
	    break;
	case 62: /* EM_X86_64 */
	    cli_dbgmsg("ELF: Machine type: AMD x86-64\n");
	    break;
	default:
	    cli_dbgmsg("ELF: Machine type: Unknown (0x%x)\n", file_hdr.hdr64.e_machine);
    }

    /* Program headers and Entry */
    if(is64) {
        ret = cli_elf_ph64(ctx, map, NULL, &(file_hdr.hdr64), conv);
    }
    else {
        ret = cli_elf_ph32(ctx, map, NULL, &(file_hdr.hdr32.hdr), conv);
    }
    if(ret == CL_BREAK) {
	return CL_CLEAN; /* break means "exit but report clean" */
    }
    else if(ret != CL_CLEAN) {
	return ret;
    }

    /* Sections */
    if(is64) {
        ret = cli_elf_sh64(ctx, map, NULL, &(file_hdr.hdr64), conv);
    }
    else {
        ret = cli_elf_sh32(ctx, map, NULL, &(file_hdr.hdr32.hdr), conv);
    }
    if(ret == CL_BREAK) {
	return CL_CLEAN; /* break means "exit but report clean" */
    }
    else if(ret != CL_CLEAN) {
	return ret;
    }

    return CL_CLEAN;
}
示例#30
0
extern cl_fmap_t *cl_fmap_open_handle(void *handle, size_t offset, size_t len,
				      clcb_pread pread_cb, int use_aging)
{
    unsigned int pages, mapsz, hdrsz;
    cl_fmap_t *m;
    int pgsz = cli_getpagesize();

    if((off_t)offset < 0 || offset != fmap_align_to(offset, pgsz)) {
	cli_warnmsg("fmap: attempted mapping with unaligned offset\n");
	return NULL;
    }
    if(!len) {
	cli_dbgmsg("fmap: attempted void mapping\n");
	return NULL;
    }
    if (offset >= len) {
	cli_warnmsg("fmap: attempted oof mapping\n");
	return NULL;
    }

    pages = fmap_align_items(len, pgsz);
    hdrsz = fmap_align_to(sizeof(fmap_t) + (pages-1) * sizeof(uint32_t), pgsz); /* fmap_t includes 1 bitmap slot, hence (pages-1) */
    mapsz = pages * pgsz + hdrsz;

#ifndef ANONYMOUS_MAP
    use_aging = 0;
#endif
#ifdef ANONYMOUS_MAP
    if (use_aging) {
	fmap_lock;
	if ((m = (fmap_t *)mmap(NULL, mapsz, PROT_READ | PROT_WRITE, MAP_PRIVATE|/*FIXME: MAP_POPULATE is ~8% faster but more memory intensive */ANONYMOUS_MAP, -1, 0)) == MAP_FAILED) {
	    m = NULL;
	} else {
#if HAVE_MADVISE
	    madvise((void *)m, mapsz, MADV_RANDOM|MADV_DONTFORK);
#endif /* madvise */
	    /* fault the header while we still have the lock - we DO context switch here a lot here :@ */
	    memset(fmap_bitmap, 0, sizeof(uint32_t) * pages);
	}
	fmap_unlock;
    }
#endif /* ANONYMOUS_MAP */
    if (!use_aging) {
	m = (fmap_t *)cli_malloc(mapsz);
    if (!(m)) {
        cli_warnmsg("fmap: map allocation failed\n");
        return NULL;
    }
	memset(m, 0, hdrsz);
    }
    if(!m) {
	cli_warnmsg("fmap: map allocation failed\n");
	return NULL;
    }
    m->handle = handle;
    m->pread_cb = pread_cb;
    m->aging = use_aging;
    m->offset = offset;
    m->nested_offset = 0;
    m->len = len;/* m->nested_offset + m->len = m->real_len */
    m->real_len = len;
    m->pages = pages;
    m->hdrsz = hdrsz;
    m->pgsz = pgsz;
    m->paged = 0;
    m->dont_cache_flag = 0;
    m->unmap = use_aging ? unmap_mmap : unmap_malloc;
    m->need = handle_need;
    m->need_offstr = handle_need_offstr;
    m->gets = handle_gets;
    m->unneed_off = handle_unneed_off;
    return m;
}