converted sigopts from char string to uint8_t

remotes/push_mirror/klin/altstr-yara
Kevin Lin 10 years ago
parent a98b86c3a7
commit dc70379a09
  1. 32
      libclamav/matcher-ac.c
  2. 13
      libclamav/matcher-ac.h
  3. 94
      libclamav/readdb.c
  4. 2
      libclamav/readdb.h
  5. 16
      unit_tests/check_matchers.c

@ -260,7 +260,7 @@ static int cli_ac_addpatt_recursive(struct cli_matcher *root, struct cli_ac_patt
/* if pattern is nocase, we need to enumerate all the combinations if applicable
* it's why this function was re-written to be recursive
*/
if(pattern->nocase && isalpha(pattern->pattern[i] & 0xff)) {
if((pattern->sigopts & ACPATT_OPTION_NOCASE) && isalpha(pattern->pattern[i] & 0xff)) {
next = pt->trans[cli_nocasei((unsigned char) (pattern->pattern[i] & 0xff))];
if(!next)
next = add_new_node(root, i, len);
@ -1637,12 +1637,12 @@ static int qcompare(const void *a, const void *b)
}
/* FIXME: clean up the code */
int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hexsig, const char *sigopts, uint32_t sigid, uint16_t parts, uint16_t partno, uint16_t rtype, uint16_t type, uint32_t mindist, uint32_t maxdist, const char *offset, const uint32_t *lsigid, unsigned int options)
int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hexsig, uint8_t sigopts, uint32_t sigid, uint16_t parts, uint16_t partno, uint16_t rtype, uint16_t type, uint32_t mindist, uint32_t maxdist, const char *offset, const uint32_t *lsigid, unsigned int options)
{
struct cli_ac_patt *new;
char *pt, *pt2, *hex = NULL, *hexcpy = NULL;
uint16_t i, j, ppos = 0, pend, *dec, nzpos = 0;
uint8_t wprefix = 0, zprefix = 1, plen = 0, nzplen = 0, nocase = 0;
uint8_t wprefix = 0, zprefix = 1, plen = 0, nzplen = 0;
struct cli_ac_special *newspecial, *specialpt, **newtable;
int ret, error = CL_SUCCESS;
@ -1657,22 +1657,6 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex
return CL_EMALFDB;
}
if (sigopts) {
i = 0;
while (sigopts[i] != '\0') {
switch (sigopts[i]) {
case 'i':
nocase = 1;
break;
default:
cli_errmsg("cli_ac_addsig: Signature for %s uses invalid option: %02x\n", virname, sigopts[i]);
return CL_EMALFDB;
}
i++;
}
}
if((new = (struct cli_ac_patt *) mpool_calloc(root->mempool, 1, sizeof(struct cli_ac_patt))) == NULL)
return CL_EMEM;
@ -1741,7 +1725,7 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex
break;
}
if(nocase && ((*dec & CLI_MATCH_METADATA) == CLI_MATCH_CHAR))
if((sigopts & ACPATT_OPTION_NOCASE) && ((*dec & CLI_MATCH_METADATA) == CLI_MATCH_CHAR))
new->ch[i] = cli_nocase(*dec) | CLI_MATCH_NOCASE;
else
new->ch[i] = *dec;
@ -1757,7 +1741,7 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex
break;
}
if(nocase && ((*dec & CLI_MATCH_METADATA) == CLI_MATCH_CHAR))
if((sigopts & ACPATT_OPTION_NOCASE) && ((*dec & CLI_MATCH_METADATA) == CLI_MATCH_CHAR))
new->ch[i] = cli_nocase(*dec) | CLI_MATCH_NOCASE;
else
new->ch[i] = *dec;
@ -1997,9 +1981,9 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex
new->length = strlen(hex ? hex : hexsig) / 2;
free(hex);
/* setting nocase match; TODO - move this to cli_realhex2ui and adjust for nocase, alter MATCH_CHAR too */
if (nocase) {
new->nocase = 1;
new->sigopts = sigopts;
/* setting nocase match; TODO - move this to cli_realhex2ui and adjust for nocase */
if (sigopts & ACPATT_OPTION_NOCASE) {
for (i = 0; i < new->length; ++i)
if ((new->pattern[i] & CLI_MATCH_METADATA) == CLI_MATCH_CHAR) {
new->pattern[i] = cli_nocase(new->pattern[i] & 0xff);

@ -34,9 +34,12 @@
#define AC_SCAN_VIR 1
#define AC_SCAN_FT 2
/* AC trie options */
#define AC_OPTION_NOOPTS 0x0
#define AC_OPTION_NOCASE 0x1
/* Pattern options */
#define ACPATT_OPTION_NOOPTS 0x00
#define ACPATT_OPTION_NOCASE 0x01
#define ACPATT_OPTION_FULLWORD 0x02
#define ACPATT_OPTION_WIDE 0x04
#define ACPATT_OPTION_ASCII 0x08
struct cli_ac_data {
int32_t ***offmatrix;
@ -73,7 +76,7 @@ struct cli_ac_patt {
uint32_t offdata[4], offset_min, offset_max;
uint32_t boundary;
uint8_t depth;
uint8_t nocase;
uint8_t sigopts;
};
struct cli_ac_list {
@ -109,6 +112,6 @@ int cli_ac_buildtrie(struct cli_matcher *root);
int cli_ac_init(struct cli_matcher *root, uint8_t mindepth, uint8_t maxdepth, uint8_t dconf_prefiltering);
int cli_ac_caloff(const struct cli_matcher *root, struct cli_ac_data *data, const struct cli_target_info *info);
void cli_ac_free(struct cli_matcher *root);
int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hexsig, const char *sigopts, uint32_t sigid, uint16_t parts, uint16_t partno, uint16_t rtype, uint16_t type, uint32_t mindist, uint32_t maxdist, const char *offset, const uint32_t *lsigid, unsigned int options);
int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hexsig, uint8_t sigopts, uint32_t sigid, uint16_t parts, uint16_t partno, uint16_t rtype, uint16_t type, uint32_t mindist, uint32_t maxdist, const char *offset, const uint32_t *lsigid, unsigned int options);
#endif

@ -116,7 +116,7 @@ char *cli_virname(const char *virname, unsigned int official)
}
#define PCRE_TOKENS 4
int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hexsig, const char *sigopts, uint16_t rtype, uint16_t type, const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options)
int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hexsig, uint8_t sigopts, uint16_t rtype, uint16_t type, const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options)
{
struct cli_bm_patt *bm_new;
char *pt, *hexcpy, *start, *n, l, r;
@ -224,10 +224,37 @@ int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hex
#endif
} else { /* get option-ed */
/* get NULL-ed */
char *opt = end+1;
uint8_t sigopts = 0;
*end = '\0';
while (*opt != '\0') {
switch (*opt) {
case 'i':
sigopts |= ACPATT_OPTION_NOCASE;
break;
case 'f':
sigopts |= ACPATT_OPTION_FULLWORD;
break;
case 'w':
sigopts |= ACPATT_OPTION_WIDE;
break;
case 'a':
sigopts |= ACPATT_OPTION_ASCII;
break;
default:
cli_errmsg("cli_parse_add: Signature for %s uses invalid option: %02x\n", virname, *opt);
return CL_EMALFDB;
}
opt++;
}
/* TODO - other option handling */
/* get called */
ret = cli_parse_add(root, virname, hexcpy, end+1, rtype, type, offset, target, lsigid, options);
ret = cli_parse_add(root, virname, hexcpy, sigopts, rtype, type, offset, target, lsigid, options);
free(hexcpy);
return ret;
}
@ -663,7 +690,7 @@ static int cli_loaddb(FILE *fs, struct cl_engine *engine, unsigned int *signo, u
if(*pt == '=') continue;
if((ret = cli_parse_add(root, start, pt, NULL, 0, 0, "*", 0, NULL, options))) {
if((ret = cli_parse_add(root, start, pt, 0, 0, 0, "*", 0, NULL, options))) {
cli_dbgmsg("cli_loaddb: cli_parse_add failed on line %d\n", line);
ret = CL_EMALFDB;
break;
@ -1063,7 +1090,7 @@ static int cli_loadndb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
offset = tokens[2];
sig = tokens[3];
if((ret = cli_parse_add(root, virname, sig, NULL, 0, 0, offset, target, NULL, options))) {
if((ret = cli_parse_add(root, virname, sig, 0, 0, 0, offset, target, NULL, options))) {
ret = CL_EMALFDB;
break;
}
@ -1520,7 +1547,7 @@ static int load_oneldb(char *buffer, int chkpua, struct cl_engine *engine, unsig
sig = tokens[3 + i];
}
if((ret = cli_parse_add(root, virname, sig, NULL, 0, 0, offset, target, lsigid, options)))
if((ret = cli_parse_add(root, virname, sig, 0, 0, 0, offset, target, lsigid, options)))
return ret;
if(sig[0] == '$' && i) {
@ -1798,7 +1825,7 @@ static int cli_loadftm(FILE *fs, struct cl_engine *engine, unsigned int options,
magictype = atoi(tokens[0]);
if(magictype == 1) { /* A-C */
if((ret = cli_parse_add(engine->root[0], tokens[3], tokens[2], NULL, rtype, type, tokens[1], 0, NULL, options)))
if((ret = cli_parse_add(engine->root[0], tokens[3], tokens[2], 0, rtype, type, tokens[1], 0, NULL, options)))
break;
} else if ((magictype == 0) || (magictype == 4)) { /* memcmp() */
@ -2863,7 +2890,7 @@ static inline void free_yararule(YR_RULE *rule)
struct cli_ytable_entry {
char *offset;
char *hexstr;
char *sigopts;
uint8_t sigopts;
};
struct cli_ytable {
@ -2896,22 +2923,23 @@ static int ytable_add_attrib(struct cli_ytable *ytable, const char *hexsig, cons
}
if (type) {
/* append to existing */
if (!ytable->table[lookup]->sigopts) {
ytable->table[lookup]->sigopts = cli_strdup(value);
if (!ytable->table[lookup]->sigopts) {
cli_yaramsg("ytable_add_attrib: ran out of memory for sigopts\n");
return CL_EMEM;
}
} else {
size_t len = strlen(ytable->table[lookup]->sigopts);
size_t newsize = strlen(value) + len + 1;
ytable->table[lookup]->sigopts = cli_realloc(ytable->table[lookup]->sigopts, newsize);
if (!ytable->table[lookup]->sigopts) {
cli_yaramsg("ytable_add_attrib: ran out of memory for sigopts\n");
return CL_EMEM;
}
snprintf(ytable->table[lookup]->sigopts+len, newsize-len, "%s", value);
/* add to sigopts */
switch (*value) {
case 'i':
ytable->table[lookup]->sigopts |= ACPATT_OPTION_NOCASE;
break;
case 'f':
ytable->table[lookup]->sigopts |= ACPATT_OPTION_FULLWORD;
break;
case 'w':
ytable->table[lookup]->sigopts |= ACPATT_OPTION_WIDE;
break;
case 'a':
ytable->table[lookup]->sigopts |= ACPATT_OPTION_ASCII;
break;
default:
cli_yaramsg("ytable_add_attrib: invalid sigopt %02x\n", *value);
return CL_EARG;
}
}
else {
@ -2987,7 +3015,6 @@ static void ytable_delete(struct cli_ytable *ytable)
for (i = 0; i < ytable->tbl_cnt; ++i) {
free(ytable->table[i]->offset);
free(ytable->table[i]->hexstr);
free(ytable->table[i]->sigopts);
free(ytable->table[i]);
}
free(ytable->table);
@ -3184,34 +3211,27 @@ static int load_oneyara(YR_RULE *rule, struct cl_engine *engine, unsigned int op
}
if (STRING_IS_ASCII(string)) {
cli_yaramsg("STRING_IS_ASCII %s\n", STRING_IS_SINGLE_MATCH(string) ? "yes" : "no");
/* what is ascii, but another way to state the same? */
if ((ret = ytable_add_attrib(&ytable, NULL, "a", 1)) != CL_SUCCESS) {
cli_yaramsg("load_oneyara: failed to add 'ascii' sigopt\n");
str_error++;
break;
}
}
if (STRING_IS_WIDE(string)) {
/* support is not implemented, caught by cli_ac_addsig() */
/* might want to redefine the string here or something */
cli_yaramsg("STRING_IS_WIDE %s\n", STRING_IS_SINGLE_MATCH(string) ? "yes" : "no");
#ifdef YARA_FINISHED
if ((ret = ytable_add_attrib(&ytable, NULL, "w", 1)) != CL_SUCCESS) {
cli_yaramsg("load_oneyara: failed to add 'wide' sigopt\n");
str_error++;
break;
}
#else
cli_warnmsg("load_oneyara: yara support is incomplete, 'wide' keyword is unsupported\n");
#endif
}
if (STRING_IS_FULL_WORD(string)) {
/* support is not implemented, caught by cli_ac_addsig() */
cli_yaramsg("STRING_IS_FULL_WORD %s\n", STRING_IS_SINGLE_MATCH(string) ? "yes" : "no");
#ifdef YARA_FINISHED
if ((ret = ytable_add_attrib(&ytable, NULL, "f", 1)) != CL_SUCCESS) {
cli_yaramsg("load_oneyara: failed to add 'fullword' sigopt\n");
str_error++;
break;
}
#else
cli_warnmsg("load_oneyara: yara support is incomplete, 'fullword' keyword is unsupported\n");
#endif
}
#ifdef YARA_FINISHED
@ -3379,7 +3399,7 @@ static int load_oneyara(YR_RULE *rule, struct cl_engine *engine, unsigned int op
for (i = 0; i < ytable.tbl_cnt; ++i) {
lsigid[1] = i;
cli_yaramsg("%d: [%s] [%s] [%s]\n", i, ytable.table[i]->hexstr, ytable.table[i]->offset, ytable.table[i]->sigopts);
cli_yaramsg("%d: [%s] [%s] [%x]\n", i, ytable.table[i]->hexstr, ytable.table[i]->offset, ytable.table[i]->sigopts);
if((ret = cli_parse_add(root, rule->id, ytable.table[i]->hexstr, ytable.table[i]->sigopts, 0, 0, ytable.table[i]->offset, target, lsigid, options)) != CL_SUCCESS) {
yara_malform++;

@ -69,7 +69,7 @@
char *cli_virname(const char *virname, unsigned int official);
int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hexsig, const char *sigopts, uint16_t rtype, uint16_t type, const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options);
int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hexsig, uint8_t sigopts, uint16_t rtype, uint16_t type, const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options);
int cli_load(const char *filename, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio);

@ -99,7 +99,7 @@ START_TEST (test_ac_scanbuff) {
for(i = 0; ac_testdata[i].data; i++) {
ret = cli_parse_add(root, ac_testdata[i].virname, ac_testdata[i].hexsig, NULL, 0, 0, "*", 0, NULL, 0);
ret = cli_parse_add(root, ac_testdata[i].virname, ac_testdata[i].hexsig, 0, 0, 0, "*", 0, NULL, 0);
fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed");
}
@ -138,11 +138,11 @@ START_TEST (test_bm_scanbuff) {
ret = cli_bm_init(root);
fail_unless(ret == CL_SUCCESS, "cli_bm_init() failed");
ret = cli_parse_add(root, "Sig1", "deadbabe", NULL, 0, 0, "*", 0, NULL, 0);
ret = cli_parse_add(root, "Sig1", "deadbabe", 0, 0, 0, "*", 0, NULL, 0);
fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed");
ret = cli_parse_add(root, "Sig2", "deadbeef", NULL, 0, 0, "*", 0, NULL, 0);
ret = cli_parse_add(root, "Sig2", "deadbeef", 0, 0, 0, "*", 0, NULL, 0);
fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed");
ret = cli_parse_add(root, "Sig3", "babedead", NULL, 0, 0, "*", 0, NULL, 0);
ret = cli_parse_add(root, "Sig3", "babedead", 0, 0, 0, "*", 0, NULL, 0);
fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed");
ret = cli_bm_scanbuff((const unsigned char*)"blah\xde\xad\xbe\xef", 12, &virname, NULL, root, 0, NULL, NULL, NULL);
@ -169,7 +169,7 @@ START_TEST (test_ac_scanbuff_allscan) {
for(i = 0; ac_testdata[i].data; i++) {
ret = cli_parse_add(root, ac_testdata[i].virname, ac_testdata[i].hexsig, NULL, 0, 0, "*", 0, NULL, 0);
ret = cli_parse_add(root, ac_testdata[i].virname, ac_testdata[i].hexsig, 0, 0, 0, "*", 0, NULL, 0);
fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed");
}
@ -214,11 +214,11 @@ START_TEST (test_bm_scanbuff_allscan) {
ret = cli_bm_init(root);
fail_unless(ret == CL_SUCCESS, "cli_bm_init() failed");
ret = cli_parse_add(root, "Sig1", "deadbabe", NULL, 0, 0, "*", 0, NULL, 0);
ret = cli_parse_add(root, "Sig1", "deadbabe", 0, 0, 0, "*", 0, NULL, 0);
fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed");
ret = cli_parse_add(root, "Sig2", "deadbeef", NULL, 0, 0, "*", 0, NULL, 0);
ret = cli_parse_add(root, "Sig2", "deadbeef", 0, 0, 0, "*", 0, NULL, 0);
fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed");
ret = cli_parse_add(root, "Sig3", "babedead", NULL, 0, 0, "*", 0, NULL, 0);
ret = cli_parse_add(root, "Sig3", "babedead", 0, 0, 0, "*", 0, NULL, 0);
fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed");
ret = cli_bm_scanbuff((const unsigned char*)"blah\xde\xad\xbe\xef", 12, &virname, NULL, root, 0, NULL, NULL, NULL);

Loading…
Cancel
Save