Browse code

add YARA condition processor (preliminary/work in progress)

Steven Morgan authored on 2015/03/03 09:37:50
Showing 5 changed files
... ...
@@ -447,6 +447,8 @@ libclamav_la_SOURCES = \
447 447
 	openioc.h \
448 448
 	yara_arena.c \
449 449
 	yara_arena.h \
450
+	yara_exec.c \
451
+	yara_exec.h \
450 452
 	yara_hash.c \
451 453
 	yara_hash.h \
452 454
 	yara_grammar.y \
... ...
@@ -239,17 +239,17 @@ am_libclamav_la_OBJECTS = libclamav_la-matcher-ac.lo \
239 239
 	libclamav_la-asn1.lo libclamav_la-fpu.lo libclamav_la-stats.lo \
240 240
 	libclamav_la-www.lo libclamav_la-stats_json.lo \
241 241
 	libclamav_la-hostid.lo libclamav_la-openioc.lo \
242
-	libclamav_la-yara_arena.lo libclamav_la-yara_hash.lo \
243
-	libclamav_la-yara_grammar.lo libclamav_la-yara_lexer.lo \
244
-	libclamav_la-yara_parser.lo libclamav_la-msdoc.lo \
245
-	libclamav_la-matcher-pcre.lo libclamav_la-regex_pcre.lo \
246
-	libclamav_la-fp_add.lo libclamav_la-fp_add_d.lo \
247
-	libclamav_la-fp_addmod.lo libclamav_la-fp_cmp.lo \
248
-	libclamav_la-fp_cmp_d.lo libclamav_la-fp_cmp_mag.lo \
249
-	libclamav_la-fp_sub.lo libclamav_la-fp_sub_d.lo \
250
-	libclamav_la-fp_submod.lo libclamav_la-s_fp_add.lo \
251
-	libclamav_la-s_fp_sub.lo libclamav_la-fp_radix_size.lo \
252
-	libclamav_la-fp_read_radix.lo \
242
+	libclamav_la-yara_arena.lo libclamav_la-yara_exec.lo \
243
+	libclamav_la-yara_hash.lo libclamav_la-yara_grammar.lo \
244
+	libclamav_la-yara_lexer.lo libclamav_la-yara_parser.lo \
245
+	libclamav_la-msdoc.lo libclamav_la-matcher-pcre.lo \
246
+	libclamav_la-regex_pcre.lo libclamav_la-fp_add.lo \
247
+	libclamav_la-fp_add_d.lo libclamav_la-fp_addmod.lo \
248
+	libclamav_la-fp_cmp.lo libclamav_la-fp_cmp_d.lo \
249
+	libclamav_la-fp_cmp_mag.lo libclamav_la-fp_sub.lo \
250
+	libclamav_la-fp_sub_d.lo libclamav_la-fp_submod.lo \
251
+	libclamav_la-s_fp_add.lo libclamav_la-s_fp_sub.lo \
252
+	libclamav_la-fp_radix_size.lo libclamav_la-fp_read_radix.lo \
253 253
 	libclamav_la-fp_read_signed_bin.lo \
254 254
 	libclamav_la-fp_read_unsigned_bin.lo \
255 255
 	libclamav_la-fp_reverse.lo libclamav_la-fp_s_rmap.lo \
... ...
@@ -835,13 +835,14 @@ libclamav_la_SOURCES = matcher-ac.c matcher-ac.h matcher-bm.c \
835 835
 	iso9660.h arc4.c arc4.h rijndael.c rijndael.h crtmgr.c \
836 836
 	crtmgr.h asn1.c asn1.h fpu.c fpu.h stats.c stats.h www.c www.h \
837 837
 	stats_json.c stats_json.h hostid.c hostid.h openioc.c \
838
-	openioc.h yara_arena.c yara_arena.h yara_hash.c yara_hash.h \
839
-	yara_grammar.y yara_lexer.l yara_lexer.h yara_parser.c \
840
-	yara_parser.h yara_clam.h msdoc.c msdoc.h matcher-pcre.c \
841
-	matcher-pcre.h regex_pcre.c regex_pcre.h bignum.h \
842
-	bignum_fast.h tomsfastmath/addsub/fp_add.c \
843
-	tomsfastmath/addsub/fp_add_d.c tomsfastmath/addsub/fp_addmod.c \
844
-	tomsfastmath/addsub/fp_cmp.c tomsfastmath/addsub/fp_cmp_d.c \
838
+	openioc.h yara_arena.c yara_arena.h yara_exec.c yara_exec.h \
839
+	yara_hash.c yara_hash.h yara_grammar.y yara_lexer.l \
840
+	yara_lexer.h yara_parser.c yara_parser.h yara_clam.h msdoc.c \
841
+	msdoc.h matcher-pcre.c matcher-pcre.h regex_pcre.c \
842
+	regex_pcre.h bignum.h bignum_fast.h \
843
+	tomsfastmath/addsub/fp_add.c tomsfastmath/addsub/fp_add_d.c \
844
+	tomsfastmath/addsub/fp_addmod.c tomsfastmath/addsub/fp_cmp.c \
845
+	tomsfastmath/addsub/fp_cmp_d.c \
845 846
 	tomsfastmath/addsub/fp_cmp_mag.c tomsfastmath/addsub/fp_sub.c \
