yara-normalize 0.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/README.rdoc +25 -11
- data/VERSION +1 -1
- data/bin/yaratool +23 -0
- data/lib/yara-normalize/yara-normalize.rb +94 -70
- data/ruby_results.txt +24 -0
- data/test/test_yara-normalize.rb +47 -107
- data/yara-normalize.gemspec +6 -2
- metadata +8 -6
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/README.rdoc
CHANGED
@@ -16,20 +16,34 @@ See test cases.
|
|
16
16
|
require 'yara-normalize'
|
17
17
|
sig =<<EOS
|
18
18
|
rule DataConversion__wide : IntegerParsing DataConversion {
|
19
|
-
|
20
|
-
weight =
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
19
|
+
meta:
|
20
|
+
weight =1
|
21
|
+
strings:
|
22
|
+
$="wtoi" nocase
|
23
|
+
$ ="wtol" nocase
|
24
|
+
$= "wtof" nocase
|
25
|
+
$ = "wtodb" nocase
|
26
|
+
condition:
|
27
27
|
any of them
|
28
28
|
}
|
29
29
|
EOS
|
30
|
-
yn =
|
31
|
-
|
32
|
-
puts
|
30
|
+
yn = YaraTools::YaraRule.new(sig)
|
31
|
+
puts yn.hash # => yn01:488085c947cb22ed:d936fceffe
|
32
|
+
puts yn.normalize # =>
|
33
|
+
rule DataConversion__wide : IntegerParsing DataConversion {
|
34
|
+
meta:
|
35
|
+
weight = 1
|
36
|
+
strings:
|
37
|
+
$ = "wtoi" nocase
|
38
|
+
$ = "wtol" nocase
|
39
|
+
$ = "wtof" nocase
|
40
|
+
$ = "wtodb" nocase
|
41
|
+
condition:
|
42
|
+
any of them
|
43
|
+
}
|
44
|
+
puts yn.name # => DataConversion__wide
|
45
|
+
pp yn.tags # => ["IntegerParsing","DataConversion"]
|
46
|
+
|
33
47
|
|
34
48
|
== Contributing to yara-normalize
|
35
49
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.1.0
|
data/bin/yaratool
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'yara-normalize'
|
4
|
+
|
5
|
+
if __FILE__ == $0
|
6
|
+
count = duplicates = 0
|
7
|
+
hashes = {}
|
8
|
+
ARGV.each do |file|
|
9
|
+
buf = open(file).read
|
10
|
+
YaraTools::Splitter.split(buf).each do |rule|
|
11
|
+
count += 1
|
12
|
+
#puts rule.normalize
|
13
|
+
hash = rule.hash
|
14
|
+
puts "#{rule.name} #{hash} #{rule.normalized_strings.join("%")}"
|
15
|
+
if hashes[hash]
|
16
|
+
duplicate += 1
|
17
|
+
end
|
18
|
+
hashes[hash] = rule
|
19
|
+
end
|
20
|
+
end
|
21
|
+
puts "Count: #{count}, Duplicates: #{duplicates}"
|
22
|
+
end
|
23
|
+
|
@@ -1,84 +1,108 @@
|
|
1
|
-
require 'digest/
|
2
|
-
|
3
|
-
module
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
1
|
+
require 'digest/md5'
|
2
|
+
require 'pp'
|
3
|
+
module YaraTools
|
4
|
+
VERSION = "01"
|
5
|
+
class YaraRule
|
6
|
+
attr_reader :original, :name, :tags, :meta, :strings, :condition, :normalized_strings
|
7
|
+
def initialize(ruletext)
|
8
|
+
ruletext = ruletext.gsub(/[\r\n]+/,"\n").gsub(/^\s*\/\/.*$/,'')
|
9
|
+
@original = ruletext
|
10
|
+
@lookup_table = {}
|
11
|
+
@next_replacement = 'a'
|
12
|
+
|
13
|
+
if ruletext =~ /rule\s+([\w\_\-]+)(\s*:\s*(\w[\w\s]+\w))?\s*\{\s*(meta:\s*(.*?))?strings:\s*(.*?)\s*condition:\s*(.*?)\s*\}/m
|
14
|
+
name,_,tags,ifmeta,meta,strings,condition = $~.captures
|
15
|
+
@name = name
|
16
|
+
@tags = tags.strip.split(/[,\s]+/) if tags
|
17
|
+
@meta = {}
|
18
|
+
meta.split(/\n/).each do |m|
|
19
|
+
k,v = m.strip.split(/\s*=\s*/,2)
|
20
|
+
if v
|
21
|
+
@meta[k] = v
|
22
|
+
end
|
21
23
|
end
|
22
|
-
|
24
|
+
@normalized_strings = []
|
25
|
+
@strings = strings.split(/\n/).map do |s|
|
26
|
+
# strip off the spaces from the edges and then replace the first = with ' = '.
|
27
|
+
s = s.strip
|
28
|
+
if s[/\s*=\s*/,0]
|
29
|
+
s[/\s*=\s*/,0] = " = "
|
30
|
+
end
|
31
|
+
if s =~ /= \{([0-9a-fA-F\s]+)\}/
|
32
|
+
# normalize the hex string
|
33
|
+
hexstr = $1.gsub(/\s+/,'').downcase.scan(/../).join(" ")
|
34
|
+
s = s.gsub(/= \{([0-9a-fA-F\s]+)\}/, "= { #{hexstr} }")
|
35
|
+
end
|
36
|
+
key, val = s.split(/ = /,2)
|
37
|
+
if val
|
38
|
+
@normalized_strings << val
|
39
|
+
else
|
40
|
+
@normalized_strings << s
|
41
|
+
end
|
42
|
+
s
|
43
|
+
end
|
44
|
+
@normalized_strings.sort!
|
45
|
+
@condition = condition.split(/\n/).map{|x| x.strip}
|
46
|
+
@normalized_condition = @condition.map{|x| _normalize_condition(x)}
|
23
47
|
end
|
24
48
|
end
|
25
49
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
arr = eval("[#{c}]")
|
36
|
-
condition_rearrange2(arr)
|
50
|
+
def _normalize_condition(condition)
|
51
|
+
condition.gsub(/[\$\#]\w+/) do |x|
|
52
|
+
key = x[1,1000]
|
53
|
+
if not @lookup_table[key]
|
54
|
+
@lookup_table[key] = @next_replacement
|
55
|
+
@next_replacement = (@next_replacement[0] + 1).chr
|
56
|
+
end
|
57
|
+
x[0].chr+@lookup_table[key]
|
58
|
+
end
|
37
59
|
end
|
38
60
|
|
39
|
-
def
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
61
|
+
def normalize
|
62
|
+
text = "rule #{@name} "
|
63
|
+
if @tags and @tags.length > 0
|
64
|
+
text += ": #{@tags.join(' ')} "
|
65
|
+
end
|
66
|
+
text += "{\n"
|
67
|
+
if @meta and @meta.length > 0
|
68
|
+
text += " meta:\n"
|
69
|
+
@meta.each do |k,v|
|
70
|
+
text += " #{k} = #{v}\n"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
if @strings and @strings.length > 0
|
74
|
+
text += " strings:\n"
|
75
|
+
@strings.each do |s|
|
76
|
+
if s =~ /\w/
|
77
|
+
text += " #{s}\n"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
if @condition and @condition.length > 0
|
82
|
+
text += " condition:\n"
|
83
|
+
@condition.each do |c|
|
84
|
+
if c =~ /\w/
|
85
|
+
text += " #{c}\n"
|
50
86
|
end
|
51
|
-
|
52
|
-
condition_rearrange2(sp)
|
53
|
-
}
|
54
|
-
else
|
55
|
-
subpart
|
87
|
+
end
|
56
88
|
end
|
89
|
+
text + "}"
|
90
|
+
end
|
91
|
+
|
92
|
+
def hash
|
93
|
+
normalized_strings = @normalized_strings.join("%")
|
94
|
+
normalized_condition = @normalized_condition.join("%")
|
95
|
+
strings_hash = Digest::MD5.hexdigest(normalized_strings)
|
96
|
+
condition_hash = Digest::MD5.hexdigest(normalized_condition)
|
97
|
+
"yn#{VERSION}:#{strings_hash[-16,16]}:#{condition_hash[-10,10]}"
|
57
98
|
end
|
58
99
|
end
|
59
100
|
|
60
|
-
class
|
61
|
-
def
|
62
|
-
|
63
|
-
|
64
|
-
def normalize(rule)
|
65
|
-
raise "Invalid rule: rules must begin with the word 'rule'" unless rule =~ /^\s*rule\s/
|
66
|
-
raise "Invalid rule: rules must end with a closing bracket, }" unless rule =~ /\}\s*$/
|
67
|
-
if rule =~ /^\s*rule\s+(\w+)(\s*:\s*(\w[\w\s]+\w))?\s*\{\s*meta:\s*(.*?)\s*strings:\s*(.*?)\s*condition:\s*(.*?)\s*\}\s*$/m
|
68
|
-
#pp $~.captures
|
69
|
-
name,_,tags,meta,strings,condition = $~.captures
|
70
|
-
tags = tags.split(/\s+/) if tags
|
71
|
-
metatags = {}
|
72
|
-
meta.split(/\n+/).each do |x|
|
73
|
-
a,b = x.split(/\s*=\s*/)
|
74
|
-
metatags[a.strip] = b.strip
|
75
|
-
end
|
76
|
-
strings = strings.split(/\n+/).map{|x| x.strip}
|
77
|
-
condition = condition.strip
|
78
|
-
Rule.new(name,tags,metatags,strings,condition)
|
79
|
-
else
|
80
|
-
nil
|
101
|
+
class Splitter
|
102
|
+
def Splitter.split(ruleset)
|
103
|
+
rules = ruleset.gsub(/[\r\n]+/,"\n").gsub(/^\s*\/\/.*$/,'').scan(/(rule\s+([\w\_\-]+)(\s*:\s*(\w[\w\s]+\w))?\s*\{\s*(meta:\s*(.*?))?strings:\s*(.*?)\s*condition:\s*(.*?)\s*\})/m).map do |rule|
|
104
|
+
YaraRule.new(rule[0])
|
81
105
|
end
|
82
106
|
end
|
83
107
|
end
|
84
|
-
end
|
108
|
+
end
|
data/ruby_results.txt
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
CF_DOC_CVE_2012_1535_original yn01:06420b6c243181e8:a7e7b4fe3a { 45 78 61 6d 70 6c 65 0b 63 72 65 61 74 65 4c 69 6e 65 73 09 68 65 61 70 53 70 72 61 79 08 68 65 78 54 6f 42 69 6e 07 6d 78 2e 63 6f 72 65 0a 49 46 6c 65 78 41 73 73 65 74 09 46 6f 6e 74 41 73 73 65 74 0a 66 6c 61 73 68 2e 74 65 78 74 } /*Example.createLines.heapSpray.hexToBin.mx.core.IFlexAsset.FontAsset.flash.text*/%{ 4d 61 69 6e 2f 70 72 69 76 61 74 65 3a } /*Main/private:*/%{ 53 00 69 00 6d 00 53 00 75 00 6e 00 } /*S.i.m.S.u.n*/%{ 57 6f 72 64 2e 44 6f 63 75 6d 65 6e 74 2e 38 } /*Word.Document.8*/%{ 66 6c 61 73 68 2e 64 69 73 70 6c 61 79 06 53 70 72 69 74 65 06 4f 62 6a 65 63 74 0f 45 76 65 6e 74 44 69 73 70 61 74 63 68 65 72 0d 44 69 73 70 6c 61 79 4f 62 6a 65 63 74 } /*flash.display.Sprite.Object.EventDispatcher.DisplayObject*/%{ 68 69 6a 6b 6c 6d 6e 6f } /*hijklmno strings */
|
2
|
+
CF_DOC_CVE_2012_1535_shellcode yn01:aed85d99267c6173:4be571de0b "9090909090E947010000C28F36D8A0DF16D5B5F0DE78D00589E91B28BF56BEF71ED697165FFAA1665256D0541988A5D913E98E3A172B9BB28253A2E362577E574F52444C2E746D7000"
|
3
|
+
CVE_2012_1535_SWF yn01:d0b0e41fbb90ee63:0c2737ef53 "Edit the world in hex"%"FontAsset"%"PSpop"%"createTextLine"%"heapSpray"%"hexToBin"%{ 46 57 53 }
|
4
|
+
cf_exe_dropper_sfx yn01:32c758a1635b4d6e:9534ef77f9 ";The comment below contains SFX script commands"%"Setup=" ascii wide%"Silent=1" ascii wide%"WinRAR" ascii wide
|
5
|
+
cf_hlp_malicious_help_file yn01:22be215570105ad6:2edd241969 "CreateThread" nocase%/RR\(.KERNEL32.DLL.,/ nocase%{ 3f 5f 03 00 }%{ 4c 4e 02 00 }
|
6
|
+
cf_html_IE8_CVE_2012_4969 yn01:18d1ab9564026f79:a7e7b4fe3a "YMjf\\u0c08\\u0c0cKDogjsiIejengNEkoPDjfiJDIWUAzdfghjAAuUFGGBSIPPPUDFJKSOQJGH"%"document.execCommand(\\"
|
7
|
+
cf_ie_cve_2012_1526 yn01:791760cc1bb44202:fa3fd96df1 /\.getElements?By/ nocase%/\.removeChild\(/ nocase%/document\..*?= ?null/ nocase%/mailto\:.{2000,}/ nocase fullword
|
8
|
+
CF_JAVA_system_cmds yn01:9369881e5d91ae88:23497b0a75 "/bin/sh"%"Math.random"%"chmod"%"cmd.exe"%"indexOf" //usually used to get result of $fingerprint2%/(os.name|java.io.tmpdir)/%/* Payload */%/* System commands */%/get(Property|env)/%{ ca fe ba be }
|
9
|
+
CF_JAVA_network_connectivity yn01:7c4e5171925f60dc:4ffbde1efc "ServerSocket"%"URLConnection" //URL class can also be used to access files in the local file system%"getMbeanServer" //used with MarshallObject%"host"%"lport"%"openConnection"%/* Network indicators */%/get(Input|Output)Stream/%/socket(lhost, lport)/%{ ca fe ba be }
|
10
|
+
CF_JAVA_changing_security yn01:cf8a3ae054b77a6d:f6b1a6926b %"AccessController.doPrivileged"%"AllPermission"%"PrivilegedActionException"%"ProtectionDomain"%"file://"%/* Modifying local security : a class that allows applications to implement a security policy */%/[sg]etSecurityManager/%{ ca fe ba be }
|
11
|
+
CF_JAVA_execute_write yn01:47d6a8c1cd7ca988:595f5c08f4 %%%"ArrayOfByte"%"Exception.printStackTrace"%"FileOutputStream" /*contains a byte stream with the serialized representation of an object given to its constructor*/%"HexDecode"%"InputStream"%"MarshalledObject"%"ObjectInputStream"%"OutputStreamWriter"%"Runtime.getRuntime"%"StringtoBytes"%"exec"%"getResourceAsStream"%"toByteArray"%"writeObject"%/* Exploit */%/* Loader indicators */%/* Local execution */%/arrayOf(Byte|String)/%/l(port|host)/%{ ca fe ba be }
|
12
|
+
CF_JAVA_possible_exploit yn01:b58561333df5354e:e51d8cdbd7 %"ByteArrayInputStream"%"Character.digit"%"ProtectionDomain"%"String.charAt"%"StringBuilder"%"arrayOfByte"%"localPermissions"%"printStackTrace"%{ ca fe ba be }
|
13
|
+
CF_PDF_CVE_2007_5659 yn01:ada07a590bb9b5b8:a7e7b4fe3a { 25 50 44 46 2d }%{ 65 70 61 63 73 65 6e 75 }%{ 6e 6f 69 74 63 6e 75 66 }%{ 79 61 72 70 73 }%{ 79 61 72 72 41 }
|
14
|
+
CF_PDF_obfuscated_alphabetic_char_blackhole yn01:78654b53f1b3a0d3:c453df481f "%PDF-"%/[a-zA-Z]
[0-9];/%/[a-zA-Z][0-9];/%/[a-zA-Z][012];/%/[a-zA-Z]	[789];/
|
15
|
+
CF_PDF_suspicious_js yn01:360cd6b36773334c:e0bbde6bd2 "%PDF-"%/(\(|\[)(.{1,4}(,|-)){64}/
|
16
|
+
CF_RTF_ACTOR_CVE_2012_0158_tnauthor_John_Doe yn01:e82aa6a75f86469c:78c8a3f51c { 07 74 6e 61 75 74 68 6f 72 20 4a 6f 68 6e 20 44 6f 65 7d } /* tnauthor John Doe}*/
|
17
|
+
CF_RTF_CVE_2012_1856 yn01:0bffc7a0c3656c46:aea71fc2f5 "0CF11E0A1B" nocase%"4d53436f6d63746c4c69622e546162537472697" nocase%"9665fb1e7c85d111b16a00c0f0283628" nocase%"D0CF11E0A1B11AE1" nocase%"D\x0a0\x0aC\x0aF" nocase%"MSComctlLib.TabStrip"%"{\\rt"%"}0105000002000000"%/objdata[[:space:].]{1,20}01.{0,1}05.{0,1}00.{0,1}00.{0,1}02.{0,1}00.{0,1}00.{0,1}00/
|
18
|
+
CF_RTF_CVE_2010_3333 yn01:5d18fb7b42dfd5c0:3873ea4382 "\\shp " nocase%"\\shp\\" nocase%"\\sp \\" nocase%"\\sp\\" nocase%"pFragments" nocase%"{\\rt" /* RTF specs */ nocase
|
19
|
+
CF_RTF_CVE_2010_3333_rare_ge_type yn01:5bbb6168467e0386:3873ea4382 "\\shp " nocase%"\\shp\\" nocase%"\\sp \\" nocase%"\\sp\\" nocase%"pFragments" nocase%"{\\ge" /* RTF specs */ nocase
|
20
|
+
CF_RTF_CVE_2012_0158_var1_objocx yn01:dd9b4fb8c95de7f6:c32f773f84 "\\object" nocase%"\\objemb" nocase%"\\objocx" nocase%"{\\rt" /* RTF specs */ nocase%{ d0 cf 11 e0 a1 b1 1a e1 }
|
21
|
+
CF_RTF_CVE_2012_0158_var2_MSComctlLib yn01:cbf14eb4327aae3e:19df01f1b8 "4C697374566965774374726C" nocase%"4D53436F6D63746C4C69622E" nocase%"54726565566965774374726C" nocase
|
22
|
+
CF_RTF_CVE_2012_0158_var3_fchars yn01:5a65c8be3acd5373:a7e7b4fe3a /(\\\'[a-f0-9]{2}){30}/%{ 5c 2a 5c 66 63 68 61 72 73 }%{ 7b 5c 72 74 }
|
23
|
+
CF_XDP_embedded_PDF yn01:d3a748381610c2e1:bd721f6929 "%PDF"%"</pdf>"%"<chunk>"%"<pdf xmlns="%"JVBERi0"
|
24
|
+
Count: 23, Duplicates: 0
|
data/test/test_yara-normalize.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
require 'helper'
|
2
|
+
require 'pp'
|
3
|
+
|
2
4
|
class TestYaraNormalize < Test::Unit::TestCase
|
3
5
|
should "normalize a simple signature" do
|
4
6
|
sig =<<EOS
|
5
7
|
rule newIE0daymshtmlExec
|
6
8
|
{
|
7
9
|
meta:
|
8
|
-
author = "
|
10
|
+
author = "redacted @ gmail.com"
|
9
11
|
ref = "http://blog.vulnhunt.com/index.php/2012/09/17/ie-execcommand-fuction-use-after-free-vulnerability-0day_en/"
|
10
12
|
description = "Internet Explorer CMshtmlEd::Exec() 0day"
|
11
13
|
cve = "CVE-2012-XXXX"
|
@@ -24,42 +26,27 @@ rule newIE0daymshtmlExec
|
|
24
26
|
($mshtmlExec_1 and $mshtmlExec_2 and $mshtmlExec_3) or ($mshtmlExec_4 and $mshtmlExec_5 and ($mshtmlExec_6 or $mshtmlExec_7))
|
25
27
|
}
|
26
28
|
EOS
|
27
|
-
yn =
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
"
|
36
|
-
"
|
37
|
-
"strings
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
"$mshtmlExec_6 = /w{1,}[0][['\"]src['\"]] = ['\"]w{1,}['\"]/ nocase",
|
44
|
-
"$mshtmlExec_7 = /<iframe src=['\"].*?['\"]/ nocase"],
|
45
|
-
"meta"=>
|
46
|
-
{"author"=>"\"adnan.shukor@gmail.com\"",
|
47
|
-
"description"=>"\"Internet Explorer CMshtmlEd::Exec() 0day\"",
|
48
|
-
"ref"=>
|
49
|
-
"\"http://blog.vulnhunt.com/index.php/2012/09/17/ie-execcommand-fuction-use-after-free-vulnerability-0day_en/\"",
|
50
|
-
"impact"=>"4",
|
51
|
-
"hide"=>"false",
|
52
|
-
"cve"=>"\"CVE-2012-XXXX\"",
|
53
|
-
"version"=>"\"1\""}}, hash)
|
54
|
-
assert_equal("ee2e32d623a0debca271cada22b35b3b904d6abd678cf2a48a87b43cd6302e73f67510c19ffe2f1a", nrm.hash_code)
|
55
|
-
end
|
56
|
-
|
57
|
-
should "normalize a simple signature with tags and spaces instead of tabs" do
|
29
|
+
yn = YaraTools::YaraRule.new(sig)
|
30
|
+
assert_equal("yn01:3c0de1ad64681376:3ff75e9945", yn.hash)
|
31
|
+
assert_equal("newIE0daymshtmlExec", yn.name)
|
32
|
+
assert_equal("\"redacted @ gmail.com\"", yn.meta['author'])
|
33
|
+
assert_equal(["$mshtmlExec_1 = /document.execCommand(['\"]selectAll['\"])/ nocase fullword",
|
34
|
+
"$mshtmlExec_2 = /YMjf\\u0c08\\u0c0cKDogjsiIejengNEkoPDjfiJDIWUAzdfghjAAuUFGGBSIPPPUDFJKSOQJGH/ nocase fullword",
|
35
|
+
"$mshtmlExec_3 = /<body on(load|select)=['\"]w*?();['\"] on(load|select)=['\"]w*?()['\"]/ nocase",
|
36
|
+
"$mshtmlExec_4 = /var w{1,} = new Array()/ nocase",
|
37
|
+
"$mshtmlExec_5 = /window.document.createElement(['\"]img['\"])/ nocase",
|
38
|
+
"$mshtmlExec_6 = /w{1,}[0][['\"]src['\"]] = ['\"]w{1,}['\"]/ nocase",
|
39
|
+
"$mshtmlExec_7 = /<iframe src=['\"].*?['\"]/ nocase"], yn.strings)
|
40
|
+
assert_equal(
|
41
|
+
["($mshtmlExec_1 and $mshtmlExec_2 and $mshtmlExec_3) or ($mshtmlExec_4 and $mshtmlExec_5 and ($mshtmlExec_6 or $mshtmlExec_7))"],
|
42
|
+
yn.condition
|
43
|
+
)
|
44
|
+
hash1 = yn.hash
|
58
45
|
sig =<<EOS
|
59
46
|
rule newIE0daymshtmlExec : tag1 tag2 tag3
|
60
47
|
{
|
61
48
|
meta:
|
62
|
-
author = "
|
49
|
+
author = "redacted @ gmail.com"
|
63
50
|
ref = "http://blog.vulnhunt.com/index.php/2012/09/17/ie-execcommand-fuction-use-after-free-vulnerability-0day_en/"
|
64
51
|
description = "Internet Explorer CMshtmlEd::Exec() 0day"
|
65
52
|
cve = "CVE-2012-XXXX"
|
@@ -78,66 +65,25 @@ rule newIE0daymshtmlExec : tag1 tag2 tag3
|
|
78
65
|
($mshtmlExec_1 and $mshtmlExec_2 and $mshtmlExec_3) or ($mshtmlExec_4 and $mshtmlExec_5 and ($mshtmlExec_6 or $mshtmlExec_7))
|
79
66
|
}
|
80
67
|
EOS
|
81
|
-
yn =
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
"
|
90
|
-
"
|
91
|
-
"
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
"$mshtmlExec_6 = /w{1,}[0][['\"]src['\"]] = ['\"]w{1,}['\"]/ nocase",
|
98
|
-
"$mshtmlExec_7 = /<iframe src=['\"].*?['\"]/ nocase"],
|
99
|
-
"meta"=>
|
100
|
-
{"author"=>"\"adnan.shukor@gmail.com\"",
|
101
|
-
"description"=>"\"Internet Explorer CMshtmlEd::Exec() 0day\"",
|
102
|
-
"ref"=>
|
103
|
-
"\"http://blog.vulnhunt.com/index.php/2012/09/17/ie-execcommand-fuction-use-after-free-vulnerability-0day_en/\"",
|
104
|
-
"impact"=>"4",
|
105
|
-
"hide"=>"false",
|
106
|
-
"cve"=>"\"CVE-2012-XXXX\"",
|
107
|
-
"version"=>"\"1\""}}, hash)
|
108
|
-
assert_equal("ee2e32d623a0debca271cada22b35b3b904d6abd678cf2a48a87b43cd6302e73f67510c19ffe2f1a", nrm.hash_code)
|
109
|
-
end
|
110
|
-
|
111
|
-
should "normalize a simple signature that has been rearranged" do
|
112
|
-
sig =<<EOS
|
113
|
-
rule newIE0daymshtmlExec
|
114
|
-
{
|
115
|
-
meta:
|
116
|
-
author = "adnan.shukor@gmail.com"
|
117
|
-
ref = "http://blog.vulnhunt.com/index.php/2012/09/17/ie-execcommand-fuction-use-after-free-vulnerability-0day_en/"
|
118
|
-
description = "Internet Explorer CMshtmlEd::Exec() 0day"
|
119
|
-
cve = "CVE-2012-XXXX"
|
120
|
-
version = "1"
|
121
|
-
impact = 4
|
122
|
-
hide = false
|
123
|
-
strings:
|
124
|
-
$mshtmlExec_3 = /\<body\son(load|select)=['"]\w*?\(\)\;['"]\son(load|select)=['"]\w*?\(\)['"]/ nocase
|
125
|
-
$mshtmlExec_5 = /window\.document\.createElement\(['"]img['"]\)/ nocase
|
126
|
-
$mshtmlExec_6 = /\w{1,}\[0\]\[['"]src['"]\]\s\=\s['"]\w{1,}['"]/ nocase
|
127
|
-
$mshtmlExec_4 = /var\s\w{1,}\s=\snew\sArray\(\)/ nocase
|
128
|
-
$mshtmlExec_1 = /document\.execCommand\(['"]selectAll['"]\)/ nocase fullword
|
129
|
-
$mshtmlExec_7 = /\<iframe\ssrc=['"].*?['"]/ nocase
|
130
|
-
$mshtmlExec_2 = /YMjf\\u0c08\\u0c0cKDogjsiIejengNEkoPDjfiJDIWUAzdfghjAAuUFGGBSIPPPUDFJKSOQJGH/ nocase fullword
|
131
|
-
condition:
|
132
|
-
($mshtmlExec_4 and ($mshtmlExec_6 or $mshtmlExec_7) and $mshtmlExec_5) or ($mshtmlExec_1 and $mshtmlExec_2 and $mshtmlExec_3)
|
133
|
-
}
|
134
|
-
EOS
|
135
|
-
yn = Yara::Normalizer.new
|
136
|
-
nrm = yn.normalize(sig)
|
137
|
-
assert_equal("ee2e32d623a0debca271cada22b35b3b904d6abd678cf2a48a87b43cd6302e73f67510c19ffe2f1a", nrm.hash_code)
|
68
|
+
yn = YaraTools::YaraRule.new(sig)
|
69
|
+
assert_equal(hash1, yn.hash)
|
70
|
+
assert_equal("newIE0daymshtmlExec", yn.name)
|
71
|
+
assert_equal(["tag1","tag2","tag3"], yn.tags)
|
72
|
+
assert_equal("\"redacted @ gmail.com\"", yn.meta['author'])
|
73
|
+
assert_equal(["$mshtmlExec_1 = /document.execCommand(['\"]selectAll['\"])/ nocase fullword",
|
74
|
+
"$mshtmlExec_2 = /YMjf\\u0c08\\u0c0cKDogjsiIejengNEkoPDjfiJDIWUAzdfghjAAuUFGGBSIPPPUDFJKSOQJGH/ nocase fullword",
|
75
|
+
"$mshtmlExec_3 = /<body on(load|select)=['\"]w*?();['\"] on(load|select)=['\"]w*?()['\"]/ nocase",
|
76
|
+
"$mshtmlExec_4 = /var w{1,} = new Array()/ nocase",
|
77
|
+
"$mshtmlExec_5 = /window.document.createElement(['\"]img['\"])/ nocase",
|
78
|
+
"$mshtmlExec_6 = /w{1,}[0][['\"]src['\"]] = ['\"]w{1,}['\"]/ nocase",
|
79
|
+
"$mshtmlExec_7 = /<iframe src=['\"].*?['\"]/ nocase"], yn.strings)
|
80
|
+
assert_equal(
|
81
|
+
["($mshtmlExec_1 and $mshtmlExec_2 and $mshtmlExec_3) or ($mshtmlExec_4 and $mshtmlExec_5 and ($mshtmlExec_6 or $mshtmlExec_7))"],
|
82
|
+
yn.condition
|
83
|
+
)
|
138
84
|
end
|
139
85
|
|
140
|
-
should "normalize a simple signature that has
|
86
|
+
should "normalize a simple signature that has a condition of 'any of them'" do
|
141
87
|
sig =<<EOS
|
142
88
|
rule DataConversion__wide : IntegerParsing DataConversion {
|
143
89
|
meta:
|
@@ -151,22 +97,16 @@ rule DataConversion__wide : IntegerParsing DataConversion {
|
|
151
97
|
any of them
|
152
98
|
}
|
153
99
|
EOS
|
154
|
-
yn =
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
"
|
162
|
-
"
|
163
|
-
|
164
|
-
["$ = \"wtoi\" nocase",
|
165
|
-
"$ = \"wtol\" nocase",
|
166
|
-
"$ = \"wtof\" nocase",
|
167
|
-
"$ = \"wtodb\" nocase"],
|
168
|
-
"meta"=>{"weight"=>"1"}},hash)
|
169
|
-
assert_equal("dacfb7f79e2ad96cb66c4784323d91e09e8ad2f8c214c8ea0a52e3a3bda71e6612f02361609e0f7a", nrm.hash_code)
|
100
|
+
yn = YaraTools::YaraRule.new(sig)
|
101
|
+
assert_equal("yn01:488085c947cb22ed:d936fceffe", yn.hash)
|
102
|
+
assert_equal("1", yn.meta['weight'])
|
103
|
+
assert_equal("DataConversion__wide", yn.name)
|
104
|
+
assert_equal(["IntegerParsing", "DataConversion"], yn.tags)
|
105
|
+
assert_equal(["$ = \"wtoi\" nocase",
|
106
|
+
"$ = \"wtol\" nocase",
|
107
|
+
"$ = \"wtof\" nocase",
|
108
|
+
"$ = \"wtodb\" nocase"], yn.strings)
|
109
|
+
assert_equal(["any of them"], yn.condition)
|
170
110
|
end
|
171
111
|
end
|
172
112
|
|
data/yara-normalize.gemspec
CHANGED
@@ -5,14 +5,16 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{yara-normalize}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["chrislee35"]
|
12
12
|
s.cert_chain = ["/Users/chris/Documents/projects/rubygems/yara-normalize/../gem-public_cert.pem"]
|
13
|
-
s.date = %q{2012-
|
13
|
+
s.date = %q{2012-10-29}
|
14
|
+
s.default_executable = %q{yaratool}
|
14
15
|
s.description = %q{To enable consistent comparisons between yara rules (signature), a uniform hashing standard was needed.}
|
15
16
|
s.email = %q{rubygems@chrislee.dhs.org}
|
17
|
+
s.executables = ["yaratool"]
|
16
18
|
s.extra_rdoc_files = [
|
17
19
|
"LICENSE.txt",
|
18
20
|
"README.rdoc"
|
@@ -25,8 +27,10 @@ Gem::Specification.new do |s|
|
|
25
27
|
"README.rdoc",
|
26
28
|
"Rakefile",
|
27
29
|
"VERSION",
|
30
|
+
"bin/yaratool",
|
28
31
|
"lib/yara-normalize.rb",
|
29
32
|
"lib/yara-normalize/yara-normalize.rb",
|
33
|
+
"ruby_results.txt",
|
30
34
|
"test/helper.rb",
|
31
35
|
"test/test_yara-normalize.rb",
|
32
36
|
"yara-normalize.gemspec"
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
+
- 1
|
7
8
|
- 0
|
8
|
-
|
9
|
-
version: 0.0.0
|
9
|
+
version: 0.1.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- chrislee35
|
@@ -36,8 +36,8 @@ cert_chain:
|
|
36
36
|
6yhklP75
|
37
37
|
-----END CERTIFICATE-----
|
38
38
|
|
39
|
-
date: 2012-
|
40
|
-
default_executable:
|
39
|
+
date: 2012-10-29 00:00:00 -04:00
|
40
|
+
default_executable: yaratool
|
41
41
|
dependencies:
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
prerelease: false
|
@@ -106,8 +106,8 @@ dependencies:
|
|
106
106
|
requirement: *id005
|
107
107
|
description: To enable consistent comparisons between yara rules (signature), a uniform hashing standard was needed.
|
108
108
|
email: rubygems@chrislee.dhs.org
|
109
|
-
executables:
|
110
|
-
|
109
|
+
executables:
|
110
|
+
- yaratool
|
111
111
|
extensions: []
|
112
112
|
|
113
113
|
extra_rdoc_files:
|
@@ -121,8 +121,10 @@ files:
|
|
121
121
|
- README.rdoc
|
122
122
|
- Rakefile
|
123
123
|
- VERSION
|
124
|
+
- bin/yaratool
|
124
125
|
- lib/yara-normalize.rb
|
125
126
|
- lib/yara-normalize/yara-normalize.rb
|
127
|
+
- ruby_results.txt
|
126
128
|
- test/helper.rb
|
127
129
|
- test/test_yara-normalize.rb
|
128
130
|
- yara-normalize.gemspec
|
metadata.gz.sig
CHANGED
Binary file
|