yara-ffi 2.1.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ac111338f4038017b3eb887d2bfcea73c2a2aa5a9b409370e13cfd01985276df
4
- data.tar.gz: 353ab52ebe038b8fbd2b3c9ce35436df1b4fb20cad1cfa0b3019e678291e0f0b
3
+ metadata.gz: 814d5fa21cda6f98707e038549321eab8ce359f013c47d36e8d0845c05ff0b2c
4
+ data.tar.gz: 531d85f217da5f9bec89de9319ee5f9f33c3a801ec75db439de1fa377612c88e
5
5
  SHA512:
6
- metadata.gz: 96a2ede305474b3457dcaf4256e3b57fa28becae0abc51eb3e45897667f5a971ba818a45a6b945b15d02208c2eee6adad43ff416c31d9528083ed7dd5a317046
7
- data.tar.gz: 6b1a3fa08e02123b655d140f30fa531494d585276591f5758b6f8c26636ea0fe388eef7fa5e6253d9fce42221b19729eab0960684a87eaf95e96f701eacd4fb7
6
+ metadata.gz: 3fd910b4f3ea435dcc5cfaa1763fe7cd33727bc77929b52d326d4f3baaad7caff2671c73100ec5102bdb61f9ac34d330ad2a33626faaeebf65ff16dde7d7e6fe
7
+ data.tar.gz: 53133f057a23dc32227a6c603322cdd5b9da273416bdd6aad9245b4c270249c83dd8e8f5211f531be1180a12c28825824977966425456bd9c18ff8883566f7bb
data/Dockerfile ADDED
@@ -0,0 +1,17 @@
1
+ FROM ruby:2.6.6
2
+
3
+ RUN apt-get update -qq
4
+ RUN apt-get install -y flex bison
5
+
6
+ WORKDIR /app
7
+
8
+ COPY . ./
9
+ RUN gem install bundler:2.2.15
10
+ RUN bundle install
11
+
12
+ RUN git clone --recursive --branch v4.1.1 https://github.com/VirusTotal/yara.git /tmp/yara && \
13
+ cd /tmp/yara/ && \
14
+ ./bootstrap.sh && \
15
+ ./configure && \
16
+ make && \
17
+ make install
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- yara-ffi (1.0.0)
4
+ yara-ffi (2.1.1)
5
5
  ffi
6
6
 
7
7
  GEM
@@ -9,7 +9,7 @@ GEM
9
9
  specs:
10
10
  ast (2.4.2)
11
11
  coderay (1.1.3)
12
- ffi (1.15.0)
12
+ ffi (1.15.4)
13
13
  method_source (1.0.0)
14
14
  minitest (5.14.4)
15
15
  parallel (1.20.1)
@@ -48,4 +48,4 @@ DEPENDENCIES
48
48
  yara-ffi!
49
49
 
50
50
  BUNDLED WITH
51
- 2.2.14
51
+ 2.2.15
data/README.md CHANGED
@@ -20,7 +20,34 @@ Or install it yourself as:
20
20
 
21
21
  ## Usage
22
22
 
23
- TODO: Write usage instructions here
23
+ ```ruby
24
+ Yara.start # run before you start using the Yara API.
25
+
26
+ rule = <<-RULE
27
+ rule ExampleRule
28
+ {
29
+ meta:
30
+ string_meta = "an example rule for testing"
31
+
32
+ strings:
33
+ $my_text_string = "we were here"
34
+ $my_text_regex = /were here/
35
+
36
+ condition:
37
+ $my_text_string or $my_text_regex
38
+ }
39
+ RULE
40
+
41
+ scanner = Yara::Scanner.new
42
+ scanner.add_rule(rule)
43
+ scanner.compile
44
+ result = scanner.call("one day we were here and then we were not")
45
+ result.match?
46
+ # => true
47
+
48
+ scanner.close # run when you are done using the scanner API and want to free up memory.
49
+ Yara.stop # run when you are completely done using the Yara API to free up memory.
50
+ ```
24
51
 
25
52
  ## Development
26
53
 
data/lib/yara/ffi.rb CHANGED
@@ -90,9 +90,9 @@ module Yara
90
90
  # void* user_data)
91
91
  callback :scan_callback, [
92
92
  :pointer, # YR_SCAN_CONTEXT*
93
- :int, # message
94
- :pointer, # message_data_pointer
95
- :pointer, # user_data_pointer
93
+ :int, # callback_type
94
+ YrRule.ptr, # rule
95
+ UserData.ptr, # user_data
96
96
  ], :int
97
97
 
98
98
  # int yr_rules_scan_mem(
@@ -6,38 +6,50 @@ module Yara
6
6
  META_FLAGS_LAST_IN_RULE = 1
7
7
 
8
8
  META_TYPE_INTEGER = 1
9
- META_TYPE_STRING = 2
9
+ # META_TYPE_STRING = 2
10
10
  META_TYPE_BOOLEAN = 3
11
11
 
12
12
  STRING_FLAGS_LAST_IN_RULE = 0
13
13
 
14
- STRING_LENGTH = 4
15
- STRING_POINTER = 5
16
-
17
- RULE_IDENTIFIER = 1
18
- METAS_IDENTIFIER = 3
19
- STRING_IDENTIFIER = 4
20
-
21
14
  attr_reader :callback_type, :rule
22
15
 
23
- def initialize(callback_type, rule_ptr)
16
+ def initialize(callback_type, rule, user_data)
24
17
  @callback_type = callback_type
25
- @rule = YrRule.new(rule_ptr)
18
+ @rule = rule
19
+ @rule_meta = extract_rule_meta
20
+ @rule_strings = extract_rule_strings
21
+ @user_data_number = user_data[:number]
26
22
  end
27
23
 
24
+ attr_reader :rule_meta, :rule_strings, :user_data_number
25
+
28
26
  def rule_name
29
- @rule.values[RULE_IDENTIFIER]
27
+ @rule[:identifier]
28
+ end
29
+
30
+ def scan_complete?
31
+ callback_type == SCAN_FINISHED
32
+ end
33
+
34
+ def rule_outcome?
35
+ [RULE_MATCHING, RULE_NOT_MATCHING].include?(callback_type)
36
+ end
37
+
38
+ def match?
39
+ callback_type == RULE_MATCHING
30
40
  end
31
41
 
32
- def rule_meta
42
+ private
43
+
44
+ def extract_rule_meta
33
45
  metas = {}
34
46
  reading_metas = true
35
47
  meta_index = 0
36
- meta_pointer = @rule.values[METAS_IDENTIFIER]
48
+ meta_pointer = @rule[:metas]
37
49
  while reading_metas do
38
50
  meta = YrMeta.new(meta_pointer + meta_index * YrMeta.size)
39
51
  metas.merge!(meta_as_hash(meta))
40
- flags = meta.values.last
52
+ flags = meta[:flags]
41
53
  if flags == META_FLAGS_LAST_IN_RULE
42
54
  reading_metas = false
43
55
  else
@@ -47,15 +59,15 @@ module Yara
47
59
  metas
48
60
  end
49
61
 
50
- def rule_strings
62
+ def extract_rule_strings
51
63
  strings = {}
52
64
  reading_strings = true
53
65
  string_index = 0
54
- string_pointer = @rule.values[STRING_IDENTIFIER]
66
+ string_pointer = @rule[:strings]
55
67
  while reading_strings do
56
68
  string = YrString.new(string_pointer + string_index * YrString.size)
57
- string_length = string.values[STRING_LENGTH]
58
- flags = string.values.first
69
+ string_length = string[:length]
70
+ flags = string[:flags]
59
71
  if flags == STRING_FLAGS_LAST_IN_RULE
60
72
  reading_strings = false
61
73
  else
@@ -66,29 +78,14 @@ module Yara
66
78
  strings
67
79
  end
68
80
 
69
- def scan_complete?
70
- callback_type == SCAN_FINISHED
71
- end
72
-
73
- def rule_outcome?
74
- [RULE_MATCHING, RULE_NOT_MATCHING].include?(callback_type)
75
- end
76
-
77
- def match?
78
- callback_type == RULE_MATCHING
79
- end
80
-
81
- private
82
-
83
81
  def meta_as_hash(meta)
84
- name, string_value, int_value, type, _flags = meta.values
85
- value = meta_value(string_value, int_value, type)
86
- { name.to_sym => value }
82
+ value = meta_value(meta[:string], meta[:integer], meta[:type])
83
+ { meta[:identifier].to_sym => value }
87
84
  end
88
85
 
89
86
  def string_as_hash(yr_string)
90
- string_pointer = yr_string.values[STRING_POINTER]
91
- string_identifier = yr_string.values.last
87
+ string_pointer = yr_string[:string]
88
+ string_identifier = yr_string[:identifier]
92
89
  { string_identifier.to_sym => string_pointer.read_string }
93
90
  end
94
91
 
@@ -0,0 +1,81 @@
1
+ module Yara
2
+ class Scanner
3
+ class NotCompiledError < StandardError; end
4
+
5
+ ERROR_CALLBACK = proc do |error_level, file_name, line_number, rule, message, user_data|
6
+ # noop
7
+ end
8
+
9
+ SCAN_FINISHED = 3
10
+
11
+ # Public: Initializes instance of scanner. Under the hood this calls yr_initialize, then
12
+ # creates a pointer, then calls yr_compiler_create with that pointer.
13
+ #
14
+ # error_callback: (optional) Proc to be called when an error occurs.
15
+ # user_data: (optional) Instance of UserData to store and pass information.
16
+ def initialize(error_callback: ERROR_CALLBACK, user_data: UserData.new)
17
+ @error_callback = error_callback
18
+ @user_data = user_data
19
+ @compiler_pointer = ::FFI::MemoryPointer.new(:pointer)
20
+ Yara::FFI.yr_compiler_create(@compiler_pointer)
21
+ @compiler_pointer = @compiler_pointer.get_pointer(0)
22
+ Yara::FFI.yr_compiler_set_callback(@compiler_pointer, error_callback, user_data)
23
+ end
24
+
25
+ # Public: Adds a rule to the scanner and returns the namespace value. If a namespace
26
+ # is not provided it will default to nil and use the global namespace.
27
+ #
28
+ # rule_string - String containing the Yara rule to be added.
29
+ # namespace: (optional) String containing the namespace to be used for the rule.
30
+ def add_rule(rule_string, namespace: nil)
31
+ Yara::FFI.yr_compiler_add_string(@compiler_pointer, rule_string, namespace)
32
+ end
33
+
34
+ def compile
35
+ @rules_pointer = ::FFI::MemoryPointer.new(:pointer)
36
+ Yara::FFI.yr_compiler_get_rules(@compiler_pointer, @rules_pointer)
37
+ @rules_pointer = @rules_pointer.get_pointer(0)
38
+ Yara::FFI.yr_compiler_destroy(@compiler_pointer)
39
+ end
40
+
41
+ def call(test_string)
42
+ raise NotCompiledError unless @rules_pointer
43
+
44
+ results = []
45
+ scanning = true
46
+ result_callback = proc do |context_ptr, callback_type, rule, user_data|
47
+ if callback_type == SCAN_FINISHED
48
+ scanning = false
49
+ else
50
+ result = ScanResult.new(callback_type, rule, user_data)
51
+ results << result if result.rule_outcome?
52
+ end
53
+
54
+ 0 # ERROR_SUCCESS
55
+ end
56
+
57
+ test_string_bytesize = test_string.bytesize
58
+ test_string_pointer = ::FFI::MemoryPointer.new(:char, test_string_bytesize)
59
+ test_string_pointer.put_bytes(0, test_string)
60
+
61
+ Yara::FFI.yr_rules_scan_mem(
62
+ @rules_pointer,
63
+ test_string_pointer,
64
+ test_string_bytesize,
65
+ 0,
66
+ result_callback,
67
+ @user_data,
68
+ 1,
69
+ )
70
+
71
+ while scanning do
72
+ end
73
+
74
+ results
75
+ end
76
+
77
+ def close
78
+ Yara::FFI.yr_rules_destroy(@rules_pointer)
79
+ end
80
+ end
81
+ end
data/lib/yara/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Yara
4
- VERSION = "2.1.1"
4
+ VERSION = "3.0.0"
5
5
  end
data/lib/yara.rb CHANGED
@@ -4,67 +4,26 @@ require "ffi"
4
4
  require "pry"
5
5
  require_relative "yara/ffi"
6
6
  require_relative "yara/scan_result"
7
+ require_relative "yara/scanner"
7
8
  require_relative "yara/version"
8
9
 
9
10
  module Yara
10
- SCAN_FINISHED = 3
11
-
12
- class Error < StandardError; end
13
-
14
- def self.test(rule_string, test_string)
15
- user_data = UserData.new
16
- scanning = true
17
- results = []
18
-
11
+ def self.start
19
12
  Yara::FFI.yr_initialize
13
+ end
20
14
 
