| ... | ... |
@@ -1,3 +1,7 @@ |
| 1 |
+Fri Aug 14 14:37:21 CEST 2009 (tk) |
|
| 2 |
+---------------------------------- |
|
| 3 |
+ * libclamav: improve handling of signature offsets |
|
| 4 |
+ |
|
| 1 | 5 |
Tue Aug 11 02:04:54 CEST 2009 (acab) |
| 2 | 6 |
------------------------------------ |
| 3 | 7 |
* libclamav/7z/Types.h: workaround "Byte" clash in lzma/7z (bb#805 - regression) |
| ... | ... |
@@ -25,6 +25,11 @@ |
| 25 | 25 |
#define CLI_DEFAULT_AC_MAXDEPTH 3 |
| 26 | 26 |
#define CLI_DEFAULT_AC_TRACKLEN 8 |
| 27 | 27 |
|
| 28 |
+#define CLI_DEFAULT_MOVETOAC_LEN 8 /* all static sigs shorter than |
|
| 29 |
+ * this value will automatically |
|
| 30 |
+ * go to AC instead of BM |
|
| 31 |
+ */ |
|
| 32 |
+ |
|
| 28 | 33 |
#define CLI_DEFAULT_LSIG_BUFSIZE 32768 |
| 29 | 34 |
#define CLI_DEFAULT_DBIO_BUFSIZE CLI_DEFAULT_LSIG_BUFSIZE + 1 |
| 30 | 35 |
|
| ... | ... |
@@ -176,7 +176,7 @@ cli_file_t cli_filetype2(int desc, const struct cl_engine *engine) |
| 176 | 176 |
if(cli_ac_initdata(&mdata, root->ac_partsigs, root->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)) |
| 177 | 177 |
return ret; |
| 178 | 178 |
|
| 179 |
- sret = cli_ac_scanbuff(buff, bread, NULL, NULL, NULL, engine->root[0], &mdata, 0, ret, desc, NULL, AC_SCAN_FT, NULL); |
|
| 179 |
+ sret = cli_ac_scanbuff(buff, bread, NULL, NULL, NULL, engine->root[0], &mdata, 0, ret, NULL, AC_SCAN_FT, NULL); |
|
| 180 | 180 |
|
| 181 | 181 |
cli_ac_freedata(&mdata); |
| 182 | 182 |
|
| ... | ... |
@@ -188,7 +188,7 @@ cli_file_t cli_filetype2(int desc, const struct cl_engine *engine) |
| 188 | 188 |
|
| 189 | 189 |
decoded = (unsigned char *) cli_utf16toascii((char *) buff, bread); |
| 190 | 190 |
if(decoded) {
|
| 191 |
- sret = cli_ac_scanbuff(decoded, strlen((char *) decoded), NULL, NULL, NULL, engine->root[0], &mdata, 0, CL_TYPE_TEXT_ASCII, desc, NULL, AC_SCAN_FT, NULL); |
|
| 191 |
+ sret = cli_ac_scanbuff(decoded, strlen((char *) decoded), NULL, NULL, NULL, engine->root[0], &mdata, 0, CL_TYPE_TEXT_ASCII, NULL, AC_SCAN_FT, NULL); |
|
| 192 | 192 |
free(decoded); |
| 193 | 193 |
if(sret == CL_TYPE_HTML) |
| 194 | 194 |
ret = CL_TYPE_HTML_UTF16; |
| ... | ... |
@@ -221,7 +221,7 @@ cli_file_t cli_filetype2(int desc, const struct cl_engine *engine) |
| 221 | 221 |
return ret; |
| 222 | 222 |
|
| 223 | 223 |
if(out_area.length > 0) {
|
| 224 |
- sret = cli_ac_scanbuff(decodedbuff, out_area.length, NULL, NULL, NULL, engine->root[0], &mdata, 0, 0, desc, NULL, AC_SCAN_FT, NULL); /* FIXME: can we use CL_TYPE_TEXT_ASCII instead of 0? */ |
|
| 224 |
+ sret = cli_ac_scanbuff(decodedbuff, out_area.length, NULL, NULL, NULL, engine->root[0], &mdata, 0, 0, NULL, AC_SCAN_FT, NULL); /* FIXME: can we use CL_TYPE_TEXT_ASCII instead of 0? */ |
|
| 225 | 225 |
if(sret == CL_TYPE_HTML) {
|
| 226 | 226 |
cli_dbgmsg("cli_filetype2: detected HTML signature in Unicode file\n");
|
| 227 | 227 |
/* htmlnorm is able to handle any unicode now, since it skips null chars */ |
| ... | ... |
@@ -1,5 +1,5 @@ |
| 1 | 1 |
/* |
| 2 |
- * Copyright (C) 2007-2008 Sourcefire, Inc. |
|
| 2 |
+ * Copyright (C) 2007-2009 Sourcefire, Inc. |
|
| 3 | 3 |
* |
| 4 | 4 |
* Authors: Tomasz Kojm |
| 5 | 5 |
* |
| ... | ... |
@@ -386,8 +386,6 @@ void cli_ac_free(struct cli_matcher *root) |
| 386 | 386 |
patt = root->ac_pattable[i]; |
| 387 | 387 |
mpool_free(root->mempool, patt->prefix ? patt->prefix : patt->pattern); |
| 388 | 388 |
mpool_free(root->mempool, patt->virname); |
| 389 |
- if(patt->offset) |
|
| 390 |
- mpool_free(root->mempool, patt->offset); |
|
| 391 | 389 |
if(patt->alt) |
| 392 | 390 |
mpool_ac_free_alt(root->mempool, patt); |
| 393 | 391 |
mpool_free(root->mempool, patt); |
| ... | ... |
@@ -395,6 +393,9 @@ void cli_ac_free(struct cli_matcher *root) |
| 395 | 395 |
if(root->ac_pattable) |
| 396 | 396 |
mpool_free(root->mempool, root->ac_pattable); |
| 397 | 397 |
|
| 398 |
+ if(root->ac_reloff) |
|
| 399 |
+ mpool_free(root->mempool, root->ac_reloff); |
|
| 400 |
+ |
|
| 398 | 401 |
for(i = 0; i < root->ac_nodes; i++) {
|
| 399 | 402 |
if(!IS_LEAF(root->ac_nodetable[i])) |
| 400 | 403 |
mpool_free(root->mempool, root->ac_nodetable[i]->trans); |
| ... | ... |
@@ -812,6 +813,31 @@ int cli_ac_initdata(struct cli_ac_data *data, uint32_t partsigs, uint32_t lsigs, |
| 812 | 812 |
return CL_SUCCESS; |
| 813 | 813 |
} |
| 814 | 814 |
|
| 815 |
+int cli_ac_caloff(struct cli_matcher *root, int fd) |
|
| 816 |
+{
|
|
| 817 |
+ int ret; |
|
| 818 |
+ unsigned int i; |
|
| 819 |
+ struct cli_ac_patt *patt; |
|
| 820 |
+ struct cli_target_info info; |
|
| 821 |
+ |
|
| 822 |
+ memset(&info, 0, sizeof(info)); |
|
| 823 |
+ for(i = 0; i < root->ac_reloff_num; i++) {
|
|
| 824 |
+ patt = root->ac_reloff[i]; |
|
| 825 |
+ if(fd == -1) {
|
|
| 826 |
+ patt->offset_min = CLI_OFF_NONE; |
|
| 827 |
+ } else if((ret = cli_caloff(NULL, &info, fd, root->type, patt->offdata, &patt->offset_min, &patt->offset_max))) {
|
|
| 828 |
+ cli_errmsg("cli_ac_caloff: Can't calculate relative offset in signature for %s\n", patt->virname);
|
|
| 829 |
+ if(info.exeinfo.section) |
|
| 830 |
+ free(info.exeinfo.section); |
|
| 831 |
+ return ret; |
|
| 832 |
+ } |
|
| 833 |
+ } |
|
| 834 |
+ if(info.exeinfo.section) |
|
| 835 |
+ free(info.exeinfo.section); |
|
| 836 |
+ |
|
| 837 |
+ return CL_SUCCESS; |
|
| 838 |
+} |
|
| 839 |
+ |
|
| 815 | 840 |
void cli_ac_freedata(struct cli_ac_data *data) |
| 816 | 841 |
{
|
| 817 | 842 |
uint32_t i; |
| ... | ... |
@@ -867,7 +893,7 @@ inline static int ac_addtype(struct cli_matched_type **list, cli_file_t type, of |
| 867 | 867 |
return CL_SUCCESS; |
| 868 | 868 |
} |
| 869 | 869 |
|
| 870 |
-int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, void **customdata, struct cli_ac_result **res, const struct cli_matcher *root, struct cli_ac_data *mdata, uint32_t offset, cli_file_t ftype, int fd, struct cli_matched_type **ftoffset, unsigned int mode, const cli_ctx *ctx) |
|
| 870 |
+int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, void **customdata, struct cli_ac_result **res, const struct cli_matcher *root, struct cli_ac_data *mdata, uint32_t offset, cli_file_t ftype, struct cli_matched_type **ftoffset, unsigned int mode, const cli_ctx *ctx) |
|
| 871 | 871 |
{
|
| 872 | 872 |
struct cli_ac_node *current; |
| 873 | 873 |
struct cli_ac_patt *patt, *pt; |
| ... | ... |
@@ -875,11 +901,9 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
| 875 | 875 |
uint16_t j; |
| 876 | 876 |
int32_t **offmatrix; |
| 877 | 877 |
uint8_t found; |
| 878 |
- struct cli_target_info info; |
|
| 879 | 878 |
int type = CL_CLEAN; |
| 880 | 879 |
struct cli_ac_result *newres; |
| 881 | 880 |
|
| 882 |
- |
|
| 883 | 881 |
if(!root->ac_root) |
| 884 | 882 |
return CL_CLEAN; |
| 885 | 883 |
|
| ... | ... |
@@ -888,7 +912,6 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
| 888 | 888 |
return CL_ENULLARG; |
| 889 | 889 |
} |
| 890 | 890 |
|
| 891 |
- memset(&info, 0, sizeof(info)); |
|
| 892 | 891 |
current = root->ac_root; |
| 893 | 892 |
|
| 894 | 893 |
for(i = 0; i < length; i++) {
|
| ... | ... |
@@ -902,24 +925,44 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
| 902 | 902 |
patt = current->list; |
| 903 | 903 |
while(patt) {
|
| 904 | 904 |
bp = i + 1 - patt->depth; |
| 905 |
- if(ac_findmatch(buffer, bp, length, patt, &matchend)) {
|
|
| 906 |
- pt = patt; |
|
| 905 |
+ pt = patt; |
|
| 906 |
+ /* |
|
| 907 |
+ while(pt) {
|
|
| 908 |
+ if((pt->type && !(mode & AC_SCAN_FT)) || (!pt->type && !(mode & AC_SCAN_VIR))) {
|
|
| 909 |
+ pt = pt->next_same; |
|
| 910 |
+ continue; |
|
| 911 |
+ } |
|
| 912 |
+ if(pt->offset_min == CLI_OFF_NONE) {
|
|
| 913 |
+ pt = pt->next_same; |
|
| 914 |
+ continue; |
|
| 915 |
+ } |
|
| 916 |
+ realoff = offset + bp - pt->prefix_length; |
|
| 917 |
+ if(pt->offset_min != CLI_OFF_ANY && (!pt->sigid || pt->partno == 1)) {
|
|
| 918 |
+ if(pt->offset_max > realoff || pt->offset_min < realoff) {
|
|
| 919 |
+ pt = pt->next_same; |
|
| 920 |
+ continue; |
|
| 921 |
+ } |
|
| 922 |
+ } |
|
| 923 |
+ break; |
|
| 924 |
+ } |
|
| 925 |
+ */ |
|
| 926 |
+ if(pt && ac_findmatch(buffer, bp, length, patt, &matchend)) {
|
|
| 907 | 927 |
while(pt) {
|
| 908 |
- |
|
| 909 | 928 |
if((pt->type && !(mode & AC_SCAN_FT)) || (!pt->type && !(mode & AC_SCAN_VIR))) {
|
| 910 | 929 |
pt = pt->next_same; |
| 911 | 930 |
continue; |
| 912 | 931 |
} |
| 913 |
- |
|
| 932 |
+ if(pt->offset_min == CLI_OFF_NONE) {
|
|
| 933 |
+ pt = pt->next_same; |
|
| 934 |
+ continue; |
|
| 935 |
+ } |
|
| 914 | 936 |
realoff = offset + bp - pt->prefix_length; |
| 915 |
- |
|
| 916 |
- if(pt->offset && (!pt->sigid || pt->partno == 1)) {
|
|
| 917 |
- if(!cli_validatesig(ftype, pt->offset, realoff, &info, fd, pt->virname)) {
|
|
| 937 |
+ if(pt->offset_min != CLI_OFF_ANY && (!pt->sigid || pt->partno == 1)) {
|
|
| 938 |
+ if(pt->offset_max > realoff || pt->offset_min < realoff) {
|
|
| 918 | 939 |
pt = pt->next_same; |
| 919 | 940 |
continue; |
| 920 | 941 |
} |
| 921 | 942 |
} |
| 922 |
- |
|
| 923 | 943 |
if(pt->sigid) { /* it's a partial signature */
|
| 924 | 944 |
|
| 925 | 945 |
if(pt->partno != 1 && (!mdata->offmatrix[pt->sigid - 1] || !mdata->offmatrix[pt->sigid - 1][pt->partno - 2][0])) {
|
| ... | ... |
@@ -931,8 +974,6 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
| 931 | 931 |
mdata->offmatrix[pt->sigid - 1] = cli_malloc(pt->parts * sizeof(int32_t *)); |
| 932 | 932 |
if(!mdata->offmatrix[pt->sigid - 1]) {
|
| 933 | 933 |
cli_errmsg("cli_ac_scanbuff: Can't allocate memory for mdata->offmatrix[%u]\n", pt->sigid - 1);
|
| 934 |
- if(info.exeinfo.section) |
|
| 935 |
- free(info.exeinfo.section); |
|
| 936 | 934 |
return CL_EMEM; |
| 937 | 935 |
} |
| 938 | 936 |
|
| ... | ... |
@@ -941,8 +982,6 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
| 941 | 941 |
cli_errmsg("cli_ac_scanbuff: Can't allocate memory for mdata->offmatrix[%u][0]\n", pt->sigid - 1);
|
| 942 | 942 |
free(mdata->offmatrix[pt->sigid - 1]); |
| 943 | 943 |
mdata->offmatrix[pt->sigid - 1] = NULL; |
| 944 |
- if(info.exeinfo.section) |
|
| 945 |
- free(info.exeinfo.section); |
|
| 946 | 944 |
return CL_EMEM; |
| 947 | 945 |
} |
| 948 | 946 |
memset(mdata->offmatrix[pt->sigid - 1][0], -1, pt->parts * (CLI_DEFAULT_AC_TRACKLEN + 1) * sizeof(int32_t)); |
| ... | ... |
@@ -981,25 +1020,17 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
| 981 | 981 |
} else if(found && pt->partno == pt->parts) {
|
| 982 | 982 |
if(pt->type) {
|
| 983 | 983 |
|
| 984 |
- if(pt->type == CL_TYPE_IGNORED && (!pt->rtype || ftype == pt->rtype)) {
|
|
| 985 |
- if(info.exeinfo.section) |
|
| 986 |
- free(info.exeinfo.section); |
|
| 987 |
- |
|
| 984 |
+ if(pt->type == CL_TYPE_IGNORED && (!pt->rtype || ftype == pt->rtype)) |
|
| 988 | 985 |
return CL_TYPE_IGNORED; |
| 989 |
- } |
|
| 990 | 986 |
|
| 991 | 987 |
if((pt->type > type || pt->type >= CL_TYPE_SFX || pt->type == CL_TYPE_MSEXE) && (!pt->rtype || ftype == pt->rtype)) {
|
| 992 | 988 |
cli_dbgmsg("Matched signature for file type %s\n", pt->virname);
|
| 993 | 989 |
type = pt->type; |
| 994 | 990 |
if(ftoffset && (!*ftoffset || (*ftoffset)->cnt < MAX_EMBEDDED_OBJ || type == CL_TYPE_ZIPSFX) && (type >= CL_TYPE_SFX || ((ftype == CL_TYPE_MSEXE || ftype == CL_TYPE_ZIP || ftype == CL_TYPE_MSOLE2) && type == CL_TYPE_MSEXE))) {
|
| 995 | 991 |
/* FIXME: we don't know which offset of the first part is the correct one */ |
| 996 |
- for(j = 1; j <= CLI_DEFAULT_AC_TRACKLEN && offmatrix[0][j] != -1; j++) {
|
|
| 997 |
- if(ac_addtype(ftoffset, type, offmatrix[pt->parts - 1][j], ctx)) {
|
|
| 998 |
- if(info.exeinfo.section) |
|
| 999 |
- free(info.exeinfo.section); |
|
| 992 |
+ for(j = 1; j <= CLI_DEFAULT_AC_TRACKLEN && offmatrix[0][j] != -1; j++) |
|
| 993 |
+ if(ac_addtype(ftoffset, type, offmatrix[pt->parts - 1][j], ctx)) |
|
| 1000 | 994 |
return CL_EMEM; |
| 1001 |
- } |
|
| 1002 |
- } |
|
| 1003 | 995 |
} |
| 1004 | 996 |
|
| 1005 | 997 |
memset(offmatrix[0], -1, pt->parts * (CLI_DEFAULT_AC_TRACKLEN + 1) * sizeof(int32_t)); |
| ... | ... |
@@ -1016,11 +1047,8 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
| 1016 | 1016 |
|
| 1017 | 1017 |
if(res) {
|
| 1018 | 1018 |
newres = (struct cli_ac_result *) malloc(sizeof(struct cli_ac_result)); |
| 1019 |
- if(!newres) {
|
|
| 1020 |
- if(info.exeinfo.section) |
|
| 1021 |
- free(info.exeinfo.section); |
|
| 1019 |
+ if(!newres) |
|
| 1022 | 1020 |
return CL_EMEM; |
| 1023 |
- } |
|
| 1024 | 1021 |
newres->virname = pt->virname; |
| 1025 | 1022 |
newres->customdata = pt->customdata; |
| 1026 | 1023 |
newres->next = *res; |
| ... | ... |
@@ -1033,10 +1061,6 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
| 1033 | 1033 |
*virname = pt->virname; |
| 1034 | 1034 |
if(customdata) |
| 1035 | 1035 |
*customdata = pt->customdata; |
| 1036 |
- |
|
| 1037 |
- if(info.exeinfo.section) |
|
| 1038 |
- free(info.exeinfo.section); |
|
| 1039 |
- |
|
| 1040 | 1036 |
return CL_VIRUS; |
| 1041 | 1037 |
} |
| 1042 | 1038 |
} |
| ... | ... |
@@ -1044,22 +1068,16 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
| 1044 | 1044 |
|
| 1045 | 1045 |
} else { /* old type signature */
|
| 1046 | 1046 |
if(pt->type) {
|
| 1047 |
- if(pt->type == CL_TYPE_IGNORED && (!pt->rtype || ftype == pt->rtype)) {
|
|
| 1048 |
- if(info.exeinfo.section) |
|
| 1049 |
- free(info.exeinfo.section); |
|
| 1050 |
- |
|
| 1047 |
+ if(pt->type == CL_TYPE_IGNORED && (!pt->rtype || ftype == pt->rtype)) |
|
| 1051 | 1048 |
return CL_TYPE_IGNORED; |
| 1052 |
- } |
|
| 1049 |
+ |
|
| 1053 | 1050 |
if((pt->type > type || pt->type >= CL_TYPE_SFX || pt->type == CL_TYPE_MSEXE) && (!pt->rtype || ftype == pt->rtype)) {
|
| 1054 | 1051 |
cli_dbgmsg("Matched signature for file type %s at %u\n", pt->virname, realoff);
|
| 1055 | 1052 |
type = pt->type; |
| 1056 | 1053 |
if(ftoffset && (!*ftoffset || (*ftoffset)->cnt < MAX_EMBEDDED_OBJ || type == CL_TYPE_ZIPSFX) && (type >= CL_TYPE_SFX || ((ftype == CL_TYPE_MSEXE || ftype == CL_TYPE_ZIP || ftype == CL_TYPE_MSOLE2) && type == CL_TYPE_MSEXE))) {
|
| 1057 | 1054 |
|
| 1058 |
- if(ac_addtype(ftoffset, type, realoff, ctx)) {
|
|
| 1059 |
- if(info.exeinfo.section) |
|
| 1060 |
- free(info.exeinfo.section); |
|
| 1055 |
+ if(ac_addtype(ftoffset, type, realoff, ctx)) |
|
| 1061 | 1056 |
return CL_EMEM; |
| 1062 |
- } |
|
| 1063 | 1057 |
} |
| 1064 | 1058 |
} |
| 1065 | 1059 |
} else {
|
| ... | ... |
@@ -1071,11 +1089,8 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
| 1071 | 1071 |
|
| 1072 | 1072 |
if(res) {
|
| 1073 | 1073 |
newres = (struct cli_ac_result *) malloc(sizeof(struct cli_ac_result)); |
| 1074 |
- if(!newres) {
|
|
| 1075 |
- if(info.exeinfo.section) |
|
| 1076 |
- free(info.exeinfo.section); |
|
| 1074 |
+ if(!newres) |
|
| 1077 | 1075 |
return CL_EMEM; |
| 1078 |
- } |
|
| 1079 | 1076 |
newres->virname = pt->virname; |
| 1080 | 1077 |
newres->customdata = pt->customdata; |
| 1081 | 1078 |
newres->next = *res; |
| ... | ... |
@@ -1088,10 +1103,6 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
| 1088 | 1088 |
*virname = pt->virname; |
| 1089 | 1089 |
if(customdata) |
| 1090 | 1090 |
*customdata = pt->customdata; |
| 1091 |
- |
|
| 1092 |
- if(info.exeinfo.section) |
|
| 1093 |
- free(info.exeinfo.section); |
|
| 1094 |
- |
|
| 1095 | 1091 |
return CL_VIRUS; |
| 1096 | 1092 |
} |
| 1097 | 1093 |
} |
| ... | ... |
@@ -1104,9 +1115,6 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
| 1104 | 1104 |
} |
| 1105 | 1105 |
} |
| 1106 | 1106 |
|
| 1107 |
- if(info.exeinfo.section) |
|
| 1108 |
- free(info.exeinfo.section); |
|
| 1109 |
- |
|
| 1110 | 1107 |
return (mode & AC_SCAN_FT) ? type : CL_CLEAN; |
| 1111 | 1108 |
} |
| 1112 | 1109 |
|
| ... | ... |
@@ -1445,26 +1453,32 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex |
| 1445 | 1445 |
if(new->lsigid[0]) |
| 1446 | 1446 |
root->ac_lsigtable[new->lsigid[1]]->virname = new->virname; |
| 1447 | 1447 |
|
| 1448 |
- if(offset) {
|
|
| 1449 |
- new->offset = cli_mpool_strdup(root->mempool, offset); |
|
| 1450 |
- if(!new->offset) {
|
|
| 1451 |
- mpool_free(root->mempool, new->prefix ? new->prefix : new->pattern); |
|
| 1452 |
- mpool_ac_free_alt(root->mempool, new); |
|
| 1453 |
- mpool_free(root->mempool, new->virname); |
|
| 1454 |
- mpool_free(root->mempool, new); |
|
| 1455 |
- return CL_EMEM; |
|
| 1456 |
- } |
|
| 1448 |
+ ret = cli_caloff(offset, NULL, -1, root->type, new->offdata, &new->offset_min, &new->offset_max); |
|
| 1449 |
+ if(ret != CL_SUCCESS) {
|
|
| 1450 |
+ mpool_free(root->mempool, new->prefix ? new->prefix : new->pattern); |
|
| 1451 |
+ mpool_ac_free_alt(root->mempool, new); |
|
| 1452 |
+ mpool_free(root->mempool, new->virname); |
|
| 1453 |
+ mpool_free(root->mempool, new); |
|
| 1454 |
+ return ret; |
|
| 1457 | 1455 |
} |
| 1458 | 1456 |
|
| 1459 | 1457 |
if((ret = cli_ac_addpatt(root, new))) {
|
| 1460 | 1458 |
mpool_free(root->mempool, new->prefix ? new->prefix : new->pattern); |
| 1461 | 1459 |
mpool_free(root->mempool, new->virname); |
| 1462 | 1460 |
mpool_ac_free_alt(root->mempool, new); |
| 1463 |
- if(new->offset) |
|
| 1464 |
- mpool_free(root->mempool, new->offset); |
|
| 1465 | 1461 |
mpool_free(root->mempool, new); |
| 1466 | 1462 |
return ret; |
| 1467 | 1463 |
} |
| 1468 | 1464 |
|
| 1465 |
+ if(new->offdata[0] != CLI_OFF_ANY && new->offdata[0] != CLI_OFF_ABSOLUTE) {
|
|
| 1466 |
+ root->ac_reloff = (struct cli_ac_patt **) mpool_realloc2(root->mempool, root->ac_reloff, (root->ac_reloff_num + 1) * sizeof(struct cli_ac_patt *)); |
|
| 1467 |
+ if(!root->ac_reloff) {
|
|
| 1468 |
+ cli_errmsg("cli_ac_addsig: Can't allocate memory for root->ac_reloff\n");
|
|
| 1469 |
+ return CL_EMEM; |
|
| 1470 |
+ } |
|
| 1471 |
+ root->ac_reloff[root->ac_reloff_num] = new; |
|
| 1472 |
+ root->ac_reloff_num++; |
|
| 1473 |
+ } |
|
| 1474 |
+ |
|
| 1469 | 1475 |
return CL_SUCCESS; |
| 1470 | 1476 |
} |
| ... | ... |
@@ -1,5 +1,5 @@ |
| 1 | 1 |
/* |
| 2 |
- * Copyright (C) 2007-2008 Sourcefire, Inc. |
|
| 2 |
+ * Copyright (C) 2007-2009 Sourcefire, Inc. |
|
| 3 | 3 |
* |
| 4 | 4 |
* Authors: Tomasz Kojm |
| 5 | 5 |
* |
| ... | ... |
@@ -50,7 +50,7 @@ struct cli_ac_patt {
|
| 50 | 50 |
uint32_t sigid; |
| 51 | 51 |
uint32_t lsigid[3]; |
| 52 | 52 |
uint16_t ch[2]; |
| 53 |
- char *virname, *offset; |
|
| 53 |
+ char *virname; |
|
| 54 | 54 |
void *customdata; |
| 55 | 55 |
uint16_t ch_mindist[2]; |
| 56 | 56 |
uint16_t ch_maxdist[2]; |
| ... | ... |
@@ -59,6 +59,7 @@ struct cli_ac_patt {
|
| 59 | 59 |
struct cli_ac_patt *next, *next_same; |
| 60 | 60 |
uint8_t depth; |
| 61 | 61 |
uint16_t rtype, type; |
| 62 |
+ uint32_t offdata[4], offset_min, offset_max; |
|
| 62 | 63 |
}; |
| 63 | 64 |
|
| 64 | 65 |
struct cli_ac_node {
|
| ... | ... |
@@ -81,9 +82,10 @@ int cli_ac_addpatt(struct cli_matcher *root, struct cli_ac_patt *pattern); |
| 81 | 81 |
int cli_ac_initdata(struct cli_ac_data *data, uint32_t partsigs, uint32_t lsigs, uint8_t tracklen); |
| 82 | 82 |
int cli_ac_chklsig(const char *expr, const char *end, uint32_t *lsigcnt, unsigned int *cnt, uint64_t *ids, unsigned int parse_only); |
| 83 | 83 |
void cli_ac_freedata(struct cli_ac_data *data); |
| 84 |
-int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, void **customdata, struct cli_ac_result **res, const struct cli_matcher *root, struct cli_ac_data *mdata, uint32_t offset, cli_file_t ftype, int fd, struct cli_matched_type **ftoffset, unsigned int mode, const cli_ctx *ctx); |
|
| 84 |
+int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, void **customdata, struct cli_ac_result **res, const struct cli_matcher *root, struct cli_ac_data *mdata, uint32_t offset, cli_file_t ftype, struct cli_matched_type **ftoffset, unsigned int mode, const cli_ctx *ctx); |
|
| 85 | 85 |
int cli_ac_buildtrie(struct cli_matcher *root); |
| 86 | 86 |
int cli_ac_init(struct cli_matcher *root, uint8_t mindepth, uint8_t maxdepth); |
| 87 |
+int cli_ac_caloff(struct cli_matcher *root, int fd); |
|
| 87 | 88 |
void cli_ac_free(struct cli_matcher *root); |
| 88 | 89 |
int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hexsig, 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); |
| 89 | 90 |
|
| ... | ... |
@@ -1,5 +1,5 @@ |
| 1 | 1 |
/* |
| 2 |
- * Copyright (C) 2007-2008 Sourcefire, Inc. |
|
| 2 |
+ * Copyright (C) 2007-2009 Sourcefire, Inc. |
|
| 3 | 3 |
* |
| 4 | 4 |
* Authors: Tomasz Kojm |
| 5 | 5 |
* |
| ... | ... |
@@ -38,11 +38,12 @@ |
| 38 | 38 |
#define BM_BLOCK_SIZE 3 |
| 39 | 39 |
#define HASH(a,b,c) (211 * a + 37 * b + c) |
| 40 | 40 |
|
| 41 |
-int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern) |
|
| 41 |
+int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern, const char *offset) |
|
| 42 | 42 |
{
|
| 43 | 43 |
uint16_t idx, i; |
| 44 | 44 |
const unsigned char *pt = pattern->pattern; |
| 45 | 45 |
struct cli_bm_patt *prev, *next = NULL; |
| 46 |
+ int ret; |
|
| 46 | 47 |
|
| 47 | 48 |
|
| 48 | 49 |
if(pattern->length < BM_MIN_LENGTH) {
|
| ... | ... |
@@ -50,6 +51,13 @@ int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern) |
| 50 | 50 |
return CL_EMALFDB; |
| 51 | 51 |
} |
| 52 | 52 |
|
| 53 |
+ if((ret = cli_caloff(offset, NULL, -1, root->type, pattern->offdata, &pattern->offset_min, &pattern->offset_max))) {
|
|
| 54 |
+ cli_errmsg("cli_bm_addpatt: Can't calculate offset for signature %s\n", pattern->virname);
|
|
| 55 |
+ return ret; |
|
| 56 |
+ } |
|
| 57 |
+ if(pattern->offdata[0] != CLI_OFF_ANY && pattern->offdata[0] != CLI_OFF_ABSOLUTE) |
|
| 58 |
+ root->bm_reloff_num++; |
|
| 59 |
+ |
|
| 53 | 60 |
#if BM_MIN_LENGTH == BM_BLOCK_SIZE |
| 54 | 61 |
/* try to load balance bm_suffix (at the cost of bm_shift) */ |
| 55 | 62 |
for(i = 0; i < pattern->length - BM_BLOCK_SIZE + 1; i++) {
|
| ... | ... |
@@ -137,8 +145,6 @@ void cli_bm_free(struct cli_matcher *root) |
| 137 | 137 |
mpool_free(root->mempool, prev->pattern); |
| 138 | 138 |
if(prev->virname) |
| 139 | 139 |
mpool_free(root->mempool, prev->virname); |
| 140 |
- if(prev->offset) |
|
| 141 |
- mpool_free(root->mempool, prev->offset); |
|
| 142 | 140 |
mpool_free(root->mempool, prev); |
| 143 | 141 |
} |
| 144 | 142 |
} |
| ... | ... |
@@ -146,7 +152,7 @@ void cli_bm_free(struct cli_matcher *root) |
| 146 | 146 |
} |
| 147 | 147 |
} |
| 148 | 148 |
|
| 149 |
-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) |
|
| 149 |
+int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, int fd) |
|
| 150 | 150 |
{
|
| 151 | 151 |
uint32_t i, j, off; |
| 152 | 152 |
uint8_t found, pchain, shift; |
| ... | ... |
@@ -154,7 +160,8 @@ int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
| 154 | 154 |
struct cli_bm_patt *p; |
| 155 | 155 |
const unsigned char *bp, *pt; |
| 156 | 156 |
unsigned char prefix; |
| 157 |
- struct cli_target_info info; |
|
| 157 |
+ struct cli_target_info info; |
|
| 158 |
+ int ret; |
|
| 158 | 159 |
|
| 159 | 160 |
|
| 160 | 161 |
if(!root || !root->bm_shift) |
| ... | ... |
@@ -164,7 +171,6 @@ int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
| 164 | 164 |
return CL_CLEAN; |
| 165 | 165 |
|
| 166 | 166 |
memset(&info, 0, sizeof(info)); |
| 167 |
- |
|
| 168 | 167 |
for(i = BM_MIN_LENGTH - BM_BLOCK_SIZE; i < length - BM_BLOCK_SIZE + 1; ) {
|
| 169 | 168 |
idx = HASH(buffer[i], buffer[i + 1], buffer[i + 2]); |
| 170 | 169 |
shift = root->bm_shift[idx]; |
| ... | ... |
@@ -214,21 +220,26 @@ int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
| 214 | 214 |
} |
| 215 | 215 |
|
| 216 | 216 |
if(found && p->length + p->prefix_length == j) {
|
| 217 |
- |
|
| 218 |
- if(p->offset) {
|
|
| 217 |
+ if(p->offset_min != CLI_OFF_ANY) {
|
|
| 218 |
+ if(p->offdata[0] != CLI_OFF_ABSOLUTE) {
|
|
| 219 |
+ ret = cli_caloff(NULL, &info, fd, root->type, p->offdata, &p->offset_min, &p->offset_max); |
|
| 220 |
+ if(ret != CL_SUCCESS) {
|
|
| 221 |
+ cli_errmsg("cli_bm_scanbuff: Can't calculate relative offset in signature for %s\n", p->virname);
|
|
| 222 |
+ if(info.exeinfo.section) |
|
| 223 |
+ free(info.exeinfo.section); |
|
| 224 |
+ return ret; |
|
| 225 |
+ } |
|
| 226 |
+ } |
|
| 219 | 227 |
off = offset + i - p->prefix_length - BM_MIN_LENGTH + BM_BLOCK_SIZE; |
| 220 |
- if(!cli_validatesig(ftype, p->offset, off, &info, fd, p->virname)) {
|
|
| 228 |
+ if(p->offset_max > off || p->offset_min < off) {
|
|
| 221 | 229 |
p = p->next; |
| 222 | 230 |
continue; |
| 223 | 231 |
} |
| 224 | 232 |
} |
| 225 |
- |
|
| 226 | 233 |
if(virname) |
| 227 | 234 |
*virname = p->virname; |
| 228 |
- |
|
| 229 | 235 |
if(info.exeinfo.section) |
| 230 | 236 |
free(info.exeinfo.section); |
| 231 |
- |
|
| 232 | 237 |
return CL_VIRUS; |
| 233 | 238 |
} |
| 234 | 239 |
|
| ... | ... |
@@ -243,6 +254,5 @@ int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
| 243 | 243 |
|
| 244 | 244 |
if(info.exeinfo.section) |
| 245 | 245 |
free(info.exeinfo.section); |
| 246 |
- |
|
| 247 | 246 |
return CL_CLEAN; |
| 248 | 247 |
} |
| ... | ... |
@@ -1,5 +1,5 @@ |
| 1 | 1 |
/* |
| 2 |
- * Copyright (C) 2007-2008 Sourcefire, Inc. |
|
| 2 |
+ * Copyright (C) 2007-2009 Sourcefire, Inc. |
|
| 3 | 3 |
* |
| 4 | 4 |
* Authors: Tomasz Kojm |
| 5 | 5 |
* |
| ... | ... |
@@ -27,17 +27,17 @@ |
| 27 | 27 |
|
| 28 | 28 |
struct cli_bm_patt {
|
| 29 | 29 |
unsigned char *pattern, *prefix; |
| 30 |
- char *virname, *offset; |
|
| 30 |
+ char *virname; |
|
| 31 |
+ uint32_t offdata[4], offset_min, offset_max; |
|
| 31 | 32 |
struct cli_bm_patt *next; |
| 32 | 33 |
uint16_t length, prefix_length; |
| 33 | 34 |
uint16_t cnt; |
| 34 | 35 |
unsigned char pattern0; |
| 35 |
- uint8_t target; |
|
| 36 | 36 |
}; |
| 37 | 37 |
|
| 38 |
-int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern); |
|
| 38 |
+int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern, const char *offset); |
|
| 39 | 39 |
int cli_bm_init(struct cli_matcher *root); |
| 40 |
-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); |
|
| 40 |
+int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, int fd); |
|
| 41 | 41 |
void cli_bm_free(struct cli_matcher *root); |
| 42 | 42 |
|
| 43 | 43 |
#endif |
| ... | ... |
@@ -1,5 +1,5 @@ |
| 1 | 1 |
/* |
| 2 |
- * Copyright (C) 2007-2008 Sourcefire, Inc. |
|
| 2 |
+ * Copyright (C) 2007-2009 Sourcefire, Inc. |
|
| 3 | 3 |
* |
| 4 | 4 |
* Authors: Tomasz Kojm |
| 5 | 5 |
* |
| ... | ... |
@@ -76,8 +76,8 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, |
| 76 | 76 |
if(!acdata && (ret = cli_ac_initdata(&mdata, troot->ac_partsigs, troot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN))) |
| 77 | 77 |
return ret; |
| 78 | 78 |
|
| 79 |
- if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, troot, offset, ftype, -1)) != CL_VIRUS) |
|
| 80 |
- ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, troot, acdata ? (acdata[0]) : (&mdata), offset, ftype, -1, NULL, AC_SCAN_VIR, NULL); |
|
| 79 |
+ if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, troot, offset, -1)) != CL_VIRUS) |
|
| 80 |
+ ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, troot, acdata ? (acdata[0]) : (&mdata), offset, ftype, NULL, AC_SCAN_VIR, NULL); |
|
| 81 | 81 |
|
| 82 | 82 |
if(!acdata) |
| 83 | 83 |
cli_ac_freedata(&mdata); |
| ... | ... |
@@ -89,8 +89,8 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, |
| 89 | 89 |
if(!acdata && (ret = cli_ac_initdata(&mdata, groot->ac_partsigs, groot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN))) |
| 90 | 90 |
return ret; |
| 91 | 91 |
|
| 92 |
- if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, groot, offset, ftype, -1)) != CL_VIRUS) |
|
| 93 |
- ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, groot, acdata ? (acdata[1]) : (&mdata), offset, ftype, -1, NULL, AC_SCAN_VIR, NULL); |
|
| 92 |
+ if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, groot, offset, -1)) != CL_VIRUS) |
|
| 93 |
+ ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, groot, acdata ? (acdata[1]) : (&mdata), offset, ftype, NULL, AC_SCAN_VIR, NULL); |
|
| 94 | 94 |
|
| 95 | 95 |
if(!acdata) |
| 96 | 96 |
cli_ac_freedata(&mdata); |
| ... | ... |
@@ -98,112 +98,188 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, |
| 98 | 98 |
return ret; |
| 99 | 99 |
} |
| 100 | 100 |
|
| 101 |
-off_t cli_caloff(const char *offstr, struct cli_target_info *info, int fd, cli_file_t ftype, int *ret, unsigned int *maxshift) |
|
| 101 |
+/* |
|
| 102 |
+ * offdata[0]: type |
|
| 103 |
+ * offdata[1]: offset value |
|
| 104 |
+ * offdata[2]: max shift |
|
| 105 |
+ * offdata[3]: section number |
|
| 106 |
+ */ |
|
| 107 |
+int cli_caloff(const char *offstr, struct cli_target_info *info, int fd, unsigned int target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max) |
|
| 102 | 108 |
{
|
| 103 | 109 |
int (*einfo)(int, struct cli_exe_info *) = NULL; |
| 110 |
+ char offcpy[65]; |
|
| 104 | 111 |
unsigned int n, val; |
| 105 |
- const char *pt; |
|
| 106 |
- off_t pos, offset; |
|
| 107 |
- |
|
| 108 |
- |
|
| 109 |
- *ret = 0; |
|
| 112 |
+ char *pt; |
|
| 113 |
+ off_t pos; |
|
| 114 |
+ struct stat sb; |
|
| 110 | 115 |
|
| 111 |
- if((pt = strchr(offstr, ','))) |
|
| 112 |
- *maxshift = atoi(++pt); |
|
| 113 | 116 |
|
| 114 |
- if(isdigit(offstr[0])) |
|
| 115 |
- return atoi(offstr); |
|
| 117 |
+ if(!info) { /* decode offset string */
|
|
| 118 |
+ if(!offstr) {
|
|
| 119 |
+ cli_errmsg("cli_caloff: offstr == NULL\n");
|
|
| 120 |
+ return CL_ENULLARG; |
|
| 121 |
+ } |
|
| 116 | 122 |
|
| 117 |
- if(fd == -1) {
|
|
| 118 |
- *ret = -1; |
|
| 119 |
- return 0; |
|
| 120 |
- } |
|
| 123 |
+ if(!strcmp(offstr, "*")) {
|
|
| 124 |
+ offdata[0] = *offset_max = *offset_min = CLI_OFF_ANY; |
|
| 125 |
+ return CL_SUCCESS; |
|
| 126 |
+ } |
|
| 121 | 127 |
|
| 122 |
- if(!strncmp(offstr, "EP", 2) || offstr[0] == 'S') {
|
|
| 128 |
+ if(strlen(offstr) > 64) {
|
|
| 129 |
+ cli_errmsg("cli_caloff: Offset string too long\n");
|
|
| 130 |
+ return CL_EMALFDB; |
|
| 131 |
+ } |
|
| 132 |
+ strcpy(offcpy, offstr); |
|
| 123 | 133 |
|
| 124 |
- if(info->status == -1) {
|
|
| 125 |
- *ret = -1; |
|
| 126 |
- return 0; |
|
| 134 |
+ if((pt = strchr(offcpy, ','))) {
|
|
| 135 |
+ if(!cli_isnumber(pt + 1)) {
|
|
| 136 |
+ cli_errmsg("cli_caloff: Invalid offset shift value\n");
|
|
| 137 |
+ return CL_EMALFDB; |
|
| 138 |
+ } |
|
| 139 |
+ offdata[2] = atoi(pt + 1); |
|
| 140 |
+ *pt = 0; |
|
| 141 |
+ } else {
|
|
| 142 |
+ offdata[2] = 0; |
|
| 143 |
+ } |
|
| 127 | 144 |
|
| 128 |
- } else if(!info->status) {
|
|
| 145 |
+ *offset_max = *offset_min = CLI_OFF_NONE; |
|
| 129 | 146 |
|
| 130 |
- if(ftype == CL_TYPE_MSEXE) |
|
| 131 |
- einfo = cli_peheader; |
|
| 132 |
- else if(ftype == CL_TYPE_ELF) |
|
| 133 |
- einfo = cli_elfheader; |
|
| 134 |
- else if(ftype == CL_TYPE_MACHO) |
|
| 135 |
- einfo = cli_machoheader; |
|
| 147 |
+ if(!strncmp(offcpy, "EP+", 3) || !strncmp(offcpy, "EP-", 3)) {
|
|
| 148 |
+ if(offcpy[2] == '+') |
|
| 149 |
+ offdata[0] = CLI_OFF_EP_PLUS; |
|
| 150 |
+ else |
|
| 151 |
+ offdata[0] = CLI_OFF_EP_MINUS; |
|
| 136 | 152 |
|
| 137 |
- if(einfo) {
|
|
| 138 |
- if((pos = lseek(fd, 0, SEEK_CUR)) == -1) {
|
|
| 139 |
- cli_dbgmsg("Invalid descriptor\n");
|
|
| 140 |
- info->status = *ret = -1; |
|
| 141 |
- return 0; |
|
| 153 |
+ if(!cli_isnumber(&offcpy[3])) {
|
|
| 154 |
+ cli_errmsg("cli_caloff: Invalid offset value\n");
|
|
| 155 |
+ return CL_EMALFDB; |
|
| 156 |
+ } |
|
| 157 |
+ offdata[1] = atoi(&offcpy[3]); |
|
| 158 |
+ |
|
| 159 |
+ } else if(offcpy[0] == 'S') {
|
|
| 160 |
+ if(!strncmp(offstr, "SL+", 3)) {
|
|
| 161 |
+ offdata[0] = CLI_OFF_SL_PLUS; |
|
| 162 |
+ if(!cli_isnumber(&offcpy[3])) {
|
|
| 163 |
+ cli_errmsg("cli_caloff: Invalid offset value\n");
|
|
| 164 |
+ return CL_EMALFDB; |
|
| 142 | 165 |
} |
| 166 |
+ offdata[1] = atoi(&offcpy[3]); |
|
| 167 |
+ |
|
| 168 |
+ } else if(sscanf(offcpy, "S%u+%u", &n, &val) == 2) {
|
|
| 169 |
+ offdata[0] = CLI_OFF_SX_PLUS; |
|
| 170 |
+ offdata[1] = val; |
|
| 171 |
+ offdata[3] = n; |
|
| 172 |
+ } else {
|
|
| 173 |
+ cli_errmsg("cli_caloff: Invalid offset string\n");
|
|
| 174 |
+ return CL_EMALFDB; |
|
| 175 |
+ } |
|
| 143 | 176 |
|
| 144 |
- lseek(fd, 0, SEEK_SET); |
|
| 145 |
- if(einfo(fd, &info->exeinfo)) {
|
|
| 146 |
- lseek(fd, pos, SEEK_SET); |
|
| 147 |
- info->status = *ret = -1; |
|
| 148 |
- return 0; |
|
| 149 |
- } |
|
| 150 |
- lseek(fd, pos, SEEK_SET); |
|
| 151 |
- info->status = 1; |
|
| 177 |
+ } else if(!strncmp(offcpy, "EOF-", 4)) {
|
|
| 178 |
+ offdata[0] = CLI_OFF_EOF_MINUS; |
|
| 179 |
+ if(!cli_isnumber(&offcpy[4])) {
|
|
| 180 |
+ cli_errmsg("cli_caloff: Invalid offset value\n");
|
|
| 181 |
+ return CL_EMALFDB; |
|
| 152 | 182 |
} |
| 183 |
+ offdata[1] = atoi(&offcpy[4]); |
|
| 184 |
+ } else {
|
|
| 185 |
+ offdata[0] = CLI_OFF_ABSOLUTE; |
|
| 186 |
+ if(!cli_isnumber(offcpy)) {
|
|
| 187 |
+ cli_errmsg("cli_caloff: Invalid offset value\n");
|
|
| 188 |
+ return CL_EMALFDB; |
|
| 189 |
+ } |
|
| 190 |
+ *offset_min = offdata[1] = atoi(offcpy); |
|
| 191 |
+ *offset_max = *offset_min + offdata[2]; |
|
| 153 | 192 |
} |
| 154 |
- } |
|
| 155 |
- |
|
| 156 |
- if(info->status == 1 && (!strncmp(offstr, "EP+", 3) || !strncmp(offstr, "EP-", 3))) {
|
|
| 157 |
- |
|
| 158 |
- if(offstr[2] == '+') |
|
| 159 |
- return info->exeinfo.ep + atoi(offstr + 3); |
|
| 160 |
- else |
|
| 161 |
- return info->exeinfo.ep - atoi(offstr + 3); |
|
| 162 | 193 |
|
| 163 |
- } else if(info->status == 1 && offstr[0] == 'S') {
|
|
| 194 |
+ if(offdata[0] != CLI_OFF_ANY && offdata[0] != CLI_OFF_ABSOLUTE && offdata[0] != CLI_OFF_EOF_MINUS) {
|
|
| 195 |
+ if(target != 1 && target != 6 && target != 9) {
|
|
| 196 |
+ cli_errmsg("cli_caloff: Invalid offset type for target %u\n", target);
|
|
| 197 |
+ return CL_EMALFDB; |
|
| 198 |
+ } |
|
| 199 |
+ } |
|
| 164 | 200 |
|
| 165 |
- if(!strncmp(offstr, "SL", 2) && info->exeinfo.section[info->exeinfo.nsections - 1].rsz) {
|
|
| 201 |
+ } else {
|
|
| 202 |
+ /* calculate relative offsets */ |
|
| 203 |
+ if(info->status == -1) {
|
|
| 204 |
+ *offset_min = *offset_max = 0; |
|
| 205 |
+ return CL_SUCCESS; |
|
| 206 |
+ } |
|
| 166 | 207 |
|
| 167 |
- if(sscanf(offstr, "SL+%u", &val) != 1) {
|
|
| 168 |
- *ret = -1; |
|
| 169 |
- return 0; |
|
| 208 |
+ if((offdata[0] == CLI_OFF_EOF_MINUS)) {
|
|
| 209 |
+ if(!info->fsize) {
|
|
| 210 |
+ if(fstat(fd, &sb) == -1) {
|
|
| 211 |
+ cli_errmsg("cli_caloff: fstat(%d) failed\n", fd);
|
|
| 212 |
+ return CL_ESTAT; |
|
| 213 |
+ } |
|
| 214 |
+ info->fsize = sb.st_size; |
|
| 170 | 215 |
} |
| 171 | 216 |
|
| 172 |
- offset = val + info->exeinfo.section[info->exeinfo.nsections - 1].raw; |
|
| 173 |
- |
|
| 174 |
- } else {
|
|
| 217 |
+ } else if(!info->status) {
|
|
| 218 |
+ if(target == 1) |
|
| 219 |
+ einfo = cli_peheader; |
|
| 220 |
+ else if(target == 6) |
|
| 221 |
+ einfo = cli_elfheader; |
|
| 222 |
+ else if(target == 9) |
|
| 223 |
+ einfo = cli_machoheader; |
|
| 175 | 224 |
|
| 176 |
- if(sscanf(offstr, "S%u+%u", &n, &val) != 2) {
|
|
| 177 |
- *ret = -1; |
|
| 178 |
- return 0; |
|
| 225 |
+ if(!einfo) {
|
|
| 226 |
+ cli_errmsg("cli_caloff: Invalid offset/filetype\n");
|
|
| 227 |
+ return CL_EMALFDB; |
|
| 179 | 228 |
} |
| 180 | 229 |
|
| 181 |
- if(n >= info->exeinfo.nsections || !info->exeinfo.section[n].rsz) {
|
|
| 182 |
- *ret = -1; |
|
| 183 |
- return 0; |
|
| 230 |
+ if((pos = lseek(fd, 0, SEEK_CUR)) == -1) {
|
|
| 231 |
+ cli_errmsg("cli_caloff: lseek(%d) failed\n", fd);
|
|
| 232 |
+ return CL_ESEEK; |
|
| 184 | 233 |
} |
| 185 | 234 |
|
| 186 |
- offset = val + info->exeinfo.section[n].raw; |
|
| 235 |
+ lseek(fd, 0, SEEK_SET); |
|
| 236 |
+ if(einfo(fd, &info->exeinfo)) {
|
|
| 237 |
+ /* einfo *may* fail */ |
|
| 238 |
+ lseek(fd, pos, SEEK_SET); |
|
| 239 |
+ info->status = -1; |
|
| 240 |
+ *offset_min = *offset_max = 0; |
|
| 241 |
+ return CL_SUCCESS; |
|
| 242 |
+ } |
|
| 243 |
+ lseek(fd, pos, SEEK_SET); |
|
| 244 |
+ info->status = 1; |
|
| 187 | 245 |
} |
| 188 | 246 |
|
| 189 |
- return offset; |
|
| 247 |
+ switch(offdata[0]) {
|
|
| 248 |
+ case CLI_OFF_EOF_MINUS: |
|
| 249 |
+ *offset_min = info->fsize - offdata[1]; |
|
| 250 |
+ break; |
|
| 190 | 251 |
|
| 191 |
- } else if(!strncmp(offstr, "EOF-", 4)) {
|
|
| 192 |
- struct stat sb; |
|
| 252 |
+ case CLI_OFF_EP_PLUS: |
|
| 253 |
+ *offset_min = info->exeinfo.ep + offdata[1]; |
|
| 254 |
+ break; |
|
| 193 | 255 |
|
| 194 |
- if(!info->fsize) {
|
|
| 195 |
- if(fstat(fd, &sb) == -1) {
|
|
| 196 |
- info->status = *ret = -1; |
|
| 197 |
- return 0; |
|
| 198 |
- } |
|
| 199 |
- info->fsize = sb.st_size; |
|
| 256 |
+ case CLI_OFF_EP_MINUS: |
|
| 257 |
+ *offset_min = info->exeinfo.ep - offdata[1]; |
|
| 258 |
+ break; |
|
| 259 |
+ |
|
| 260 |
+ case CLI_OFF_SL_PLUS: |
|
| 261 |
+ *offset_min = info->exeinfo.section[info->exeinfo.nsections - 1].raw + offdata[1]; |
|
| 262 |
+ break; |
|
| 263 |
+ |
|
| 264 |
+ case CLI_OFF_SX_PLUS: |
|
| 265 |
+ if(offdata[3] >= info->exeinfo.nsections) |
|
| 266 |
+ *offset_min = 0; |
|
| 267 |
+ else |
|
| 268 |
+ *offset_min = info->exeinfo.section[offdata[3]].raw + offdata[1]; |
|
| 269 |
+ break; |
|
| 270 |
+ |
|
| 271 |
+ default: |
|
| 272 |
+ cli_errmsg("cli_caloff: Not a relative offset (type: %u)\n", offdata[0]);
|
|
| 273 |
+ return CL_EARG; |
|
| 200 | 274 |
} |
| 201 | 275 |
|
| 202 |
- return info->fsize - atoi(offstr + 4); |
|
| 276 |
+ if(!*offset_min) |
|
| 277 |
+ *offset_max = 0; |
|
| 278 |
+ else |
|
| 279 |
+ *offset_max = *offset_min + offdata[2]; |
|
| 203 | 280 |
} |
| 204 | 281 |
|
| 205 |
- *ret = -1; |
|
| 206 |
- return 0; |
|
| 282 |
+ return CL_SUCCESS; |
|
| 207 | 283 |
} |
| 208 | 284 |
|
| 209 | 285 |
int cli_checkfp(int fd, cli_ctx *ctx) |
| ... | ... |
@@ -227,7 +303,7 @@ int cli_checkfp(int fd, cli_ctx *ctx) |
| 227 | 227 |
return 0; |
| 228 | 228 |
} |
| 229 | 229 |
|
| 230 |
- if(cli_bm_scanbuff(digest, 16, &virname, ctx->engine->md5_fp, 0, 0, -1) == CL_VIRUS) {
|
|
| 230 |
+ if(cli_bm_scanbuff(digest, 16, &virname, ctx->engine->md5_fp, 0, -1) == CL_VIRUS) {
|
|
| 231 | 231 |
cli_dbgmsg("cli_checkfp(): Found false positive detection (fp sig: %s)\n", virname);
|
| 232 | 232 |
free(digest); |
| 233 | 233 |
lseek(fd, pos, SEEK_SET); |
| ... | ... |
@@ -240,33 +316,6 @@ int cli_checkfp(int fd, cli_ctx *ctx) |
| 240 | 240 |
return 0; |
| 241 | 241 |
} |
| 242 | 242 |
|
| 243 |
-int cli_validatesig(cli_file_t ftype, const char *offstr, off_t fileoff, struct cli_target_info *info, int desc, const char *virname) |
|
| 244 |
-{
|
|
| 245 |
- off_t offset; |
|
| 246 |
- int ret; |
|
| 247 |
- unsigned int maxshift = 0; |
|
| 248 |
- |
|
| 249 |
- |
|
| 250 |
- if(offstr) {
|
|
| 251 |
- offset = cli_caloff(offstr, info, desc, ftype, &ret, &maxshift); |
|
| 252 |
- |
|
| 253 |
- if(ret == -1) |
|
| 254 |
- return 0; |
|
| 255 |
- |
|
| 256 |
- if(maxshift) {
|
|
| 257 |
- if((fileoff < offset) || (fileoff > offset + (off_t) maxshift)) {
|
|
| 258 |
- /* cli_dbgmsg("Signature offset: %lu, expected: [%lu..%lu] (%s)\n", (unsigned long int) fileoff, (unsigned long int) offset, (unsigned long int) (offset + maxshift), virname); */
|
|
| 259 |
- return 0; |
|
| 260 |
- } |
|
| 261 |
- } else if(fileoff != offset) {
|
|
| 262 |
- /* cli_dbgmsg("Signature offset: %lu, expected: %lu (%s)\n", (unsigned long int) fileoff, (unsigned long int) offset, virname); */
|
|
| 263 |
- return 0; |
|
| 264 |
- } |
|
| 265 |
- } |
|
| 266 |
- |
|
| 267 |
- return 1; |
|
| 268 |
-} |
|
| 269 |
- |
|
| 270 | 243 |
int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode) |
| 271 | 244 |
{
|
| 272 | 245 |
unsigned char *buffer, *buff, *endbl, *upt; |
| ... | ... |
@@ -316,12 +365,16 @@ int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struc |
| 316 | 316 |
return CL_EMEM; |
| 317 | 317 |
} |
| 318 | 318 |
|
| 319 |
- if(!ftonly && (ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN))) |
|
| 320 |
- return ret; |
|
| 319 |
+ if(!ftonly) |
|
| 320 |
+ if((ret = cli_ac_caloff(groot, desc)) || (ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN))) |
|
| 321 |
+ return ret; |
|
| 321 | 322 |
|
| 322 | 323 |
if(troot) {
|
| 323 |
- if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN))) |
|
| 324 |
+ if((ret = cli_ac_caloff(troot, desc)) || (ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN))) {
|
|
| 325 |
+ if(!ftonly) |
|
| 326 |
+ cli_ac_freedata(&gdata); |
|
| 324 | 327 |
return ret; |
| 328 |
+ } |
|
| 325 | 329 |
} |
| 326 | 330 |
|
| 327 | 331 |
if(!ftonly && ctx->engine->md5_hdb) |
| ... | ... |
@@ -344,8 +397,8 @@ int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struc |
| 344 | 344 |
length += maxpatlen; |
| 345 | 345 |
|
| 346 | 346 |
if(troot) {
|
| 347 |
- if(troot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, troot, offset, ftype, desc)) != CL_VIRUS) |
|
| 348 |
- ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, troot, &tdata, offset, ftype, desc, ftoffset, acmode, NULL); |
|
| 347 |
+ if(troot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, troot, offset, desc)) != CL_VIRUS) |
|
| 348 |
+ ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, troot, &tdata, offset, ftype, ftoffset, acmode, NULL); |
|
| 349 | 349 |
|
| 350 | 350 |
if(ret == CL_VIRUS) {
|
| 351 | 351 |
free(buffer); |
| ... | ... |
@@ -361,8 +414,8 @@ int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struc |
| 361 | 361 |
} |
| 362 | 362 |
|
| 363 | 363 |
if(!ftonly) {
|
| 364 |
- if(groot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, groot, offset, ftype, desc)) != CL_VIRUS) |
|
| 365 |
- ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, groot, &gdata, offset, ftype, desc, ftoffset, acmode, NULL); |
|
| 364 |
+ if(groot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, groot, offset, desc)) != CL_VIRUS) |
|
| 365 |
+ ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, groot, &gdata, offset, ftype, ftoffset, acmode, NULL); |
|
| 366 | 366 |
|
| 367 | 367 |
if(ret == CL_VIRUS) {
|
| 368 | 368 |
free(buffer); |
| ... | ... |
@@ -439,7 +492,7 @@ int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struc |
| 439 | 439 |
|
| 440 | 440 |
if(!ftonly && ctx->engine->md5_hdb) {
|
| 441 | 441 |
cli_md5_final(digest, &md5ctx); |
| 442 |
- if(cli_bm_scanbuff(digest, 16, ctx->virname, ctx->engine->md5_hdb, 0, 0, -1) == CL_VIRUS && (cli_bm_scanbuff(digest, 16, NULL, ctx->engine->md5_fp, 0, 0, -1) != CL_VIRUS)) |
|
| 442 |
+ if(cli_bm_scanbuff(digest, 16, ctx->virname, ctx->engine->md5_hdb, 0, -1) == CL_VIRUS && (cli_bm_scanbuff(digest, 16, NULL, ctx->engine->md5_fp, 0, -1) != CL_VIRUS)) |
|
| 443 | 443 |
return CL_VIRUS; |
| 444 | 444 |
} |
| 445 | 445 |
|
| ... | ... |
@@ -1,5 +1,5 @@ |
| 1 | 1 |
/* |
| 2 |
- * Copyright (C) 2007-2008 Sourcefire, Inc. |
|
| 2 |
+ * Copyright (C) 2007-2009 Sourcefire, Inc. |
|
| 3 | 3 |
* |
| 4 | 4 |
* Authors: Tomasz Kojm |
| 5 | 5 |
* |
| ... | ... |
@@ -69,18 +69,22 @@ struct cli_ac_lsig {
|
| 69 | 69 |
}; |
| 70 | 70 |
|
| 71 | 71 |
struct cli_matcher {
|
| 72 |
+ unsigned int type; |
|
| 73 |
+ |
|
| 72 | 74 |
/* Extended Boyer-Moore */ |
| 73 | 75 |
uint8_t *bm_shift; |
| 74 | 76 |
struct cli_bm_patt **bm_suffix; |
| 75 | 77 |
struct cli_hashset md5_sizes_hs; |
| 76 | 78 |
uint32_t *soff, soff_len; /* for PE section sigs */ |
| 77 |
- uint32_t bm_patterns; |
|
| 79 |
+ uint32_t bm_patterns, bm_reloff_num; |
|
| 78 | 80 |
|
| 79 | 81 |
/* Extended Aho-Corasick */ |
| 80 | 82 |
uint32_t ac_partsigs, ac_nodes, ac_patterns, ac_lsigs; |
| 81 | 83 |
struct cli_ac_lsig **ac_lsigtable; |
| 82 | 84 |
struct cli_ac_node *ac_root, **ac_nodetable; |
| 83 | 85 |
struct cli_ac_patt **ac_pattable; |
| 86 |
+ struct cli_ac_patt **ac_reloff; |
|
| 87 |
+ uint32_t ac_reloff_num; |
|
| 84 | 88 |
uint8_t ac_mindepth, ac_maxdepth; |
| 85 | 89 |
|
| 86 | 90 |
uint16_t maxpatlen; |
| ... | ... |
@@ -124,13 +128,20 @@ struct cli_target_info {
|
| 124 | 124 |
int8_t status; /* 0 == not initialised, 1 == initialised OK, -1 == error */ |
| 125 | 125 |
}; |
| 126 | 126 |
|
| 127 |
+#define CLI_OFF_ANY 0xffffffff |
|
| 128 |
+#define CLI_OFF_NONE 0xfffffffe |
|
| 129 |
+#define CLI_OFF_ABSOLUTE 1 |
|
| 130 |
+#define CLI_OFF_EOF_MINUS 2 |
|
| 131 |
+#define CLI_OFF_EP_PLUS 3 |
|
| 132 |
+#define CLI_OFF_EP_MINUS 4 |
|
| 133 |
+#define CLI_OFF_SL_PLUS 5 |
|
| 134 |
+#define CLI_OFF_SX_PLUS 6 |
|
| 135 |
+ |
|
| 127 | 136 |
int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, cli_ctx *ctx, cli_file_t ftype, struct cli_ac_data **acdata); |
| 128 | 137 |
|
| 129 | 138 |
int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode); |
| 130 | 139 |
|
| 131 |
-int cli_validatesig(cli_file_t ftype, const char *offstr, off_t fileoff, struct cli_target_info *info, int desc, const char *virname); |
|
| 132 |
- |
|
| 133 |
-off_t cli_caloff(const char *offstr, struct cli_target_info *info, int fd, cli_file_t ftype, int *ret, unsigned int *maxshift); |
|
| 140 |
+int cli_caloff(const char *offstr, struct cli_target_info *info, int fd, unsigned int target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max); |
|
| 134 | 141 |
|
| 135 | 142 |
int cli_checkfp(int fd, cli_ctx *ctx); |
| 136 | 143 |
|
| ... | ... |
@@ -928,8 +928,8 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
| 928 | 928 |
for(j = 0; j < md5_sect->soff_len && md5_sect->soff[j] <= exe_sections[i].rsz; j++) {
|
| 929 | 929 |
if(md5_sect->soff[j] == exe_sections[i].rsz) {
|
| 930 | 930 |
unsigned char md5_dig[16]; |
| 931 |
- if(cli_md5sect(desc, &exe_sections[i], md5_dig) && cli_bm_scanbuff(md5_dig, 16, ctx->virname, ctx->engine->md5_mdb, 0, 0, -1) == CL_VIRUS) {
|
|
| 932 |
- if(cli_bm_scanbuff(md5_dig, 16, NULL, ctx->engine->md5_fp, 0, 0, -1) != CL_VIRUS) {
|
|
| 931 |
+ if(cli_md5sect(desc, &exe_sections[i], md5_dig) && cli_bm_scanbuff(md5_dig, 16, ctx->virname, ctx->engine->md5_mdb, 0, -1) == CL_VIRUS) {
|
|
| 932 |
+ if(cli_bm_scanbuff(md5_dig, 16, NULL, ctx->engine->md5_fp, 0, -1) != CL_VIRUS) {
|
|
| 933 | 933 |
|
| 934 | 934 |
free(section_hdr); |
| 935 | 935 |
free(exe_sections); |
| ... | ... |
@@ -1198,13 +1198,13 @@ static int hash_match(const struct regex_matcher *rlist, const char *host, size_ |
| 1198 | 1198 |
h[64]='\0'; |
| 1199 | 1199 |
cli_dbgmsg("Looking up hash %s for %s(%u)%s(%u)\n", h, host, (unsigned)hlen, path, (unsigned)plen);
|
| 1200 | 1200 |
if (prefix_matched) {
|
| 1201 |
- if (cli_bm_scanbuff(sha256_dig, 4, &virname, &rlist->hostkey_prefix,0,0,-1) == CL_VIRUS) {
|
|
| 1201 |
+ if (cli_bm_scanbuff(sha256_dig, 4, &virname, &rlist->hostkey_prefix,0,-1) == CL_VIRUS) {
|
|
| 1202 | 1202 |
cli_dbgmsg("prefix matched\n");
|
| 1203 | 1203 |
*prefix_matched = 1; |
| 1204 | 1204 |
} else |
| 1205 | 1205 |
return CL_SUCCESS; |
| 1206 | 1206 |
} |
| 1207 |
- if (cli_bm_scanbuff(sha256_dig, 32, &virname, &rlist->sha256_hashes,0,0,-1) == CL_VIRUS) {
|
|
| 1207 |
+ if (cli_bm_scanbuff(sha256_dig, 32, &virname, &rlist->sha256_hashes,0,-1) == CL_VIRUS) {
|
|
| 1208 | 1208 |
cli_dbgmsg("This hash matched: %s\n", h);
|
| 1209 | 1209 |
switch(*virname) {
|
| 1210 | 1210 |
case 'W': |
| ... | ... |
@@ -120,10 +120,11 @@ int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hex |
| 120 | 120 |
struct cli_bm_patt *bm_new; |
| 121 | 121 |
char *pt, *hexcpy, *start, *n; |
| 122 | 122 |
int ret, asterisk = 0; |
| 123 |
- unsigned int i, j, len, parts = 0; |
|
| 123 |
+ unsigned int i, j, hexlen, parts = 0; |
|
| 124 | 124 |
int mindist = 0, maxdist = 0, error = 0; |
| 125 | 125 |
|
| 126 | 126 |
|
| 127 |
+ hexlen = strlen(hexsig); |
|
| 127 | 128 |
if(strchr(hexsig, '{')) {
|
| 128 | 129 |
|
| 129 | 130 |
root->ac_partsigs++; |
| ... | ... |
@@ -131,8 +132,7 @@ int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hex |
| 131 | 131 |
if(!(hexcpy = cli_strdup(hexsig))) |
| 132 | 132 |
return CL_EMEM; |
| 133 | 133 |
|
| 134 |
- len = strlen(hexsig); |
|
| 135 |
- for(i = 0; i < len; i++) |
|
| 134 |
+ for(i = 0; i < hexlen; i++) |
|
| 136 | 135 |
if(hexsig[i] == '{' || hexsig[i] == '*')
|
| 137 | 136 |
parts++; |
| 138 | 137 |
|
| ... | ... |
@@ -224,8 +224,7 @@ int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hex |
| 224 | 224 |
} else if(strchr(hexsig, '*')) {
|
| 225 | 225 |
root->ac_partsigs++; |
| 226 | 226 |
|
| 227 |
- len = strlen(hexsig); |
|
| 228 |
- for(i = 0; i < len; i++) |
|
| 227 |
+ for(i = 0; i < hexlen; i++) |
|
| 229 | 228 |
if(hexsig[i] == '*') |
| 230 | 229 |
parts++; |
| 231 | 230 |
|
| ... | ... |
@@ -247,7 +246,7 @@ int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hex |
| 247 | 247 |
free(pt); |
| 248 | 248 |
} |
| 249 | 249 |
|
| 250 |
- } else if(root->ac_only || strpbrk(hexsig, "?(") || type || lsigid) {
|
|
| 250 |
+ } else if(root->ac_only || type || lsigid /* || (hexlen / 2 < CLI_DEFAULT_MOVETOAC_LEN) FIXME: unit tests */ || strpbrk(hexsig, "?(")) {
|
|
| 251 | 251 |
if((ret = cli_ac_addsig(root, virname, hexsig, 0, 0, 0, rtype, type, 0, 0, offset, lsigid, options))) {
|
| 252 | 252 |
cli_errmsg("cli_parse_add(): Problem adding signature (3).\n");
|
| 253 | 253 |
return ret; |
| ... | ... |
@@ -262,7 +261,7 @@ int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hex |
| 262 | 262 |
mpool_free(root->mempool, bm_new); |
| 263 | 263 |
return CL_EMALFDB; |
| 264 | 264 |
} |
| 265 |
- bm_new->length = strlen(hexsig) / 2; |
|
| 265 |
+ bm_new->length = hexlen / 2; |
|
| 266 | 266 |
|
| 267 | 267 |
bm_new->virname = cli_mpool_virname(root->mempool, (char *) virname, options & CL_DB_OFFICIAL); |
| 268 | 268 |
if(!bm_new->virname) {
|
| ... | ... |
@@ -271,22 +270,10 @@ int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hex |
| 271 | 271 |
return CL_EMEM; |
| 272 | 272 |
} |
| 273 | 273 |
|
| 274 |
- if(offset) {
|
|
| 275 |
- bm_new->offset = cli_mpool_strdup(root->mempool, offset); |
|
| 276 |
- if(!bm_new->offset) {
|
|
| 277 |
- mpool_free(root->mempool, bm_new->pattern); |
|
| 278 |
- mpool_free(root->mempool, bm_new->virname); |
|
| 279 |
- mpool_free(root->mempool, bm_new); |
|
| 280 |
- return CL_EMEM; |
|
| 281 |
- } |
|
| 282 |
- } |
|
| 283 |
- |
|
| 284 |
- bm_new->target = target; |
|
| 285 |
- |
|
| 286 | 274 |
if(bm_new->length > root->maxpatlen) |
| 287 | 275 |
root->maxpatlen = bm_new->length; |
| 288 | 276 |
|
| 289 |
- if((ret = cli_bm_addpatt(root, bm_new))) {
|
|
| 277 |
+ if((ret = cli_bm_addpatt(root, bm_new, offset))) {
|
|
| 290 | 278 |
cli_errmsg("cli_parse_add(): Problem adding signature (4).\n");
|
| 291 | 279 |
mpool_free(root->mempool, bm_new->pattern); |
| 292 | 280 |
mpool_free(root->mempool, bm_new->virname); |
| ... | ... |
@@ -308,14 +295,14 @@ static int cli_initroots(struct cl_engine *engine, unsigned int options) |
| 308 | 308 |
if(!engine->root[i]) {
|
| 309 | 309 |
cli_dbgmsg("Initializing engine->root[%d]\n", i);
|
| 310 | 310 |
root = engine->root[i] = (struct cli_matcher *) mpool_calloc(engine->mempool, 1, sizeof(struct cli_matcher)); |
| 311 |
-#ifdef USE_MPOOL |
|
| 312 |
- root->mempool = engine->mempool; |
|
| 313 |
-#endif |
|
| 314 | 311 |
if(!root) {
|
| 315 | 312 |
cli_errmsg("cli_initroots: Can't allocate memory for cli_matcher\n");
|
| 316 | 313 |
return CL_EMEM; |
| 317 | 314 |
} |
| 318 |
- |
|
| 315 |
+#ifdef USE_MPOOL |
|
| 316 |
+ root->mempool = engine->mempool; |
|
| 317 |
+#endif |
|
| 318 |
+ root->type = i; |
|
| 319 | 319 |
if(cli_mtargets[i].ac_only || engine->ac_only) |
| 320 | 320 |
root->ac_only = 1; |
| 321 | 321 |
|
| ... | ... |
@@ -511,7 +498,7 @@ static int cli_loaddb(FILE *fs, struct cl_engine *engine, unsigned int *signo, u |
| 511 | 511 |
|
| 512 | 512 |
if(*pt == '=') continue; |
| 513 | 513 |
|
| 514 |
- if((ret = cli_parse_add(root, start, pt, 0, 0, NULL, 0, NULL, options))) {
|
|
| 514 |
+ if((ret = cli_parse_add(root, start, pt, 0, 0, "*", 0, NULL, options))) {
|
|
| 515 | 515 |
ret = CL_EMALFDB; |
| 516 | 516 |
break; |
| 517 | 517 |
} |
| ... | ... |
@@ -576,27 +563,6 @@ static int cli_loadpdb(FILE *fs, struct cl_engine *engine, unsigned int *signo, |
| 576 | 576 |
return CL_SUCCESS; |
| 577 | 577 |
} |
| 578 | 578 |
|
| 579 |
-static int cli_checkoffset(const char *offset, unsigned int type) |
|
| 580 |
-{
|
|
| 581 |
- unsigned int foo; |
|
| 582 |
- const char *pt = offset; |
|
| 583 |
- |
|
| 584 |
- if(isdigit(*offset)) {
|
|
| 585 |
- while(*pt++) |
|
| 586 |
- if(!strchr("0123456789,", *pt))
|
|
| 587 |
- return 1; |
|
| 588 |
- return 0; |
|
| 589 |
- } |
|
| 590 |
- |
|
| 591 |
- if(!strncmp(offset, "EOF-", 4)) |
|
| 592 |
- return 0; |
|
| 593 |
- |
|
| 594 |
- if((type == 1 || type == 6 || type == 9) && (!strncmp(offset, "EP+", 3) || !strncmp(offset, "EP-", 3) || (sscanf(offset, "SL+%u", &foo) == 1) || (sscanf(offset, "S%u+%u", &foo, &foo) == 2))) |
|
| 595 |
- return 0; |
|
| 596 |
- |
|
| 597 |
- return 1; |
|
| 598 |
-} |
|
| 599 |
- |
|
| 600 | 579 |
#define NDB_TOKENS 6 |
| 601 | 580 |
static int cli_loadndb(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned short sdb, unsigned int options, struct cli_dbio *dbio, const char *dbname) |
| 602 | 581 |
{
|
| ... | ... |
@@ -680,15 +646,6 @@ static int cli_loadndb(FILE *fs, struct cl_engine *engine, unsigned int *signo, |
| 680 | 680 |
root = engine->root[target]; |
| 681 | 681 |
|
| 682 | 682 |
offset = tokens[2]; |
| 683 |
- if(!strcmp(offset, "*")) |
|
| 684 |
- offset = NULL; |
|
| 685 |
- |
|
| 686 |
- if(offset && cli_checkoffset(offset, target)) {
|
|
| 687 |
- cli_errmsg("Incorrect offset '%s' for signature type-%u\n", offset, target);
|
|
| 688 |
- ret = CL_EMALFDB; |
|
| 689 |
- break; |
|
| 690 |
- } |
|
| 691 |
- |
|
| 692 | 683 |
sig = tokens[3]; |
| 693 | 684 |
|
| 694 | 685 |
if((ret = cli_parse_add(root, virname, sig, 0, 0, offset, target, NULL, options))) {
|
| ... | ... |
@@ -1025,19 +982,11 @@ static int cli_loadldb(FILE *fs, struct cl_engine *engine, unsigned int *signo, |
| 1025 | 1025 |
*pt = 0; |
| 1026 | 1026 |
sig = ++pt; |
| 1027 | 1027 |
offset = tokens[3 + i]; |
| 1028 |
- if(!strcmp(offset, "*")) |
|
| 1029 |
- offset = NULL; |
|
| 1030 | 1028 |
} else {
|
| 1031 |
- offset = NULL; |
|
| 1029 |
+ offset = "*"; |
|
| 1032 | 1030 |
sig = tokens[3 + i]; |
| 1033 | 1031 |
} |
| 1034 | 1032 |
|
| 1035 |
- if(offset && cli_checkoffset(offset, tdb.target[0])) {
|
|
| 1036 |
- cli_errmsg("Incorrect offset '%s' in subsignature id %u for signature type-%u\n", offset, i, tdb.target[0]);
|
|
| 1037 |
- ret = CL_EMALFDB; |
|
| 1038 |
- break; |
|
| 1039 |
- } |
|
| 1040 |
- |
|
| 1041 | 1033 |
if((ret = cli_parse_add(root, virname, sig, 0, 0, offset, target, lsigid, options))) {
|
| 1042 | 1034 |
ret = CL_EMALFDB; |
| 1043 | 1035 |
break; |
| ... | ... |
@@ -1131,7 +1080,7 @@ static int cli_loadftm(FILE *fs, struct cl_engine *engine, unsigned int options, |
| 1131 | 1131 |
} |
| 1132 | 1132 |
|
| 1133 | 1133 |
if(atoi(tokens[0]) == 1) { /* A-C */
|
| 1134 |
- if((ret = cli_parse_add(engine->root[0], tokens[3], tokens[2], rtype, type, strcmp(tokens[1], "*") ? tokens[1] : NULL, 0, NULL, options))) |
|
| 1134 |
+ if((ret = cli_parse_add(engine->root[0], tokens[3], tokens[2], rtype, type, tokens[1], 0, NULL, options))) |
|
| 1135 | 1135 |
break; |
| 1136 | 1136 |
|
| 1137 | 1137 |
} else if(atoi(tokens[0]) == 0) { /* memcmp() */
|
| ... | ... |
@@ -1394,7 +1343,7 @@ static int cli_loadmd5(FILE *fs, struct cl_engine *engine, unsigned int *signo, |
| 1394 | 1394 |
MD5_DB; |
| 1395 | 1395 |
} |
| 1396 | 1396 |
|
| 1397 |
- if((ret = cli_bm_addpatt(db, new))) {
|
|
| 1397 |
+ if((ret = cli_bm_addpatt(db, new, "0"))) {
|
|
| 1398 | 1398 |
cli_errmsg("cli_loadmd5: Error adding BM pattern\n");
|
| 1399 | 1399 |
mpool_free(engine->mempool, new->pattern); |
| 1400 | 1400 |
mpool_free(engine->mempool, new->virname); |
| ... | ... |
@@ -2203,7 +2152,7 @@ int cl_engine_compile(struct cl_engine *engine) |
| 2203 | 2203 |
if((root = engine->root[i])) {
|
| 2204 | 2204 |
if((ret = cli_ac_buildtrie(root))) |
| 2205 | 2205 |
return ret; |
| 2206 |
- cli_dbgmsg("matcher[%u]: %s: AC sigs: %u BM sigs: %u %s\n", i, cli_mtargets[i].name, root->ac_patterns, root->bm_patterns, root->ac_only ? "(ac_only mode)" : "");
|
|
| 2206 |
+ cli_dbgmsg("matcher[%u]: %s: AC sigs: %u (reloff: %u) BM sigs: %u (reloff: %u) %s\n", i, cli_mtargets[i].name, root->ac_patterns, root->ac_reloff_num, root->bm_patterns, root->bm_reloff_num, root->ac_only ? "(ac_only mode)" : "");
|
|
| 2207 | 2207 |
} |
| 2208 | 2208 |
} |
| 2209 | 2209 |
|
| ... | ... |
@@ -305,7 +305,7 @@ int regex_list_match(struct regex_matcher* matcher,char* real_url,const char* di |
| 305 | 305 |
* negatives */ |
| 306 | 306 |
return 0; |
| 307 | 307 |
} |
| 308 |
- rc = cli_ac_scanbuff((const unsigned char*)bufrev,buffer_len, NULL, (void*)®ex, &res, &matcher->suffixes,&mdata,0,0,-1,NULL,AC_SCAN_VIR,NULL); |
|
| 308 |
+ rc = cli_ac_scanbuff((const unsigned char*)bufrev,buffer_len, NULL, (void*)®ex, &res, &matcher->suffixes,&mdata,0,0,NULL,AC_SCAN_VIR,NULL); |
|
| 309 | 309 |
free(bufrev); |
| 310 | 310 |
cli_ac_freedata(&mdata); |
| 311 | 311 |
|
| ... | ... |
@@ -455,7 +455,7 @@ static int add_hash(struct regex_matcher *matcher, char* pattern, const char fl, |
| 455 | 455 |
|
| 456 | 456 |
if (fl != 'W' && pat->length == 32 && |
| 457 | 457 |
cli_hashset_contains(&matcher->sha256_pfx_set, cli_readint32(pat->pattern)) && |
| 458 |
- cli_bm_scanbuff(pat->pattern, 32, &vname, &matcher->sha256_hashes,0,0,-1) == CL_VIRUS) {
|
|
| 458 |
+ cli_bm_scanbuff(pat->pattern, 32, &vname, &matcher->sha256_hashes,0,-1) == CL_VIRUS) {
|
|
| 459 | 459 |
if (*vname == 'W') {
|
| 460 | 460 |
/* hash is whitelisted in local.gdb */ |
| 461 | 461 |
cli_dbgmsg("Skipping hash %s\n", pattern);
|
| ... | ... |
@@ -471,7 +471,7 @@ static int add_hash(struct regex_matcher *matcher, char* pattern, const char fl, |
| 471 | 471 |
} |
| 472 | 472 |
*pat->virname = fl; |
| 473 | 473 |
cli_hashset_addkey(&matcher->sha256_pfx_set, cli_readint32(pat->pattern)); |
| 474 |
- if((rc = cli_bm_addpatt(bm, pat))) {
|
|
| 474 |
+ if((rc = cli_bm_addpatt(bm, pat, "*"))) {
|
|
| 475 | 475 |
cli_errmsg("add_hash: failed to add BM pattern\n");
|
| 476 | 476 |
free(pat->pattern); |
| 477 | 477 |
free(pat->virname); |
| ... | ... |
@@ -675,7 +675,7 @@ static int add_newsuffix(struct regex_matcher *matcher, struct regex_list *info, |
| 675 | 675 |
new->partno = 0; |
| 676 | 676 |
new->mindist = 0; |
| 677 | 677 |
new->maxdist = 0; |
| 678 |
- new->offset = 0; |
|
| 678 |
+ new->offset_min = CLI_OFF_ANY; |
|
| 679 | 679 |
new->length = len; |
| 680 | 680 |
|
| 681 | 681 |
new->ch[0] = new->ch[1] |= CLI_MATCH_IGNORE; |
| ... | ... |
@@ -69,7 +69,7 @@ START_TEST (test_ac_scanbuff) {
|
| 69 | 69 |
fail_unless(ret == CL_SUCCESS, "cli_ac_init() failed"); |
| 70 | 70 |
|
| 71 | 71 |
for(i = 0; ac_testdata[i].data; i++) {
|
| 72 |
- ret = cli_parse_add(root, ac_testdata[i].virname, ac_testdata[i].hexsig, 0, 0, NULL, 0, NULL, 0); |
|
| 72 |
+ ret = cli_parse_add(root, ac_testdata[i].virname, ac_testdata[i].hexsig, 0, 0, "*", 0, NULL, 0); |
|
| 73 | 73 |
fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed"); |
| 74 | 74 |
} |
| 75 | 75 |
|
| ... | ... |
@@ -80,7 +80,7 @@ START_TEST (test_ac_scanbuff) {
|
| 80 | 80 |
fail_unless(ret == CL_SUCCESS, "cli_ac_initdata() failed"); |
| 81 | 81 |
|
| 82 | 82 |
for(i = 0; ac_testdata[i].data; i++) {
|
| 83 |
- ret = cli_ac_scanbuff(ac_testdata[i].data, strlen(ac_testdata[i].data), &virname, NULL, NULL, root, &mdata, 0, 0, -1, NULL, AC_SCAN_VIR, NULL); |
|
| 83 |
+ ret = cli_ac_scanbuff(ac_testdata[i].data, strlen(ac_testdata[i].data), &virname, NULL, NULL, root, &mdata, 0, 0, NULL, AC_SCAN_VIR, NULL); |
|
| 84 | 84 |
fail_unless_fmt(ret == CL_VIRUS, "cli_ac_scanbuff() failed for %s", ac_testdata[i].virname); |
| 85 | 85 |
fail_unless_fmt(!strncmp(virname, ac_testdata[i].virname, strlen(ac_testdata[i].virname)), "Dataset %u matched with %s", i, virname); |
| 86 | 86 |
} |
| ... | ... |
@@ -109,14 +109,14 @@ START_TEST (test_bm_scanbuff) {
|
| 109 | 109 |
ret = cli_bm_init(root); |
| 110 | 110 |
fail_unless(ret == CL_SUCCESS, "cli_bm_init() failed"); |
| 111 | 111 |
|
| 112 |
- ret = cli_parse_add(root, "Sig1", "deadbabe", 0, 0, NULL, 0, NULL, 0); |
|
| 112 |
+ ret = cli_parse_add(root, "Sig1", "deadbabe", 0, 0, "*", 0, NULL, 0); |
|
| 113 | 113 |
fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed"); |
| 114 |
- ret = cli_parse_add(root, "Sig2", "deadbeef", 0, 0, NULL, 0, NULL, 0); |
|
| 114 |
+ ret = cli_parse_add(root, "Sig2", "deadbeef", 0, 0, "*", 0, NULL, 0); |
|
| 115 | 115 |
fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed"); |
| 116 |
- ret = cli_parse_add(root, "Sig3", "babedead", 0, 0, NULL, 0, NULL, 0); |
|
| 116 |
+ ret = cli_parse_add(root, "Sig3", "babedead", 0, 0, "*", 0, NULL, 0); |
|
| 117 | 117 |
fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed"); |
| 118 | 118 |
|
| 119 |
- ret = cli_bm_scanbuff("blah\xde\xad\xbe\xef", 12, &virname, root, 0, 0, -1);
|
|
| 119 |
+ ret = cli_bm_scanbuff("blah\xde\xad\xbe\xef", 12, &virname, root, 0, -1);
|
|
| 120 | 120 |
fail_unless(ret == CL_VIRUS, "cli_bm_scanbuff() failed"); |
| 121 | 121 |
fail_unless(!strncmp(virname, "Sig2", 4), "Incorrect signature matched in cli_bm_scanbuff()\n"); |
| 122 | 122 |
cli_bm_free(root); |