846 847
 	tomsfastmath/addsub/fp_sub_d.c tomsfastmath/addsub/fp_submod.c \
847 848
 	tomsfastmath/addsub/s_fp_add.c tomsfastmath/addsub/s_fp_sub.c \
... ...
@@ -1250,6 +1251,7 @@ distclean-compile:
1250 1250
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-xdp.Plo@am__quote@
1251 1251
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-xz_iface.Plo@am__quote@
1252 1252
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-yara_arena.Plo@am__quote@
1253
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-yara_exec.Plo@am__quote@
1253 1254
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-yara_grammar.Plo@am__quote@
1254 1255
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-yara_hash.Plo@am__quote@
1255 1256
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-yara_lexer.Plo@am__quote@
... ...
@@ -2253,6 +2255,13 @@ libclamav_la-yara_arena.lo: yara_arena.c
2253 2253
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2254 2254
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-yara_arena.lo `test -f 'yara_arena.c' || echo '$(srcdir)/'`yara_arena.c
2255 2255
 
2256
+libclamav_la-yara_exec.lo: yara_exec.c
2257
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-yara_exec.lo -MD -MP -MF $(DEPDIR)/libclamav_la-yara_exec.Tpo -c -o libclamav_la-yara_exec.lo `test -f 'yara_exec.c' || echo '$(srcdir)/'`yara_exec.c
2258
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-yara_exec.Tpo $(DEPDIR)/libclamav_la-yara_exec.Plo
2259
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='yara_exec.c' object='libclamav_la-yara_exec.lo' libtool=yes @AMDEPBACKSLASH@
2260
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2261
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-yara_exec.lo `test -f 'yara_exec.c' || echo '$(srcdir)/'`yara_exec.c
2262
+
2256 2263
 libclamav_la-yara_hash.lo: yara_hash.c
2257 2264
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-yara_hash.lo -MD -MP -MF $(DEPDIR)/libclamav_la-yara_hash.Tpo -c -o libclamav_la-yara_hash.lo `test -f 'yara_hash.c' || echo '$(srcdir)/'`yara_hash.c
2258 2265
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-yara_hash.Tpo $(DEPDIR)/libclamav_la-yara_hash.Plo
... ...
@@ -166,6 +166,21 @@ typedef struct _YR_OBJECT
166 166
 
167 167
 } YR_OBJECT;
168 168
 
169
+typedef struct _YR_OBJECT_INTEGER
170
+{
171
+  OBJECT_COMMON_FIELDS
172
+  int64_t value;
173
+
174
+} YR_OBJECT_INTEGER;
175
+
176
+
177
+typedef struct _YR_OBJECT_STRING
178
+{
179
+  OBJECT_COMMON_FIELDS
180
+  char* value;
181
+
182
+} YR_OBJECT_STRING;
183
+
169 184
 typedef struct _YR_OBJECT_ARRAY
170 185
 {
171 186
   OBJECT_COMMON_FIELDS
... ...
@@ -173,6 +188,30 @@ typedef struct _YR_OBJECT_ARRAY
173 173
 
174 174
 } YR_OBJECT_ARRAY;
175 175
 
176
+#if 1
177
+//TDB TEMP for exec.c compile
178
+typedef struct _YR_SCAN_CONTEXT
179
+{
180
+  uint64_t  file_size;
181
+  uint64_t  entry_point;
182
+
183
+  int flags;
184
+  void* user_data;
185
+
186
+    //YR_MEMORY_BLOCK*  mem_block;
187
+  YR_HASH_TABLE*  objects_table;
188
+    //YR_CALLBACK_FUNC  callback;
189
+
190
+} YR_SCAN_CONTEXT;
191
+#endif
192
+
193
+struct _YR_OBJECT_FUNCTION;
194
+
195
+typedef int (*YR_MODULE_FUNC)(
196
+    void* args,
197
+    YR_SCAN_CONTEXT* context,
198
+    struct _YR_OBJECT_FUNCTION* function_obj);
199
+
176 200
 typedef struct _YR_OBJECT_FUNCTION
177 201
 {
178 202
   OBJECT_COMMON_FIELDS
... ...
@@ -180,9 +219,9 @@ typedef struct _YR_OBJECT_FUNCTION
180 180
   const char* arguments_fmt;
181 181
 
182 182
   YR_OBJECT* return_obj;
183
-#if REAL_YARA
183
+    //#if REAL_YARA
184 184
   YR_MODULE_FUNC code;
185
-#endif
185
+    //#endif
186 186
 
187 187
 } YR_OBJECT_FUNCTION;