21
- compiler_pointer = ::FFI::MemoryPointer.new(:pointer)
22
- Yara::FFI.yr_compiler_create(compiler_pointer)
23
- compiler_pointer = compiler_pointer.get_pointer(0)
24
-
25
- error_callback = proc do |error_level, file_name, line_number, rule, message, user_data|
26
- # noop
27
- end
28
-
29
- Yara::FFI.yr_compiler_set_callback(compiler_pointer, error_callback, user_data)
30
- Yara::FFI.yr_compiler_add_string(compiler_pointer, rule_string, nil)
31
-
32
- rules_pointer =::FFI::MemoryPointer.new(:pointer)
33
- Yara::FFI.yr_compiler_get_rules(compiler_pointer, rules_pointer)
34
- rules_pointer = rules_pointer.get_pointer(0)
35
-
36
- result_callback = proc do |context_ptr, callback_type, rule_ptr, user_data_ptr|
37
- if callback_type == SCAN_FINISHED
38
- scanning = false
39
- else
40
- result = ScanResult.new(callback_type, rule_ptr)
41
- results << result if result.rule_outcome?
42
- end
43
-
44
- 0 # ERROR_SUCCESS
45
- end
46
-
47
- test_string_bytesize = test_string.bytesize
48
- test_string_pointer = ::FFI::MemoryPointer.new(:char, test_string_bytesize)
49
- test_string_pointer.put_bytes(0, test_string)
50
-
51
- Yara::FFI.yr_rules_scan_mem(
52
- rules_pointer,
53
- test_string_pointer,
54
- test_string_bytesize,
55
- 0,
56
- result_callback,
57
- user_data,
58
- 1,
59
- )
60
-
61
- while scanning do
62
- end
15
+ def self.stop
16
+ Yara::FFI.yr_finalize
17
+ end
63
18
 
64
- results
19
+ def self.test(rule_string, test_string)
20
+ start
21
+ scanner = Yara::Scanner.new
22
+ scanner.add_rule(rule_string)
23
+ scanner.compile
24
+ scanner.call(test_string)
65
25
  ensure
66
- Yara::FFI.yr_rules_destroy(rules_pointer)
67
- Yara::FFI.yr_compiler_destroy(compiler_pointer)
68
- Yara::FFI.yr_finalize
26
+ scanner.close
27
+ stop
69
28
  end
70
29
  end
data/script/bootstrap ADDED
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+
3
+ docker build . -t yara-ffi
data/script/test ADDED
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+
3
+ docker run -it --mount type=bind,src="$(pwd)",dst=/app yara-ffi bundle exec rake
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yara-ffi
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Hoyt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-31 00:00:00.000000000 Z
11
+ date: 2021-10-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -36,6 +36,7 @@ files:
36
36
  - ".rubocop.yml"
37
37
  - CHANGELOG.md
38
38
  - CODE_OF_CONDUCT.md
39
+ - Dockerfile
39
40
  - Gemfile
40
41
  - Gemfile.lock
41
42
  - LICENSE.txt
@@ -46,28 +47,15 @@ files:
46
47
  - lib/yara.rb
47
48
  - lib/yara/ffi.rb
48
49
  - lib/yara/scan_result.rb
50
+ - lib/yara/scanner.rb
49
51
  - lib/yara/user_data.rb
50
52
  - lib/yara/version.rb
51
53
  - lib/yara/yr_meta.rb
52
54
  - lib/yara/yr_namespace.rb
53
55
  - lib/yara/yr_rule.rb
54
56
  - lib/yara/yr_string.rb
55
- - vendor/cache/ast-2.4.2.gem
56
- - vendor/cache/coderay-1.1.3.gem
57
- - vendor/cache/ffi-1.15.0.gem
58
- - vendor/cache/method_source-1.0.0.gem
59
- - vendor/cache/minitest-5.14.4.gem
60
- - vendor/cache/parallel-1.20.1.gem
61
- - vendor/cache/parser-3.0.0.0.gem
62
- - vendor/cache/pry-0.14.0.gem
63
- - vendor/cache/rainbow-3.0.0.gem
64
- - vendor/cache/rake-13.0.3.gem
65
- - vendor/cache/regexp_parser-2.1.1.gem
66
- - vendor/cache/rexml-3.2.4.gem
67
- - vendor/cache/rubocop-1.11.0.gem
68
- - vendor/cache/rubocop-ast-1.4.1.gem
69
- - vendor/cache/ruby-progressbar-1.11.0.gem
70
- - vendor/cache/unicode-display_width-2.0.0.gem
57
+ - script/bootstrap
58
+ - script/test
71
59
  - yara-ffi.gemspec
72
60
  homepage: https://github.com/jonmagic/yara-ffi
73
61
  licenses:
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file