yara-normalize 0.2.0 → 1.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 +4 -4
- data/README.rdoc +69 -35
- data/lib/yara-normalize/yara-normalize.rb +153 -108
- metadata +43 -39
- data/.document +0 -5
- data/Gemfile +0 -14
- data/Gemfile.lock +0 -88
- data/Rakefile +0 -46
- data/VERSION +0 -1
- data/test/helper.rb +0 -20
- data/test/test_yara-normalize.rb +0 -113
- data/yara-normalize.gemspec +0 -60
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 13f41905bf9f1f9e8d8f30146578908c1752bffb95f8058cd849f985655104d0
|
|
4
|
+
data.tar.gz: f03ec512ead274a1e8990fe2d6448c2f62361e3a5729db0f0c7f24ea10dc69d9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 485d6e7e454a7ea967b11d9065f31403a7e8b7a08b9b218d674d4007f07cbe2ec702258794acf021b75b4a35627dcbe6dc4eda2d91b17f37ee392f235fdc5005
|
|
7
|
+
data.tar.gz: 2379f78b6e1b4d283a4e0f209e76a18597da2b8a8e0b4e596c85e86ad4e59a2c69c748f72e857c86186ebaa460a0e91fb3d58e7308d1308bcd7898042caccb14
|
data/README.rdoc
CHANGED
|
@@ -1,35 +1,34 @@
|
|
|
1
1
|
= yara-normalize
|
|
2
2
|
|
|
3
|
-
Normalizes
|
|
4
|
-
|
|
3
|
+
Normalizes YARA signatures into a repeatable, stable hash even when
|
|
4
|
+
non-semantic changes are made (whitespace, comments, tag ordering, variable
|
|
5
|
+
renaming, etc.).
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
with $a $b $c, etc. Then hash the result of this.
|
|
7
|
+
To enable consistent comparisons between YARA rules, a uniform fingerprinting
|
|
8
|
+
standard is applied:
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
1. *Strings section* — each string value (the part after the '=') is extracted,
|
|
11
|
+
sorted alphabetically, and the sorted list is hashed with SHA-256. Variable
|
|
12
|
+
names ($a, $mshtmlExec_1, …) are excluded from the hash so that renaming
|
|
13
|
+
does not change the fingerprint.
|
|
11
14
|
|
|
12
|
-
|
|
15
|
+
2. *Condition section* — variable references ($name, #name) are replaced with
|
|
16
|
+
positional tokens ($0, $1, …) in order of first appearance, so cosmetic
|
|
17
|
+
renames do not affect the hash. The resulting text is hashed with SHA-256.
|
|
18
|
+
|
|
19
|
+
The rule fingerprint is:
|
|
20
|
+
|
|
21
|
+
yn<VERSION>:<last-16-hex-chars-of-strings-SHA256>:<last-10-hex-chars-of-condition-SHA256>
|
|
13
22
|
|
|
14
|
-
|
|
23
|
+
Prior to version 0.4.0 the fingerprint used MD5 and carried the prefix +yn01+.
|
|
24
|
+
Since 0.4.0 the fingerprint uses SHA-256 and carries the prefix +yn02+. The
|
|
25
|
+
two identifier series are not interchangeable.
|
|
26
|
+
|
|
27
|
+
== Usage
|
|
15
28
|
|
|
16
29
|
require 'yara-normalize'
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
meta:
|
|
20
|
-
weight =1
|
|
21
|
-
strings:
|
|
22
|
-
$="wtoi" nocase
|
|
23
|
-
$ ="wtol" nocase
|
|
24
|
-
$= "wtof" nocase
|
|
25
|
-
$ = "wtodb" nocase
|
|
26
|
-
condition:
|
|
27
|
-
any of them
|
|
28
|
-
}
|
|
29
|
-
EOS
|
|
30
|
-
yn = YaraTools::YaraRule.new(sig)
|
|
31
|
-
puts yn.hash # => yn01:488085c947cb22ed:d936fceffe
|
|
32
|
-
puts yn.normalize # =>
|
|
30
|
+
|
|
31
|
+
sig = <<~EOS
|
|
33
32
|
rule DataConversion__wide : IntegerParsing DataConversion {
|
|
34
33
|
meta:
|
|
35
34
|
weight = 1
|
|
@@ -41,22 +40,57 @@ See test cases.
|
|
|
41
40
|
condition:
|
|
42
41
|
any of them
|
|
43
42
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
EOS
|
|
44
|
+
|
|
45
|
+
yn = YaraTools::YaraRule.new(sig)
|
|
46
|
+
|
|
47
|
+
puts yn.hash
|
|
48
|
+
# => yn02:6783b7082bed88dc:6821e3f6a3
|
|
49
|
+
|
|
50
|
+
puts yn.name # => DataConversion__wide
|
|
51
|
+
pp yn.tags # => ["IntegerParsing", "DataConversion"]
|
|
52
|
+
pp yn.meta # => {"weight"=>"1"}
|
|
53
|
+
pp yn.strings # => ["$ = \"wtoi\" nocase", ...]
|
|
54
|
+
|
|
55
|
+
puts yn.normalize
|
|
56
|
+
# => rule DataConversion__wide : IntegerParsing DataConversion {
|
|
57
|
+
# meta:
|
|
58
|
+
# weight = 1
|
|
59
|
+
# strings:
|
|
60
|
+
# $ = "wtoi" nocase
|
|
61
|
+
# $ = "wtol" nocase
|
|
62
|
+
# $ = "wtof" nocase
|
|
63
|
+
# $ = "wtodb" nocase
|
|
64
|
+
# condition:
|
|
65
|
+
# any of them
|
|
66
|
+
# }
|
|
67
|
+
|
|
68
|
+
Splitting a multi-rule file:
|
|
69
|
+
|
|
70
|
+
rules = YaraTools::Splitter.split(File.read("ruleset.yar"))
|
|
71
|
+
rules.each { |r| puts "#{r.name}: #{r.hash}" }
|
|
72
|
+
|
|
73
|
+
== Security notes
|
|
74
|
+
|
|
75
|
+
* Fingerprints use SHA-256 (as of yn02). MD5-based yn01 hashes should be
|
|
76
|
+
considered legacy and re-computed.
|
|
77
|
+
* +YaraRule#hash+ overrides Ruby's +Object#hash+. Do *not* use +YaraRule+
|
|
78
|
+
objects as Hash keys; the method returns a String fingerprint, not the
|
|
79
|
+
Integer that Ruby's Hash tables require.
|
|
47
80
|
|
|
48
81
|
== Contributing to yara-normalize
|
|
49
|
-
|
|
50
|
-
* Check out the latest master to make sure the feature hasn't been implemented
|
|
51
|
-
|
|
82
|
+
|
|
83
|
+
* Check out the latest master to make sure the feature hasn't been implemented
|
|
84
|
+
or the bug hasn't been fixed yet.
|
|
85
|
+
* Check out the issue tracker to make sure someone already hasn't requested it
|
|
86
|
+
and/or contributed it.
|
|
52
87
|
* Fork the project.
|
|
53
88
|
* Start a feature/bugfix branch.
|
|
54
89
|
* Commit and push until you are happy with your contribution.
|
|
55
|
-
* Make sure to add tests for it. This is important so I don't break it in a
|
|
56
|
-
|
|
90
|
+
* Make sure to add tests for it. This is important so I don't break it in a
|
|
91
|
+
future version unintentionally.
|
|
92
|
+
* Please try not to mess with the Rakefile, version, or history.
|
|
57
93
|
|
|
58
94
|
== Copyright
|
|
59
95
|
|
|
60
|
-
Copyright (c) 2012 chrislee35. See LICENSE.txt for
|
|
61
|
-
further details.
|
|
62
|
-
|
|
96
|
+
Copyright (c) 2012 chrislee35. See LICENSE.txt for further details.
|
|
@@ -1,110 +1,155 @@
|
|
|
1
|
-
require 'digest
|
|
2
|
-
|
|
1
|
+
require 'digest'
|
|
2
|
+
|
|
3
3
|
module YaraTools
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
4
|
+
# Hash format version embedded in every yn-hash identifier.
|
|
5
|
+
# Increment when the normalization algorithm changes so consumers can
|
|
6
|
+
# detect that two hashes are not directly comparable (e.g. yn01 vs yn02).
|
|
7
|
+
VERSION = "02"
|
|
8
|
+
|
|
9
|
+
class YaraRule
|
|
10
|
+
attr_reader :original, :name, :tags, :meta, :strings, :condition, :normalized_strings
|
|
11
|
+
|
|
12
|
+
def initialize(ruletext)
|
|
13
|
+
# Normalize line endings and strip single-line (//) comments before
|
|
14
|
+
# any further parsing so they never appear in meta/strings/condition.
|
|
15
|
+
ruletext = ruletext.gsub(/[\r\n]+/, "\n").gsub(/^\s*\/\/.*$/, '')
|
|
16
|
+
@original = ruletext
|
|
17
|
+
|
|
18
|
+
# Lookup table used by _normalize_condition to replace variable names
|
|
19
|
+
# ($foo, #foo) with stable positional tokens ($0, $1, …) so that
|
|
20
|
+
# cosmetic renames do not affect the normalized condition hash.
|
|
21
|
+
@lookup_table = {}
|
|
22
|
+
@next_replacement = 0
|
|
23
|
+
|
|
24
|
+
# Single-pass regex parse. The rule grammar is:
|
|
25
|
+
# rule <name> [: <tags>] { [meta: …] strings: … condition: … }
|
|
26
|
+
# The .*? quantifiers are non-greedy so they stop at the first matching
|
|
27
|
+
# delimiter keyword rather than consuming the whole file.
|
|
28
|
+
rule_re = /rule\s+([\w\-]+)(\s*:\s*(\w[\w\s]+\w))?\s*\{\s*(meta:\s*(.*?))?strings:\s*(.*?)\s*condition:\s*(.*?)\s*\}/m
|
|
29
|
+
if ruletext =~ rule_re
|
|
30
|
+
name, _, tags, _, meta, strings, condition = $~.captures
|
|
31
|
+
|
|
32
|
+
@name = name
|
|
33
|
+
|
|
34
|
+
# Tags are optional; split on whitespace/commas when present.
|
|
35
|
+
@tags = tags.strip.split(/[,\s]+/) if tags
|
|
36
|
+
|
|
37
|
+
# Parse the meta section into a key/value Hash. Each line has the
|
|
38
|
+
# form: key = value (value may contain spaces and quotes).
|
|
39
|
+
@meta = {}
|
|
40
|
+
if meta
|
|
41
|
+
meta.split(/\n/).each do |m|
|
|
42
|
+
k, v = m.strip.split(/\s*=\s*/, 2)
|
|
43
|
+
@meta[k] = v if v
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Parse the strings section, normalizing whitespace around '=' and
|
|
48
|
+
# canonicalizing any hex byte strings (e.g. { 4D 5A } → { 4d 5a }).
|
|
49
|
+
@normalized_strings = []
|
|
50
|
+
@strings = strings.split(/\n/).map do |s|
|
|
51
|
+
s = s.strip
|
|
52
|
+
|
|
53
|
+
# Collapse any amount of whitespace around '=' to a single ' = '.
|
|
54
|
+
s[/\s*=\s*/, 0] = " = " if s[/\s*=\s*/, 0]
|
|
55
|
+
|
|
56
|
+
# Hex byte strings: normalise spacing and case so that
|
|
57
|
+
# { 4D5A } and { 4d 5a } produce the same output.
|
|
58
|
+
if s =~ /= \{([0-9a-fA-F\s]+)\}/
|
|
59
|
+
hexstr = $1.gsub(/\s+/, '').downcase.scan(/../).join(" ")
|
|
60
|
+
s = s.gsub(/= \{([0-9a-fA-F\s]+)\}/, "= { #{hexstr} }")
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Collect only the value portion (right of ' = ') for hashing,
|
|
64
|
+
# so that variable renames ($a → $b) do not change the hash.
|
|
65
|
+
_, val = s.split(/ = /, 2)
|
|
66
|
+
@normalized_strings << (val || s)
|
|
67
|
+
s
|
|
68
|
+
end
|
|
69
|
+
@normalized_strings.sort!
|
|
70
|
+
|
|
71
|
+
@condition = condition.split(/\n/).map(&:strip)
|
|
72
|
+
@normalized_condition = @condition.map { |x| _normalize_condition(x) }
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Replace named variable references in a condition line with positional
|
|
77
|
+
# tokens so that renaming $mshtmlExec_1 → $a does not change the hash.
|
|
78
|
+
# Both count (#) and match ($) sigils are preserved.
|
|
79
|
+
# NOTE: This method is intentionally prefixed with _ to signal that it is
|
|
80
|
+
# an internal implementation detail; do not call it from outside this class.
|
|
81
|
+
def _normalize_condition(condition)
|
|
82
|
+
condition.gsub(/[\$\#]\w+/) do |x|
|
|
83
|
+
key = x[1, 1000]
|
|
84
|
+
@lookup_table[key] ||= begin
|
|
85
|
+
val = @next_replacement.to_s
|
|
86
|
+
@next_replacement += 1
|
|
87
|
+
val
|
|
88
|
+
end
|
|
89
|
+
x[0].chr + @lookup_table[key]
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Return a canonical, human-readable rendering of the rule with
|
|
94
|
+
# consistent indentation and ordering. Tags, meta, strings, and
|
|
95
|
+
# condition are preserved in their original order.
|
|
96
|
+
def normalize
|
|
97
|
+
text = "rule #{@name} "
|
|
98
|
+
text += ": #{@tags.join(' ')} " if @tags && !@tags.empty?
|
|
99
|
+
text += "{\n"
|
|
100
|
+
|
|
101
|
+
if @meta && !@meta.empty?
|
|
102
|
+
text += " meta:\n"
|
|
103
|
+
@meta.each { |k, v| text += " #{k} = #{v}\n" }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
if @strings && !@strings.empty?
|
|
107
|
+
text += " strings:\n"
|
|
108
|
+
@strings.each { |s| text += " #{s}\n" if s =~ /\w/ }
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
if @condition && !@condition.empty?
|
|
112
|
+
text += " condition:\n"
|
|
113
|
+
@condition.each { |c| text += " #{c}\n" if c =~ /\w/ }
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
text + "}"
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Return a stable identifier for this rule in the form:
|
|
120
|
+
# yn<VERSION>:<strings_fingerprint>:<condition_fingerprint>
|
|
121
|
+
#
|
|
122
|
+
# The strings fingerprint is the last 16 hex chars of the SHA-256 digest
|
|
123
|
+
# of the sorted, normalised string values joined by '%'.
|
|
124
|
+
# The condition fingerprint is the last 10 hex chars of the SHA-256 digest
|
|
125
|
+
# of the normalised condition lines joined by '%'.
|
|
126
|
+
#
|
|
127
|
+
# Using SHA-256 (replacing the previous MD5) gives 256-bit collision
|
|
128
|
+
# resistance and avoids MD5's well-known preimage and collision weaknesses.
|
|
129
|
+
#
|
|
130
|
+
# SECURITY NOTE: This method is named `hash` to match the public API, but
|
|
131
|
+
# it overrides Ruby's built-in Object#hash, which is expected to return an
|
|
132
|
+
# Integer for use as a Hash table key. Do NOT use YaraRule objects as Hash
|
|
133
|
+
# keys; use .hash (this method) only for YARA rule fingerprinting.
|
|
134
|
+
def hash
|
|
135
|
+
normalized_strings = @normalized_strings.join("%")
|
|
136
|
+
normalized_condition = @normalized_condition.join("%")
|
|
137
|
+
strings_digest = Digest::SHA256.hexdigest(normalized_strings)
|
|
138
|
+
condition_digest = Digest::SHA256.hexdigest(normalized_condition)
|
|
139
|
+
"yn#{VERSION}:#{strings_digest[-16, 16]}:#{condition_digest[-10, 10]}"
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Splits a multi-rule YARA file into individual YaraRule objects.
|
|
144
|
+
class Splitter
|
|
145
|
+
# Parse a string containing one or more YARA rules and return an Array of
|
|
146
|
+
# YaraRule instances, one per rule found in +ruleset+.
|
|
147
|
+
def self.split(ruleset)
|
|
148
|
+
# Strip line endings and single-line comments before scanning so that
|
|
149
|
+
# comment text cannot interfere with the rule boundary regex.
|
|
150
|
+
clean = ruleset.gsub(/[\r\n]+/, "\n").gsub(/^\s*\/\/.*$/, '')
|
|
151
|
+
rule_re = /(rule\s+([\w\-]+)(\s*:\s*(\w[\w\s]+\w))?\s*\{\s*(meta:\s*(.*?))?strings:\s*(.*?)\s*condition:\s*(.*?)\s*\})/m
|
|
152
|
+
clean.scan(rule_re).map { |rule| YaraRule.new(rule[0]) }
|
|
153
|
+
end
|
|
154
|
+
end
|
|
110
155
|
end
|
metadata
CHANGED
|
@@ -1,113 +1,117 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: yara-normalize
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
-
|
|
8
|
-
autorequire:
|
|
7
|
+
- Chris Lee
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-04-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: test-unit
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '3.6'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '3.6'
|
|
13
27
|
- !ruby/object:Gem::Dependency
|
|
14
28
|
name: shoulda
|
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
|
16
30
|
requirements:
|
|
17
|
-
- - "
|
|
31
|
+
- - "~>"
|
|
18
32
|
- !ruby/object:Gem::Version
|
|
19
33
|
version: '4'
|
|
20
34
|
type: :development
|
|
21
35
|
prerelease: false
|
|
22
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
37
|
requirements:
|
|
24
|
-
- - "
|
|
38
|
+
- - "~>"
|
|
25
39
|
- !ruby/object:Gem::Version
|
|
26
40
|
version: '4'
|
|
27
41
|
- !ruby/object:Gem::Dependency
|
|
28
|
-
name:
|
|
42
|
+
name: rspec
|
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
|
30
44
|
requirements:
|
|
31
45
|
- - "~>"
|
|
32
46
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '
|
|
47
|
+
version: '3.12'
|
|
34
48
|
type: :development
|
|
35
49
|
prerelease: false
|
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
51
|
requirements:
|
|
38
52
|
- - "~>"
|
|
39
53
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '
|
|
54
|
+
version: '3.12'
|
|
41
55
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
56
|
+
name: rake
|
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
|
44
58
|
requirements:
|
|
45
59
|
- - "~>"
|
|
46
60
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '
|
|
61
|
+
version: '13.3'
|
|
48
62
|
type: :development
|
|
49
63
|
prerelease: false
|
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
65
|
requirements:
|
|
52
66
|
- - "~>"
|
|
53
67
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '
|
|
68
|
+
version: '13.3'
|
|
55
69
|
- !ruby/object:Gem::Dependency
|
|
56
|
-
name:
|
|
70
|
+
name: bundler
|
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
|
58
72
|
requirements:
|
|
59
73
|
- - "~>"
|
|
60
74
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: 2.
|
|
75
|
+
version: '2.7'
|
|
62
76
|
type: :development
|
|
63
77
|
prerelease: false
|
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
79
|
requirements:
|
|
66
80
|
- - "~>"
|
|
67
81
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: 2.
|
|
82
|
+
version: '2.7'
|
|
69
83
|
- !ruby/object:Gem::Dependency
|
|
70
|
-
name:
|
|
84
|
+
name: rdoc
|
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
|
72
86
|
requirements:
|
|
73
87
|
- - "~>"
|
|
74
88
|
- !ruby/object:Gem::Version
|
|
75
|
-
version:
|
|
89
|
+
version: '6.6'
|
|
76
90
|
type: :development
|
|
77
91
|
prerelease: false
|
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
93
|
requirements:
|
|
80
94
|
- - "~>"
|
|
81
95
|
- !ruby/object:Gem::Version
|
|
82
|
-
version:
|
|
83
|
-
description:
|
|
84
|
-
|
|
85
|
-
|
|
96
|
+
version: '6.6'
|
|
97
|
+
description: Provides normalization and hashing utilities for Yara rule comparisons.
|
|
98
|
+
email:
|
|
99
|
+
- rubygems@chrislee.dhs.org
|
|
86
100
|
executables:
|
|
87
101
|
- yaratool
|
|
88
102
|
extensions: []
|
|
89
|
-
extra_rdoc_files:
|
|
90
|
-
- LICENSE.txt
|
|
91
|
-
- README.rdoc
|
|
103
|
+
extra_rdoc_files: []
|
|
92
104
|
files:
|
|
93
|
-
- ".document"
|
|
94
|
-
- Gemfile
|
|
95
|
-
- Gemfile.lock
|
|
96
105
|
- LICENSE.txt
|
|
97
106
|
- README.rdoc
|
|
98
|
-
- Rakefile
|
|
99
|
-
- VERSION
|
|
100
107
|
- bin/yaratool
|
|
101
108
|
- lib/yara-normalize.rb
|
|
102
109
|
- lib/yara-normalize/yara-normalize.rb
|
|
103
|
-
|
|
104
|
-
- test/test_yara-normalize.rb
|
|
105
|
-
- yara-normalize.gemspec
|
|
106
|
-
homepage: http://github.com/chrislee35/yara-normalize
|
|
110
|
+
homepage: https://github.com/chrislee35/yara-normalize
|
|
107
111
|
licenses:
|
|
108
112
|
- MIT
|
|
109
113
|
metadata: {}
|
|
110
|
-
post_install_message:
|
|
114
|
+
post_install_message:
|
|
111
115
|
rdoc_options: []
|
|
112
116
|
require_paths:
|
|
113
117
|
- lib
|
|
@@ -115,16 +119,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
115
119
|
requirements:
|
|
116
120
|
- - ">="
|
|
117
121
|
- !ruby/object:Gem::Version
|
|
118
|
-
version: '0'
|
|
122
|
+
version: '3.0'
|
|
119
123
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
120
124
|
requirements:
|
|
121
125
|
- - ">="
|
|
122
126
|
- !ruby/object:Gem::Version
|
|
123
127
|
version: '0'
|
|
124
128
|
requirements: []
|
|
125
|
-
rubygems_version: 3.
|
|
126
|
-
signing_key:
|
|
129
|
+
rubygems_version: 3.4.20
|
|
130
|
+
signing_key:
|
|
127
131
|
specification_version: 4
|
|
128
|
-
summary: Normalizes Yara
|
|
129
|
-
changes are made
|
|
132
|
+
summary: Normalizes Yara signatures into a repeatable hash even when non-transforming
|
|
133
|
+
changes are made.
|
|
130
134
|
test_files: []
|
data/.document
DELETED
data/Gemfile
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
source "http://rubygems.org"
|
|
2
|
-
# Add dependencies required to use your gem here.
|
|
3
|
-
# Example:
|
|
4
|
-
# gem "activesupport", ">= 2.3.5"
|
|
5
|
-
|
|
6
|
-
# Add dependencies to develop your gem here.
|
|
7
|
-
# Include everything needed to run rake, tests, features, etc.
|
|
8
|
-
group :development do
|
|
9
|
-
gem "shoulda", ">= 4"
|
|
10
|
-
gem "rdoc", "~> 6.4"
|
|
11
|
-
gem "bundler", "~> 2.3"
|
|
12
|
-
gem "jeweler", "~> 2.3.9"
|
|
13
|
-
gem "test-unit", "~> 3.5.3"
|
|
14
|
-
end
|
data/Gemfile.lock
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
GEM
|
|
2
|
-
remote: http://rubygems.org/
|
|
3
|
-
specs:
|
|
4
|
-
activesupport (7.0.2.4)
|
|
5
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
6
|
-
i18n (>= 1.6, < 2)
|
|
7
|
-
minitest (>= 5.1)
|
|
8
|
-
tzinfo (~> 2.0)
|
|
9
|
-
addressable (2.4.0)
|
|
10
|
-
builder (3.2.4)
|
|
11
|
-
concurrent-ruby (1.1.10)
|
|
12
|
-
descendants_tracker (0.0.4)
|
|
13
|
-
thread_safe (~> 0.3, >= 0.3.1)
|
|
14
|
-
faraday (0.9.2)
|
|
15
|
-
multipart-post (>= 1.2, < 3)
|
|
16
|
-
git (1.11.0)
|
|
17
|
-
rchardet (~> 1.8)
|
|
18
|
-
github_api (0.16.0)
|
|
19
|
-
addressable (~> 2.4.0)
|
|
20
|
-
descendants_tracker (~> 0.0.4)
|
|
21
|
-
faraday (~> 0.8, < 0.10)
|
|
22
|
-
hashie (>= 3.4)
|
|
23
|
-
mime-types (>= 1.16, < 3.0)
|
|
24
|
-
oauth2 (~> 1.0)
|
|
25
|
-
hashie (5.0.0)
|
|
26
|
-
highline (2.0.3)
|
|
27
|
-
i18n (1.10.0)
|
|
28
|
-
concurrent-ruby (~> 1.0)
|
|
29
|
-
jeweler (2.3.9)
|
|
30
|
-
builder
|
|
31
|
-
bundler
|
|
32
|
-
git (>= 1.2.5)
|
|
33
|
-
github_api (~> 0.16.0)
|
|
34
|
-
highline (>= 1.6.15)
|
|
35
|
-
nokogiri (>= 1.5.10)
|
|
36
|
-
psych
|
|
37
|
-
rake
|
|
38
|
-
rdoc
|
|
39
|
-
semver2
|
|
40
|
-
jwt (2.3.0)
|
|
41
|
-
mime-types (2.99.3)
|
|
42
|
-
minitest (5.15.0)
|
|
43
|
-
multi_json (1.15.0)
|
|
44
|
-
multi_xml (0.6.0)
|
|
45
|
-
multipart-post (2.1.1)
|
|
46
|
-
nokogiri (1.13.4-x86_64-linux)
|
|
47
|
-
racc (~> 1.4)
|
|
48
|
-
oauth2 (1.4.8)
|
|
49
|
-
faraday (>= 0.8, < 3.0)
|
|
50
|
-
jwt (>= 1.0, < 3.0)
|
|
51
|
-
multi_json (~> 1.3)
|
|
52
|
-
multi_xml (~> 0.5)
|
|
53
|
-
rack (>= 1.2, < 3)
|
|
54
|
-
power_assert (2.0.1)
|
|
55
|
-
psych (4.0.3)
|
|
56
|
-
stringio
|
|
57
|
-
racc (1.6.0)
|
|
58
|
-
rack (2.2.3)
|
|
59
|
-
rake (13.0.6)
|
|
60
|
-
rchardet (1.8.0)
|
|
61
|
-
rdoc (6.4.0)
|
|
62
|
-
psych (>= 4.0.0)
|
|
63
|
-
semver2 (3.4.2)
|
|
64
|
-
shoulda (4.0.0)
|
|
65
|
-
shoulda-context (~> 2.0)
|
|
66
|
-
shoulda-matchers (~> 4.0)
|
|
67
|
-
shoulda-context (2.0.0)
|
|
68
|
-
shoulda-matchers (4.5.1)
|
|
69
|
-
activesupport (>= 4.2.0)
|
|
70
|
-
stringio (3.0.1)
|
|
71
|
-
test-unit (3.5.3)
|
|
72
|
-
power_assert
|
|
73
|
-
thread_safe (0.3.6)
|
|
74
|
-
tzinfo (2.0.4)
|
|
75
|
-
concurrent-ruby (~> 1.0)
|
|
76
|
-
|
|
77
|
-
PLATFORMS
|
|
78
|
-
x86_64-linux
|
|
79
|
-
|
|
80
|
-
DEPENDENCIES
|
|
81
|
-
bundler (~> 2.3)
|
|
82
|
-
jeweler (~> 2.3.9)
|
|
83
|
-
rdoc (~> 6.4)
|
|
84
|
-
shoulda (>= 4)
|
|
85
|
-
test-unit (~> 3.5.3)
|
|
86
|
-
|
|
87
|
-
BUNDLED WITH
|
|
88
|
-
2.3.12
|
data/Rakefile
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
|
|
3
|
-
require 'rubygems'
|
|
4
|
-
require 'bundler'
|
|
5
|
-
begin
|
|
6
|
-
Bundler.setup(:default, :development)
|
|
7
|
-
rescue Bundler::BundlerError => e
|
|
8
|
-
$stderr.puts e.message
|
|
9
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
|
10
|
-
exit e.status_code
|
|
11
|
-
end
|
|
12
|
-
require 'rake'
|
|
13
|
-
|
|
14
|
-
require 'jeweler'
|
|
15
|
-
Jeweler::Tasks.new do |gem|
|
|
16
|
-
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
|
17
|
-
gem.name = "yara-normalize"
|
|
18
|
-
gem.homepage = "http://github.com/chrislee35/yara-normalize"
|
|
19
|
-
gem.license = "MIT"
|
|
20
|
-
gem.summary = %Q{Normalizes Yara Signatures into a repeatable hash even when non-transforming changes are made}
|
|
21
|
-
gem.description = %Q{To enable consistent comparisons between yara rules (signature), a uniform hashing standard was needed.}
|
|
22
|
-
gem.email = "rubygems@chrislee.dhs.org"
|
|
23
|
-
gem.authors = ["chrislee35"]
|
|
24
|
-
#gem.signing_key = "#{File.dirname(__FILE__)}/../gem-private_key.pem"
|
|
25
|
-
#gem.cert_chain = ["#{File.dirname(__FILE__)}/../gem-public_cert.pem"]
|
|
26
|
-
end
|
|
27
|
-
Jeweler::RubygemsDotOrgTasks.new
|
|
28
|
-
|
|
29
|
-
require 'rake/testtask'
|
|
30
|
-
Rake::TestTask.new(:test) do |test|
|
|
31
|
-
test.libs << 'test'
|
|
32
|
-
test.pattern = FileList['test/test*.rb']
|
|
33
|
-
test.verbose = true
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
task :default => :test
|
|
37
|
-
|
|
38
|
-
require 'rdoc/task'
|
|
39
|
-
Rake::RDocTask.new do |rdoc|
|
|
40
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
|
41
|
-
|
|
42
|
-
rdoc.rdoc_dir = 'rdoc'
|
|
43
|
-
rdoc.title = "yara-normalize #{version}"
|
|
44
|
-
rdoc.rdoc_files.include('README*')
|
|
45
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
46
|
-
end
|
data/VERSION
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.2.0
|
data/test/helper.rb
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
require 'rubygems'
|
|
2
|
-
require 'bundler'
|
|
3
|
-
begin
|
|
4
|
-
Bundler.setup(:default, :development)
|
|
5
|
-
rescue Bundler::BundlerError => e
|
|
6
|
-
$stderr.puts e.message
|
|
7
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
|
8
|
-
exit e.status_code
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
require 'test/unit'
|
|
12
|
-
require 'shoulda'
|
|
13
|
-
|
|
14
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
15
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
16
|
-
|
|
17
|
-
require 'yara-normalize'
|
|
18
|
-
|
|
19
|
-
class Test::Unit::TestCase
|
|
20
|
-
end
|
data/test/test_yara-normalize.rb
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
require 'helper'
|
|
2
|
-
require 'pp'
|
|
3
|
-
|
|
4
|
-
class TestYaraNormalize < Test::Unit::TestCase
|
|
5
|
-
should "normalize a simple signature" do
|
|
6
|
-
sig =<<EOS
|
|
7
|
-
rule newIE0daymshtmlExec
|
|
8
|
-
{
|
|
9
|
-
meta:
|
|
10
|
-
author = "redacted @ gmail.com"
|
|
11
|
-
ref = "http://blog.vulnhunt.com/index.php/2012/09/17/ie-execcommand-fuction-use-after-free-vulnerability-0day_en/"
|
|
12
|
-
description = "Internet Explorer CMshtmlEd::Exec() 0day"
|
|
13
|
-
cve = "CVE-2012-XXXX"
|
|
14
|
-
version = "1"
|
|
15
|
-
impact = 4
|
|
16
|
-
hide = false
|
|
17
|
-
strings:
|
|
18
|
-
$mshtmlExec_1 = /document\.execCommand\(['"]selectAll['"]\)/ nocase fullword
|
|
19
|
-
$mshtmlExec_2 = /YMjf\\u0c08\\u0c0cKDogjsiIejengNEkoPDjfiJDIWUAzdfghjAAuUFGGBSIPPPUDFJKSOQJGH/ nocase fullword
|
|
20
|
-
$mshtmlExec_3 = /\<body\son(load|select)=['"]\w*?\(\)\;['"]\son(load|select)=['"]\w*?\(\)['"]/ nocase
|
|
21
|
-
$mshtmlExec_4 = /var\s\w{1,}\s=\snew\sArray\(\)/ nocase
|
|
22
|
-
$mshtmlExec_5 = /window\.document\.createElement\(['"]img['"]\)/ nocase
|
|
23
|
-
$mshtmlExec_6 = /\w{1,}\[0\]\[['"]src['"]\]\s\=\s['"]\w{1,}['"]/ nocase
|
|
24
|
-
$mshtmlExec_7 = /\<iframe\ssrc=['"].*?['"]/ nocase
|
|
25
|
-
condition:
|
|
26
|
-
($mshtmlExec_1 and $mshtmlExec_2 and $mshtmlExec_3) or ($mshtmlExec_4 and $mshtmlExec_5 and ($mshtmlExec_6 or $mshtmlExec_7))
|
|
27
|
-
}
|
|
28
|
-
EOS
|
|
29
|
-
puts sig
|
|
30
|
-
yn = YaraTools::YaraRule.new(sig)
|
|
31
|
-
assert_equal("yn01:66dd624d64a79f17:ecf1725295", yn.hash)
|
|
32
|
-
assert_equal("newIE0daymshtmlExec", yn.name)
|
|
33
|
-
assert_equal("\"redacted @ gmail.com\"", yn.meta['author'])
|
|
34
|
-
assert_equal(["$mshtmlExec_1 = /document.execCommand(['\"]selectAll['\"])/ nocase fullword",
|
|
35
|
-
"$mshtmlExec_2 = /YMjf\\u0c08\\u0c0cKDogjsiIejengNEkoPDjfiJDIWUAzdfghjAAuUFGGBSIPPPUDFJKSOQJGH/ nocase fullword",
|
|
36
|
-
"$mshtmlExec_3 = /<body on(load|select)=['\"]w*?();['\"] on(load|select)=['\"]w*?()['\"]/ nocase",
|
|
37
|
-
"$mshtmlExec_4 = /var w{1,} = new Array()/ nocase",
|
|
38
|
-
"$mshtmlExec_5 = /window.document.createElement(['\"]img['\"])/ nocase",
|
|
39
|
-
"$mshtmlExec_6 = /w{1,}[0][['\"]src['\"]] = ['\"]w{1,}['\"]/ nocase",
|
|
40
|
-
"$mshtmlExec_7 = /<iframe src=['\"].*?['\"]/ nocase"], yn.strings)
|
|
41
|
-
assert_equal(
|
|
42
|
-
["($mshtmlExec_1 and $mshtmlExec_2 and $mshtmlExec_3) or ($mshtmlExec_4 and $mshtmlExec_5 and ($mshtmlExec_6 or $mshtmlExec_7))"],
|
|
43
|
-
yn.condition
|
|
44
|
-
)
|
|
45
|
-
hash1 = yn.hash
|
|
46
|
-
sig =<<EOS
|
|
47
|
-
rule newIE0daymshtmlExec : tag1 tag2 tag3
|
|
48
|
-
{
|
|
49
|
-
meta:
|
|
50
|
-
author = "redacted @ gmail.com"
|
|
51
|
-
ref = "http://blog.vulnhunt.com/index.php/2012/09/17/ie-execcommand-fuction-use-after-free-vulnerability-0day_en/"
|
|
52
|
-
description = "Internet Explorer CMshtmlEd::Exec() 0day"
|
|
53
|
-
cve = "CVE-2012-XXXX"
|
|
54
|
-
version = "1"
|
|
55
|
-
impact = 4
|
|
56
|
-
hide = false
|
|
57
|
-
strings:
|
|
58
|
-
$mshtmlExec_1 = /document\.execCommand\(['"]selectAll['"]\)/ nocase fullword
|
|
59
|
-
$mshtmlExec_2 = /YMjf\\u0c08\\u0c0cKDogjsiIejengNEkoPDjfiJDIWUAzdfghjAAuUFGGBSIPPPUDFJKSOQJGH/ nocase fullword
|
|
60
|
-
$mshtmlExec_3 = /\<body\son(load|select)=['"]\w*?\(\)\;['"]\son(load|select)=['"]\w*?\(\)['"]/ nocase
|
|
61
|
-
$mshtmlExec_4 = /var\s\w{1,}\s=\snew\sArray\(\)/ nocase
|
|
62
|
-
$mshtmlExec_5 = /window\.document\.createElement\(['"]img['"]\)/ nocase
|
|
63
|
-
$mshtmlExec_6 = /\w{1,}\[0\]\[['"]src['"]\]\s\=\s['"]\w{1,}['"]/ nocase
|
|
64
|
-
$mshtmlExec_7 = /\<iframe\ssrc=['"].*?['"]/ nocase
|
|
65
|
-
condition:
|
|
66
|
-
($mshtmlExec_1 and $mshtmlExec_2 and $mshtmlExec_3) or ($mshtmlExec_4 and $mshtmlExec_5 and ($mshtmlExec_6 or $mshtmlExec_7))
|
|
67
|
-
}
|
|
68
|
-
EOS
|
|
69
|
-
yn = YaraTools::YaraRule.new(sig)
|
|
70
|
-
assert_equal(hash1, yn.hash)
|
|
71
|
-
assert_equal("newIE0daymshtmlExec", yn.name)
|
|
72
|
-
assert_equal(["tag1","tag2","tag3"], yn.tags)
|
|
73
|
-
assert_equal("\"redacted @ gmail.com\"", yn.meta['author'])
|
|
74
|
-
assert_equal(["$mshtmlExec_1 = /document.execCommand(['\"]selectAll['\"])/ nocase fullword",
|
|
75
|
-
"$mshtmlExec_2 = /YMjf\\u0c08\\u0c0cKDogjsiIejengNEkoPDjfiJDIWUAzdfghjAAuUFGGBSIPPPUDFJKSOQJGH/ nocase fullword",
|
|
76
|
-
"$mshtmlExec_3 = /<body on(load|select)=['\"]w*?();['\"] on(load|select)=['\"]w*?()['\"]/ nocase",
|
|
77
|
-
"$mshtmlExec_4 = /var w{1,} = new Array()/ nocase",
|
|
78
|
-
"$mshtmlExec_5 = /window.document.createElement(['\"]img['\"])/ nocase",
|
|
79
|
-
"$mshtmlExec_6 = /w{1,}[0][['\"]src['\"]] = ['\"]w{1,}['\"]/ nocase",
|
|
80
|
-
"$mshtmlExec_7 = /<iframe src=['\"].*?['\"]/ nocase"], yn.strings)
|
|
81
|
-
assert_equal(
|
|
82
|
-
["($mshtmlExec_1 and $mshtmlExec_2 and $mshtmlExec_3) or ($mshtmlExec_4 and $mshtmlExec_5 and ($mshtmlExec_6 or $mshtmlExec_7))"],
|
|
83
|
-
yn.condition
|
|
84
|
-
)
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
should "normalize a simple signature that has a condition of 'any of them'" do
|
|
88
|
-
sig =<<EOS
|
|
89
|
-
rule DataConversion__wide : IntegerParsing DataConversion {
|
|
90
|
-
meta:
|
|
91
|
-
weight = 1
|
|
92
|
-
strings:
|
|
93
|
-
$ = "wtoi" nocase
|
|
94
|
-
$ = "wtol" nocase
|
|
95
|
-
$ = "wtof" nocase
|
|
96
|
-
$ = "wtodb" nocase
|
|
97
|
-
condition:
|
|
98
|
-
any of them
|
|
99
|
-
}
|
|
100
|
-
EOS
|
|
101
|
-
yn = YaraTools::YaraRule.new(sig)
|
|
102
|
-
assert_equal("yn01:a5fd8576f2da34e2:d936fceffe", yn.hash)
|
|
103
|
-
assert_equal("1", yn.meta['weight'])
|
|
104
|
-
assert_equal("DataConversion__wide", yn.name)
|
|
105
|
-
assert_equal(["IntegerParsing", "DataConversion"], yn.tags)
|
|
106
|
-
assert_equal(["$ = \"wtoi\" nocase",
|
|
107
|
-
"$ = \"wtol\" nocase",
|
|
108
|
-
"$ = \"wtof\" nocase",
|
|
109
|
-
"$ = \"wtodb\" nocase"], yn.strings)
|
|
110
|
-
assert_equal(["any of them"], yn.condition)
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
|
data/yara-normalize.gemspec
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
# Generated by jeweler
|
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
|
3
|
-
# Instead, edit Jeweler::Tasks in rakefile, and run 'rake gemspec'
|
|
4
|
-
# -*- encoding: utf-8 -*-
|
|
5
|
-
# stub: yara-normalize 0.2.0 ruby lib
|
|
6
|
-
|
|
7
|
-
Gem::Specification.new do |s|
|
|
8
|
-
s.name = "yara-normalize".freeze
|
|
9
|
-
s.version = "0.2.0"
|
|
10
|
-
|
|
11
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
|
12
|
-
s.require_paths = ["lib".freeze]
|
|
13
|
-
s.authors = ["chrislee35".freeze]
|
|
14
|
-
s.date = "2022-05-01"
|
|
15
|
-
s.description = "To enable consistent comparisons between yara rules (signature), a uniform hashing standard was needed.".freeze
|
|
16
|
-
s.email = "rubygems@chrislee.dhs.org".freeze
|
|
17
|
-
s.executables = ["yaratool".freeze]
|
|
18
|
-
s.extra_rdoc_files = [
|
|
19
|
-
"LICENSE.txt",
|
|
20
|
-
"README.rdoc"
|
|
21
|
-
]
|
|
22
|
-
s.files = [
|
|
23
|
-
".document",
|
|
24
|
-
"Gemfile",
|
|
25
|
-
"Gemfile.lock",
|
|
26
|
-
"LICENSE.txt",
|
|
27
|
-
"README.rdoc",
|
|
28
|
-
"Rakefile",
|
|
29
|
-
"VERSION",
|
|
30
|
-
"bin/yaratool",
|
|
31
|
-
"lib/yara-normalize.rb",
|
|
32
|
-
"lib/yara-normalize/yara-normalize.rb",
|
|
33
|
-
"test/helper.rb",
|
|
34
|
-
"test/test_yara-normalize.rb",
|
|
35
|
-
"yara-normalize.gemspec"
|
|
36
|
-
]
|
|
37
|
-
s.homepage = "http://github.com/chrislee35/yara-normalize".freeze
|
|
38
|
-
s.licenses = ["MIT".freeze]
|
|
39
|
-
s.rubygems_version = "3.2.3".freeze
|
|
40
|
-
s.summary = "Normalizes Yara Signatures into a repeatable hash even when non-transforming changes are made".freeze
|
|
41
|
-
|
|
42
|
-
if s.respond_to? :specification_version then
|
|
43
|
-
s.specification_version = 4
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
if s.respond_to? :add_runtime_dependency then
|
|
47
|
-
s.add_development_dependency(%q<shoulda>.freeze, [">= 4"])
|
|
48
|
-
s.add_development_dependency(%q<rdoc>.freeze, ["~> 6.4"])
|
|
49
|
-
s.add_development_dependency(%q<bundler>.freeze, ["~> 2.3"])
|
|
50
|
-
s.add_development_dependency(%q<jeweler>.freeze, ["~> 2.3.9"])
|
|
51
|
-
s.add_development_dependency(%q<test-unit>.freeze, ["~> 3.5.3"])
|
|
52
|
-
else
|
|
53
|
-
s.add_dependency(%q<shoulda>.freeze, [">= 4"])
|
|
54
|
-
s.add_dependency(%q<rdoc>.freeze, ["~> 6.4"])
|
|
55
|
-
s.add_dependency(%q<bundler>.freeze, ["~> 2.3"])
|
|
56
|
-
s.add_dependency(%q<jeweler>.freeze, ["~> 2.3.9"])
|
|
57
|
-
s.add_dependency(%q<test-unit>.freeze, ["~> 3.5.3"])
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|