188 188
 
... ...
@@ -473,6 +512,7 @@ struct RE {
473 473
 #define OBJECT_TYPE_REGEXP      6
474 474
 
475 475
 /* From libyara/include/yara/utils.h */
476
+#define UINT64_TO_PTR(type, x)  ((type)(size_t) x)
476 477
 #define PTR_TO_UINT64(x)  ((uint64_t) (size_t) x)
477 478
 
478 479
 #define YARA_PROTO
479 480
new file mode 100644
... ...
@@ -0,0 +1,811 @@
0
+/*
1
+Copyright (c) 2013. The YARA Authors. All Rights Reserved.
2
+
3
+Licensed under the Apache License, Version 2.0 (the "License");
4
+you may not use this file except in compliance with the License.
5
+You may obtain a copy of the License at
6
+
7
+   http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+Unless required by applicable law or agreed to in writing, software
10
+distributed under the License is distributed on an "AS IS" BASIS,
11
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+See the License for the specific language governing permissions and
13
+limitations under the License.
14
+*/
15
+
16
+#include <string.h>
17
+#include <assert.h>
18
+#include <time.h>
19
+
20
+#if REAL_YARA
21
+#include <yara/exec.h>
22
+#include <yara/limits.h>
23
+#include <yara/error.h>
24
+#include <yara/object.h>
25
+#include <yara/modules.h>
26
+#include <yara/re.h>
27
+
28
+
29
+#include <yara.h>
30
+#else
31
+#include <stdint.h>
32
+//Temp for ClamAV compilation
33
+typedef struct _YR_MATCH
34
+{
35
+  int64_t base;
36
+  int64_t offset;
37
+  int32_t length;
38
+
39
+  union {
40
+    uint8_t* data;           // Confirmed matches use "data",
41
+    int32_t chain_length;    // unconfirmed ones use "chain_length"
42
+  };
43
+
44
+  struct _YR_MATCH*  prev;
45
+  struct _YR_MATCH*  next;
46
+
47
+} YR_MATCH;
48
+
49
+// End of temp for clamAV
50
+#include "yara_clam.h"
51
+#include "yara_exec.h"
52
+#endif
53
+
54
+#define STACK_SIZE 16384
55
+#define MEM_SIZE   MAX_LOOP_NESTING * LOOP_LOCAL_VARS
56
+
57
+
58
+#define push(x)  \
59
+    do { \
60
+      if (sp < STACK_SIZE) stack[sp++] = (x); \
61
+      else return ERROR_EXEC_STACK_OVERFLOW; \
62
+    } while(0)
63
+
64
+
65
+#define pop(x)  x = stack[--sp]
66
+
67
+
68
+#define operation(operator, op1, op2) \
69
+    (IS_UNDEFINED(op1) || IS_UNDEFINED(op2)) ? (UNDEFINED) : (op1 operator op2)
70
+
71
+
72
+#define comparison(operator, op1, op2) \
73
+    (IS_UNDEFINED(op1) || IS_UNDEFINED(op2)) ? (0) : (op1 operator op2)
74
+
75
+
76
+#if REAL_YARA
77
+#define function_read(type) \
78
+    int64_t read_##type(YR_MEMORY_BLOCK* block, size_t offset) \
79
+    { \
80
+      while (block != NULL) \
81
+      { \
82
+        if (offset >= block->base && \
83
+            block->size >= sizeof(type) && \
84
+            offset <= block->base + block->size - sizeof(type)) \
85
+        { \
86
+          return *((type *) (block->data + offset - block->base)); \
87
+        } \
88
+        block = block->next; \
89
+      } \
90
+      return UNDEFINED; \
91
+    };
92
+
93
+function_read(uint8_t)
94
+function_read(uint16_t)
95
+function_read(uint32_t)
96
+function_read(int8_t)
97
+function_read(int16_t)
98
+function_read(int32_t)
99
+#endif
100
+
101
+int yr_execute_code(
102
+#if REAL_YARA
103
+    YR_RULES* rules,
104
+#else
105
+    uint8_t* ip,
106
+#endif
107
+    YR_SCAN_CONTEXT* context,
108
+    int timeout,
109
+    time_t start_time)
110
+{
111
+  int64_t r1;
112
+  int64_t r2;
113
+  int64_t r3;
114
+  int64_t mem[MEM_SIZE];
115
+  int64_t stack[STACK_SIZE];
116
+  int64_t args[MAX_FUNCTION_ARGS];
117
+  int32_t sp = 0;
118
+#if REAL_YARA
119
+  uint8_t* ip = rules->code_start;
120
+#endif
121
+
122
+  YR_RULE* rule;
123
+  YR_STRING* string;
124
+  YR_MATCH* match;
125
+  YR_OBJECT* object;
126
+  YR_OBJECT_FUNCTION* function;
127
+
128
+  char* identifier;
129
+
130
+  int i;
131
+  int found;
132
+  int count;
133
+  int result;
134
+  int cycle = 0;
135
+#if REAL_YARA
136
+  int tidx = yr_get_tidx();
137
+#endif
138
+
139
+  #ifdef PROFILING_ENABLED
140
+  clock_t start = clock();
141
+  #endif
142
+
143
+  while(1)
144
+  {
145
+    switch(*ip)
146
+    {
147
+      case OP_HALT:
148
+        // When the halt instruction is reached the stack
149
+        // should be empty.
150
+        assert(sp == 0);
151
+        return ERROR_SUCCESS;
152
+
153
+      case OP_PUSH:
154
+        r1 = *(uint64_t*)(ip + 1);
155
+        ip += sizeof(uint64_t);
156
+        push(r1);
157
+        break;
158
+
159
+      case OP_POP:
160
+        pop(r1);
161
+        break;
162
+
163
+      case OP_CLEAR_M:
164
+        r1 = *(uint64_t*)(ip + 1);
165
+        ip += sizeof(uint64_t);
166
+        mem[r1] = 0;
167
+        break;
168
+
169
+      case OP_ADD_M:
170
+        r1 = *(uint64_t*)(ip + 1);
171
+        ip += sizeof(uint64_t);
172
+        pop(r2);
173
+        mem[r1] += r2;
174
+        break;
175
+
176
+      case OP_INCR_M:
177
+        r1 = *(uint64_t*)(ip + 1);
178
+        ip += sizeof(uint64_t);
179
+        mem[r1]++;
180
+        break;
181
+
182
+      case OP_PUSH_M:
183
+        r1 = *(uint64_t*)(ip + 1);
184
+        ip += sizeof(uint64_t);
185
+        push(mem[r1]);
186
+        break;
187
+
188
+      case OP_POP_M:
189
+        r1 = *(uint64_t*)(ip + 1);
190
+        ip += sizeof(uint64_t);
191
+        pop(mem[r1]);
192
+        break;
193
+
194
+      case OP_SWAPUNDEF:
195
+        r1 = *(uint64_t*)(ip + 1);
196
+        ip += sizeof(uint64_t);
197
+        pop(r2);
198
+        if (r2 != UNDEFINED)
199
+          push(r2);
200
+        else
201
+          push(mem[r1]);
202
+        break;
203
+
204
+      case OP_JNUNDEF:
205
+        pop(r1);
206
+        push(r1);
207
+
208
+        if (r1 != UNDEFINED)
209
+        {
210
+          ip = *(uint8_t**)(ip + 1);
211
+          // ip will be incremented at the end of the loop,
212
+          // decrement it here to compensate.
213
+          ip--;
214
+        }
215
+        else
216
+        {
217
+          ip += sizeof(uint64_t);
218
+        }
219
+        break;
220
+
221
+      case OP_JLE:
222
+        pop(r2);
223
+        pop(r1);
224
+        push(r1);
225
+        push(r2);
226
+
227
+        if (r1 <= r2)
228
+        {
229
+          ip = *(uint8_t**)(ip + 1);
230
+          // ip will be incremented at the end of the loop,
231
+          // decrement it here to compensate.
232
+          ip--;
233
+        }
234
+        else
235
+        {
236
+          ip += sizeof(uint64_t);
237
+        }
238
+        break;
239
+
240
+      case OP_AND:
241
+        pop(r2);
242
+        pop(r1);
243
+        if (IS_UNDEFINED(r1) || IS_UNDEFINED(r2))
244
+          push(0);
245
+        else
246
+          push(r1 & r2);
247
+        break;
248
+
249
+      case OP_OR:
250
+        pop(r2);
251
+        pop(r1);
252
+        if (IS_UNDEFINED(r1))
253
+          push(r2);
254
+        else if (IS_UNDEFINED(r2))
255
+          push(r1);
256
+        else
257
+          push(r1 | r2);
258
+        break;
259
+
260
+      case OP_NOT:
261
+        pop(r1);
262
+        if (IS_UNDEFINED(r1))
263
+          push(UNDEFINED);
264
+        else
265
+          push(!r1);
266
+        break;
267
+
268
+      case OP_LT:
269
+        pop(r2);
270
+        pop(r1);
271
+        push(comparison(<, r1, r2));
272
+        break;
273
+
274
+      case OP_GT:
275
+        pop(r2);
276
+        pop(r1);
277
+        push(comparison(>, r1, r2));
278
+        break;
279
+
280
+      case OP_LE:
281
+        pop(r2);
282
+        pop(r1);
283
+        push(comparison(<=, r1, r2));
284
+        break;
285
+
286
+      case OP_GE:
287
+        pop(r2);
288
+        pop(r1);
289
+        push(comparison(>=, r1, r2));
290
+        break;
291
+
292
+      case OP_EQ:
293
+        pop(r2);
294
+        pop(r1);
295
+        push(comparison(==, r1, r2));
296
+        break;
297
+
298
+      case OP_NEQ:
299
+        pop(r2);
300
+        pop(r1);
301
+        push(comparison(!=, r1, r2));
302
+        break;
303
+
304
+      case OP_SZ_EQ:
305
+        pop(r2);
306
+        pop(r1);
307
+
308
+        if (IS_UNDEFINED(r1) || IS_UNDEFINED(r2))
309
+          push(UNDEFINED);
310
+        else
311
+          push(strcmp(UINT64_TO_PTR(char*, r1),
312
+                      UINT64_TO_PTR(char*, r2)) == 0);
313
+        break;
314
+
315
+      case OP_SZ_NEQ:
316
+        pop(r2);
317
+        pop(r1);
318
+
319
+        if (IS_UNDEFINED(r1) || IS_UNDEFINED(r2))
320
+          push(UNDEFINED);
321
+        else
322
+          push(strcmp(UINT64_TO_PTR(char*, r1),
323
+                      UINT64_TO_PTR(char*, r2)) != 0);
324
+        break;
325
+
326
+      case OP_SZ_TO_BOOL:
327
+        pop(r1);
328
+
329
+        if (IS_UNDEFINED(r1))
330
+          push(UNDEFINED);
331
+        else
332
+          push(strlen(UINT64_TO_PTR(char*, r1)) > 0);
333
+
334
+        break;
335
+
336
+      case OP_ADD:
337
+        pop(r2);
338
+        pop(r1);
339
+        push(operation(+, r1, r2));
340
+        break;
341
+
342
+      case OP_SUB:
343
+        pop(r2);
344
+        pop(r1);
345
+        push(operation(-, r1, r2));
346
+        break;
347
+
348
+      case OP_MUL:
349
+        pop(r2);
350
+        pop(r1);
351
+        push(operation(*, r1, r2));
352
+        break;
353
+
354
+      case OP_DIV:
355
+        pop(r2);
356
+        pop(r1);
357
+        push(operation(/, r1, r2));
358
+        break;
359
+
360
+      case OP_MOD:
361
+        pop(r2);
362
+        pop(r1);
363
+        push(operation(%, r1, r2));
364
+        break;
365
+
366
+      case OP_NEG:
367
+        pop(r1);
368
+        push(IS_UNDEFINED(r1) ? UNDEFINED : ~r1);
369
+        break;
370
+
371
+      case OP_SHR:
372
+        pop(r2);
373
+        pop(r1);
374
+        push(operation(>>, r1, r2));
375
+        break;
376
+
377
+      case OP_SHL:
378
+        pop(r2);
379
+        pop(r1);
380
+        push(operation(<<, r1, r2));
381
+        break;
382
+
383
+      case OP_XOR:
384
+        pop(r2);
385
+        pop(r1);
386
+        push(operation(^, r1, r2));
387
+        break;
388
+
389
+      case OP_PUSH_RULE:
390
+        rule = *(YR_RULE**)(ip + 1);
391
+        ip += sizeof(uint64_t);
392
+#if REAL_YARA
393
+        push(rule->t_flags[tidx] & RULE_TFLAGS_MATCH ? 1 : 0);
394
+#else
395
+        //tbd clamav
396
+        push(rule->g_flags & RULE_TFLAGS_MATCH ? 1 : 0);
397
+#endif
398
+        break;
399
+
400
+      case OP_MATCH_RULE:
401
+        pop(r1);
402
+        rule = *(YR_RULE**)(ip + 1);
403
+        ip += sizeof(uint64_t);
404
+
405
+        if (!IS_UNDEFINED(r1) && r1)
406
+#if REAL_YARA
407
+          rule->t_flags[tidx] |= RULE_TFLAGS_MATCH;
408
+#else
409
+        //tbd clamav
410
+          rule->g_flags |= RULE_TFLAGS_MATCH;
411
+#endif
412
+
413
+        #ifdef PROFILING_ENABLED
414
+        rule->clock_ticks += clock() - start;
415
+        start = clock();
416
+        #endif
417
+        break;
418
+
419
+      case OP_OBJ_LOAD:
420
+        identifier = *(char**)(ip + 1);
421
+        ip += sizeof(uint64_t);
422
+
423
+        object = (YR_OBJECT*) yr_hash_table_lookup(
424
+            context->objects_table,
425
+            identifier,
426
+            NULL);
427
+
428
+        assert(object != NULL);
429
+        push(PTR_TO_UINT64(object));
430
+        break;
431
+
432
+#if REAL_YARA
433
+      case OP_OBJ_FIELD:
434
+        pop(r1);
435
+
436
+        identifier = *(char**)(ip + 1);
437
+        ip += sizeof(uint64_t);
438
+
439
+        if (IS_UNDEFINED(r1))
440
+        {
441
+          push(UNDEFINED);
442
+          break;
443
+        }
444
+
445
+        object = UINT64_TO_PTR(YR_OBJECT*, r1);
446
+        object = yr_object_lookup_field(object, identifier);
447
+        assert(object != NULL);
448
+        push(PTR_TO_UINT64(object));
449
+        break;
450
+#endif
451
+
452
+      case OP_OBJ_VALUE:
453
+        pop(r1);
454
+
455
+        if (IS_UNDEFINED(r1))
456
+        {
457
+          push(UNDEFINED);
458
+          break;
459
+        }
460
+
461
+        object = UINT64_TO_PTR(YR_OBJECT*, r1);
462
+
463
+        switch(object->type)
464
+        {
465
+          case OBJECT_TYPE_INTEGER:
466
+            push(((YR_OBJECT_INTEGER*) object)->value);
467
+            break;
468
+
469
+          case OBJECT_TYPE_STRING:
470
+            if (((YR_OBJECT_STRING*) object)->value != NULL)
471
+              push(PTR_TO_UINT64(((YR_OBJECT_STRING*) object)->value));
472
+            else
473
+              push(UNDEFINED);
474
+            break;
475
+
476
+          default:
477
+            assert(FALSE);
478
+        }
479
+
480
+        break;
481
+
482
+#if REAL_YARA
483
+      case OP_INDEX_ARRAY:
484
+        pop(r1);
485
+        pop(r2);
486
+
487
+        if (r1 == UNDEFINED)
488
+        {
489
+          push(UNDEFINED);
490
+          break;
491
+        }
492
+
493
+        object = UINT64_TO_PTR(YR_OBJECT*, r2);
494
+        assert(object->type == OBJECT_TYPE_ARRAY);
495
+        object = yr_object_array_get_item(object, 0, r1);
496
+
497
+        if (object != NULL)
498
+          push(PTR_TO_UINT64(object));
499
+        else
500
+          push(UNDEFINED);
501
+
502
+        break;
503
+#endif
504
+
505
+      case OP_CALL:
506
+
507
+        // r1 = number of arguments
508
+
509
+        r1 = *(uint64_t*)(ip + 1);
510
+        ip += sizeof(uint64_t);
511
+
512
+        // pop arguments from stack and copy them to args array
513
+
514
+        while (r1 > 0)
515
+        {
516
+          pop(args[r1 - 1]);
517
+          r1--;
518
+        }
519
+
520
+        pop(r2);
521
+
522
+        function = UINT64_TO_PTR(YR_OBJECT_FUNCTION*, r2);
523
+        result = function->code((void*) args, context, function);
524
+
525
+        if (result == ERROR_SUCCESS)
526
+          push(PTR_TO_UINT64(function->return_obj));
527
+        else
528
+          return result;
529
+
530
+        break;
531
+
532
+      case OP_STR_FOUND:
533
+        pop(r1);
534
+        string = UINT64_TO_PTR(YR_STRING*, r1);
535
+#if REAL_YARA
536
+        push(string->matches[tidx].tail != NULL ? 1 : 0);
537
+#else
538
+        //TBD: find clamav matches
539
+        push(1); //TEMP
540
+#endif
541
+        break;
542
+
543
+      case OP_STR_FOUND_AT:
544
+        pop(r2);
545
+        pop(r1);
546
+
547
+        if (IS_UNDEFINED(r1))
548
+        {
549
+          push(0);
550
+          break;
551
+        }
552
+
553
+        string = UINT64_TO_PTR(YR_STRING*, r2);
554
+#if REAL_YARA
555
+        match = string->matches[tidx].head;
556
+#else
557
+        //TBD: find clamav matches
558
+        match = NULL; //TEMP
559
+#endif
560
+
561
+        found = 0;
562
+
563
+        while (match != NULL)
564
+        {
565
+          if (r1 == match->base + match->offset)
566
+          {
567
+            push(1);
568
+            found = 1;
569
+            break;
570
+          }
571
+
572
+          if (r1 < match->base + match->offset)
573
+            break;
574
+
575
+          match = match->next;
576
+        }
577
+
578
+        if (!found)
579
+          push(0);
580
+
581
+        break;
582
+
583
+      case OP_STR_FOUND_IN:
584
+        pop(r3);
585
+        pop(r2);
586
+        pop(r1);
587
+
588
+        if (IS_UNDEFINED(r1) || IS_UNDEFINED(r2))
589
+        {
590
+          push(0);
591
+          break;
592
+        }
593
+
594
+        string = UINT64_TO_PTR(YR_STRING*, r3);
595
+#if REAL_YARA
596
+        match = string->matches[tidx].head;
597
+#else
598
+        //TBD: find clamav matches
599
+        match = NULL; //TEMP
600
+#endif
601
+        found = FALSE;
602
+
603
+        while (match != NULL && !found)
604
+        {
605
+          if (match->base + match->offset >= r1 &&
606
+              match->base + match->offset <= r2)
607
+          {
608
+            push(1);
609
+            found = TRUE;
610
+          }
611
+
612
+          if (match->base + match->offset > r2)
613
+            break;
614
+
615
+          match = match->next;
616
+        }
617
+
618
+        if (!found)
619
+          push(0);
620
+
621
+        break;
622
+
623
+      case OP_STR_COUNT:
624
+        pop(r1);
625
+        string = UINT64_TO_PTR(YR_STRING*, r1);
626
+#if REAL_YARA
627
+        push(string->matches[tidx].count);
628
+#else
629
+        //TBD: find #clamav matches
630
+        push(0); //TEMP
631
+#endif
632
+        break;
633
+
634
+      case OP_STR_OFFSET:
635
+        pop(r2);
636
+        pop(r1);
637
+
638
+        if (IS_UNDEFINED(r1))
639
+        {
640
+          push(UNDEFINED);
641
+          break;
642
+        }
643
+
644
+        string = UINT64_TO_PTR(YR_STRING*, r2);
645
+#if REAL_YARA
646
+        match = string->matches[tidx].head;
647
+#else
648
+        //TBD: find clamav matches
649
+        match = NULL; //TEMP
650
+#endif
651
+        i = 1;
652
+        found = FALSE;
653
+
654
+        while (match != NULL && !found)
655
+        {
656
+          if (r1 == i)
657
+          {
658
+            push(match->base + match->offset);
659
+            found = TRUE;
660
+          }
661
+
662
+          i++;
663
+          match = match->next;
664
+        }
665
+
666
+        if (!found)
667
+          push(UNDEFINED);
668
+
669
+        break;
670
+
671
+      case OP_OF:
672
+        found = 0;
673
+        count = 0;
674
+        pop(r1);
675
+
676
+        while (r1 != UNDEFINED)
677
+        {
678
+          string = UINT64_TO_PTR(YR_STRING*, r1);
679
+#if REAL_YARA
680
+          if (string->matches[tidx].tail != NULL)
681
+            found++;
682
+#else
683
+        //TBD: clamav
684
+#endif
685
+          count++;
686
+          pop(r1);
687
+        }
688
+
689
+        pop(r2);
690
+
691
+        if (r2 != UNDEFINED)
692
+          push(found >= r2 ? 1 : 0);
693
+        else
694
+          push(found >= count ? 1 : 0);
695
+
696
+        break;
697
+
698
+      case OP_FILESIZE:
699
+        push(context->file_size);
700
+        break;
701
+
702
+      case OP_ENTRYPOINT:
703
+        push(context->entry_point);
704
+        break;
705
+
706
+#if REAL_YARA
707
+      case OP_INT8:
708
+        pop(r1);
709
+        push(read_int8_t(context->mem_block, r1));
710
+        break;
711
+
712
+      case OP_INT16:
713
+        pop(r1);
714
+        push(read_int16_t(context->mem_block, r1));
715
+        break;
716
+
717
+      case OP_INT32:
718
+        pop(r1);
719
+        push(read_int32_t(context->mem_block, r1));
720
+        break;
721
+
722
+      case OP_UINT8:
723
+        pop(r1);
724
+        push(read_uint8_t(context->mem_block, r1));
725
+        break;
726
+
727
+      case OP_UINT16:
728
+        pop(r1);
729
+        push(read_uint16_t(context->mem_block, r1));
730
+        break;
731
+
732
+      case OP_UINT32:
733
+        pop(r1);
734
+        push(read_uint32_t(context->mem_block, r1));
735
+        break;
736
+#endif
737
+
738
+      case OP_CONTAINS:
739
+        pop(r2);
740
+        pop(r1);
741
+        push(strstr(UINT64_TO_PTR(char*, r1),
742
+                    UINT64_TO_PTR(char*, r2)) != NULL);
743
+        break;
744
+
745
+
746
+#if REAL_YARA //not supported ClamAV
747
+      case OP_IMPORT:
748
+        r1 = *(uint64_t*)(ip + 1);
749
+        ip += sizeof(uint64_t);
750
+
751
+        FAIL_ON_ERROR(yr_modules_load(
752
+            UINT64_TO_PTR(char*, r1),
753
+            context));
754
+
755
+        break;
756
+#endif
757
+
758
+      case OP_MATCHES:
759
+        pop(r2);
760
+        pop(r1);
761
+
762
+        count = strlen(UINT64_TO_PTR(char*, r1));
763
+
764
+        if (count == 0)
765
+        {
766
+          push(FALSE);
767
+          break;
768
+        }
769
+
770
+#if REAL_YARA
771
+        result = yr_re_exec(
772
+          UINT64_TO_PTR(uint8_t*, r2),
773
+          UINT64_TO_PTR(uint8_t*, r1),
774
+          count,
775
+          RE_FLAGS_SCAN,
776
+          NULL,
777
+          NULL);
778
+#else
779
+        //TDB CLAMAV
780
+#endif
781
+
782
+        push(result >= 0);
783
+        break;
784
+
785
+      default:
786
+        // Unknown instruction, this shouldn't happen.
787
+        assert(FALSE);
788
+    }
789
+
790
+    if (timeout > 0)  // timeout == 0 means no timeout
791
+    {
792
+      // Check for timeout every 10 instruction cycles.
793
+
794
+      if (++cycle == 10)
795
+      {
796
+        if (difftime(time(NULL), start_time) > timeout)
797
+          return ERROR_SCAN_TIMEOUT;
798
+
799
+        cycle = 0;
800
+      }
801
+    }
802
+
803
+    ip++;
804
+  }
805
+
806
+  // After executing the code the stack should be empty.
807
+  assert(sp == 0);
808
+
809
+  return ERROR_SUCCESS;
810
+}
0 811
new file mode 100644
... ...
@@ -0,0 +1,99 @@
0
+/*
1
+Copyright (c) 2013. The YARA Authors. All Rights Reserved.
2
+
3
+Licensed under the Apache License, Version 2.0 (the "License");
4
+you may not use this file except in compliance with the License.
5
+You may obtain a copy of the License at
6
+
7
+   http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+Unless required by applicable law or agreed to in writing, software
10
+distributed under the License is distributed on an "AS IS" BASIS,
11
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+See the License for the specific language governing permissions and
13
+limitations under the License.
14
+*/
15
+
16
+#ifndef YR_EXEC_H
17
+#define YR_EXEC_H
18
+
19
+#if REAL_YARA
20
+#include <yara/hash.h>
21
+#include <yara/scan.h>
22
+#include <yara/types.h>
23
+#include <yara/rules.h>
24
+#endif
25
+
26
+#define UNDEFINED           0xFFFABADAFABADAFFLL
27
+#define IS_UNDEFINED(x)     ((x) == UNDEFINED)
28
+
29
+#define OP_HALT           255
30
+
31
+#define OP_AND            1
32
+#define OP_OR             2
33
+#define OP_XOR            3
34
+#define OP_NOT            4
35
+#define OP_LT             5
36
+#define OP_GT             6
37
+#define OP_LE             7
38
+#define OP_GE             8
39
+#define OP_EQ             9
40
+#define OP_NEQ            10
41
+#define OP_SZ_EQ          11
42
+#define OP_SZ_NEQ         12
43
+#define OP_SZ_TO_BOOL     13
44
+#define OP_ADD            14
45
+#define OP_SUB            15
46
+#define OP_MUL            16
47
+#define OP_DIV            17
48
+#define OP_MOD            18
49
+#define OP_NEG            19
50
+#define OP_SHL            20
51
+#define OP_SHR            21
52
+#define OP_PUSH           22
53
+#define OP_POP            23
54
+#define OP_CALL           24
55
+#define OP_OBJ_LOAD       25
56
+#define OP_OBJ_VALUE      26
57
+#define OP_OBJ_FIELD      27
58
+#define OP_INDEX_ARRAY    28
59
+#define OP_STR_COUNT      29
60
+#define OP_STR_FOUND      30
61
+#define OP_STR_FOUND_AT   31
62
+#define OP_STR_FOUND_IN   32
63
+#define OP_STR_OFFSET     33
64
+#define OP_OF             34
65
+#define OP_PUSH_RULE      35
66
+#define OP_MATCH_RULE     36
67
+#define OP_INCR_M         37
68
+#define OP_CLEAR_M        38
69
+#define OP_ADD_M          39
70
+#define OP_POP_M          40
71
+#define OP_PUSH_M         41
72
+#define OP_SWAPUNDEF      42
73
+#define OP_JNUNDEF        43
74
+#define OP_JLE            44
75
+#define OP_FILESIZE       45
76
+#define OP_ENTRYPOINT     46
77
+#define OP_INT8           47
78
+#define OP_INT16          48
79
+#define OP_INT32          49
80
+#define OP_UINT8          50
81
+#define OP_UINT16         51
82
+#define OP_UINT32         52
83
+#define OP_CONTAINS       53
84
+#define OP_MATCHES        54
85
+#define OP_IMPORT         55
86
+
87
+
88
+int yr_execute_code(
89
+#if REAL_YARA
90
+    YR_RULES* rules,
91
+#else
92
+    uint8_t* ip,
93
+#endif
94
+    YR_SCAN_CONTEXT* context,
95
+    int timeout,
96
+    time_t start_time);
97
+
98
+#endif