yara 1.4.1 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,7 @@
1
1
  = yara
2
+ Eric Monti - emonti at trustwave dot com
3
+
4
+ == Introduction
2
5
 
3
6
  Ruby bindings for the yara malware analysis library.
4
7
 
@@ -8,9 +11,11 @@ based on textual or binary information contained on samples of those families.
8
11
  These descriptions, named rules, consist of a set of strings and a Boolean
9
12
  expression which determines the rule logic.
10
13
 
11
- See http://code.google.com/p/yara-project for more information.
14
+ Yara and it's code are copyrights of Victor M. Alvarez. Please see
15
+ http://code.google.com/p/yara-project/
16
+
12
17
 
13
- == Synopsis
18
+ == Usage
14
19
 
15
20
  # basic example... find all PE files under the current dir
16
21
 
@@ -29,15 +34,48 @@ See http://code.google.com/p/yara-project for more information.
29
34
  end
30
35
 
31
36
  == Versioning
32
- The current version is of libyara at the time of writing 1.4.0.
37
+ The current version of libyara at the time of writing is 1.4.0. Bindings
38
+ have been written against this API and may not work with earlier versions
39
+ of the libyara library.
40
+
33
41
  The major and minor version numbers of the ruby library are intended
34
42
  to be in step with the C api version.
35
43
 
36
44
  == Requirements
37
45
  * libyara 1.4 must be installed - http://code.google.com/p/yara-project/
38
46
 
47
+ == Installation
48
+
49
+ First make sure you have libyara and its dependencies installed. You'll need
50
+ libyara and yara.h in your search paths.
51
+
52
+ Install the yara ruby package from a gem:
53
+
54
+ (sudo)? gem install yara
55
+
56
+ Or from the github package.
57
+
58
+ git clone https://github.com/SpiderLabs/yara-ruby.git
59
+ cd yara-ruby
60
+ rake compile
61
+
62
+
39
63
  == Copyright
64
+ yara-ruby - Ruby bindings for the yara malware analysis library.
65
+ Eric Monti
66
+ Copyright (C) 2011 Trustwave Holdings
67
+
68
+ This program is free software: you can redistribute it and/or modify it
69
+ under the terms of the GNU General Public License as published by the
70
+ Free Software Foundation, either version 3 of the License, or (at your
71
+ option) any later version.
72
+
73
+ This program is distributed in the hope that it will be useful, but
74
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
75
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
76
+ for more details.
40
77
 
41
- Copyright (c) 2011 Eric Monti. See LICENSE.txt for
42
- further details.
78
+ You should have received a copy of the GNU General Public License along
79
+ with this program. If not, see <http://www.gnu.org/licenses/>.
43
80
 
81
+ See LICENSE.txt
data/Rakefile CHANGED
@@ -16,8 +16,8 @@ Jeweler::Tasks.new do |gem|
16
16
  # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
17
  gem.name = "yara"
18
18
  gem.homepage = "http://github.com/SpiderLabs/yara-ruby"
19
- gem.summary = %Q{Ruby Bindings for libyara}
20
- gem.description = %Q{Ruby Bindings for the yara malware analysis library}
19
+ gem.summary = %Q{Ruby bindings for libyara}
20
+ gem.description = %Q{Ruby bindings for the yara malware analysis library}
21
21
  gem.email = "emonti@trustwave.com"
22
22
  gem.authors = ["Eric Monti"]
23
23
 
@@ -50,3 +50,13 @@ task :default => :spec
50
50
 
51
51
  require 'yard'
52
52
  YARD::Rake::YardocTask.new
53
+
54
+ require 'rake/rdoctask'
55
+ Rake::RDocTask.new do |rd|
56
+ rd.rdoc_dir = 'rdoc'
57
+ rd.main = "README.rdoc"
58
+ rd.rdoc_files.include [
59
+ "README.rdoc", "History.txt", "LICENSE.txt", "VERSION",
60
+ "lib/**/*", "ext/**/*.c" ]
61
+ end
62
+
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.4.1
1
+ 1.4.2
@@ -1,8 +1,29 @@
1
- #include "Match.h"
1
+ /*
2
+ * yara-ruby - Ruby bindings for the yara malware analysis library.
3
+ * Eric Monti
4
+ * Copyright (C) 2011 Trustwave Holdings
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify it
7
+ * under the terms of the GNU General Public License as published by the
8
+ * Free Software Foundation, either version 3 of the License, or (at your
9
+ * option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful, but
12
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
+ * for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License along
17
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ *
19
+ */
20
+
21
+ #include "Yara_native.h"
2
22
  #include <strings.h>
