librex 0.0.32 → 0.0.33

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,7 +3,7 @@
3
3
  A non-official re-packaging of the Rex library as a gem for easy of usage of the Metasploit REX framework in a non Metasploit application. I received permission from HDM to create this package.
4
4
 
5
5
  Currently based on:
6
- SVN Revision: 12612
6
+ SVN Revision: 12724
7
7
 
8
8
  # Credits
9
9
  The Metasploit development team <http://www.metasploit.com>
@@ -20,6 +20,7 @@ module Exploitation
20
20
  # Checksum code merged to Egghunter by jduck
21
21
  # Conversion to use Metasm by jduck
22
22
  # Startreg code added by corelanc0d3r
23
+ # Added routine to disable DEP for discovered egg (for win, added by corelanc0d3r)
23
24
  #
24
25
  ###
25
26
  class Egghunter
@@ -57,7 +58,95 @@ class Egghunter
57
58
  end
58
59
  startstub << "\n\t" if startstub.length > 0
59
60
 
61
+ getpointer = ''
62
+ getsize = ''
63
+ getpc = ''
64
+ jmppayload = "jmp edi"
65
+
66
+ apireg = (opts[:depreg] || 'esi').downcase
67
+ apidest = opts[:depdest]
68
+ depsize = opts[:depsize]
69
+
70
+ freeregs = [ "esi", "ebp", "ecx", "ebx" ]
71
+
72
+ if opts[:depmethod]
73
+
74
+ if freeregs.index(apireg) == nil
75
+ getpointer << "mov #{freeregs[0]},#{apireg}\n\t"
76
+ apireg = freeregs[0]
77
+ end
78
+ freeregs.delete(apireg)
79
+
80
+ if opts[:depmethod].downcase == "copy" || opts[:depmethod].downcase == "copy_size"
81
+ if apidest
82
+ if freeregs.index(apidest) == nil
83
+ getpointer << "mov #{freeregs[0]},#{apidest}\n\t"
84
+ apidest = freeregs[0]
85
+ end
86
+ else
87
+ getpc = "fldpi\n\tfstenv [esp-0xc]\n\tpop #{freeregs[0]}\n\t"
88
+ apidest = freeregs[0]
89
+ end
90
+ freeregs.delete(apidest)
91
+ end
92
+
93
+
94
+ sizereg = freeregs[0]
95
+
96
+ if not depsize
97
+ depsize = payload.length * 2
98
+ if opts[:depmethod]
99
+ if opts[:depmethod].downcase == "copy_size"
100
+ depsize = payload.length
101
+ end
102
+ end
103
+ end
104
+
105
+
106
+ blockcnt = 0
107
+ vpsize = 0
108
+ blocksize = depsize
109
+ while blocksize >= 127
110
+ blocksize = blocksize / 2
111
+ blockcnt += 1
112
+ end
113
+ if blockcnt > 0
114
+ getsize << "xor #{sizereg},#{sizereg}\n\tadd #{sizereg},0x%02x\n\t" % blocksize
115
+ vpsize = blocksize
116
+ depblockcnt = 0
117
+ while depblockcnt < blockcnt
118
+ getsize << "add #{sizereg},#{sizereg}\n\t"
119
+ vpsize += vpsize
120
+ depblockcnt += 1
121
+ end
122
+ delta = depsize - vpsize
123
+ if delta > 0
124
+ getsize << "add #{sizereg},0x%02x\n\t" % delta
125
+ end
126
+ else
127
+ getsize << "xor #{sizereg},#{sizereg}\n\tadd #{sizereg},0x%02x\n\t" % depsize
128
+ end
129
+
130
+
131
+ case opts[:depmethod].downcase
132
+ when "virtualprotect"
133
+ jmppayload = "push esp\n\tpush 0x40\n\t"
134
+ jmppayload << getsize
135
+ jmppayload << "push #{sizereg}\n\tpush edi\n\tpush edi\n\tpush #{apireg}\n\tret"
136
+ when "copy"
137
+ jmppayload = getpc
138
+ jmppayload << "push edi\n\tpush #{apidest}\n\tpush #{apidest}\n\tpush #{apireg}\n\tmov edi,#{apidest}\n\tret"
139
+ when "copy_size"
140
+ jmppayload = getpc
141
+ jmppayload << getsize
142
+ jmppayload << "push #{sizereg}\n\tpush edi\n\tpush #{apidest}\n\tpush #{apidest}\n\tpush #{apireg}\n\tmov edi,#{apidest}\n\tret"
143
+ end
144
+ end
145
+
146
+ jmppayload << "\n" if jmppayload.length > 0
147
+
60
148
  assembly = <<EOS
