yara-ffi 1.0.0 → 2.1.1

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: 380c0c04b4e921df435344606ae662123cdf59e8e1bb20bc442f1282285d87d1
4
- data.tar.gz: 5348991427d0376f4d0b31e8a1e9cd64275e760a2a9839e10eb0cc87dcedbfaf
3
+ metadata.gz: ac111338f4038017b3eb887d2bfcea73c2a2aa5a9b409370e13cfd01985276df
4
+ data.tar.gz: 353ab52ebe038b8fbd2b3c9ce35436df1b4fb20cad1cfa0b3019e678291e0f0b
5
5
  SHA512:
6
- metadata.gz: a640d8ef7adce2b261de4e7144e2c8ea35519c566cbd2c6a75c04ab68bda54bbf0d339b37bb210fdf60b1bed7bb152fe3c0e0e20355c7f8ec45364c2dd25dc31
7
- data.tar.gz: 9063e8934d649121a5c2e9489d662c5bdb64b695ac359981d0801bc439ba64699fded19c8d0096c3ae4900fb59b8823c84cec153e0573bc81219e3d4e0e74b12
6
+ metadata.gz: 96a2ede305474b3457dcaf4256e3b57fa28becae0abc51eb3e45897667f5a971ba818a45a6b945b15d02208c2eee6adad43ff416c31d9528083ed7dd5a317046
7
+ data.tar.gz: 6b1a3fa08e02123b655d140f30fa531494d585276591f5758b6f8c26636ea0fe388eef7fa5e6253d9fce42221b19729eab0960684a87eaf95e96f701eacd4fb7
data/lib/yara/ffi.rb CHANGED
@@ -35,6 +35,11 @@ module Yara
35
35
  :pointer, # compiler_pointer
36
36
  ], :void
37
37
 
38
+ # int yr_rules_destroy(YR_RULES* rules)
39
+ attach_function :yr_rules_destroy, [
40
+ :pointer, # rules_pointer
41
+ ], :void
42
+
38
43
  # void callback_function(
39
44
  # int error_level,
40
45
  # const char* file_name,
@@ -100,7 +105,7 @@ module Yara
100
105
  # int timeout)
101
106
  attach_function :yr_rules_scan_mem, [
102
107
  :pointer, # rules_pointer*
103
- :string, # buffer (aka test subject)
108
+ :pointer, # buffer (aka test subject)
104
109
  :size_t, # buffer size (String#bytesize)
105
110
  :int, # flags
106
111
  :scan_callback, # proc
@@ -0,0 +1,105 @@
1
+ module Yara
2
+ class ScanResult
3
+ RULE_MATCHING = 1
4
+ RULE_NOT_MATCHING = 2
5
+
6
+ META_FLAGS_LAST_IN_RULE = 1
7
+
8
+ META_TYPE_INTEGER = 1
9
+ META_TYPE_STRING = 2
10
+ META_TYPE_BOOLEAN = 3
11
+
12
+ STRING_FLAGS_LAST_IN_RULE = 0
13
+
14
+ STRING_LENGTH = 4
15
+ STRING_POINTER = 5
16
+
17
+ RULE_IDENTIFIER = 1
18
+ METAS_IDENTIFIER = 3
19
+ STRING_IDENTIFIER = 4
20
+
21
+ attr_reader :callback_type, :rule
22
+
23
+ def initialize(callback_type, rule_ptr)
24
+ @callback_type = callback_type
25
+ @rule = YrRule.new(rule_ptr)
26
+ end
27
+
28
+ def rule_name
29
+ @rule.values[RULE_IDENTIFIER]
30
+ end
31
+
32
+ def rule_meta
33
+ metas = {}
34
+ reading_metas = true
35
+ meta_index = 0
36
+ meta_pointer = @rule.values[METAS_IDENTIFIER]
37
+ while reading_metas do
38
+ meta = YrMeta.new(meta_pointer + meta_index * YrMeta.size)
39
+ metas.merge!(meta_as_hash(meta))
40
+ flags = meta.values.last
41
+ if flags == META_FLAGS_LAST_IN_RULE
42
+ reading_metas = false
43
+ else
44
+ meta_index += 1
45
+ end
46
+ end
47
+ metas
48
+ end
49
+
50
+ def rule_strings
51
+ strings = {}
52
+ reading_strings = true
53
+ string_index = 0
54
+ string_pointer = @rule.values[STRING_IDENTIFIER]
55
+ while reading_strings do
56
+ string = YrString.new(string_pointer + string_index * YrString.size)
57
+ string_length = string.values[STRING_LENGTH]
58
+ flags = string.values.first
59
+ if flags == STRING_FLAGS_LAST_IN_RULE
60
+ reading_strings = false
61
+ else
62
+ strings.merge!(string_as_hash(string)) unless string_length == 0
63
+ string_index += 1
64
+ end
65
+ end
66
+ strings
67
+ end
68
+
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
+ 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 }
87
+ end
88
+
89
+ def string_as_hash(yr_string)
90
+ string_pointer = yr_string.values[STRING_POINTER]
91
+ string_identifier = yr_string.values.last
92
+ { string_identifier.to_sym => string_pointer.read_string }
93
+ end
94
+
95
+ def meta_value(string_value, int_value, type)
96
+ if type == META_TYPE_INTEGER
97
+ int_value
98
+ elsif type == META_TYPE_BOOLEAN
99
+ int_value == 1
100
+ else
101
+ string_value
102
+ end
103
+ end
104
+ end
105
+ 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 = "1.0.0"
4
+ VERSION = "2.1.1"
5
5
  end
