yara-ffi 2.1.1 → 3.0.0

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.
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