149
+ #{getpointer}
61
150
  #{startstub}
62
151
  check_readable:
63
152
  or dx,0xfff
@@ -84,7 +173,7 @@ check_for_tag:
84
173
  #{checksum}
85
174
 
86
175
  ; jump to the payload
87
- jmp edi
176
+ #{jmppayload}
88
177
  EOS
89
178
 
90
179
  assembled_code = Metasm::Shellcode.assemble(Metasm::Ia32.new, assembly).encode_string
@@ -636,6 +636,12 @@ function getVersion(){
636
636
  os_flavor = "XP";
637
637
  os_sp = "SP3";
638
638
  break;
639
+ case "576000":
640
+ // IE 7.0.6000.16386, Vista Ultimate SP0 English
641
+ ua_version = "7.0";
642
+ os_flavor = "Vista";
643
+ os_sp = "SP0";
644
+ break;
639
645
  case "5822960":
640
646
  // IE 8.0.6001.18702, XP Professional SP3 Greek
641
647
  case "5818702":
@@ -650,6 +656,8 @@ function getVersion(){
650
656
  case "5816385":
651
657
  // IE 8.0.7600.16385, Windows 7 English
652
658
  case "5816475":
659
+ case "5816762":
660
+ // IE 8.0.7600.16385, Windows 7 English
653
661
  ua_version = "8.0";
654
662
  os_flavor = "7";
655
663
  os_sp = "SP0";
@@ -816,7 +824,7 @@ function ua_ver_cmp(ver_a, ver_b) {
816
824
 
817
825
  a = ver_a.split(".");
818
826
  b = ver_b.split(".");
819
- for (i = 0; i < Math.max(a.length, b.length); i++) {
827
+ for (var i = 0; i < Math.max(a.length, b.length); i++) {
820
828
  // 3.0 == 3
821
829
  if (!b[i]) { b[i] = "0"; }
822
830
  if (!a[i]) { a[i] = "0"; }
@@ -0,0 +1,134 @@
1
+
2
+ $:.unshift(File.join(File.dirname(__FILE__), '..', '..'))
3
+
4
+ require 'test/unit'
5
+ require 'rex/socket'
6
+ require 'rex/io/ring_buffer'
7
+
8
+ #
9
+ # TODO: Mock up the socket so this test doesn't take so long
10
+ #
11
+ class Rex::IO::RingBuffer::UnitTest < Test::Unit::TestCase
12
+
13
+ def setup
14
+ server = Rex::Socket.create_tcp_server('LocalPort' => 0)
15
+ lport = server.getsockname[2]
16
+ @client = Rex::Socket.create_tcp('PeerHost' => '127.0.0.1', 'PeerPort' => lport)
17
+ conn = server.accept
18
+ #server.close
19
+
20
+ @r = Rex::IO::RingBuffer.new(conn, {:size => 64})
21
+ @r.start_monitor
22
+ end
23
+
24
+ def teardown
25
+ begin
26
+ @client.close
27
+ @r.stop_monitor
28
+ rescue ::Exception
29
+ end
30
+ end
31
+
32
+ def test_single_read_data
33
+ @client.put("123")
34
+ @r.wait(0)
35
+ s,d = @r.read_data
36
+
37
+ assert_equal("123", d)
38
+ end
39
+
40
+ def test_sequential_read_data
41
+ @r.clear_data
42
+
43
+ s = nil
44
+ 0.upto(10) do |num|
45
+ @client.put(num.to_s)
46
+ @r.wait(s)
47
+ s,d = @r.read_data(s)
48
+ assert_equal(num.to_s, d)
49
+ end
50
+ end
51
+
52
+ def test_wrap
53
+ @r.clear_data
54
+ 0.upto(@r.size - 1) {
55
+ @client.put("a")
56
+ # Need to sleep so the socket doesn't get all the data in one read()
57
+ sleep 0.05
58
+ }
59
+ s,d = @r.read_data
60
+
61
+ @client.put("b")
62
+ sleep 0.01
63
+ s,d = @r.read_data(s)
64
+
65
+ assert_equal("b", d)
66
+
67
+ end
68
+
69
+ end
70
+ =begin
71
+ client.put("4")
72
+ client.put("5")
73
+ client.put("6")
74
+ s,d = r.read_data(s)
75
+
76
+ client.put("7")
77
+ client.put("8")
78
+ client.put("9")
79
+ s,d = r.read_data(s)
80
+
81
+ client.put("0")
82
+ s,d = r.read_data(s)
83
+
84
+ test_counter = 11
85
+ 1.upto(100) do
86
+ client.put( "X" )
87
+ test_counter += 1
88
+ end
89
+
90
+ sleep(1)
91
+
92
+ s,d = r.read_data
93
+ p s
94
+ p d
95
+
96
+ fdata = ''
97
+ File.open("/bin/ls", "rb") do |fd|
98
+ fdata = fd.read(fd.stat.size)
99
+ fdata = fdata * 10
100
+ client.put(fdata)
101
+ end
102
+
103
+ sleep(1)
104
+
105
+ s,vdata = r.read_data(s)
106
+
107
+ if vdata != fdata
108
+ puts "DATA FAILED"
109
+ else
110
+ puts "DATA VERIFIED"
111
+ end
112
+
113
+ r.clear_data
114
+
115
+ a = r.create_stream
116
+ b = r.create_stream
117
+
118
+ client.put("ABC123")
119
+ sleep(1)
120
+
121
+ p a.read
122
+ p b.read
123
+
124
+ client.put("$$$$$$")
125
+ sleep(1)
126
+
127
+ p a.read
128
+ p b.read
129
+
130
+ c = r.create_stream
131
+ p c.read
132
+
133
+ end
134
+ =end
@@ -1,3 +1,5 @@
1
+ require 'thread'
2
+
1
3
  module Rex
2
4
  module IO
3
5
 
@@ -61,6 +63,7 @@ module StreamServer
61
63
  #
62
64
  def start
63
65
  self.clients = []
66
+ self.client_waiter = ::Queue.new
64
67
 
65
68
  self.listener_thread = Rex::ThreadFactory.spawn("StreamServerListener", false) {
66
69
  monitor_listener
@@ -128,6 +131,7 @@ module StreamServer
128
131
 
129
132
  attr_accessor :clients # :nodoc:
130
133
  attr_accessor :listener_thread, :clients_thread # :nodoc:
134
+ attr_accessor :client_waiter
131
135
 
132
136
  protected
133
137
 
@@ -151,6 +155,9 @@ protected
151
155
 
152
156
  # Initialize the connection processing
153
157
  on_client_connect(cli)
158
+
159
+ # Notify the client monitor
160
+ self.client_waiter.push(cli)
154
161
 
155
162
  # Skip exceptions caused by accept() [ SSL ]
156
163
  rescue ::EOFError, ::Errno::ECONNRESET, ::Errno::ENOTCONN, ::Errno::ECONNABORTED
@@ -170,12 +177,14 @@ protected
170
177
  #
171
178
  def monitor_clients
172
179
  begin
180
+
181
+ # Wait for a notify if our client list is empty
173
182
  if (clients.length == 0)
174
- Rex::ThreadSafe::sleep(0.25)
183
+ self.client_waiter.pop
175
184
  next
176
185
  end
177
186
 
178
- sd = Rex::ThreadSafe.select(clients)
187
+ sd = Rex::ThreadSafe.select(clients, nil, nil, nil)
179
188
 
180
189
  sd[0].each { |cfd|
181
190
  begin
@@ -17,7 +17,8 @@ class NessusXMLStreamParser
17
17
  def reset_state
18
18
  @host = {'hname' => nil, 'addr' => nil, 'mac' => nil, 'os' => nil, 'ports' => [
19
19
  'port' => {'port' => nil, 'svc_name' => nil, 'proto' => nil, 'severity' => nil,
20
- 'nasl' => nil, 'description' => nil, 'cve' => [], 'bid' => [], 'xref' => [], 'msf' => nil } ] }
20
+ 'nasl' => nil, 'nasl_name' => nil, 'description' => nil,
21
+ 'cve' => [], 'bid' => [], 'xref' => [], 'msf' => nil } ] }
21
22
  @state = :generic_state
22
23
  end
23
24
 
@@ -46,7 +47,8 @@ class NessusXMLStreamParser
46
47
  @bid = Array.new
47
48
  @xref = Array.new
48
49
  @x = Hash.new
49
- @x['nasl'] = [attributes['pluginID'],attributes['pluginName']].join(" ")
50
+ @x['nasl'] = attributes['pluginID']
51
+ @x['nasl_name'] = attributes['pluginName']
50
52
  @x['port'] = attributes['port']
51
53
  @x['proto'] = attributes['protocol']
52
54
  @x['svc_name'] = attributes['svc_name']
@@ -13,8 +13,16 @@ class NexposeXMLStreamParser
13
13
 
14
14
  def reset_state
15
15
  @state = :generic_state
16
- @host = { "status" => nil, "endpoints" => [], "names" => [], "vulns" => {} }
17
- @vuln = { "refs" => [] }
16
+ @only_vuln_states_needed = true
17
+ @current_vuln_id = nil
18
+ @vulnerable_markers = ['vulnerable-exploited', 'vulnerable-version', 'potential']
19
+ @host = {"status" => nil, "endpoints" => [], "names" => [], "vulns" => {}}
20
+ @vuln = {"refs" => [], "description" => [], "solution" => []}
21
+ end
22
+
23
+ # If all vuln states are required set this to false
24
+ def parse_vulnerable_states_only only_vuln_states_needed
25
+ @only_vuln_states_needed = only_vuln_states_needed
18
26
  end
19
27
 
20
28
  def tag_start(name, attributes)
@@ -48,19 +56,31 @@ class NexposeXMLStreamParser
48
56
  if @state == :in_service
49
57
  @host["endpoints"].last.merge!(attributes)
50
58
  end
51
- when "test"
52
- if attributes["status"] == "vulnerable-exploited" or attributes["status"] == "vulnerable-version"
53
- @host["vulns"][attributes["id"]] = attributes.dup
54
- if attributes["key"]
55
- @host["notes"] ||= []
56
- @host["notes"] << [attributes["id"], attributes["key"]]
59
+ when "test"
60
+ if (not @only_vuln_states_needed) or (@vulnerable_markers.include? attributes["status"].to_s.chomp and @only_vuln_states_needed)
61
+ @state = :in_test
62
+ @current_vuln_id = attributes["id"]
63
+ @host["vulns"][@current_vuln_id] = attributes.dup
64
+ # Append the endpoint info for how the vuln was discovered
65
+ unless @host["endpoints"].empty?
66
+ @host["vulns"][@current_vuln_id].merge!("endpoint_data" => @host["endpoints"].last)
67
+ end
68
+ if attributes["key"]
69
+ @host["notes"] ||= []
70
+ @host["notes"] << [@current_vuln_id, attributes["key"]]
71
+ end
57
72
  end
58
- end
59
- when "vulnerability"
60
- @vuln.merge! attributes
61
- when "reference"
62
- @state = :in_reference
63
- @vuln["refs"].push attributes
73
+ when "vulnerability"
74
+ @vuln.merge! attributes
75
+ when "reference"
76
+ @state = :in_reference
77
+ @vuln["refs"].push attributes
78
+ when "solution"
79
+ @state = :in_solution
80
+ when "description"
81
+ @state = :in_description
82
+ when "URLLink"
83
+ @vuln["solution"] << attributes
64
84
  end
65
85
  end
66
86
 
@@ -70,7 +90,17 @@ class NexposeXMLStreamParser
70
90
  @host["names"].push str
71
91
  when :in_reference
72
92
  @vuln["refs"].last["value"] = str
73
- end
93
+ when :in_solution
94
+ @vuln["solution"] << str
95
+ when :in_description
96
+ @vuln["description"] << str
97
+ when :in_test
98
+ if @host["vulns"][@current_vuln_id]
99
+ proof = @host["vulns"][@current_vuln_id]["proof"] || []
100
+ proof << str
101
+ @host["vulns"][@current_vuln_id]["proof"] = proof
102
+ end
103
+ end
74
104
  end
75
105
 
76
106
  def tag_end(name)
@@ -0,0 +1,385 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)),"nokogiri_doc_mixin")
2
+
3
+ module Rex
4
+ module Parser
5
+
6
+ # If Nokogiri is available, define Nmap document class.
7
+ load_nokogiri && class NmapDocument < Nokogiri::XML::SAX::Document
8
+
9
+ include NokogiriDocMixin
10
+
11
+ def determine_port_state(v)
12
+ case v
13
+ when "open"
14
+ Msf::ServiceState::Open
15
+ when "closed"
16
+ Msf::ServiceState::Closed
17
+ when "filtered"
18
+ Msf::ServiceState::Filtered
19
+ when "unknown"
20
+ Msf::ServiceState::Unknown
21
+ end
22
+ end
23
+
24
+ # Compare OS fingerprinting data
25
+ def better_os_match(orig_hash,new_hash)
26
+ return false unless new_hash.has_key? "accuracy"
27
+ return true unless orig_hash.has_key? "accuracy"
28
+ new_hash["accuracy"].to_i > orig_hash["accuracy"].to_i
29
+ end
30
+
31
+ # Triggered every time a new element is encountered. We keep state
32
+ # ourselves with the @state variable, turning things on when we
33
+ # get here (and turning things off when we exit in end_element()).
34
+ def start_element(name=nil,attrs=[])
35
+ attrs = normalize_attrs(attrs)
36
+ block = @block
37
+ @state[:current_tag][name] = true
38
+ case name
39
+ when "host"
40
+ @state[:in_host] = true
41
+ when "os"
42
+ if @state[:in_host]
43
+ @state[:in_os] = true
44
+ end
45
+ when "status"
46
+ record_host_status(attrs)
47
+ when "address"
48
+ record_address(attrs)
49
+ when "osclass"
50
+ record_host_osclass(attrs)
51
+ when "osmatch"
52
+ record_host_osmatch(attrs)
53
+ when "uptime"
54
+ record_host_uptime(attrs)
55
+ when "hostname"
56
+ record_hostname(attrs)
57
+ when "port"
58
+ record_port(attrs)
59
+ when "state"
60
+ record_port_state(attrs)
61
+ when "service"
62
+ record_port_service(attrs)
63
+ when "script" # Not actually used in import?
64
+ record_port_script(attrs)
65
+ record_host_script(attrs)
66
+ # Ignoring post scripts completely
67
+ when "trace"
68
+ record_host_trace(attrs)
69
+ when "hop"
70
+ record_host_hop(attrs)
71
+ end
72
+ end
73
+
74
+ # We can certainly get fancier with self.send() magic, but
75
+ # leaving this pretty simple for now.
76
+
77
+ def record_host_hop(attrs)
78
+ return unless @state[:in_host]
79
+ return unless @state[:in_trace]
80
+ hops = attr_hash(attrs)
81
+ hops["name"] = hops.delete "host"
82
+ @state[:trace][:hops] << hops
83
+ end
84
+
85
+ def record_host_trace(attrs)
86
+ return unless @state[:in_host]
87
+ @state[:in_trace] = true
88
+ @state[:trace] = attr_hash(attrs)
89
+ @state[:trace][:hops] = []
90
+ end
91
+
92
+ def record_host_uptime(attrs)
93
+ return unless @state[:in_host]
94
+ @state[:uptime] = attr_hash(attrs)
95
+ end
96
+
97
+ def record_host_osmatch(attrs)
98
+ return unless @state[:in_host]
99
+ return unless @state[:in_os]
100
+ temp_hash = attr_hash(attrs)
101
+ if temp_hash["accuracy"].to_i == 100
102
+ @state[:os]["osmatch"] = temp_hash["name"]
103
+ end
104
+ end
105
+
106
+ def record_host_osclass(attrs)
107
+ return unless @state[:in_host]
108
+ return unless @state[:in_os]
109
+ @state[:os] ||= {}
110
+ temp_hash = attr_hash(attrs)
111
+ if better_os_match(@state[:os],temp_hash)
112
+ @state[:os] = temp_hash
113
+ end
114
+ end
115
+
116
+ def record_hostname(attrs)
117
+ return unless @state[:in_host]
118
+ if attr_hash(attrs)["type"] == "PTR"
119
+ @state[:hostname] = attr_hash(attrs)["name"]
120
+ end
121
+ end
122
+
123
+ def record_host_script(attrs)
124
+ return unless @state[:in_host]
125
+ return if @state[:in_port]
126
+ temp_hash = attr_hash(attrs)
127
+ @state[:hostscripts] ||= {}
128
+ @state[:hostscripts].merge! temp_hash
129
+ temp_hash[:addresses] = @state[:addresses]
130
+ db.emit(:host_script,temp_hash,&block) if block
131
+ end
132
+
133
+ def record_port_script(attrs)
134
+ return unless @state[:in_host]
135
+ return unless @state[:in_port]
136
+ temp_hash = attr_hash(attrs)
137
+ @state[:portscripts] ||= {}
138
+ @state[:portscripts].merge! temp_hash
139
+ temp_hash[:addresses] = @state[:addresses]
140
+ temp_hash[:port] = @state[:port]
141
+ db.emit(:port_script,temp_hash,&block) if block
142
+ end
143
+
144
+ def record_port_service(attrs)
145
+ return unless @state[:in_host]
146
+ return unless @state[:in_port]
147
+ svc = attr_hash(attrs)
148
+ if svc["name"] && @args[:fix_services]
149
+ svc["name"] = db.nmap_msf_service_map(svc["name"])
150
+ end
151
+ @state[:port] = @state[:port].merge(svc)
152
+ end
153
+
154
+ def record_port_state(attrs)
155
+ return unless @state[:in_host]
156
+ return unless @state[:in_port]
157
+ temp_hash = attr_hash(attrs)
158
+ @state[:port] = @state[:port].merge(temp_hash)
159
+ end
160
+
161
+ def record_port(attrs)
162
+ return unless @state[:in_host]
163
+ @state[:in_port] = true
164
+ @state[:port] ||= {}
165
+ svc = attr_hash(attrs)
166
+ @state[:port] = @state[:port].merge(svc)
167
+ end
168
+
169
+ def record_host_status(attrs)
170
+ return unless @state[:in_host]
171
+ attrs.each do |k,v|
172
+ next unless k == "state"
173
+ @state[:host_alive] = (v == "up")
174
+ end
175
+ end
176
+
177
+ def record_address(attrs)
178
+ return unless @state[:in_host]
179
+ @state[:addresses] ||= {}
180
+ address = nil
181
+ type = nil
182
+ attrs.each do |k,v|
183
+ if k == "addr"
184
+ address = v
185
+ elsif k == "addrtype"
186
+ type = v
187
+ end
188
+ end
189
+ @state[:addresses][type] = address
190
+ end
191
+
192
+ # When we exit a tag, this is triggered.
193
+ def end_element(name=nil)
194
+ block = @block
195
+ @state[:current_tag].delete name
196
+ case name
197
+ when "os"
198
+ collect_os_data
199
+ @state[:in_os] = false
200
+ @state[:os] = {}
201
+ when "port"
202
+ collect_port_data
203
+ @state[:in_port] = false
204
+ @state[:port] = {}
205
+ when "script"
206
+ if @state[:in_host]
207
+ if @state[:in_port]
208
+ @state[:portscripts] = {}
209
+ else
210
+ @state[:hostscripts] = {}
211
+ end
212
+ end
213
+ when "trace"
214
+ @state[:in_trace] = false
215
+ when "host" # Roll everything up now
216
+ collect_host_data
217
+ host_object = report_host &block
218
+ if host_object
219
+ db.report_import_note(@args[:wspace],host_object)
220
+ report_services(host_object,&block)
221
+ report_fingerprint(host_object)
222
+ report_uptime(host_object)
223
+ report_traceroute(host_object)
224
+ end
225
+ @state.delete_if {|k| k != :current_tag}
226
+ end
227
+ end
228
+
229
+ def end_document
230
+ block = @block
231
+ unless @state[:current_tag].empty?
232
+ missing_ends = @state[:current_tag].keys.map {|x| "'#{x}'"}.join(", ")
233
+ msg = "Warning, the provided file is incomplete, and there may be missing\n"
234
+ msg << "data. The following tags were not closed: #{missing_ends}."
235
+ db.emit(:warning,msg,&block)
236
+ end
237
+ end
238
+
239
+ def collect_os_data
240
+ return unless @state[:in_host]
241
+ if @state[:os]
242
+ @report_data[:os_fingerprint] = {
243
+ :type => "host.os.nmap_fingerprint",
244
+ :data => {
245
+ :os_vendor => @state[:os]["vendor"],
246
+ :os_family => @state[:os]["osfamily"],
247
+ :os_version => @state[:os]["osgen"],
248
+ :os_accuracy => @state[:os]["accuracy"].to_i
249
+ }
250
+ }
251
+ if @state[:os].has_key? "osmatch"
252
+ @report_data[:os_fingerprint][:data][:os_match] = @state[:os]["osmatch"]
253
+ end
254
+ end
255
+ end
256
+
257
+ def collect_host_data
258
+ if @state[:host_alive]
259
+ @report_data[:state] = Msf::HostState::Alive
260
+ else
261
+ @report_data[:state] = Msf::HostState::Dead
262
+ end
263
+ if @state[:addresses]
264
+ if @state[:addresses].has_key? "ipv4"
265
+ @report_data[:host] = @state[:addresses]["ipv4"]
266
+ elsif @state[:addresses].has_key? "ipv6"
267
+ @report_data[:host] = @state[:addresses]["ipv6"]
268
+ end
269
+ end
270
+ if @state[:addresses] and @state[:addresses].has_key?("mac")
271
+ @report_data[:mac] = @state[:addresses]["mac"]
272
+ end
273
+ if @state[:hostname]
274
+ @report_data[:name] = @state[:hostname]
275
+ end
276
+ if @state[:uptime]
277
+ @report_data[:last_boot] = @state[:uptime]["lastboot"]
278
+ end
279
+ if @state[:trace] and @state[:trace].has_key?(:hops)
280
+ @report_data[:traceroute] = @state[:trace]
281
+ end
282
+ end
283
+
284
+ def collect_port_data(&block)
285
+ return unless @state[:in_host]
286
+ if @args[:fix_services]
287
+ if @state[:port]["state"] == "filtered"
288
+ return
289
+ end
290
+ end
291
+ @report_data[:ports] ||= []
292
+ port_hash = {}
293
+ extra = []
294
+ @state[:port].each do |k,v|
295
+ case k
296
+ when "protocol"
297
+ port_hash[:protocol] = v
298
+ when "portid"
299
+ port_hash[:port] = v
300
+ when "state"
301
+ port_hash[:state] = determine_port_state(v)
302
+ when "name"
303
+ port_hash[:name] = v
304
+ when "reason"
305
+ port_hash[:reason] = v
306
+ when "product"
307
+ extra[0] = v
308
+ when "version"
309
+ extra[1] = v
310
+ when "extrainfo"
311
+ extra[2] = v
312
+ end
313
+ end
314
+ port_hash[:info] = extra.compact.join(" ") unless extra.empty?
315
+ # Skip localhost port results when they're unknown
316
+ if( port_hash[:reason] == "localhost-response" &&
317
+ port_hash[:state] == Msf::ServiceState::Unknown )
318
+ @report_data[:ports]
319
+ else
320
+ @report_data[:ports] << port_hash
321
+ end
322
+ end
323
+
324
+ def report_traceroute(host_object)
325
+ return unless host_object.kind_of? ::Msf::DBManager::Host
326
+ return unless @report_data[:traceroute]
327
+ db.report_note(
328
+ :workspace => host_object.workspace,
329
+ :host => host_object,
330
+ :type => "host.nmap.traceroute",
331
+ :data => {
332
+ 'port' => @report_data[:traceroute]["port"].to_i,
333
+ 'proto' => @report_data[:traceroute]["proto"].to_s,
334
+ 'hops' => @report_data[:traceroute][:hops]
335
+ }
336
+ )
337
+ end
338
+
339
+ def report_uptime(host_object)
340
+ return unless host_object.kind_of? ::Msf::DBManager::Host
341
+ return unless @report_data[:last_boot]
342
+ db.report_note(
343
+ :workspace => host_object.workspace,
344
+ :host => host_object,
345
+ :type => "host.last_boot",
346
+ :data => { :time => @report_data[:last_boot] }
347
+ )
348
+ end
349
+
350
+ def report_fingerprint(host_object)
351
+ return unless host_object.kind_of? ::Msf::DBManager::Host
352
+ return unless @report_data[:os_fingerprint]
353
+ db.report_note(
354
+ @report_data[:os_fingerprint].merge(
355
+ :workspace => host_object.workspace,
356
+ :host => host_object
357
+ )
358
+ )
359
+ end
360
+
361
+ def report_host(&block)
362
+ if host_is_okay
363
+ host_object = db.report_host( @report_data.merge(
364
+ :workspace => @args[:wspace] ) )
365
+ db.emit(:address,@report_data[:host],&block) if block
366
+ host_object
367
+ end
368
+ end
369
+
370
+ def report_services(host_object,&block)
371
+ return unless host_object.kind_of? ::Msf::DBManager::Host
372
+ return unless @report_data[:ports]
373
+ return if @report_data[:ports].empty?
374
+ reported = []
375
+ @report_data[:ports].each do |svc|
376
+ reported << db.report_service(svc.merge(:host => host_object))
377
+ end
378
+ reported
379
+ end
380
+
381
+ end
382
+
383
+ end
384
+ end
385
+