mirror of
https://github.com/Cisco-Talos/clamav.git
synced 2025-10-19 10:23:17 +00:00
Fix byte-compare subsignature premature alert
The byte compare feature in logical signatures will cause the rule to alert if it successfully matches regardless of the rest of the logical signature. An easy way to test this is with a logical signature that has two bcomp subsignatures and requires both to match for the rule to alert. In the following example, we have 4 signatures where - the first will match both bcomp subsigs. - the second will match neither. - the last two match just one bcomp subsig. In an --allmatch test, you'll find that the 3 of these match, with the first one matching *twice*, once for each bcomp subsig. test.ldb: ``` bcomp.both;Engine:51-255,Target:0;0&1&2&3;4141;0(>>5#hb2#=123);4242;2(>>5#hb2#=255) bcomp.neither;Engine:51-255,Target:0;0&1&2&3;4141;0(>>5#hb2#=124);4242;2(>>5#hb2#=254) bcomp.second;Engine:51-255,Target:0;0&1&2&3;4141;0(>>5#hb2#=124);4242;2(>>5#hb2#=255) bcomp.first;Engine:51-255,Target:0;0&1&2&3;4141;0(>>5#hb2#=123);4242;2(>>5#hb2#=254) ``` test.sample: ``` AA = 7B; BB = FF ``` You can also try a similar test to compare the behavior with regular ac-pattern-match subsigs with this lsig-test.ldb: ``` pattern.both;Engine:51-255,Target:0;0&1;4141;4242 pattern.neither;Engine:51-255,Target:0;0&1;4140;4241 pattern.second;Engine:51-255,Target:0;0&1;4140;4242 pattern.first;Engine:51-255,Target:0;0&1;4141;4241 ``` This commit fixes the issue by incrementing the logical subsignature count for each bcomp subsig match instead of appending an alert for each bcomp match. Also removed call to `lsig_sub_matched()` that didn't do anything.
This commit is contained in:
parent
a21cc6dcd7
commit
2e55c901b1
3 changed files with 15 additions and 39 deletions
|
@ -457,13 +457,14 @@ cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, cons
|
|||
* @param ctx the clamav context struct
|
||||
*
|
||||
*/
|
||||
cl_error_t cli_bcomp_scanbuf(const unsigned char *buffer, size_t buffer_length, const char **virname, struct cli_ac_result **res, const struct cli_matcher *root, struct cli_ac_data *mdata, cli_ctx *ctx)
|
||||
cl_error_t cli_bcomp_scanbuf(const unsigned char *buffer, size_t buffer_length, struct cli_ac_result **res, const struct cli_matcher *root, struct cli_ac_data *mdata, cli_ctx *ctx)
|
||||
{
|
||||
|
||||
int64_t i = 0, val = 0, ret = CL_SUCCESS;
|
||||
size_t i;
|
||||
int val = 0;
|
||||
cl_error_t ret = CL_SUCCESS;
|
||||
cl_error_t bcomp_check = CL_SUCCESS;
|
||||
uint32_t lsigid, ref_subsigid;
|
||||
uint32_t offset = 0;
|
||||
uint8_t viruses_found = 0;
|
||||
struct cli_bcomp_meta *bcomp = NULL;
|
||||
struct cli_ac_result *newres = NULL;
|
||||
|
||||
|
@ -488,17 +489,11 @@ cl_error_t cli_bcomp_scanbuf(const unsigned char *buffer, size_t buffer_length,
|
|||
|
||||
/* verify the ref_subsigid */
|
||||
val = cli_ac_chklsig(subsigid, subsigid + strlen(subsigid), mdata->lsigcnt[bcomp->lsigid[1]], &evalcnt, &evalids, 0);
|
||||
|
||||
if (val != 1) {
|
||||
bcm_dbgmsg("cli_bcomp_scanbuf: could not verify a match for lsig reference subsigid (%s)\n", subsigid);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* ensures the referenced subsig matches as expected, and also ensures mdata has the needed offset */
|
||||
if ((ret = lsig_sub_matched(root, mdata, lsigid, ref_subsigid, CLI_OFF_NONE, 0))) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* grab the needed offset using from the last matched subsig offset matrix, i.e. the match performed above */
|
||||
if (mdata->lsigsuboff_last[lsigid]) {
|
||||
offset = mdata->lsigsuboff_last[lsigid][ref_subsigid];
|
||||
|
@ -507,7 +502,7 @@ cl_error_t cli_bcomp_scanbuf(const unsigned char *buffer, size_t buffer_length,
|
|||
continue;
|
||||
}
|
||||
} else {
|
||||
/* can't run lsig_sub_matched in sigtool, and mdata isn't populated so run the raw matcher stuffs */
|
||||
/* mdata isn't populated in sigtool so run the raw matcher stuffs */
|
||||
if (res) {
|
||||
newres = (struct cli_ac_result *)cli_calloc(1, sizeof(struct cli_ac_result));
|
||||
if (!newres) {
|
||||
|
@ -528,27 +523,16 @@ cl_error_t cli_bcomp_scanbuf(const unsigned char *buffer, size_t buffer_length,
|
|||
}
|
||||
|
||||
/* now we have all the pieces of the puzzle, so lets do our byte compare check */
|
||||
ret = cli_bcomp_compare_check(buffer, buffer_length, offset, bcomp);
|
||||
bcomp_check = cli_bcomp_compare_check(buffer, buffer_length, offset, bcomp);
|
||||
|
||||
/* set and append our lsig's virus name if the comparison came back positive */
|
||||
if (CL_VIRUS == ret) {
|
||||
viruses_found = 1;
|
||||
|
||||
if (virname) {
|
||||
*virname = bcomp->virname;
|
||||
}
|
||||
/* if we aren't scanning all, let's just exit here */
|
||||
if (!SCAN_ALLMATCHES) {
|
||||
break;
|
||||
} else {
|
||||
ret = cli_append_virus(ctx, (const char *)bcomp->virname);
|
||||
}
|
||||
/* Increase the lsig count for our subsig if the comparison came back positive.
|
||||
* Later, the lsig-eval will evaluate the logical condition, based on these counts
|
||||
* and will append the virus alert if the whole logical signature matches. */
|
||||
if (CL_VIRUS == bcomp_check) {
|
||||
mdata->lsigcnt[bcomp->lsigid[1]][bcomp->lsigid[2]]++;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == CL_SUCCESS && viruses_found) {
|
||||
return CL_VIRUS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue