Class: Yara::Rule
- Inherits:
-
Object
- Object
- Yara::Rule
- Defined in:
- lib/yara/rule.rb
Overview
Public: Represents a YARA rule from compiled rules.
A Rule provides access to a YARA rule’s metadata, tags, and patterns without needing to scan any data. This is useful for inspecting compiled rules, extracting metadata, and understanding rule structure.
Examples
# Typically created by Scanner#each_rule
scanner.each_rule do |rule|
puts "Rule: #{rule.identifier}"
puts "Namespace: #{rule.namespace}"
puts "Tags: #{rule..join(', ')}"
rule..each { |k, v| puts " #{k}: #{v}" }
end
Instance Attribute Summary collapse
-
#identifier ⇒ Object
readonly
Public: The identifier (name) of the rule.
-
#namespace ⇒ Object
readonly
Public: The namespace of the rule.
-
#rule_ptr ⇒ Object
readonly
Public: FFI pointer to the underlying YRX_RULE structure.
Instance Method Summary collapse
-
#extract_identifier ⇒ Object
Internal: Extract the rule identifier using YARA-X API.
-
#extract_metadata ⇒ Object
Internal: Extract metadata from the rule using YARA-X API.
-
#extract_namespace ⇒ Object
Internal: Extract the rule namespace using YARA-X API.
-
#extract_tags ⇒ Object
Internal: Extract tags from the rule using YARA-X API.
-
#has_tag?(tag) ⇒ Boolean
Public: Check if the rule has a specific tag.
-
#initialize(rule_ptr) ⇒ Rule
constructor
Public: Initialize a new Rule from a YRX_RULE pointer.
-
#metadata ⇒ Object
Public: Get the rule’s metadata as a Hash.
-
#metadata_bool(key) ⇒ Object
Public: Get a Boolean metadata value with type validation.
-
#metadata_float(key) ⇒ Object
Public: Get a Float metadata value with type validation.
-
#metadata_int(key) ⇒ Object
Public: Get an Integer metadata value with type validation.
-
#metadata_string(key) ⇒ Object
Public: Get a String metadata value with type validation.
-
#metadata_value(key) ⇒ Object
Public: Get a metadata value by key with type checking.
-
#qualified_name ⇒ Object
Public: Get a qualified name combining namespace and identifier.
-
#tags ⇒ Object
Public: Get the rule’s tags as an Array.
Constructor Details
#initialize(rule_ptr) ⇒ Rule
Public: Initialize a new Rule from a YRX_RULE pointer.
This constructor extracts the rule identifier, namespace, metadata, and tags using the YARA-X C API.
rule_ptr - An FFI Pointer to the YRX_RULE structure
Examples
# Typically created internally by Scanner#each_rule
rule = Rule.new(rule_ptr)
40 41 42 43 44 45 46 |
# File 'lib/yara/rule.rb', line 40 def initialize(rule_ptr) @rule_ptr = rule_ptr @identifier = extract_identifier @namespace = extract_namespace @metadata_cache = nil @tags_cache = nil end |
Instance Attribute Details
#identifier ⇒ Object (readonly)
Public: The identifier (name) of the rule.
21 22 23 |
# File 'lib/yara/rule.rb', line 21 def identifier @identifier end |
#namespace ⇒ Object (readonly)
Public: The namespace of the rule.
24 25 26 |
# File 'lib/yara/rule.rb', line 24 def namespace @namespace end |
#rule_ptr ⇒ Object (readonly)
Public: FFI pointer to the underlying YRX_RULE structure.
27 28 29 |
# File 'lib/yara/rule.rb', line 27 def rule_ptr @rule_ptr end |
Instance Method Details
#extract_identifier ⇒ Object
Internal: Extract the rule identifier using YARA-X API.
Returns a String containing the rule name.
183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/yara/rule.rb', line 183 def extract_identifier ident_ptr = ::FFI::MemoryPointer.new(:pointer) len_ptr = ::FFI::MemoryPointer.new(:size_t) result = Yara::FFI.yrx_rule_identifier(@rule_ptr, ident_ptr, len_ptr) if result != Yara::FFI::YRX_SUCCESS raise "Failed to extract rule identifier: #{Yara::FFI.yrx_last_error}" end ident = ident_ptr.read_pointer length = len_ptr.read(:size_t) ident.read_bytes(length).force_encoding("UTF-8") end |
#extract_metadata ⇒ Object
Internal: Extract metadata from the rule using YARA-X API.
Returns a Hash mapping metadata keys to their values.
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
# File 'lib/yara/rule.rb', line 220 def = {} = proc do |, _user_data| begin # Read identifier (first field, pointer at offset 0) identifier_ptr = .get_pointer(0) next if identifier_ptr.null? identifier = identifier_ptr.read_string.to_sym # Read value_type (int at offset 8, after the 8-byte pointer) value_type = .get_int32(8) # The value union starts at offset 16 (pointer:8 + int:4 + padding:4) # This is due to struct alignment requirements value_offset = 16 value = case value_type when Yara::FFI::YRX_METADATA_TYPE_I64 .get_int64(value_offset) when Yara::FFI::YRX_METADATA_TYPE_F64 .get_double(value_offset) when Yara::FFI::YRX_METADATA_TYPE_BOOLEAN .get_uint8(value_offset) != 0 when Yara::FFI::YRX_METADATA_TYPE_STRING str_ptr = .get_pointer(value_offset) str_ptr.null? ? nil : str_ptr.read_string when Yara::FFI::YRX_METADATA_TYPE_BYTES length = .get_size_t(value_offset) data_ptr = .get_pointer(value_offset + 8) (data_ptr.null? || length == 0) ? nil : data_ptr.read_bytes(length) else nil end [identifier] = value unless value.nil? rescue => e # Skip problematic metadata entries to ensure partial extraction works end end result = Yara::FFI.(@rule_ptr, , nil) if result != Yara::FFI::YRX_SUCCESS raise "Failed to iterate rule metadata: #{Yara::FFI.yrx_last_error}" end end |
#extract_namespace ⇒ Object
Internal: Extract the rule namespace using YARA-X API.
Returns a String containing the namespace, or nil if default namespace.
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/yara/rule.rb', line 200 def extract_namespace ns_ptr = ::FFI::MemoryPointer.new(:pointer) len_ptr = ::FFI::MemoryPointer.new(:size_t) result = Yara::FFI.yrx_rule_namespace(@rule_ptr, ns_ptr, len_ptr) if result != Yara::FFI::YRX_SUCCESS raise "Failed to extract rule namespace: #{Yara::FFI.yrx_last_error}" end ns = ns_ptr.read_pointer length = len_ptr.read(:size_t) namespace_str = ns.read_bytes(length).force_encoding("UTF-8") # Return nil for default namespace namespace_str.empty? ? nil : namespace_str end |
#extract_tags ⇒ Object
Internal: Extract tags from the rule using YARA-X API.
Returns an Array of Strings containing the rule’s tags.
272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
# File 'lib/yara/rule.rb', line 272 def = [] tag_callback = proc do |tag_ptr, _user_data| << tag_ptr.read_string unless tag_ptr.null? end result = Yara::FFI.(@rule_ptr, tag_callback, nil) if result != Yara::FFI::YRX_SUCCESS raise "Failed to iterate rule tags: #{Yara::FFI.yrx_last_error}" end end |
#has_tag?(tag) ⇒ Boolean
Public: Check if the rule has a specific tag.
tag - A String or Symbol representing the tag to check
Returns true if the tag exists, false otherwise.
Examples
rule.has_tag?("malware")
# => true
102 103 104 |
# File 'lib/yara/rule.rb', line 102 def has_tag?(tag) .include?(tag.to_s) end |
#metadata ⇒ Object
Public: Get the rule’s metadata as a Hash.
Metadata is extracted from the rule’s meta section and includes various types: strings, integers, floats, booleans, and bytes.
Returns a Hash mapping metadata keys (Symbols) to their values.
Examples
= rule.
# => { author: "test", severity: 5, is_malware: true }
59 60 61 |
# File 'lib/yara/rule.rb', line 59 def @metadata_cache ||= end |
#metadata_bool(key) ⇒ Object
Public: Get a Boolean metadata value with type validation.
key - A Symbol or String representing the metadata key
Returns the Boolean value if found and is a Boolean, nil otherwise.
Examples
rule.(:is_malware)
# => true
160 161 162 163 |
# File 'lib/yara/rule.rb', line 160 def (key) value = (key) [true, false].include?(value) ? value : nil end |
#metadata_float(key) ⇒ Object
Public: Get a Float metadata value with type validation.
key - A Symbol or String representing the metadata key
Returns the Float value if found and is a Float, nil otherwise.
Examples
rule.(:confidence)
# => 0.95
175 176 177 178 |
# File 'lib/yara/rule.rb', line 175 def (key) value = (key) value.is_a?(Float) ? value : nil end |
#metadata_int(key) ⇒ Object
Public: Get an Integer metadata value with type validation.
key - A Symbol or String representing the metadata key
Returns the Integer value if found and is an Integer, nil otherwise.
Examples
rule.(:severity)
# => 5
145 146 147 148 |
# File 'lib/yara/rule.rb', line 145 def (key) value = (key) value.is_a?(Integer) ? value : nil end |
#metadata_string(key) ⇒ Object
Public: Get a String metadata value with type validation.
key - A Symbol or String representing the metadata key
Returns the String value if found and is a String, nil otherwise.
Examples
rule.(:author)
# => "test_author"
130 131 132 133 |
# File 'lib/yara/rule.rb', line 130 def (key) value = (key) value.is_a?(String) ? value : nil end |
#metadata_value(key) ⇒ Object
Public: Get a metadata value by key with type checking.
key - A Symbol or String representing the metadata key
Returns the metadata value if found, nil otherwise.
Examples
rule.(:author)
# => "test_author"
116 117 118 |
# File 'lib/yara/rule.rb', line 116 def (key) [key.to_sym] end |
#qualified_name ⇒ Object
Public: Get a qualified name combining namespace and identifier.
Returns a String in the format “namespace.identifier”.
Examples
rule.qualified_name
# => "malware.trojan_detector"
86 87 88 89 90 |
# File 'lib/yara/rule.rb', line 86 def qualified_name return identifier if namespace.nil? || namespace.empty? "#{namespace}.#{identifier}" end |
#tags ⇒ Object
Public: Get the rule’s tags as an Array.
Tags are labels used to categorize and organize rules, defined after the rule name in the rule definition.
Returns an Array of Strings containing the rule’s tags.
Examples
= rule.
# => ["malware", "trojan"]
74 75 76 |
# File 'lib/yara/rule.rb', line 74 def @tags_cache ||= end |