3
23
  #include <stdlib.h>
4
24
 
5
25
  VALUE class_Match = Qnil;
26
+
6
27
  VALUE class_MatchString = Qnil;
7
28
 
8
29
  const char * SCAN_ERRORS[] = {
@@ -38,7 +59,6 @@ const char * SCAN_ERRORS[] = {
38
59
  "incorrect external variable type",
39
60
  };
40
61
 
41
-
42
62
  typedef struct {
43
63
  VALUE rule;
44
64
  VALUE namespace;
@@ -53,7 +73,7 @@ typedef struct {
53
73
  VALUE buffer;
54
74
  } match_string;
55
75
 
56
- VALUE
76
+ static VALUE
57
77
  MatchString_NEW(int offset, char *ident, char *buf, size_t buflen) {
58
78
  match_string *ms;
59
79
 
@@ -66,7 +86,7 @@ MatchString_NEW(int offset, char *ident, char *buf, size_t buflen) {
66
86
  ms->identifier = rb_obj_freeze(rb_str_new2(ident));
67
87
  ms->buffer = rb_obj_freeze(rb_str_new(buf, buflen));
68
88
 
69
- return rb_obj_freeze(Data_Wrap_Struct(class_MatchString, 0, 0, ms));
89
+ return rb_obj_freeze(Data_Wrap_Struct(class_MatchString, 0, free, ms));
70
90
  }
71
91
 
72
92
  int
@@ -104,7 +124,11 @@ Match_NEW_from_rule(RULE *rule, unsigned char *buffer, VALUE *match) {
104
124
  if (string->flags & STRING_FLAGS_FOUND) {
105
125
  m = string->matches;
106
126
  while (m) {
107
- rb_ary_push(mi->strings, MatchString_NEW(m->offset, string->identifier, buffer + m->offset, m->length));
127
+ rb_ary_push(mi->strings,
128
+ MatchString_NEW(m->offset,
129
+ string->identifier,
130
+ buffer + m->offset,
131
+ m->length));
108
132
  m = m->next;
109
133
  }
110
134
  }
@@ -114,75 +138,168 @@ Match_NEW_from_rule(RULE *rule, unsigned char *buffer, VALUE *match) {
114
138
 
115
139
  meta = rule->meta_list_head;
116
140
  while(meta) {
117
- // ... TODO
141
+ if (meta->type == META_TYPE_INTEGER) {
142
+ rb_hash_aset(mi->meta,
143
+ rb_str_new2(meta->identifier),
144
+ INT2NUM(meta->integer));
145
+ }
146
+ else if (meta->type == META_TYPE_BOOLEAN) {
147
+ rb_hash_aset(mi->meta,
148
+ rb_str_new2(meta->identifier),
149
+ ((meta->boolean) ? Qtrue : Qfalse));
150
+ }
151
+ else {
152
+ rb_hash_aset(mi->meta,
153
+ rb_str_new2(meta->identifier),
154
+ rb_obj_freeze(rb_str_new2(meta->string)));
155
+ }
156
+
118
157
  meta = meta->next;
119
158
  }
120
159
  rb_obj_freeze(mi->meta);
121
160
 
122
- *(match) = rb_obj_freeze(Data_Wrap_Struct(class_Match, 0, 0, mi));
161
+ *(match) = rb_obj_freeze(Data_Wrap_Struct(class_Match, 0, free, mi));
123
162
 
124
163
  return 0;
125
164
  }
126
165
 
127
- VALUE match_rule(VALUE self) {
166
+ /*
167
+ * Document-method: rule
168
+ *
169
+ * call-seq:
170
+ * match.rule() -> String
171
+ *
172
+ * Returns the rule identifier string for this match.
173
+ */
174
+ static VALUE match_rule(VALUE self) {
128
175
  match_info *mi;
129
176
  Data_Get_Struct(self, match_info, mi);
130
177
  return mi->rule;
131
178
  }
132
179
 
133
- VALUE match_namespace(VALUE self) {
180
+ /*
181
+ * Document-method: namespace
182
+ *
183
+ * call-seq:
184
+ * match.namespace() -> String
185
+ *
186
+ * Returns the namespace for this match.
187
+ */
188
+ static VALUE match_namespace(VALUE self) {
134
189
  match_info *mi;
135
190
  Data_Get_Struct(self, match_info, mi);
136
191
  return mi->namespace;
137
192
  }
138
193
 
139
- VALUE match_tags(VALUE self) {
194
+ /*
195
+ * Document-method: tags
196
+ *
197
+ * call-seq:
198
+ * match.tags() -> Array
199
+ *
200
+ * Returns an array of tag Strings for this match.
201
+ */
202
+ static VALUE match_tags(VALUE self) {
140
203
  match_info *mi;
141
204
  Data_Get_Struct(self, match_info, mi);
142
205
  return mi->tags;
143
206
  }
144
207
 
145
- VALUE match_strings(VALUE self) {
208
+ /*
209
+ * Document-method: strings
210
+ *
211
+ * call-seq:
212
+ * match.strings() -> Array
213
+ *
214
+ * Returns an array of MatchString objects for this match.
215
+ */
216
+ static VALUE match_strings(VALUE self) {
146
217
  match_info *mi;
147
218
  Data_Get_Struct(self, match_info, mi);
148
219
  return mi->strings;
149
220
  }
150
221
 
151
- VALUE match_meta(VALUE self) {
222
+ /*
223
+ * Document-method: meta
224
+ *
225
+ * call-seq:
226
+ * match.meta() -> Hash
227
+ *
228
+ * Returns a hash of metadata for the match object.
229
+ */
230
+ static VALUE match_meta(VALUE self) {
152
231
  match_info *mi;
153
232
  Data_Get_Struct(self, match_info, mi);
154
233
  return mi->meta;
155
234
  }
156
235
 
157
- VALUE matchstring_identifier(VALUE self) {
236
+ /*
237
+ * Document-method: identifier
238
+ *
239
+ * call-seq:
240
+ * matchstring.identifier() -> String
241
+ *
242
+ * Returns the identification label for the string.
243
+ */
244
+ static VALUE matchstring_identifier(VALUE self) {
158
245
  match_string *ms;
159
246
  Data_Get_Struct(self, match_string, ms);
160
247
  return ms->identifier;
161
248
  }
162
249
 
163
- VALUE matchstring_offset(VALUE self) {
250
+ /*
251
+ * Document-method: offset
252
+ *
253
+ * call-seq:
254
+ * matchstring.offset() -> fixnum
255
+ *
256
+ * Returns the offset where the match occurred.
257
+ */
258
+ static VALUE matchstring_offset(VALUE self) {
164
259
  match_string *ms;
165
260
  Data_Get_Struct(self, match_string, ms);
166
261
  return ms->offset;
167
262
  }
168
263
 
169
- VALUE matchstring_buffer(VALUE self) {
264
+ /*
265
+ * Document-method: buffer
266
+ *
267
+ * call-seq:
268
+ * matchstring.buffer() -> String
269
+ *
270
+ * Returns the data matched.
271
+ */
272
+ static VALUE matchstring_buffer(VALUE self) {
170
273
  match_string *ms;
171
274
  Data_Get_Struct(self, match_string, ms);
172
275
  return ms->buffer;
173
276
  }
174
277
 
175
-
176
278
  void
177
- init_match(VALUE rb_ns) {
178
- class_Match = rb_define_class_under(rb_ns, "Match", rb_cObject);
279
+ init_Match() {
280
+ VALUE module_Yara = rb_define_module("Yara");
281
+
282
+ /*
283
+ * Document-class: Yara::Match
284
+ *
285
+ * Encapsulates a match object returned from Yara::Rules#scan_string or
286
+ * Yara::Rules#scan_file. A Match contains one or more MatchString objects.
287
+ */
288
+ class_Match = rb_define_class_under(module_Yara, "Match", rb_cObject);
179
289
  rb_define_method(class_Match, "rule", match_rule, 0);
180
290
  rb_define_method(class_Match, "namespace", match_namespace, 0);
181
291
  rb_define_method(class_Match, "tags", match_tags, 0);
182
292
  rb_define_method(class_Match, "strings", match_strings, 0);
183
293
  rb_define_method(class_Match, "meta", match_meta, 0);
184
294
 
185
- class_MatchString = rb_define_class_under(rb_ns, "MatchString", rb_cObject);
295
+
296
+ /*
297
+ * Document-class: Yara::MatchString
298
+ *
299
+ * Encapsulates an individual matched string location. One or more of these
300
+ * will be available from a Match object.
301
+ */
302
+ class_MatchString = rb_define_class_under(module_Yara, "MatchString", rb_cObject);
186
303
  rb_define_method(class_MatchString, "identifier", matchstring_identifier, 0);
187
304
  rb_define_method(class_MatchString, "offset", matchstring_offset, 0);
188
305
  rb_define_method(class_MatchString, "buffer", matchstring_buffer, 0);
@@ -1,20 +1,36 @@
1
+ /*
2
+ * yara-ruby - Ruby bindings for the yara malware analysis library.
3
+ * Eric Monti
4
+ * Copyright (C) 2011 Trustwave Holdings
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify it
7
+ * under the terms of the GNU General Public License as published by the
8
+ * Free Software Foundation, either version 3 of the License, or (at your
9
+ * option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful, but
12
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
+ * for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License along
17
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ *
19
+ */
20
+
1
21
  #ifndef RB_MATCH_H_GUARD
2
22
  #define RB_MATCH_H_GUARD
3
23
 
4
24
  #include "ruby.h"
5
25
  #include <yara.h>
6
26
 
7
- extern VALUE class_Match;
8
- extern VALUE class_MatchString;
9
-
10
- extern void
11
- init_match(VALUE ruby_namespace);
12
-
13
27
  extern int
14
28
  Match_NEW_from_rule(RULE * rule, unsigned char * buffer, VALUE * match);
15
29
 
16
30
  extern const char * SCAN_ERRORS[];
17
31
 
32
+ void init_Match();
33
+
18
34
  #define MAX_SCAN_ERROR 29
19
35
 
20
36
  #endif
@@ -1,9 +1,28 @@
1
- #include "errors.h"
2
- #include "Rules.h"
1
+ /*
2
+ * yara-ruby - Ruby bindings for the yara malware analysis library.
3
+ * Eric Monti
4
+ * Copyright (C) 2011 Trustwave Holdings
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify it
7
+ * under the terms of the GNU General Public License as published by the
8
+ * Free Software Foundation, either version 3 of the License, or (at your
9
+ * option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful, but
12
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
+ * for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License along
17
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ *
19
+ */
20
+
3
21
  #include "Match.h"
22
+ #include "Yara_native.h"
4
23
  #include <stdio.h>
5
24
 
6
- static VALUE class_Rules = Qnil;
25
+ VALUE class_Rules = Qnil;
7
26
 
8
27
  void rules_mark(YARA_CONTEXT *ctx) { }
9
28
 
@@ -17,6 +36,19 @@ VALUE rules_allocate(VALUE klass) {
17
36
  return Data_Wrap_Struct(klass, rules_mark, rules_free, ctx);
18
37
  }
19
38
 
39
+ /*
40
+ * Document-method: compile_file
41
+ *
42
+ * call-seq:
43
+ * rules.compile_file(filename) -> nil
44
+ *
45
+ * Compiles rules taken from a file by its filename. This method
46
+ * can be called more than once using multiple rules strings and
47
+ * can be used in combination with compile_file.
48
+ *
49
+ * To avoid namespace conflicts, you can use set_namespace
50
+ * before compiling rules.
51
+ */
20
52
  VALUE rules_compile_file(VALUE self, VALUE rb_fname) {
21
53
  FILE * file;
22
54
  char * fname;
@@ -43,6 +75,19 @@ VALUE rules_compile_file(VALUE self, VALUE rb_fname) {
43
75
  }
44
76
  }
45
77
 
78
+ /*
79
+ * Document-method: compile_string
80
+ *
81
+ * call-seq:
82
+ * rules.compile_string(rules_string) -> nil
83
+ *
84
+ * Compiles rules taken from a ruby string. This method
85
+ * can be called more than once using multiple rules strings
86
+ * and can be used in combination with compile_file.
87
+ *
88
+ * To avoid namespace conflicts, you can use set_namespace
89
+ * before compiling rules.
90
+ */
46
91
  VALUE rules_compile_string(VALUE self, VALUE rb_rules) {
47
92
  YARA_CONTEXT *ctx;
48
93
  char *rules;
@@ -60,13 +105,29 @@ VALUE rules_compile_string(VALUE self, VALUE rb_rules) {
60
105
  return Qtrue;
61
106
  }
62
107
 
108
+ /*
109
+ * Document-method: weight
110
+ *
111
+ * call-seq:
112
+ * rules.weight() -> fixnum
113
+ *
114
+ * Returns a weight value for the compiled rules.
115
+ */
116
+
63
117
  VALUE rules_weight(VALUE self) {
64
118
  YARA_CONTEXT *ctx;
65
119
  Data_Get_Struct(self, YARA_CONTEXT, ctx);
66
120
  return INT2NUM(yr_calculate_rules_weight(ctx));
67
121
  }
68
122
 
69
-
123
+ /*
124
+ * Document-method: current_namespace
125
+ *
126
+ * call-seq:
127
+ * rules.current_namespace() -> String
128
+ *
129
+ * Returns the name of the currently active namespace.
130
+ */
70
131
  VALUE rules_current_namespace(VALUE self) {
71
132
  YARA_CONTEXT *ctx;
72
133
  Data_Get_Struct(self, YARA_CONTEXT, ctx);
@@ -76,6 +137,14 @@ VALUE rules_current_namespace(VALUE self) {
76
137
  return Qnil;
77
138
  }
78
139
 
140
+ /*
141
+ * Document-method: namespaces
142
+ *
143
+ * call-seq:
144
+ * rules.namespaces() -> Array
145
+ *
146
+ * Returns the namespaces available in this rules context.
147
+ */
79
148
  VALUE rules_namespaces(VALUE self) {
80
149
  YARA_CONTEXT *ctx;
81
150
  NAMESPACE *ns;
@@ -102,6 +171,18 @@ NAMESPACE * find_namespace(YARA_CONTEXT *ctx, const char *name) {
102
171
  return (NAMESPACE*) NULL;
103
172
  }
104
173
 
174
+ /*
175
+ * Document-method: set_namespace
176
+ *
177
+ * call-seq:
178
+ * rules.set_namespace(name) -> nil
179
+ *
180
+ * Sets the current namespace to the given name. If the namespace
181
+ * does not yet exist it is added.
182
+ *
183
+ * To avoid namespace conflicts, you can use set_namespace
184
+ * before compiling rules.
185
+ */
105
186
  VALUE rules_set_namespace(VALUE self, VALUE rb_namespace) {
106
187
  YARA_CONTEXT *ctx;
107
188
  NAMESPACE *ns = NULL;
@@ -139,7 +220,15 @@ scan_callback(RULE *rule, unsigned char *buffer, unsigned int buffer_size, void
139
220
  return match_ret;
140
221
  }
141
222
 
142
-
223
+ /*
224
+ * Document-method: scan_file
225
+ *
226
+ * call-seq:
227
+ * rules.scan_file(filename) -> nil
228
+ *
229
+ * Scans a file using the compiled rules supplied
230
+ * with either compile_file or compile_string (or both).
231
+ */
143
232
  VALUE rules_scan_file(VALUE self, VALUE rb_fname) {
144
233
  YARA_CONTEXT *ctx;
145
234
  VALUE results;
@@ -161,6 +250,16 @@ VALUE rules_scan_file(VALUE self, VALUE rb_fname) {
161
250
  return results;
162
251
  }
163
252
 
253
+
254
+ /*
255
+ * Document-method: scan_file
256
+ *
257
+ * call-seq:
258
+ * rules.scan_string(data) -> nil
259
+ *
260
+ * Scans a ruby string using the compiled rules supplied
261
+ * with either compile_file or compile_string (or both).
262
+ */
164
263
  VALUE rules_scan_string(VALUE self, VALUE rb_dat) {
165
264
  YARA_CONTEXT *ctx;
166
265
  VALUE results;
@@ -184,9 +283,16 @@ VALUE rules_scan_string(VALUE self, VALUE rb_dat) {
184
283
  return results;
185
284
  }
186
285
 
187
- void init_rules(VALUE rb_ns) {
286
+ /*
287
+ * Document-class: Yara::Rules
288
+ *
289
+ * Encapsulates a Yara context against which you can compile rules and
290
+ * scan inputs.
291
+ */
292
+ void init_Rules() {
293
+ VALUE module_Yara = rb_define_module("Yara");
188
294
 
189
- class_Rules = rb_define_class_under(rb_ns, "Rules", rb_cObject);
295
+ class_Rules = rb_define_class_under(module_Yara, "Rules", rb_cObject);
190
296
  rb_define_alloc_func(class_Rules, rules_allocate);
191
297
 
192
298
  rb_define_method(class_Rules, "compile_file", rules_compile_file, 1);
@@ -197,7 +303,5 @@ void init_rules(VALUE rb_ns) {
197
303
  rb_define_method(class_Rules, "set_namespace", rules_set_namespace, 1);
198
304
  rb_define_method(class_Rules, "scan_file", rules_scan_file, 1);
199
305
  rb_define_method(class_Rules, "scan_string", rules_scan_string, 1);
200
-
201
- init_match(rb_ns);
202
306
  }
203
307