int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, cli_file_t ftype, int fd) { uint32_t i, j, off; uint8_t found, pchain, shift; uint16_t idx, idxchk; struct cli_bm_patt *p; const unsigned char *bp, *pt; unsigned char prefix; struct cli_target_info info; if(!root || !root->bm_shift) return CL_CLEAN; if(length < BM_MIN_LENGTH) return CL_CLEAN; memset(&info, 0, sizeof(info)); for(i = BM_MIN_LENGTH - BM_BLOCK_SIZE; i < length - BM_BLOCK_SIZE + 1; ) { idx = HASH(buffer[i], buffer[i + 1], buffer[i + 2]); shift = root->bm_shift[idx]; if(shift == 0) { prefix = buffer[i - BM_MIN_LENGTH + BM_BLOCK_SIZE]; p = root->bm_suffix[idx]; pchain = 0; while(p) { if(p->pattern0 != prefix) { if(pchain) break; p = p->next; continue; } else pchain = 1; off = i - BM_MIN_LENGTH + BM_BLOCK_SIZE; bp = buffer + off; if((off + p->length > length) || (p->prefix_length > off)) { p = p->next; continue; } idxchk = MIN(p->length, length - off) - 1; if(idxchk) { if((bp[idxchk] != p->pattern[idxchk]) || (bp[idxchk / 2] != p->pattern[idxchk / 2])) { p = p->next; continue; } } if(p->prefix_length) { off -= p->prefix_length; bp -= p->prefix_length; pt = p->prefix; } else { pt = p->pattern; } found = 1; for(j = 0; j < p->length + p->prefix_length && off < length; j++, off++) { if(bp[j] != pt[j]) { found = 0; break; } } if(found && p->length + p->prefix_length == j) { if(p->offset) { off = offset + i - p->prefix_length - BM_MIN_LENGTH + BM_BLOCK_SIZE; if(!cli_validatesig(ftype, p->offset, off, &info, fd, p->virname)) { p = p->next; continue; } } if(virname) *virname = p->virname; if(info.exeinfo.section) free(info.exeinfo.section); return CL_VIRUS; } p = p->next; } shift = 1; } i += shift; } if(info.exeinfo.section) free(info.exeinfo.section); return CL_CLEAN; }
int cli_bm_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_node *root, unsigned long int offset, unsigned short ftype, int fd) { unsigned int i, j, shift, off, found = 0; uint16_t idx; struct cli_bm_patt *p; const char *bp; char prefix; if(!root->bm_shift) return CL_CLEAN; if(length < BM_MIN_LENGTH) return CL_CLEAN; for(i = BM_MIN_LENGTH - BM_BLOCK_SIZE; i < length - BM_BLOCK_SIZE + 1; ) { idx = HASH(buffer[i], buffer[i + 1], buffer[i + 2]); shift = root->bm_shift[idx]; if(shift == 0) { prefix = buffer[i - BM_MIN_LENGTH + BM_BLOCK_SIZE]; p = root->bm_suffix[idx]; while(p && p->pattern[0] != prefix) p = p->next; while(p && p->pattern[0] == prefix) { off = i - BM_MIN_LENGTH + BM_BLOCK_SIZE; bp = buffer + off; #ifdef BM_TEST_OFFSET if(bp[BM_TEST_OFFSET] != p->pattern[BM_TEST_OFFSET]) { p = p->next; continue; } #endif found = 1; for(j = 0; j < p->length && off < length; j++, off++) { if(bp[j] != p->pattern[j]) { found = 0; break; } } if(found && p->length == j) { if(p->target || p->offset) { off = offset + i - BM_MIN_LENGTH + BM_BLOCK_SIZE; if((fd == -1 && !ftype) || !cli_validatesig(p->target, ftype, p->offset, off, fd, p->virname)) { p = p->next; continue; } } if(virname) *virname = p->virname; return CL_VIRUS; } p = p->next; } shift = 1; } i += shift; } return 0; }