yara 1.4.1 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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