data/lib/yara/yr_meta.rb CHANGED
@@ -2,6 +2,9 @@ module Yara
2
2
  class YrMeta < FFI::Struct
3
3
  layout \
4
4
  :identifier, :string,
5
- :type, :int32_t
5
+ :string, :string,
6
+ :integer, :int64_t,
7
+ :type, :int32_t,
8
+ :flags, :int32_t
6
9
  end
7
10
  end
data/lib/yara/yr_rule.rb CHANGED
@@ -4,8 +4,8 @@ module Yara
4
4
  :flags, :int32_t,
5
5
  :identifier, :string,
6
6
  :tags, :string,
7
- :metas, YrMeta.ptr,
8
- :strings, YrString.ptr,
7
+ :metas, :pointer,
8
+ :strings, :pointer,
9
9
  :ns, YrNamespace.ptr
10
10
  end
11
11
  end
@@ -1,5 +1,15 @@
1
1
  module Yara
2
2
  class YrString < FFI::Struct
3
- layout :identifier, :string
3
+ layout \
4
+ :flags, :uint32_t,
5
+ :idx, :uint32_t,
6
+ :fixed_offset, :int64_t,
7
+ :rule_idx, :uint32_t,
8
+ :length, :int32_t,
9
+ :string, :pointer,
10
+ :chained_to, :pointer,
11
+ :chain_gap_min, :int32_t,
12
+ :chain_gap_max, :int32_t,
13
+ :identifier, :string
4
14
  end
5
15
  end
data/lib/yara.rb CHANGED
@@ -2,22 +2,17 @@
2
2
 
3
3
  require "ffi"
4
4
  require "pry"
5
- require_relative "yara/version"
6
5
  require_relative "yara/ffi"
6
+ require_relative "yara/scan_result"
7
+ require_relative "yara/version"
7
8
 
8
- # TBD
9
9
  module Yara
10
- class Error < StandardError; end
11
-
12
- CALLBACK_MSG_RULE_MATCHING = 1
13
- CALLBACK_MSG_RULE_NOT_MATCHING = 2
14
- CALLBACK_MSG_SCAN_FINISHED = 3
10
+ SCAN_FINISHED = 3
15
11
 
16
- RULE_IDENTIFIER = 1
12
+ class Error < StandardError; end
17
13
 
18
14
  def self.test(rule_string, test_string)
19
15
  user_data = UserData.new
20
- user_data[:number] = 42
21
16
  scanning = true
22
17
  results = []
23
18
 
@@ -38,23 +33,25 @@ module Yara
38
33
  Yara::FFI.yr_compiler_get_rules(compiler_pointer, rules_pointer)
39
34
  rules_pointer = rules_pointer.get_pointer(0)
40
35
 
41
- result_callback = proc do |context_ptr, message, message_data_ptr, user_data_ptr|
42
- rule = YrRule.new(message_data_ptr)
43
-
44
- case message
45
- when CALLBACK_MSG_RULE_MATCHING
46
- results << rule.values[RULE_IDENTIFIER]
47
- when CALLBACK_MSG_SCAN_FINISHED
36
+ result_callback = proc do |context_ptr, callback_type, rule_ptr, user_data_ptr|
37
+ if callback_type == SCAN_FINISHED
48
38
  scanning = false
39
+ else
40
+ result = ScanResult.new(callback_type, rule_ptr)
41
+ results << result if result.rule_outcome?
49
42
  end
50
43
 
51
44
  0 # ERROR_SUCCESS
52
45
  end
53
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
+
54
51
  Yara::FFI.yr_rules_scan_mem(
55
52
  rules_pointer,
56
- test_string,
57
- test_string.bytesize,
53
+ test_string_pointer,
54
+ test_string_bytesize,
58
55
  0,
59
56
  result_callback,
60
57
  user_data,
@@ -66,6 +63,8 @@ module Yara
66
63
 
67
64
  results
68
65
  ensure
66
+ Yara::FFI.yr_rules_destroy(rules_pointer)
67
+ Yara::FFI.yr_compiler_destroy(compiler_pointer)
69
68
  Yara::FFI.yr_finalize
70
69
  end
71
70
  end
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: 1.0.0
4
+ version: 2.1.1
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-16 00:00:00.000000000 Z
11
+ date: 2021-08-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -45,6 +45,7 @@ files:
45
45
  - bin/setup
46
46
  - lib/yara.rb
47
47
  - lib/yara/ffi.rb
48
+ - lib/yara/scan_result.rb
48
49
  - lib/yara/user_data.rb
49
50
  - lib/yara/version.rb
50
51
  - lib/yara/yr_meta.rb