... | ... |
@@ -2733,9 +2733,15 @@ static int cli_loadopenioc(FILE *fs, const char *dbname, struct cl_engine *engin |
2733 | 2733 |
} |
2734 | 2734 |
|
2735 | 2735 |
#ifndef _WIN32 |
2736 |
-#define YARATARGET0 "Target:0;" |
|
2737 |
-#define YARATARGET1 "Target:1;" |
|
2738 |
-#define EPSTR "EP+0:" |
|
2736 |
+#define YARA_DEBUG 1 |
|
2737 |
+#if YARA_DEBUG == 2 |
|
2738 |
+#define cli_yaramsg(...) cli_errmsg(__VA_ARGS__) |
|
2739 |
+#elseif YARA_DEBUG == 1 |
|
2740 |
+#define cli_yaramsg(...) cli_dbgmsg(__VA_ARGS__) |
|
2741 |
+#else |
|
2742 |
+#define cli_yaramsg(...) |
|
2743 |
+#endif |
|
2744 |
+ |
|
2739 | 2745 |
static char *parse_yara_hex_string(YR_STRING *string); |
2740 | 2746 |
|
2741 | 2747 |
static char *parse_yara_hex_string(YR_STRING *string) |
... | ... |
@@ -2805,250 +2811,362 @@ static char *parse_yara_hex_string(YR_STRING *string) |
2805 | 2805 |
return res; |
2806 | 2806 |
} |
2807 | 2807 |
|
2808 |
+int ytable_add(char ***ytablep, uint32_t *ytbl_cntp) |
|
2809 |
+{ |
|
2810 |
+} |
|
2811 |
+ |
|
2812 |
+uint32_t ytable_lookup(char **ytable, uint32_t ytbl_cnt) |
|
2813 |
+{ |
|
2814 |
+} |
|
2815 |
+ |
|
2816 |
+void ytable_delete(char **ytable, uint32_t ytbl_cnt) |
|
2817 |
+{ |
|
2818 |
+ uint32_t i; |
|
2819 |
+ |
|
2820 |
+ if (ytable) { |
|
2821 |
+ for (i = 0; i < ytbl_cnt; ++i) |
|
2822 |
+ free(ytable[i]); |
|
2823 |
+ free(ytable); |
|
2824 |
+ } |
|
2825 |
+} |
|
2826 |
+ |
|
2808 | 2827 |
static unsigned int yara_total, yara_malform, yara_complex; |
2828 |
+#define YARATARGET0 "Target:0" |
|
2829 |
+#define YARATARGET1 "Target:1" |
|
2830 |
+#define EPSTR "EP+0:" |
|
2809 | 2831 |
|
2810 |
-static int cli_loadyara(FILE *fs, const char *dbname, struct cl_engine *engine, unsigned int options, struct cli_dbio *dbio) |
|
2832 |
+/* yara has no apparent cap on the number of strings; TODO - should we have one? */ |
|
2833 |
+/* function base off load_oneldb */ |
|
2834 |
+static int load_oneyara(YR_RULE *rule, struct cl_engine *engine, unsigned int options, unsigned int *sigs) |
|
2811 | 2835 |
{ |
2812 |
- char buffer[FILEBUFF]; |
|
2813 |
- char * current_rule = NULL; |
|
2814 |
- char * current_meta = NULL; |
|
2815 |
- char * current_string = NULL; |
|
2816 |
- char * current_condition = NULL; |
|
2817 |
- int rc = CL_SUCCESS; |
|
2818 |
- uint32_t line = 0; |
|
2819 |
- uint8_t is_comment; |
|
2820 |
- uint8_t rule_state; |
|
2821 |
- YR_COMPILER compiler = {0}; |
|
2822 |
- YR_RULE * rule; |
|
2823 |
- YR_STRING * string; |
|
2824 |
- size_t nstrings, allstringsize, totsize; |
|
2825 |
- char *rulestr, *ruledup; |
|
2826 |
- unsigned int sigs, i; |
|
2827 |
- uint8_t has_short_string; |
|
2828 |
- char * exp_op = "|"; |
|
2836 |
+ YR_STRING *string; |
|
2837 |
+ int str_error = 0, i = 0, ret = CL_SUCCESS; |
|
2838 |
+ struct cli_lsig_tdb tdb; |
|
2839 |
+ uint32_t lsigid[2]; |
|
2840 |
+ struct cli_matcher *root; |
|
2841 |
+ struct cli_ac_lsig **newtable, *lsig; |
|
2842 |
+ unsigned short target = 0; |
|
2843 |
+ size_t lsize; |
|
2844 |
+ char *logic = NULL; |
|
2845 |
+ char *exp_op = "|"; |
|
2846 |
+ char *offset; |
|
2829 | 2847 |
|
2830 |
- if((rc = cli_initroots(engine, options))) |
|
2831 |
- return rc; |
|
2848 |
+ char **ytable = NULL; |
|
2849 |
+ uint32_t ytbl_cnt = 0; |
|
2832 | 2850 |
|
2833 |
- compiler.last_result = ERROR_SUCCESS; |
|
2834 |
- STAILQ_INIT(&compiler.rules); |
|
2835 |
- STAILQ_INIT(&compiler.current_rule_strings); |
|
2851 |
+ cli_yaramsg("called load_oneyara()\n"); |
|
2836 | 2852 |
|
2837 |
- // cli_errmsg("Loading yara signatures\n"); |
|
2838 |
-#if 1 /* for compilation */ |
|
2839 |
- yr_lex_parse_rules_file(fs, &compiler); |
|
2840 |
-#endif |
|
2841 |
- while (!STAILQ_EMPTY(&compiler.rules)) { |
|
2842 |
- yara_total++; |
|
2843 |
- sigs=0; |
|
2844 |
- nstrings=0; |
|
2845 |
- rule = STAILQ_FIRST(&compiler.rules); |
|
2846 |
- STAILQ_REMOVE(&compiler.rules, rule, _yc_rule, link); |
|
2853 |
+ if (!rule) { |
|
2854 |
+ cli_errmsg("load_oneyara: empty rule passed as argument\n"); |
|
2855 |
+ return CL_ENULLARG; |
|
2856 |
+ } |
|
2847 | 2857 |
|
2848 |
- /* First find out how long our dynamically-build ldb string should be */ |
|
2849 |
- allstringsize = 0; |
|
2850 |
- totsize = strlen(rule->id) + 2 + strlen(YARATARGET0); |
|
2851 |
- STAILQ_FOREACH(string, &rule->strings, link) { |
|
2852 |
- nstrings++; |
|
2853 |
- if (STRING_IS_HEX(string)) { |
|
2854 |
- size_t len = strlen(string->string); |
|
2855 |
- for (i=0; i < len; i++) { |
|
2856 |
- int ch = string->string[i]; |
|
2857 |
- if (!isspace(ch)) |
|
2858 |
- allstringsize++; |
|
2859 |
- } |
|
2860 |
- } else if (STRING_IS_REGEXP(string)) { |
|
2861 |
- char *trigger = PCRE_BYPASS; |
|
2862 |
- allstringsize += strlen(trigger); |
|
2863 |
- allstringsize += (strlen(string->string)+2); /* 2 from delimiters */ |
|
2864 |
- } else if (STRING_IS_NO_CASE(string)) { |
|
2865 |
- allstringsize += (strlen(string->string)+2); /* 2 from delimiter+option */ |
|
2866 |
- } else { |
|
2867 |
- allstringsize += strlen(string->string); |
|
2858 |
+ /* PUA stuff, for the future |
|
2859 |
+ if (chkpua && cli_chkpua(rule->id, engine->pua_cats, options)) |
|
2860 |
+ return CL_SUCCESS; |
|
2861 |
+ |
|
2862 |
+ if (engine->ignored && cli_chkign(engine->ignored, rule->id, buffer_cpy ? buffer_cpy : rule->id)) { |
|
2863 |
+ if(skip) |
|
2864 |
+ *skip = 1; |
|
2865 |
+ return CL_SUCCESS; |
|
2866 |
+ } |
|
2867 |
+ */ |
|
2868 |
+ |
|
2869 |
+ /*** rule specific checks ***/ |
|
2870 |
+ if (RULE_IS_PRIVATE(rule) || RULE_IS_GLOBAL(rule) || RULE_IS_NULL(rule) || |
|
2871 |
+ ((rule->g_flags) & RULE_GFLAGS_REQUIRE_FILE) || ((rule->g_flags) & RULE_GFLAGS_REQUIRE_EXECUTABLE)) { |
|
2872 |
+ |
|
2873 |
+ cli_warnmsg("load_oneyara: skipping %s due to unsupported rule gflags\n", rule->id); |
|
2874 |
+ (*sigs)--; |
|
2875 |
+ return CL_SUCCESS; |
|
2876 |
+ } |
|
2877 |
+ |
|
2878 |
+ if(engine->cb_sigload && engine->cb_sigload("yara", rule->id, ~options & CL_DB_OFFICIAL, engine->cb_sigload_ctx)) { |
|
2879 |
+ cli_dbgmsg("load_oneyara: skipping %s due to callback\n", rule->id); |
|
2880 |
+ (*sigs)--; |
|
2881 |
+ return CL_SUCCESS; |
|
2882 |
+ } |
|
2883 |
+ |
|
2884 |
+ /*** verification step - can clamav load it? ***/ |
|
2885 |
+ /*** initial population pass for the strings table ***/ |
|
2886 |
+ STAILQ_FOREACH(string, &rule->strings, link) { |
|
2887 |
+ char *substr; |
|
2888 |
+ |
|
2889 |
+ /* string type handler */ |
|
2890 |
+ if (STRING_IS_NULL(string)) { |
|
2891 |
+ cli_warnmsg("load_oneyara: skipping NULL string %s\n", rule->id); |
|
2892 |
+ //str_error++; /* kill the insertion? */ |
|
2893 |
+ continue; |
|
2894 |
+ } else if (STRING_IS_HEX(string)) { |
|
2895 |
+ substr = parse_yara_hex_string(string); |
|
2896 |
+ if (substr) { |
|
2897 |
+ /* |
|
2898 |
+ if (strlen(substr)/2 <= CLI_DEFAULT_AC_MINDEPTH) //FIXME: Yara has no length minimum |
|
2899 |
+ has_short_string = 1; |
|
2900 |
+ snprintf(rulestr+len, totsize-len, "%s", substr); |
|
2901 |
+ free(substr); |
|
2902 |
+ */ |
|
2868 | 2903 |
} |
2869 |
- } |
|
2870 | 2904 |
|
2871 |
- if (!nstrings) { |
|
2872 |
- cli_errmsg("Rule %s contains to readable strings\n", rule->id); |
|
2873 |
-#ifdef YARA_PROTO |
|
2874 |
- yara_malform++; |
|
2875 |
- free(rule->id); |
|
2876 |
- free(rule); |
|
2905 |
+ cli_yaramsg("Yara hex string: \"%s\"\n", substr); |
|
2906 |
+ } else if (STRING_IS_LITERAL(string)) { |
|
2907 |
+ } else if (STRING_IS_REGEXP(string)) { |
|
2908 |
+ } else { |
|
2909 |
+ cli_warnmsg("load_oneyara: skipping undefined typed string %s\n", rule->id); |
|
2910 |
+ //str_error++; /* kill the insertion? */ |
|
2877 | 2911 |
continue; |
2878 |
-#else |
|
2879 |
- return CL_EMALFDB; |
|
2880 |
-#endif |
|
2881 | 2912 |
} |
2882 | 2913 |
|
2883 |
- /* ldb can only handle MAX_LDB_SUBSIGS(currently 64) substrings */ |
|
2884 |
- if (nstrings > MAX_LDB_SUBSIGS) { |
|
2885 |
- cli_errmsg("cli_loadyara: rule %s exceeds MAX_LDB_SUBSIGS maximum strings - skipping.\n", rule->id); |
|
2886 |
- free(rule->id); |
|
2887 |
- free(rule); |
|
2914 |
+ /* modifier handler */ |
|
2915 |
+ if (STRING_IS_NO_CASE(string)) { |
|
2916 |
+ } |
|
2917 |
+ if (STRING_IS_ASCII(string)) { |
|
2918 |
+ } |
|
2919 |
+ if (STRING_IS_WIDE(string)) { |
|
2920 |
+ } |
|
2921 |
+ if (STRING_IS_FULL_WORD(string)) { |
|
2922 |
+ } |
|
2923 |
+ |
|
2924 |
+ /* special modifier handler */ |
|
2925 |
+ if (STRING_IS_ANONYMOUS(string)) { /* empty */ } |
|
2926 |
+ |
|
2927 |
+ /* unsupported(?) modifier handler */ |
|
2928 |
+ if (STRING_IS_REFERENCED(string) || STRING_IS_SINGLE_MATCH(string) || STRING_IS_FAST_HEX_REGEXP(string) || |
|
2929 |
+ STRING_IS_CHAIN_PART(string) || STRING_IS_CHAIN_TAIL(string) || STRING_FITS_IN_ATOM(string)) { |
|
2930 |
+ cli_warnmsg("load_oneyara: skipping unsupported string %s\n", rule->id); |
|
2931 |
+ str_error++; |
|
2932 |
+ free(substr); |
|
2888 | 2933 |
continue; |
2889 | 2934 |
} |
2935 |
+ } |
|
2890 | 2936 |
|
2891 |
- allstringsize *= 2; /* For converting to hex */ |
|
2892 |
- totsize += allstringsize; |
|
2893 |
- totsize += (nstrings * 3); /* 3 for |; */ |
|
2894 |
- if (nstrings > 10) |
|
2895 |
- totsize += nstrings-10; |
|
2896 |
- totsize++; |
|
2937 |
+ if (str_error > 0) { |
|
2938 |
+ cli_errmsg("load_oneyara: clamav does not support %d input strings\n", str_error); |
|
2939 |
+ ytable_delete(ytable, ytbl_cnt); |
|
2940 |
+ (*sigs)--; |
|
2941 |
+ return CL_SUCCESS; /* TODO - kill signature instead? */ |
|
2942 |
+ } else if (ytbl_cnt == 0) { |
|
2943 |
+ cli_errmsg("load_oneyara: yara contains no supported strings\n"); |
|
2944 |
+ ytable_delete(ytable, ytbl_cnt); |
|
2945 |
+ (*sigs)--; |
|
2946 |
+ return CL_SUCCESS; /* TODO - kill signature instead? */ |
|
2947 |
+ } |
|
2897 | 2948 |
|
2898 |
-#ifdef YARA_PROTO |
|
2899 |
- if (rule->g_flags & RULE_EP && nstrings == 1) |
|
2900 |
- totsize += strlen(EPSTR); |
|
2901 |
-#endif |
|
2949 |
+ /*** conditional verification step (ex. do we define too many strings versus used?) ***/ |
|
2950 |
+ /*** additional string table population (ex. offsets), second translation table pass ***/ |
|
2902 | 2951 |
|
2903 |
- rulestr = cli_calloc(totsize, sizeof(char)); |
|
2904 |
- if (!rulestr) { |
|
2905 |
- free(rule->id); |
|
2906 |
- free(rule); |
|
2907 |
- rc = CL_EMEM; |
|
2908 |
- break; |
|
2952 |
+ lsize = 3*ytbl_cnt; |
|
2953 |
+ logic = cli_calloc(lsize, sizeof(char)); |
|
2954 |
+ if (!logic) { |
|
2955 |
+ cli_errmsg("load_oneyara: cannot allocate memory for logic statement\n"); |
|
2956 |
+ ytable_delete(ytable, ytbl_cnt); |
|
2957 |
+ return CL_EMEM; |
|
2958 |
+ } |
|
2959 |
+ |
|
2960 |
+ if (rule->g_flags & RULE_ALL && rule->g_flags & RULE_THEM) |
|
2961 |
+ exp_op = "&"; |
|
2962 |
+ else { |
|
2963 |
+ exp_op = "|"; |
|
2964 |
+ if ((!(rule->g_flags & RULE_ANY && rule->g_flags & RULE_THEM) && ytbl_cnt > 1) && |
|
2965 |
+ !(rule->g_flags & RULE_EP && ytbl_cnt == 1)) |
|
2966 |
+ yara_complex++; |
|
2967 |
+ } |
|
2968 |
+ |
|
2969 |
+ for (i=0; i<ytbl_cnt; i++) { |
|
2970 |
+ size_t len=strlen(logic); |
|
2971 |
+ snprintf(logic+len, lsize-len, "%u%s", i, (i+1 == ytbl_cnt) ? "" : exp_op); |
|
2972 |
+ } |
|
2973 |
+ |
|
2974 |
+ /*** END CONDITIONAL HANDLING ***/ |
|
2975 |
+ |
|
2976 |
+ /* TDB */ |
|
2977 |
+ memset(&tdb, 0, sizeof(tdb)); |
|
2978 |
+#ifdef USE_MPOOL |
|
2979 |
+ tdb.mempool = engine->mempool; |
|
2980 |
+#endif |
|
2981 |
+ if((ret = lsigattribs(YARATARGET0, &tdb))) { |
|
2982 |
+ FREE_TDB(tdb); |
|
2983 |
+ if(ret == 1) { |
|
2984 |
+ cli_dbgmsg("load_oneyara: Not supported attribute(s) in logical signature for %s, skipping\n", rule->id); |
|
2985 |
+ ytable_delete(ytable, ytbl_cnt); |
|
2986 |
+ free(logic); |
|
2987 |
+ (*sigs)--; |
|
2988 |
+ return CL_SUCCESS; |
|
2909 | 2989 |
} |
2990 |
+ return CL_EMALFDB; |
|
2991 |
+ } |
|
2910 | 2992 |
|
2911 |
-#ifdef YARA_PROTO |
|
2912 |
- if (rule->g_flags & RULE_ALL && rule->g_flags & RULE_THEM) |
|
2913 |
- exp_op = "&"; |
|
2914 |
- else { |
|
2915 |
- exp_op = "|"; |
|
2916 |
- if ((!(rule->g_flags & RULE_ANY && rule->g_flags & RULE_THEM) && nstrings > 1) && |
|
2917 |
- !(rule->g_flags & RULE_EP && nstrings == 1)) |
|
2918 |
- yara_complex++; |
|
2993 |
+ if(tdb.engine) { |
|
2994 |
+ if(tdb.engine[0] > cl_retflevel()) { |
|
2995 |
+ cli_dbgmsg("load_oneyara: Signature for %s not loaded (required f-level: %u)\n", rule->id, tdb.engine[0]); |
|
2996 |
+ FREE_TDB(tdb); |
|
2997 |
+ ytable_delete(ytable, ytbl_cnt); |
|
2998 |
+ free(logic); |
|
2999 |
+ (*sigs)--; |
|
3000 |
+ return CL_SUCCESS; |
|
3001 |
+ } else if(tdb.engine[1] < cl_retflevel()) { |
|
3002 |
+ FREE_TDB(tdb); |
|
3003 |
+ ytable_delete(ytable, ytbl_cnt); |
|
3004 |
+ free(logic); |
|
3005 |
+ (*sigs)--; |
|
3006 |
+ return CL_SUCCESS; |
|
2919 | 3007 |
} |
2920 |
- if (rule->g_flags & RULE_EP) |
|
2921 |
- sprintf(rulestr, "%s;%s(", rule->id, YARATARGET1); |
|
2922 |
- else |
|
2923 |
-#endif |
|
2924 |
- sprintf(rulestr, "%s;%s(", rule->id, YARATARGET0); |
|
2925 |
- for (i=0; i<nstrings; i++) { |
|
2926 |
- size_t len=strlen(rulestr); |
|
2927 |
- snprintf(rulestr+len, totsize-len, "%u%s", i, (i+1 == nstrings) ? "" : exp_op); |
|
3008 |
+ } |
|
3009 |
+ |
|
3010 |
+ if(!tdb.target) { |
|
3011 |
+ cli_errmsg("load_oneyara: No target specified in TDB\n"); |
|
3012 |
+ FREE_TDB(tdb); |
|
3013 |
+ ytable_delete(ytable, ytbl_cnt); |
|
3014 |
+ free(logic); |
|
3015 |
+ return CL_EMALFDB; |
|
3016 |
+ } else if(tdb.target[0] >= CLI_MTARGETS) { |
|
3017 |
+ cli_dbgmsg("load_oneyara: Not supported target type in logical signature for %s, skipping\n", rule->id); |
|
3018 |
+ FREE_TDB(tdb); |
|
3019 |
+ ytable_delete(ytable, ytbl_cnt); |
|
3020 |
+ free(logic); |
|
3021 |
+ (*sigs)--; |
|
3022 |
+ return CL_SUCCESS; |
|
3023 |
+ } |
|
3024 |
+ |
|
3025 |
+ if((tdb.icongrp1 || tdb.icongrp2) && tdb.target[0] != 1) { |
|
3026 |
+ cli_errmsg("load_oneyara: IconGroup is only supported in PE (target 1) signatures\n"); |
|
3027 |
+ FREE_TDB(tdb); |
|
3028 |
+ ytable_delete(ytable, ytbl_cnt); |
|
3029 |
+ free(logic); |
|
3030 |
+ return CL_EMALFDB; |
|
3031 |
+ } |
|
3032 |
+ |
|
3033 |
+ if((tdb.ep || tdb.nos) && tdb.target[0] != 1 && tdb.target[0] != 6 && tdb.target[0] != 9) { |
|
3034 |
+ cli_errmsg("load_oneyara: EntryPoint/NumberOfSections is only supported in PE/ELF/Mach-O signatures\n"); |
|
3035 |
+ FREE_TDB(tdb); |
|
3036 |
+ ytable_delete(ytable, ytbl_cnt); |
|
3037 |
+ free(logic); |
|
3038 |
+ return CL_EMALFDB; |
|
3039 |
+ } |
|
3040 |
+ |
|
3041 |
+ /*** populating lsig ***/ |
|
3042 |
+ root = engine->root[tdb.target[0]]; |
|
3043 |
+ |
|
3044 |
+ lsig = (struct cli_ac_lsig *) mpool_calloc(engine->mempool, 1, sizeof(struct cli_ac_lsig)); |
|
3045 |
+ if(!lsig) { |
|
3046 |
+ cli_errmsg("load_oneyara: Can't allocate memory for lsig\n"); |
|
3047 |
+ FREE_TDB(tdb); |
|
3048 |
+ ytable_delete(ytable, ytbl_cnt); |
|
3049 |
+ free(logic); |
|
3050 |
+ return CL_EMEM; |
|
3051 |
+ } |
|
3052 |
+ |
|
3053 |
+ if (logic) { |
|
3054 |
+ lsig->type = CLI_NORMAL_LSIG; |
|
3055 |
+ lsig->u.logic = cli_mpool_strdup(engine->mempool, logic); |
|
3056 |
+ if(!lsig->u.logic) { |
|
3057 |
+ cli_errmsg("load_oneyara: Can't allocate memory for lsig->logic\n"); |
|
3058 |
+ FREE_TDB(tdb); |
|
3059 |
+ ytable_delete(ytable, ytbl_cnt); |
|
3060 |
+ free(logic); |
|
3061 |
+ mpool_free(engine->mempool, lsig); |
|
3062 |
+ return CL_EMEM; |
|
2928 | 3063 |
} |
3064 |
+ } else { |
|
3065 |
+ cli_errmsg("load_oneyara: Unsupported logic type\n"); |
|
3066 |
+ FREE_TDB(tdb); |
|
3067 |
+ ytable_delete(ytable, ytbl_cnt); |
|
3068 |
+ free(logic); |
|
3069 |
+ mpool_free(engine->mempool, lsig); |
|
3070 |
+ return CL_EMEM; |
|
3071 |
+ } |
|
3072 |
+ free(logic); |
|
2929 | 3073 |
|
2930 |
- strcat(rulestr, ");"); |
|
3074 |
+ lsigid[0] = lsig->id = root->ac_lsigs; |
|
2931 | 3075 |
|
2932 |
- has_short_string = 0; |
|
2933 |
- int dcount = 0; |
|
2934 |
- while (!STAILQ_EMPTY(&rule->strings)) { |
|
2935 |
- string = STAILQ_FIRST(&rule->strings); |
|
2936 |
- STAILQ_REMOVE(&rule->strings, string, _yc_string, link); |
|
3076 |
+ root->ac_lsigs++; |
|
3077 |
+ newtable = (struct cli_ac_lsig **) mpool_realloc(engine->mempool, root->ac_lsigtable, root->ac_lsigs * sizeof(struct cli_ac_lsig *)); |
|
3078 |
+ if(!newtable) { |
|
3079 |
+ root->ac_lsigs--; |
|
3080 |
+ cli_errmsg("cli_loadldb: Can't realloc root->ac_lsigtable\n"); |
|
3081 |
+ FREE_TDB(tdb); |
|
3082 |
+ ytable_delete(ytable, ytbl_cnt); |
|
3083 |
+ mpool_free(engine->mempool, lsig); |
|
3084 |
+ return CL_EMEM; |
|
3085 |
+ } |
|
2937 | 3086 |
|
2938 |
-#if 0 |
|
2939 |
- cli_errmsg("%i:", ++dcount); |
|
2940 |
-#endif |
|
2941 |
-#ifdef YARA_PROTO |
|
2942 |
- if (rule->g_flags & RULE_EP && nstrings == 1) { |
|
2943 |
- size_t len = strlen(rulestr); |
|
2944 |
- snprintf(rulestr+len, totsize-len, "%s", EPSTR); |
|
2945 |
- } |
|
2946 |
-#endif |
|
3087 |
+ newtable[root->ac_lsigs - 1] = lsig; |
|
3088 |
+ root->ac_lsigtable = newtable; |
|
3089 |
+ tdb.subsigs = ytbl_cnt; |
|
2947 | 3090 |
|
2948 |
- if (STRING_IS_HEX(string)) { |
|
2949 |
- char *substr; |
|
2950 |
- size_t len = strlen(rulestr); |
|
3091 |
+ /*** loading step - put things into the AC trie ***/ |
|
3092 |
+ for (i = 0; i < ytbl_cnt; ++i) { |
|
3093 |
+ lsigid[1] = i; |
|
2951 | 3094 |
|
2952 |
- substr = parse_yara_hex_string(string); |
|
2953 |
-#if 0 |
|
2954 |
- cli_errmsg("Yara hex string: \"%s\"\n", substr); |
|
2955 |
-#endif |
|
2956 |
- if (substr) { |
|
2957 |
- if (strlen(substr)/2 <= CLI_DEFAULT_AC_MINDEPTH) //FIXME: Yara has no length minimum |
|
2958 |
- has_short_string = 1; |
|
2959 |
- snprintf(rulestr+len, totsize-len, "%s", substr); |
|
2960 |
- free(substr); |
|
2961 |
- } |
|
2962 |
- } else if (STRING_IS_REGEXP(string)) { |
|
2963 |
- size_t len = strlen(rulestr); |
|
2964 |
-#if 0 |
|
2965 |
- cli_errmsg("Yara regex string: \"%s\"\n", string->string); |
|
2966 |
-#endif |
|
2967 |
- snprintf(rulestr+len, totsize-len, "%s/%s/", PCRE_BYPASS, string->string); |
|
2968 |
- } else if (STRING_IS_NO_CASE(string)) { |
|
2969 |
- size_t len; |
|
2970 |
-#if 0 |
|
2971 |
- cli_errmsg("Yara nocase string: \"%s\"\n", string->string); |
|
2972 |
-#endif |
|
2973 |
- if (strlen(string->string) <= CLI_DEFAULT_AC_MINDEPTH) //FIXME: Yara has no length minimum |
|
2974 |
- has_short_string = 1; |
|
2975 |
- for (i=0; i < strlen(string->string); i++) { |
|
2976 |
- len = strlen(rulestr); |
|
2977 |
- snprintf(rulestr+len, totsize-len, "%02x", string->string[i]); |
|
2978 |
- } |
|
3095 |
+ /* TODO - offsets as separate table or integrated into ytable[i]? */ |
|
3096 |
+ offset = "*"; |
|
2979 | 3097 |
|
2980 |
- len = strlen(rulestr); |
|
2981 |
- snprintf(rulestr+len, totsize-len, "/i"); |
|
2982 |
- } else { |
|
2983 |
-#if 0 |
|
2984 |
- cli_errmsg("Yara literal string: \"%s\"\n", string->string); |
|
2985 |
-#endif |
|
2986 |
- if (strlen(string->string) <= CLI_DEFAULT_AC_MINDEPTH) //FIXME: Yara has no length minimum |
|
2987 |
- has_short_string = 1; |
|
2988 |
- for (i=0; i < strlen(string->string); i++) { |
|
2989 |
- size_t len = strlen(rulestr); |
|
2990 |
- snprintf(rulestr+len, totsize-len, "%02x", string->string[i]); |
|
2991 |
- } |
|
2992 |
- } |
|
3098 |
+ /* TODO - options as separate table or integrated into ytable[i]? */ |
|
2993 | 3099 |
|
2994 |
- if (!STAILQ_EMPTY(&rule->strings)) |
|
2995 |
- strcat(rulestr, ";"); |
|
3100 |
+ if((ret = cli_parse_add(root, rule->id, ytable[i], NULL, 0, 0, offset, target, lsigid, options))) |
|
3101 |
+ return ret; |
|
3102 |
+ } |
|
2996 | 3103 |
|
2997 |
- free(string->id); |
|
2998 |
- free(string->string); |
|
2999 |
- free(string); |
|
3000 |
- } |
|
3104 |
+ memcpy(&lsig->tdb, &tdb, sizeof(tdb)); |
|
3105 |
+ ytable_delete(ytable, ytbl_cnt); |
|
3106 |
+ return CL_SUCCESS; |
|
3107 |
+} |
|
3001 | 3108 |
|
3002 |
- if (rulestr[strlen(rulestr)-1] == ';') |
|
3003 |
- rulestr[strlen(rulestr)-1] = '\0'; |
|
3109 |
+//TODO - pua? dbio? |
|
3110 |
+static int cli_loadyara(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio, const char *dbname) |
|
3111 |
+{ |
|
3112 |
+ YR_COMPILER compiler = {0}; |
|
3113 |
+ YR_RULE *rule; |
|
3114 |
+ unsigned int sigs = 0, rules = 0; |
|
3115 |
+ int rc; |
|
3004 | 3116 |
|
3005 |
-#if 0 |
|
3006 |
- printf("[+] computed ldb: \"%s\"\n", rulestr); |
|
3007 |
-#endif |
|
3008 |
- ruledup = cli_malloc(strlen(rulestr)+1); |
|
3009 |
- if (!ruledup) { |
|
3010 |
- free(rulestr); |
|
3011 |
- free(rule->id); |
|
3012 |
- free(rule); |
|
3013 |
- rc = CL_EMEM; |
|
3014 |
- break; |
|
3015 |
- } |
|
3117 |
+ UNUSEDPARAM(dbio); |
|
3016 | 3118 |
|
3017 |
- strcpy(ruledup, rulestr); |
|
3119 |
+ if((rc = cli_initroots(engine, options))) |
|
3120 |
+ return rc; |
|
3018 | 3121 |
|
3019 |
- if (has_short_string == 0) { |
|
3020 |
-#if 1 |
|
3021 |
- rc = load_oneldb(rulestr, |
|
3022 |
- engine->pua_cats && (options & CL_DB_PUA_MODE) && (options & (CL_DB_PUA_INCLUDE | CL_DB_PUA_EXCLUDE)), |
|
3023 |
- engine, options, rule->id, line++, &sigs, 0, ruledup, NULL); |
|
3024 |
-#endif |
|
3122 |
+ compiler.last_result = ERROR_SUCCESS; |
|
3123 |
+ STAILQ_INIT(&compiler.rules); |
|
3124 |
+ STAILQ_INIT(&compiler.current_rule_strings); |
|
3025 | 3125 |
|
3026 |
- } |
|
3027 |
- else { |
|
3028 |
- cli_errmsg("cli_loadyara: has short strings, rule %s excluded\n", rulestr); |
|
3029 |
- } |
|
3030 |
-#if 0 |
|
3031 |
- printf("totsize: %zu\treal size: %zu\n", totsize, strlen(ruledup)); |
|
3032 |
-#endif |
|
3126 |
+ rc = yr_lex_parse_rules_file(fs, &compiler); |
|
3127 |
+ if (rc > 0) { /* rc = number of errors */ |
|
3128 |
+ /* TODO - handle the various errors? */ |
|
3129 |
+ cli_errmsg("cli_loadyara: failed to parse rules file\n"); |
|
3130 |
+ return CL_EMALFDB; |
|
3131 |
+ } |
|
3033 | 3132 |
|
3034 |
- free(rulestr); |
|
3035 |
- free(ruledup); |
|
3036 |
- free(rule->id); |
|
3037 |
- free(rule); |
|
3038 |
-#ifdef YARA_PROTO |
|
3039 |
- if (rc == CL_EMALFDB) { |
|
3040 |
- yara_malform++; |
|
3041 |
- cli_errmsg("+++++++++++++ load_oneldb returns CL_EMALFORMDB +++++++++++++\n"); |
|
3042 |
- rc = CL_SUCCESS; |
|
3043 |
- continue; |
|
3044 |
- } |
|
3045 |
-#endif |
|
3133 |
+ while (!STAILQ_EMPTY(&compiler.rules)) { |
|
3134 |
+ rule = STAILQ_FIRST(&compiler.rules); |
|
3135 |
+ STAILQ_REMOVE(&compiler.rules, rule, _yc_rule, link); |
|
3136 |
+ |
|
3137 |
+ rules++; |
|
3138 |
+ sigs++; |
|
3139 |
+ |
|
3140 |
+ /* TODO - PUA and engine->ignored */ |
|
3141 |
+ rc = load_oneyara(rule, engine, options, &sigs); |
|
3046 | 3142 |
if (rc != CL_SUCCESS) |
3047 | 3143 |
break; |
3048 | 3144 |
} |
3049 | 3145 |
|
3050 |
- return rc; |
|
3146 |
+ if(rc) { |
|
3147 |
+ cli_errmsg("cli_loadyara: problem parsing yara rule %s\n", rule->id); |
|
3148 |
+ return rc; |
|
3149 |
+ } |
|
3150 |
+ |
|
3151 |
+ if(!rules) { |
|
3152 |
+ cli_errmsg("cli_loadyara: empty database file\n"); |
|
3153 |
+ return CL_EMALFDB; |
|
3154 |
+ } |
|
3155 |
+ |
|
3156 |
+ if(signo) |
|
3157 |
+ *signo += sigs; |
|
3158 |
+ |
|
3159 |
+ cli_yaramsg("Successfully loaded %u of %u yara signatures from %s\n", sigs, rules, dbname); |
|
3160 |
+ |
|
3161 |
+ return CL_SUCCESS; |
|
3051 | 3162 |
} |
3163 |
+ |
|
3052 | 3164 |
#endif |
3053 | 3165 |
|
3054 | 3166 |
static int cli_loaddbdir(const char *dirname, struct cl_engine *engine, unsigned int *signo, unsigned int options); |
... | ... |
@@ -3183,7 +3301,7 @@ int cli_load(const char *filename, struct cl_engine *engine, unsigned int *signo |
3183 | 3183 |
ret = cli_loadopenioc(fs, dbname, engine, options); |
3184 | 3184 |
#ifndef _WIN32 /* FIXME: temp until clam yara for windows */ |
3185 | 3185 |
} else if(cli_strbcasestr(dbname, ".yar") || cli_strbcasestr(dbname, ".yara")) { |
3186 |
- ret = cli_loadyara(fs, dbname, engine, options, dbio); |
|
3186 |
+ ret = cli_loadyara(fs, engine, signo, options, dbio, dbname); |
|
3187 | 3187 |
#endif |
3188 | 3188 |
} else { |
3189 | 3189 |
cli_dbgmsg("cli_load: unknown extension - assuming old database format\n"); |