RubyIOC 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +19 -19
- data/Gemfile +3 -3
- data/Rakefile +7 -7
- data/RubyIOC.gemspec +24 -24
- data/iocaware.iocterms +12 -0
- data/lib/RubyIOC.rb +38 -38
- data/lib/RubyIOC/iocitem/arp_entry_item.rb +86 -1
- data/lib/RubyIOC/iocitem/dns_entry_item.rb +47 -11
- data/lib/RubyIOC/iocitem/event_log_item.rb +49 -0
- data/lib/RubyIOC/iocitem/port_item.rb +117 -0
- data/lib/RubyIOC/iocitem/service_item.rb +100 -0
- data/lib/RubyIOC/iocitem/user_item.rb +1 -1
- data/lib/RubyIOC/iocitem/volume_item.rb +65 -0
- data/lib/RubyIOC/platform.rb +2 -2
- data/lib/RubyIOC/scanner.rb +15 -28
- data/lib/RubyIOC/version.rb +15 -15
- data/test/test_arp_entry_item.ioc +57 -0
- data/test/test_dns_entry_item.ioc +26 -5
- data/test/test_event_log_item.ioc +55 -0
- data/test/test_port_item.ioc +51 -0
- data/test/test_scan.rb +29 -4
- data/test/test_service_item.ioc +143 -0
- data/test/test_user_item.ioc +9 -8
- data/test/test_volume_item.ioc +63 -0
- metadata +16 -5
data/.gitignore
CHANGED
@@ -1,20 +1,20 @@
|
|
1
|
-
*.gem
|
2
|
-
.bundle
|
3
|
-
Gemfile.lock
|
4
|
-
pkg/*
|
5
|
-
*.rbc
|
6
|
-
.config
|
7
|
-
coverage
|
8
|
-
InstalledFiles
|
9
|
-
lib/bundler/man
|
10
|
-
pkg
|
11
|
-
rdoc
|
12
|
-
spec/reports
|
13
|
-
test/tmp
|
14
|
-
test/version_tmp
|
15
|
-
tmp
|
16
|
-
|
17
|
-
# YARD artifacts
|
18
|
-
.yardoc
|
19
|
-
_yardoc
|
1
|
+
*.gem
|
2
|
+
.bundle
|
3
|
+
Gemfile.lock
|
4
|
+
pkg/*
|
5
|
+
*.rbc
|
6
|
+
.config
|
7
|
+
coverage
|
8
|
+
InstalledFiles
|
9
|
+
lib/bundler/man
|
10
|
+
pkg
|
11
|
+
rdoc
|
12
|
+
spec/reports
|
13
|
+
test/tmp
|
14
|
+
test/version_tmp
|
15
|
+
tmp
|
16
|
+
|
17
|
+
# YARD artifacts
|
18
|
+
.yardoc
|
19
|
+
_yardoc
|
20
20
|
doc/
|
data/Gemfile
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
source "http://rubygems.org"
|
2
|
-
# Specify your gem's dependencies in RubyIOC.gemspec
|
3
|
-
gemspec
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Specify your gem's dependencies in RubyIOC.gemspec
|
3
|
+
gemspec
|
data/Rakefile
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
require "bundler/gem_tasks"
|
2
|
-
require "rake/testtask"
|
3
|
-
|
4
|
-
Rake::TestTask.new do |t|
|
5
|
-
t.libs << "test"
|
6
|
-
t.test_files = FileList['test/test*.rb']
|
7
|
-
t.verbose = false
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/testtask"
|
3
|
+
|
4
|
+
Rake::TestTask.new do |t|
|
5
|
+
t.libs << "test"
|
6
|
+
t.test_files = FileList['test/test*.rb']
|
7
|
+
t.verbose = false
|
8
8
|
end
|
data/RubyIOC.gemspec
CHANGED
@@ -1,24 +1,24 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require "RubyIOC/version"
|
4
|
-
|
5
|
-
Gem::Specification.new do |s|
|
6
|
-
s.name = "RubyIOC"
|
7
|
-
s.version = RubyIOC::VERSION
|
8
|
-
s.authors = ["Matt Jezorek"]
|
9
|
-
s.email = ["mjezorek@gmail.com"]
|
10
|
-
s.homepage = ""
|
11
|
-
s.summary = %q{RubyIOC is a ruby library used for indicators of compromise}
|
12
|
-
s.description = %q{RubyIOC is a ruby library used for indicators of compromise}
|
13
|
-
|
14
|
-
s.rubyforge_project = "RubyIOC"
|
15
|
-
|
16
|
-
s.files = `git ls-files`.split("\n")
|
17
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
-
s.require_paths = ["lib"]
|
20
|
-
|
21
|
-
# specify any dependencies here; for example:
|
22
|
-
# s.add_development_dependency "rspec"
|
23
|
-
s.add_runtime_dependency "roxml"
|
24
|
-
end
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "RubyIOC/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "RubyIOC"
|
7
|
+
s.version = RubyIOC::VERSION
|
8
|
+
s.authors = ["Matt Jezorek"]
|
9
|
+
s.email = ["mjezorek@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{RubyIOC is a ruby library used for indicators of compromise}
|
12
|
+
s.description = %q{RubyIOC is a ruby library used for indicators of compromise}
|
13
|
+
|
14
|
+
s.rubyforge_project = "RubyIOC"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
# s.add_development_dependency "rspec"
|
23
|
+
s.add_runtime_dependency "roxml"
|
24
|
+
end
|
data/iocaware.iocterms
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
<?xml version="1.0" encoding="us-ascii"?>
|
2
|
+
<ioctermlist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" last-modified="2013-07-15T21:26:28" description="New IOC Terms File" xmlns="http://schemas.mandiant.com/2010/ioc">
|
3
|
+
<iocterm text="FileItem/Md54ksum" title="File MD54K" data-type="MD5Sum" display-type="md5" term-source="application/iocaware" />
|
4
|
+
<iocterm text="FileItem/Ssdeep" title="File SSDeep" data-type="xs:string" display-type="string" term-source="application/iocaware" />
|
5
|
+
<iocterm text="FileItem/Sha512sum" title="File Sha512sum" data-type="HashSum" display-type="string" term-source="application/iocaware" />
|
6
|
+
<iocterm text="ServiceItem/pathMd54ksum" title="Service Path MD54K" data-type="MD5Sum" display-type="md5" term-source="application/iocaware" />
|
7
|
+
<iocterm text="ServiceItem/pathSsdeep" title="Service Path SSDeep" data-type="xs:string" display-type="string" term-source="application/iocaware" />
|
8
|
+
<iocterm text="ServiceItem/pathSha512sum" title="Service Path Sha512Sum" data-type="HashSum" display-type="string" term-source="application/iocaware" />
|
9
|
+
<iocterm text="ServiceItem/serviceDLLMd54Ksum" title="Service DLL MD54K" data-type="MD5Sum" display-type="md5" term-source="application/iocaware" />
|
10
|
+
<iocterm text="ServiceItem/serviceDLLSsdeep" title="Service DLL SSDeep" data-type="xs:string" display-type="string" term-source="application/iocaware" />
|
11
|
+
<iocterm text="ServiceItem/serviceDLLSha512Sum" title="Service DLL Sha512Sum" data-type="HashSum" display-type="string" term-source="application/iocaware" />
|
12
|
+
</ioctermlist>
|
data/lib/RubyIOC.rb
CHANGED
@@ -1,39 +1,39 @@
|
|
1
|
-
# Copyright (c) 2013 Matt Jezorek
|
2
|
-
#
|
3
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
4
|
-
# to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
5
|
-
# and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
6
|
-
#
|
7
|
-
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
8
|
-
#
|
9
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
10
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
11
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
12
|
-
# IN THE SOFTWARE.
|
13
|
-
require "rexml/document"
|
14
|
-
|
15
|
-
require "RubyIOC/version"
|
16
|
-
require "RubyIOC/platform"
|
17
|
-
require "RubyIOC/iocterm"
|
18
|
-
require "RubyIOC/iocitem"
|
19
|
-
require "RubyIOC/ioc"
|
20
|
-
require "RubyIOC/scanner"
|
21
|
-
|
22
|
-
=begin rdoc
|
23
|
-
RubyIOC is a simple gem that will allow the scanning of a system with indicators of compromise. RubyIOC will not tell you if the machine
|
24
|
-
is compromised or not but it will give you a score and what indicators have been found. Ideally you will want to see 0% and 0 found indicators.
|
25
|
-
However you may come back with 1% ond 2 indicators out of 200. It will also provide you a reference to the found indicators. From here you
|
26
|
-
can investigate whatever machine you wish to investigate.
|
27
|
-
|
28
|
-
Please note that when you use this software you are running on possibly compromised machiens, any credentials you use to facilitate the scan
|
29
|
-
should be considered compromised
|
30
|
-
=end
|
31
|
-
|
32
|
-
|
33
|
-
class String
|
34
|
-
def to_bool
|
35
|
-
return true if self == true || self =~ (/(true|t|yes|y|1)$/i)
|
36
|
-
return false if self == false || self.blank? || self =~ (/(false|f|no|n|0)$/i)
|
37
|
-
raise ArgumentError.new("invalid value for Boolean: \"#{self}\"")
|
38
|
-
end
|
1
|
+
# Copyright (c) 2013 Matt Jezorek
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
4
|
+
# to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
5
|
+
# and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
6
|
+
#
|
7
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
8
|
+
#
|
9
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
10
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
11
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
12
|
+
# IN THE SOFTWARE.
|
13
|
+
require "rexml/document"
|
14
|
+
|
15
|
+
require "RubyIOC/version"
|
16
|
+
require "RubyIOC/platform"
|
17
|
+
require "RubyIOC/iocterm"
|
18
|
+
require "RubyIOC/iocitem"
|
19
|
+
require "RubyIOC/ioc"
|
20
|
+
require "RubyIOC/scanner"
|
21
|
+
|
22
|
+
=begin rdoc
|
23
|
+
RubyIOC is a simple gem that will allow the scanning of a system with indicators of compromise. RubyIOC will not tell you if the machine
|
24
|
+
is compromised or not but it will give you a score and what indicators have been found. Ideally you will want to see 0% and 0 found indicators.
|
25
|
+
However you may come back with 1% ond 2 indicators out of 200. It will also provide you a reference to the found indicators. From here you
|
26
|
+
can investigate whatever machine you wish to investigate.
|
27
|
+
|
28
|
+
Please note that when you use this software you are running on possibly compromised machiens, any credentials you use to facilitate the scan
|
29
|
+
should be considered compromised
|
30
|
+
=end
|
31
|
+
|
32
|
+
|
33
|
+
class String
|
34
|
+
def to_bool
|
35
|
+
return true if self == true || self =~ (/(true|t|yes|y|1)$/i)
|
36
|
+
return false if self == false || self.blank? || self =~ (/(false|f|no|n|0)$/i)
|
37
|
+
raise ArgumentError.new("invalid value for Boolean: \"#{self}\"")
|
38
|
+
end
|
39
39
|
end
|
@@ -16,6 +16,89 @@ module RubyIOC
|
|
16
16
|
def get_type
|
17
17
|
"ArpEntryItem"
|
18
18
|
end
|
19
|
+
|
20
|
+
def scan(indicator)
|
21
|
+
if RubyIOC::Platform.windows?
|
22
|
+
return search_windows_arp(indicator)
|
23
|
+
elseif Ruby::Platform::mac?
|
24
|
+
return search_mac_arp(indicator)
|
25
|
+
else
|
26
|
+
puts "Not implemented on this platform yet"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def search_windows_arp(indicator)
|
31
|
+
arp = get_arp_cache
|
32
|
+
|
33
|
+
arp.each_line do |line|
|
34
|
+
indicator.each { |i|
|
35
|
+
content = i[:content]
|
36
|
+
|
37
|
+
case i[:search]
|
38
|
+
when "ArpEntryItem/PhysicalAddress", "ArpEntryItem/CacheType", "ArpEntryItem/IPv4Address"
|
39
|
+
if !(line.downcase.include? "interface") && (line.downcase.gsub("-", ":").include? content.downcase)
|
40
|
+
return true
|
41
|
+
end
|
42
|
+
when "ArpEntryItem/Interface"
|
43
|
+
if (line.downcase.include? "interface") && (line.downcase.include? content.downcase)
|
44
|
+
return true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
}
|
48
|
+
end
|
49
|
+
#puts arp
|
50
|
+
#puts arp.to_yaml
|
51
|
+
return false
|
52
|
+
end
|
53
|
+
|
54
|
+
def search_mac_arp(indicator)
|
55
|
+
arp = get_arp_cache
|
56
|
+
arp.each_line do |line|
|
57
|
+
fields = line.split(' ')
|
58
|
+
ip = fields[1].gsub('(', '').gsub(')', '')
|
59
|
+
physical = fields[3].downcase
|
60
|
+
iface = fields[5].downcase
|
61
|
+
|
62
|
+
indicator.each { |i|
|
63
|
+
content = i[:content].downcase
|
64
|
+
|
65
|
+
case i[:search]
|
66
|
+
when "ArpEntryItem/PhysicalAddress"
|
67
|
+
octets = physical.split(':')
|
68
|
+
i = 0
|
69
|
+
while i < octets.length do
|
70
|
+
if octets[i].length == 1 then
|
71
|
+
octets[i] = '0' + octets[i]
|
72
|
+
end
|
73
|
+
i += 1
|
74
|
+
end
|
75
|
+
physical = octets.join(':')
|
76
|
+
|
77
|
+
if physical == content then
|
78
|
+
return true
|
79
|
+
end
|
80
|
+
when "ArpEntryItem/CacheType"
|
81
|
+
when "ArpEntryItem/IPv4Address"
|
82
|
+
if ip == content then
|
83
|
+
return true
|
84
|
+
end
|
85
|
+
when "ArpEntryItem/Interface"
|
86
|
+
if iface == content then
|
87
|
+
return true
|
88
|
+
end
|
89
|
+
end
|
90
|
+
}
|
91
|
+
end
|
92
|
+
#puts arp
|
93
|
+
#puts arp.to_yaml
|
94
|
+
return false
|
95
|
+
end
|
96
|
+
|
97
|
+
def get_arp_cache
|
98
|
+
arp_cache =`arp -a`
|
99
|
+
|
100
|
+
return arp_cache
|
101
|
+
end
|
19
102
|
end
|
20
103
|
|
21
104
|
class ArpEntryItemFactory < RubyIOC::IOCItem::IOCItemFactory
|
@@ -30,4 +113,6 @@ module RubyIOC
|
|
30
113
|
|
31
114
|
ArpEntryItemFactory.add_factory(ArpEntryItemFactory)
|
32
115
|
end
|
33
|
-
end
|
116
|
+
end
|
117
|
+
|
118
|
+
|
@@ -26,18 +26,16 @@ module RubyIOC
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def search_windows_dns(indicator)
|
29
|
-
|
30
|
-
|
31
|
-
return false
|
32
|
-
end
|
33
|
-
|
34
|
-
def get_windows_dns_cache
|
35
|
-
dns = []
|
36
|
-
dns_cache =`ipconfig /displaydns`
|
29
|
+
dns_cache = get_windows_dns_cache
|
30
|
+
|
37
31
|
blocks = dns_cache.split(/\n\n/)
|
32
|
+
|
38
33
|
blocks.each do | block |
|
39
|
-
|
34
|
+
noblanklines = block.gsub(/^$\n/, '').downcase
|
35
|
+
host = noblanklines.lines.first
|
36
|
+
|
40
37
|
temp = {}
|
38
|
+
temp[:host] = host
|
41
39
|
temp[:record_name] = block.match(/\s*Record Name.*:\s(?<record>.*)/).to_a[1]
|
42
40
|
temp[:record_type] = block.match(/\s*Record Type.*:\s(?<record>.*)/).to_a[1]
|
43
41
|
temp[:time_to_live] = block.match(/\s*Time To Live.*:\s(?<record>.*)/).to_a[1]
|
@@ -45,9 +43,47 @@ module RubyIOC
|
|
45
43
|
temp[:section] = block.match(/\s*Section.*:\s(?<record>.*)/).to_a[1]
|
46
44
|
temp[:a_record] = block.match(/\s*A \(Host\) Record.*:\s(?<record>.*)/).to_a[1]
|
47
45
|
temp[:cname] = block.match(/\s*CNAME Record.*:\s(?<record>.*)/).to_a[1]
|
48
|
-
|
46
|
+
#puts temp
|
47
|
+
indicator.each { |i|
|
48
|
+
content = i[:content].downcase
|
49
|
+
|
50
|
+
case i[:search]
|
51
|
+
when "DnsEntryItem/Host"
|
52
|
+
if !temp[:host].nil? and temp[:host].downcase.strip == content then
|
53
|
+
return true
|
54
|
+
end
|
55
|
+
when "DnsEntryItem/RecordName"
|
56
|
+
if !temp[:record_name].nil? and temp[:record_name].downcase.strip == content then
|
57
|
+
return true
|
58
|
+
end
|
59
|
+
when "DnsEntryItem/RecordType"
|
60
|
+
if !temp[:record_type].nil? and temp[:record_type].downcase.strip == content then
|
61
|
+
return true
|
62
|
+
end
|
63
|
+
when "DnsEntryItem/TimeToLive"
|
64
|
+
if !temp[:time_to_live].nil? and temp[:time_to_live].downcase.strip == content then
|
65
|
+
return true
|
66
|
+
end
|
67
|
+
when "DnsEntryItem/Flags"
|
68
|
+
when "DnsEntryItem/DataLength"
|
69
|
+
if !temp[:data_length].nil? and temp[:data_length].downcase.strip == content then
|
70
|
+
return true
|
71
|
+
end
|
72
|
+
when "DnsEntryItem/RecordData/Host"
|
73
|
+
when "DnsEntryItem/RecordData/IPv4Address"
|
74
|
+
if !temp[:a_record].nil? and temp[:a_record].downcase.strip == content then
|
75
|
+
return true
|
76
|
+
end
|
77
|
+
end
|
78
|
+
}
|
49
79
|
end
|
50
|
-
|
80
|
+
|
81
|
+
return false
|
82
|
+
end
|
83
|
+
|
84
|
+
def get_windows_dns_cache
|
85
|
+
dns_cache =`ipconfig /displaydns`
|
86
|
+
return dns_cache
|
51
87
|
end
|
52
88
|
end
|
53
89
|
|
@@ -10,12 +10,61 @@
|
|
10
10
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
11
11
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
12
12
|
# IN THE SOFTWARE.
|
13
|
+
|
14
|
+
if RubyIOC::Platform.windows?
|
15
|
+
require "win32ole"
|
16
|
+
end
|
17
|
+
|
13
18
|
module RubyIOC
|
14
19
|
module IOCItem
|
15
20
|
class EventLogItem < RubyIOC::IOCTerm
|
16
21
|
def get_type
|
17
22
|
"EventLogItem"
|
18
23
|
end
|
24
|
+
|
25
|
+
def scan(indicator)
|
26
|
+
if RubyIOC::Platform.windows?
|
27
|
+
return search_windows_events(indicator)
|
28
|
+
else
|
29
|
+
puts "Not implemented on this platform yet"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def search_windows_events(indicator)
|
34
|
+
wmi = WIN32OLE.connect("winmgmts:{impersonationLevel=impersonate,(Security)}!\\")
|
35
|
+
query = "Select * from Win32_NTLogEvent where "
|
36
|
+
|
37
|
+
indicator.each { |i|
|
38
|
+
case i[:search]
|
39
|
+
when "EventLogItem/category"
|
40
|
+
query += "CategoryString = '#{i[:content]}' "
|
41
|
+
when "EventLogItem/categoryNum"
|
42
|
+
query += "Category = #{i[:content]} "
|
43
|
+
when "EventLogItem/genTime"
|
44
|
+
when "EventLogItem/EID"
|
45
|
+
query += "EventIdentifier = #{i[:content]} "
|
46
|
+
when "EventLogItem/log"
|
47
|
+
query += "LogFile = '#{i[:content]}' "
|
48
|
+
when "EventLogItem/machine"
|
49
|
+
query += "ComputerName = '#{i[:content]}' "
|
50
|
+
when "EventLogItem/message"
|
51
|
+
query += "Message like '%#{i[:content]}%' "
|
52
|
+
when "EventLogItem/source"
|
53
|
+
query += "SourceName = '#{i[:content]}' "
|
54
|
+
when "EventLogItem/type"
|
55
|
+
query += "Type = '#{i[:content]}' "
|
56
|
+
when "EventLogItem/user"
|
57
|
+
query += "User like '%#{i[:content]}%' "
|
58
|
+
when "EventLogItem/writeTime"
|
59
|
+
end
|
60
|
+
}
|
61
|
+
|
62
|
+
events = wmi.ExecQuery(query)
|
63
|
+
events.each { |e|
|
64
|
+
return true
|
65
|
+
}
|
66
|
+
return false
|
67
|
+
end
|
19
68
|
end
|
20
69
|
|
21
70
|
class EventLogItemFactory < RubyIOC::IOCItem::IOCItemFactory
|
@@ -16,6 +16,123 @@ module RubyIOC
|
|
16
16
|
def get_type
|
17
17
|
"PortItem"
|
18
18
|
end
|
19
|
+
|
20
|
+
def scan(indicator)
|
21
|
+
if RubyIOC::Platform.windows?
|
22
|
+
return search_windows_netstat(indicator)
|
23
|
+
else
|
24
|
+
puts "Not implemented on this platform yet"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def search_windows_netstat(indicator)
|
29
|
+
netstat = get_windows_netstat
|
30
|
+
|
31
|
+
blocks = netstat.split(/\n/)
|
32
|
+
i = 1
|
33
|
+
|
34
|
+
entries = []
|
35
|
+
entry = ""
|
36
|
+
blocks.each do | block |
|
37
|
+
if i<5 then
|
38
|
+
i+=1
|
39
|
+
next
|
40
|
+
end
|
41
|
+
|
42
|
+
line = block.strip.gsub(/[ ]{2,}/, " ")
|
43
|
+
localip = ""
|
44
|
+
localport = ""
|
45
|
+
pid = ""
|
46
|
+
process = ""
|
47
|
+
protocol = ""
|
48
|
+
remoteip = ""
|
49
|
+
remoteport = ""
|
50
|
+
state = ""
|
51
|
+
|
52
|
+
if line.match(/^TCP/) or line.match(/^UDP/) then
|
53
|
+
nsentry = line.downcase.split(' ')
|
54
|
+
protocol = nsentry[0]
|
55
|
+
if nsentry[1].match(/\[/) then
|
56
|
+
localip = nsentry[1].split(']:')[0].gsub(/\[/, '')
|
57
|
+
localport = nsentry[1].split(']:')[1]
|
58
|
+
else
|
59
|
+
localip = nsentry[1].split(':')[0]
|
60
|
+
localport = nsentry[1].split(':')[1]
|
61
|
+
end
|
62
|
+
if nsentry[2].match(/\[/) then
|
63
|
+
remoteip = nsentry[2].split(']:')[0].gsub(/\[/, '')
|
64
|
+
remoteport = nsentry[2].split(']:')[1]
|
65
|
+
else
|
66
|
+
remoteip = nsentry[2].split(':')[0]
|
67
|
+
remoteport = nsentry[2].split(':')[1]
|
68
|
+
end
|
69
|
+
if nsentry.length < 5 then
|
70
|
+
pid = nsentry[3]
|
71
|
+
else
|
72
|
+
state = nsentry[3]
|
73
|
+
pid = nsentry[4]
|
74
|
+
end
|
75
|
+
|
76
|
+
indicator.each { |i|
|
77
|
+
content = i[:content].downcase
|
78
|
+
|
79
|
+
case i[:search]
|
80
|
+
when "PortItem/CreationTime"
|
81
|
+
when "PortItem/localIP"
|
82
|
+
if content == localip then
|
83
|
+
return true
|
84
|
+
end
|
85
|
+
when "PortItem/localPort"
|
86
|
+
if content == localport then
|
87
|
+
return true
|
88
|
+
end
|
89
|
+
when "PortItem/path"
|
90
|
+
when "PortItem/pid"
|
91
|
+
if content == pid then
|
92
|
+
return true
|
93
|
+
end
|
94
|
+
when "PortItem/protocol"
|
95
|
+
if content == protocol then
|
96
|
+
return true
|
97
|
+
end
|
98
|
+
when "PortItem/remoteIP"
|
99
|
+
if content == remoteip then
|
100
|
+
return true
|
101
|
+
end
|
102
|
+
when "PortItem/remotePort"
|
103
|
+
if content == remoteport then
|
104
|
+
return true
|
105
|
+
end
|
106
|
+
when "PortItem/state"
|
107
|
+
if content == state then
|
108
|
+
return true
|
109
|
+
end
|
110
|
+
end
|
111
|
+
}
|
112
|
+
else
|
113
|
+
if line.match(/^\[/)
|
114
|
+
process = line.downcase.gsub("[", "").gsub("]", "")
|
115
|
+
|
116
|
+
indicator.each { |i|
|
117
|
+
content = i[:content].downcase
|
118
|
+
case i[:search]
|
119
|
+
when "PortItem/process"
|
120
|
+
if content == process then
|
121
|
+
return true
|
122
|
+
end
|
123
|
+
end
|
124
|
+
}
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
return false
|
130
|
+
end
|
131
|
+
|
132
|
+
def get_windows_netstat
|
133
|
+
netstat = `netstat -anbo`
|
134
|
+
return netstat
|
135
|
+
end
|
19
136
|
end
|
20
137
|
|
21
138
|
class PortItemFactory < RubyIOC::IOCItem::IOCItemFactory
|