nmap-parser 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/BUGS +3 -1
- data/LICENSE +1 -1
- data/README +5 -4
- data/examples/listopentcp.rb +20 -0
- data/examples/services.rb +29 -0
- data/lib/nmap/parser.rb +151 -262
- metadata +4 -2
data/BUGS
CHANGED
data/LICENSE
CHANGED
data/README
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
== Kris Katterjohn katterjohn@gmail.com ==
|
4
4
|
===============================================================================
|
5
5
|
|
6
|
-
$Id: README
|
6
|
+
$Id: README 126 2009-02-08 15:32:04Z kjak $
|
7
7
|
|
8
8
|
|
9
9
|
OVERVIEW
|
@@ -13,10 +13,11 @@ This library provides a Ruby interface to Nmap's scan data. It can run Nmap
|
|
13
13
|
and parse its XML output directly from the scan, parse a file containing the
|
14
14
|
XML data from a separate scan, parse a String of XML data from a scan, or parse
|
15
15
|
XML data from an object via its read() method. This information is presented
|
16
|
-
in an easy-to-use and intuitive fashion for
|
16
|
+
in an easy-to-use and intuitive fashion for storage and manipulation.
|
17
17
|
|
18
|
-
|
19
|
-
are more classes, many different methods, and blocks are
|
18
|
+
Keep in mind that this is not just some Ruby port of Anthony Persaud's Perl
|
19
|
+
Nmap::Parser! There are more classes, many different methods, and blocks are
|
20
|
+
extensively available.
|
20
21
|
|
21
22
|
|
22
23
|
REQUIREMENTS and RECOMMENDATIONS
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#
|
3
|
+
# Very simple script to print out the open TCP ports for each host
|
4
|
+
#
|
5
|
+
# Kris Katterjohn 01/27/2009
|
6
|
+
|
7
|
+
require 'nmap/parser'
|
8
|
+
|
9
|
+
p = Nmap::Parser.parsescan("nmap", "192.168.11.0/24")
|
10
|
+
|
11
|
+
p.hosts("up") do |host|
|
12
|
+
puts "#{host.addr}:"
|
13
|
+
|
14
|
+
host.tcp_ports("open") do |port|
|
15
|
+
puts "Got #{port.num}/tcp"
|
16
|
+
end
|
17
|
+
|
18
|
+
puts
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#
|
3
|
+
# A really simplistic script which prints out service information for the
|
4
|
+
# open TCP and UDP ports found by scanning a host
|
5
|
+
#
|
6
|
+
# Kris Katterjohn 01/27/2009
|
7
|
+
|
8
|
+
require 'nmap/parser'
|
9
|
+
|
10
|
+
def printport(port, proto)
|
11
|
+
srv = port.service
|
12
|
+
|
13
|
+
puts
|
14
|
+
puts "Port ##{port.num}/#{proto} is open (#{port.reason})"
|
15
|
+
puts "\tService: #{srv.name}" if srv.name
|
16
|
+
puts "\tProduct: #{srv.product}" if srv.product
|
17
|
+
puts "\tVersion: #{srv.version}" if srv.version
|
18
|
+
puts
|
19
|
+
end
|
20
|
+
|
21
|
+
p = Nmap::Parser.parsescan("sudo nmap", "-sSUV 192.168.11.1")
|
22
|
+
|
23
|
+
p.hosts("up") do |host|
|
24
|
+
puts "#{host.addr}:"
|
25
|
+
host.tcp_ports("open") { |port| printport(port, "tcp") }
|
26
|
+
host.udp_ports("open") { |port| printport(port, "udp") }
|
27
|
+
puts
|
28
|
+
end
|
29
|
+
|
data/lib/nmap/parser.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
#
|
5
5
|
# Author: Kris Katterjohn <katterjohn@gmail.com>
|
6
6
|
#
|
7
|
-
# Copyright (c) 2007
|
7
|
+
# Copyright (c) 2007-2009 Kris Katterjohn
|
8
8
|
#
|
9
9
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
10
10
|
# of this software and associated documentation files (the "Software"), to deal
|
@@ -24,7 +24,7 @@
|
|
24
24
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
25
25
|
# THE SOFTWARE.
|
26
26
|
|
27
|
-
# $Id: parser.rb
|
27
|
+
# $Id: parser.rb 129 2009-02-08 17:14:39Z kjak $
|
28
28
|
# https://rubynmap.svn.sourceforge.net/svnroot/rubynmap
|
29
29
|
|
30
30
|
require 'rexml/document'
|
@@ -32,7 +32,7 @@ require 'rexml/document'
|
|
32
32
|
begin
|
33
33
|
require 'open3'
|
34
34
|
rescue LoadError
|
35
|
-
# We'll
|
35
|
+
# We'll just use IO.popen()
|
36
36
|
end
|
37
37
|
|
38
38
|
# Just holds the big Parser class.
|
@@ -47,12 +47,13 @@ This library provides a Ruby interface to Nmap's scan data. It can run Nmap
|
|
47
47
|
and parse its XML output directly from the scan, parse a file containing the
|
48
48
|
XML data from a separate scan, parse a String of XML data from a scan, or parse
|
49
49
|
XML data from an object via its read() method. This information is presented
|
50
|
-
in an easy-to-use and intuitive fashion for
|
50
|
+
in an easy-to-use and intuitive fashion for storage and manipulation.
|
51
51
|
|
52
|
-
|
53
|
-
are more classes, many different methods, and blocks are
|
52
|
+
Keep in mind that this is not just some Ruby port of Anthony Persaud's Perl
|
53
|
+
Nmap::Parser! There are more classes, many different methods, and blocks are
|
54
|
+
extensively available.
|
54
55
|
|
55
|
-
The Nmap Security Scanner is
|
56
|
+
The Nmap Security Scanner is an awesome program written and maintained by
|
56
57
|
Fyodor <fyodor@insecure.org>. Its main function is port scanning, but it also
|
57
58
|
has service and operating system detection, its own scripting engine and a
|
58
59
|
whole lot more. One of its many available output formats is XML, which allows
|
@@ -88,7 +89,7 @@ is given.
|
|
88
89
|
|
|
89
90
|
+ Script <- NSE Script information (both host and port)
|
90
91
|
|
|
91
|
-
+ Times <- Timimg information (
|
92
|
+
+ Times <- Timimg information (round-trip time, etc)
|
92
93
|
|
|
93
94
|
+ Traceroute <- General Traceroute information
|
94
95
|
| |
|
@@ -104,7 +105,8 @@ is given.
|
|
104
105
|
|
105
106
|
require 'nmap/parser'
|
106
107
|
|
107
|
-
parser = Nmap::Parser.
|
108
|
+
parser = Nmap::Parser.parsestring(xml) # String of XML
|
109
|
+
parser = Nmap::Parser.new(xml) # Same thing
|
108
110
|
|
109
111
|
== Reading and Parsing from a File
|
110
112
|
|
@@ -115,7 +117,7 @@ is given.
|
|
115
117
|
== Reading and Parsing from an Object
|
116
118
|
|
117
119
|
This method can read from any object that responds to a read() method that
|
118
|
-
returns a String
|
120
|
+
returns a String.
|
119
121
|
|
120
122
|
require 'nmap/parser'
|
121
123
|
|
@@ -123,7 +125,7 @@ returns a String: $stdin is just one example.
|
|
123
125
|
|
124
126
|
== Scanning and Parsing
|
125
127
|
|
126
|
-
This is the only
|
128
|
+
This is the only Parser method that requires Nmap to be available.
|
127
129
|
|
128
130
|
require 'nmap/parser'
|
129
131
|
|
@@ -132,48 +134,30 @@ This is the only parser method that requires Nmap to be available.
|
|
132
134
|
== Actually Doing Something
|
133
135
|
|
134
136
|
After printing a little session information, this example will cycle
|
135
|
-
through all of the up hosts, printing service information on
|
136
|
-
open TCP ports
|
137
|
-
|
137
|
+
through all of the up hosts, printing state and service information on
|
138
|
+
the open TCP ports. See the examples directory that comes with this
|
139
|
+
library for more examples.
|
138
140
|
|
139
141
|
puts "Nmap args: #{parser.session.scan_args}"
|
140
142
|
puts "Runtime: #{parser.session.scan_time} seconds"
|
141
143
|
puts
|
142
144
|
|
143
145
|
parser.hosts("up") do |host|
|
144
|
-
puts "
|
146
|
+
puts "#{host.addr} is up:"
|
145
147
|
puts
|
146
148
|
|
147
149
|
host.tcp_ports("open") do |port|
|
148
150
|
srv = port.service
|
149
151
|
|
150
|
-
puts "Port ##{port.num} is open (#{port.reason})"
|
152
|
+
puts "Port ##{port.num}/tcp is open (#{port.reason})"
|
151
153
|
puts "\tService: #{srv.name}" if srv.name
|
152
154
|
puts "\tProduct: #{srv.product}" if srv.product
|
153
155
|
puts "\tVersion: #{srv.version}" if srv.version
|
154
156
|
puts
|
155
|
-
|
156
|
-
port.scripts do |script|
|
157
|
-
puts "\tScript Name: #{script.id}"
|
158
|
-
puts "\tScript Output: #{script.output}"
|
159
|
-
puts
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
if host.scripts.any?
|
164
|
-
puts "Host Scripts Run:"
|
165
|
-
puts
|
166
|
-
|
167
|
-
host.scripts do |script|
|
168
|
-
puts "\tScript Name: #{script.id}"
|
169
|
-
puts "\tScript Output: #{script.output}"
|
170
|
-
puts
|
171
|
-
end
|
172
157
|
end
|
173
158
|
|
174
159
|
puts
|
175
160
|
end
|
176
|
-
|
177
161
|
=end
|
178
162
|
class Nmap::Parser
|
179
163
|
# Holds the raw XML output from Nmap
|
@@ -189,36 +173,38 @@ class Nmap::Parser
|
|
189
173
|
# one is given
|
190
174
|
def self.parseread(obj) # :yields: parser
|
191
175
|
if not obj.respond_to?("read")
|
192
|
-
raise "
|
176
|
+
raise "Passed object must respond to read()"
|
193
177
|
end
|
194
178
|
|
195
179
|
r = obj.read
|
196
180
|
|
197
|
-
if not r.is_a?String
|
198
|
-
raise "read()
|
181
|
+
if not r.is_a?(String)
|
182
|
+
raise "Passed object's read() must return a String (got #{r.class})"
|
199
183
|
end
|
200
184
|
|
201
|
-
|
202
|
-
|
203
|
-
yield p if block_given?
|
204
|
-
|
205
|
-
p
|
185
|
+
new(r) { |p| yield p if block_given? }
|
206
186
|
end
|
207
187
|
|
208
|
-
# Read and parse contents of the Nmap XML file +filename+
|
188
|
+
# Read and parse the contents of the Nmap XML file +filename+
|
209
189
|
#
|
210
190
|
# Returns a new Nmap::Parser object, and passes it to a block if
|
211
191
|
# one is given
|
212
192
|
def self.parsefile(filename) # :yields: parser
|
213
193
|
begin
|
214
|
-
|
194
|
+
File.open(filename) { |f|
|
195
|
+
parseread(f) { |p| yield p if block_given? }
|
196
|
+
}
|
215
197
|
rescue
|
216
198
|
raise "Error parsing \"#{filename}\": #{$!}"
|
217
199
|
end
|
200
|
+
end
|
218
201
|
|
219
|
-
|
220
|
-
|
221
|
-
|
202
|
+
# Read and parse the String of XML. Currently an alias for new().
|
203
|
+
#
|
204
|
+
# Returns a new Nmap::Parser object, and passes it to a block if
|
205
|
+
# one is given
|
206
|
+
def self.parsestring(str) # :yields: parser
|
207
|
+
new(str) { |p| yield p if block_given? }
|
222
208
|
end
|
223
209
|
|
224
210
|
# Runs "+nmap+ -d +args+ +targets+"; returns a new Nmap::Parser object,
|
@@ -316,14 +302,9 @@ class Nmap::Parser
|
|
316
302
|
#
|
317
303
|
# If an argument is given, only hosts matching +status+ are given
|
318
304
|
def get_ips(status = "") # :yields: host.addr
|
319
|
-
ips =
|
305
|
+
ips = hosts(status).map { |h| h.addr }
|
320
306
|
|
321
|
-
|
322
|
-
if status.empty? or host.status == status
|
323
|
-
ips << host.addr
|
324
|
-
yield host.addr if block_given?
|
325
|
-
end
|
326
|
-
end
|
307
|
+
ips.each { |ip| yield host.addr } if block_given?
|
327
308
|
|
328
309
|
ips
|
329
310
|
end
|
@@ -336,8 +317,8 @@ class Nmap::Parser
|
|
336
317
|
private
|
337
318
|
|
338
319
|
def initialize(xml) # :yields: parser
|
339
|
-
if not xml.is_a?String
|
340
|
-
raise "
|
320
|
+
if not xml.is_a?(String)
|
321
|
+
raise "Must be passed a String (got #{xml.class})"
|
341
322
|
end
|
342
323
|
|
343
324
|
parse(xml)
|
@@ -377,7 +358,7 @@ class Nmap::Parser::Session
|
|
377
358
|
attr_reader :start_str, :start_time
|
378
359
|
# Ending time
|
379
360
|
attr_reader :stop_str, :stop_time
|
380
|
-
#
|
361
|
+
# Total scan time in seconds (can differ from stop_time - start_time)
|
381
362
|
attr_reader :scan_time
|
382
363
|
# Amount of verbosity (-v) used while scanning
|
383
364
|
attr_reader :verbose
|
@@ -456,7 +437,7 @@ class Nmap::Parser::Session
|
|
456
437
|
@stop_str = root.elements['runstats/finished'].attributes['timestr']
|
457
438
|
@stop_time = root.elements['runstats/finished'].attributes['time'].to_i
|
458
439
|
|
459
|
-
@scan_time =
|
440
|
+
@scan_time = root.elements['runstats/finished'].attributes['elapsed'].to_f
|
460
441
|
|
461
442
|
@verbose = root.elements['verbose'].attributes['level'].to_i
|
462
443
|
@debug = root.elements['debugging'].attributes['level'].to_i
|
@@ -536,11 +517,7 @@ class Nmap::Parser::Host
|
|
536
517
|
# Returns an array containing all of the hostnames for this host,
|
537
518
|
# and passes them each to a block if one is given
|
538
519
|
def all_hostnames
|
539
|
-
if block_given?
|
540
|
-
@hostnames.each do |hostname|
|
541
|
-
yield hostname
|
542
|
-
end
|
543
|
-
end
|
520
|
+
@hostnames.each { |hostname| yield hostname } if block_given?
|
544
521
|
|
545
522
|
@hostnames
|
546
523
|
end
|
@@ -554,12 +531,8 @@ class Nmap::Parser::Host
|
|
554
531
|
|
555
532
|
# Returns an array of ExtraPorts objects, and passes them each to a
|
556
533
|
# block if one if given
|
557
|
-
def extraports
|
558
|
-
if block_given?
|
559
|
-
@extraports.each do |extraports|
|
560
|
-
yield extraports
|
561
|
-
end
|
562
|
-
end
|
534
|
+
def extraports # :yields: extraports
|
535
|
+
@extraports.each { |e| yield e } if block_given?
|
563
536
|
|
564
537
|
@extraports
|
565
538
|
end
|
@@ -567,26 +540,25 @@ class Nmap::Parser::Host
|
|
567
540
|
# Returns the Port object for the TCP port +portnum+, and passes it to
|
568
541
|
# a block if one is given
|
569
542
|
def tcp_port(portnum) # :yields: port
|
570
|
-
|
571
|
-
|
572
|
-
|
543
|
+
port = @tcpPorts[portnum.to_i]
|
544
|
+
yield port if block_given?
|
545
|
+
port
|
573
546
|
end
|
574
547
|
|
575
548
|
# Returns an array of Port objects for each TCP port, and passes them
|
576
549
|
# each to a block if one is given
|
577
550
|
#
|
578
|
-
# If an argument is given, only ports matching +state+ are given.
|
579
|
-
#
|
551
|
+
# If an argument is given, only ports matching +state+ are given. Note
|
552
|
+
# that combinations like "open|filtered" will get matched by "open" and
|
553
|
+
# "filtered"
|
580
554
|
def tcp_ports(state = "")
|
581
|
-
list = @tcpPorts.
|
582
|
-
state.empty? or
|
555
|
+
list = @tcpPorts.values.find_all { |port|
|
556
|
+
state.empty? or
|
557
|
+
port.state == state or
|
558
|
+
port.state.split(/\|/).include?(state)
|
583
559
|
}.sort
|
584
560
|
|
585
|
-
if block_given?
|
586
|
-
list.each do |port|
|
587
|
-
yield port
|
588
|
-
end
|
589
|
-
end
|
561
|
+
list.each { |port| yield port } if block_given?
|
590
562
|
|
591
563
|
list
|
592
564
|
end
|
@@ -595,94 +567,79 @@ class Nmap::Parser::Host
|
|
595
567
|
# if one given
|
596
568
|
#
|
597
569
|
# If an argument is given, only ports matching +state+ are given.
|
598
|
-
# Note: "open" will also match "open|filtered", but not vice versa.
|
599
570
|
def tcp_port_list(state = "")
|
600
|
-
list =
|
601
|
-
|
602
|
-
}.compact.sort
|
603
|
-
|
604
|
-
if block_given?
|
605
|
-
list.each do |port|
|
606
|
-
yield port
|
607
|
-
end
|
608
|
-
end
|
609
|
-
|
571
|
+
list = tcp_ports(state).map { |p| p.num }
|
572
|
+
list.each { |port| yield port } if block_given?
|
610
573
|
list
|
611
574
|
end
|
612
575
|
|
613
576
|
# Returns the state reason of TCP port +portnum+
|
614
577
|
def tcp_reason(portnum)
|
615
|
-
|
616
|
-
|
617
|
-
|
578
|
+
port = tcp_port(portnum)
|
579
|
+
return nil if port.nil?
|
580
|
+
port.reason
|
618
581
|
end
|
619
582
|
|
620
583
|
# Returns the Script object for the script +name+ run against the
|
621
584
|
# TCP port +portnum+
|
622
585
|
def tcp_script(portnum, name)
|
623
|
-
|
624
|
-
|
625
|
-
|
586
|
+
port = tcp_port(portnum)
|
587
|
+
return nil if port.nil?
|
588
|
+
port.script(name)
|
626
589
|
end
|
627
590
|
|
628
591
|
# Returns an array of Script objects for each script run on the
|
629
592
|
# TCP port +portnum+, and passes them each to a block if given
|
630
|
-
def tcp_scripts(portnum)
|
631
|
-
|
632
|
-
|
633
|
-
if block_given?
|
634
|
-
|
635
|
-
yield script
|
636
|
-
end
|
637
|
-
end
|
638
|
-
|
639
|
-
@tcpPorts[portnum.to_s].scripts
|
593
|
+
def tcp_scripts(portnum) # :yields: script
|
594
|
+
port = tcp_port(portnum)
|
595
|
+
return nil if port.nil?
|
596
|
+
port.scripts { |s| yield s } if block_given?
|
597
|
+
port.scripts
|
640
598
|
end
|
641
599
|
|
642
600
|
# Returns the output of the script +name+ on the TCP port +portnum+
|
643
601
|
def tcp_script_output(portnum, name)
|
644
|
-
|
645
|
-
|
646
|
-
|
602
|
+
port = tcp_port(portnum)
|
603
|
+
return nil if port.nil?
|
604
|
+
port.script_output(name)
|
647
605
|
end
|
648
606
|
|
649
607
|
# Returns a Port::Service object for TCP port +portnum+
|
650
608
|
def tcp_service(portnum)
|
651
|
-
|
652
|
-
|
653
|
-
|
609
|
+
port = tcp_port(portnum)
|
610
|
+
return nil if port.nil?
|
611
|
+
port.service
|
654
612
|
end
|
655
613
|
|
656
614
|
# Returns the state of TCP port +portnum+
|
657
615
|
def tcp_state(portnum)
|
658
|
-
|
659
|
-
|
660
|
-
|
616
|
+
port = tcp_port(portnum)
|
617
|
+
return nil if port.nil?
|
618
|
+
port.state
|
661
619
|
end
|
662
620
|
|
663
621
|
# Returns the Port object for the UDP port +portnum+, and passes it to
|
664
622
|
# a block if one is given
|
665
623
|
def udp_port(portnum) # :yields: port
|
666
|
-
|
667
|
-
|
668
|
-
|
624
|
+
port = @udpPorts[portnum.to_i]
|
625
|
+
yield port if block_given?
|
626
|
+
port
|
669
627
|
end
|
670
628
|
|
671
629
|
# Returns an array of Port objects for each UDP port, and passes them
|
672
630
|
# each to a block if one is given
|
673
631
|
#
|
674
|
-
# If an argument is given, only ports matching +state+ are given.
|
675
|
-
#
|
632
|
+
# If an argument is given, only ports matching +state+ are given. Note
|
633
|
+
# that combinations like "open|filtered" will get matched by "open" and
|
634
|
+
# "filtered"
|
676
635
|
def udp_ports(state = "")
|
677
|
-
list = @udpPorts.
|
678
|
-
state.empty? or
|
636
|
+
list = @udpPorts.values.find_all { |port|
|
637
|
+
state.empty? or
|
638
|
+
port.state == state or
|
639
|
+
port.state.split(/\|/).include?(state)
|
679
640
|
}.sort
|
680
641
|
|
681
|
-
if block_given?
|
682
|
-
list.each do |port|
|
683
|
-
yield port
|
684
|
-
end
|
685
|
-
end
|
642
|
+
list.each { |port| yield port } if block_given?
|
686
643
|
|
687
644
|
list
|
688
645
|
end
|
@@ -691,94 +648,79 @@ class Nmap::Parser::Host
|
|
691
648
|
# if one is given
|
692
649
|
#
|
693
650
|
# If an argument is given, only ports matching +state+ are given.
|
694
|
-
# Note: "open" will also match "open|filtered", but not vice versa.
|
695
651
|
def udp_port_list(state = "")
|
696
|
-
list =
|
697
|
-
|
698
|
-
}.compact.sort
|
699
|
-
|
700
|
-
if block_given?
|
701
|
-
list.each do |port|
|
702
|
-
yield port
|
703
|
-
end
|
704
|
-
end
|
705
|
-
|
652
|
+
list = udp_ports(state).map { |p| p.num }
|
653
|
+
list.each { |port| yield port } if block_given?
|
706
654
|
list
|
707
655
|
end
|
708
656
|
|
709
657
|
# Returns the state reason of UDP port +portnum+
|
710
658
|
def udp_reason(portnum)
|
711
|
-
|
712
|
-
|
713
|
-
|
659
|
+
port = udp_port(portnum)
|
660
|
+
return nil if port.nil?
|
661
|
+
port.reason
|
714
662
|
end
|
715
663
|
|
716
664
|
# Returns the Script object for the script +name+ run against the
|
717
665
|
# UDP port +portnum+
|
718
666
|
def udp_script(portnum, name)
|
719
|
-
|
720
|
-
|
721
|
-
|
667
|
+
port = udp_port(portnum)
|
668
|
+
return nil if port.nil?
|
669
|
+
port.script(name)
|
722
670
|
end
|
723
671
|
|
724
672
|
# Returns an array of Script objects for each script run on the
|
725
673
|
# UDP port +portnum+, and passes them each to a block if given
|
726
|
-
def udp_scripts(portnum)
|
727
|
-
|
728
|
-
|
729
|
-
if block_given?
|
730
|
-
|
731
|
-
yield script
|
732
|
-
end
|
733
|
-
end
|
734
|
-
|
735
|
-
@udpPorts[portnum.to_s].scripts
|
674
|
+
def udp_scripts(portnum) # :yields: script
|
675
|
+
port = udp_port(portnum)
|
676
|
+
return nil if port.nil?
|
677
|
+
port.scripts { |s| yield s } if block_given?
|
678
|
+
port.scripts
|
736
679
|
end
|
737
680
|
|
738
681
|
# Returns the output of the script +name+ on the UDP port +portnum+
|
739
682
|
def udp_script_output(portnum, name)
|
740
|
-
|
741
|
-
|
742
|
-
|
683
|
+
port = udp_port(portnum)
|
684
|
+
return nil if port.nil?
|
685
|
+
port.script_output(name)
|
743
686
|
end
|
744
687
|
|
745
688
|
# Returns a Port::Service object for UDP port +portnum+
|
746
689
|
def udp_service(portnum)
|
747
|
-
|
748
|
-
|
749
|
-
|
690
|
+
port = udp_port(portnum)
|
691
|
+
return nil if port.nil?
|
692
|
+
port.service
|
750
693
|
end
|
751
694
|
|
752
695
|
# Returns the state of UDP port +portnum+
|
753
696
|
def udp_state(portnum)
|
754
|
-
|
755
|
-
|
756
|
-
|
697
|
+
port = udp_port(portnum)
|
698
|
+
return nil if port.nil?
|
699
|
+
port.state
|
757
700
|
end
|
758
701
|
|
759
702
|
# Returns the Port object for the IP protocol +protonum+, and passes it
|
760
703
|
# to a block if one is given
|
761
704
|
def ip_proto(protonum) # :yields: proto
|
762
|
-
|
763
|
-
|
764
|
-
|
705
|
+
proto = @ipProtos[protonum.to_i]
|
706
|
+
yield proto if block_given?
|
707
|
+
proto
|
765
708
|
end
|
766
709
|
|
767
710
|
# Returns an array of Port objects for each IP protocol, and passes
|
768
711
|
# them each to a block if one is given
|
769
712
|
#
|
770
713
|
# If an argument is given, only protocols matching +state+ are given.
|
771
|
-
# Note
|
714
|
+
# Note that combinations like "open|filtered" will get matched by
|
715
|
+
# "open" and "filtered"
|
772
716
|
def ip_protos(state = "")
|
773
|
-
list = @ipProtos.
|
774
|
-
state.empty? or
|
717
|
+
list = @ipProtos.values.find_all { |proto|
|
718
|
+
state.empty? or
|
719
|
+
proto.state == state or
|
720
|
+
proto.state.split(/\|/).include?(state)
|
775
721
|
}.sort
|
776
722
|
|
777
|
-
if block_given?
|
778
|
-
list.each do |proto|
|
779
|
-
yield proto
|
780
|
-
end
|
781
|
-
end
|
723
|
+
list.each { |proto| yield proto } if block_given?
|
782
724
|
|
783
725
|
list
|
784
726
|
end
|
@@ -787,57 +729,42 @@ class Nmap::Parser::Host
|
|
787
729
|
# block if one given
|
788
730
|
#
|
789
731
|
# If an argument is given, only protocols matching +state+ are given.
|
790
|
-
# Note: "open" will also match "open|filtered", but not vice versa.
|
791
732
|
def ip_proto_list(state = "")
|
792
|
-
list =
|
793
|
-
|
794
|
-
}.compact.sort
|
795
|
-
|
796
|
-
if block_given?
|
797
|
-
list.each do |proto|
|
798
|
-
yield proto
|
799
|
-
end
|
800
|
-
end
|
801
|
-
|
733
|
+
list = ip_protos(state).map { |p| p.num }
|
734
|
+
list.each { |proto| yield proto } if block_given?
|
802
735
|
list
|
803
736
|
end
|
804
737
|
|
805
738
|
# Returns the state reason of IP protocol +protonum+
|
806
739
|
def ip_reason(protonum)
|
807
|
-
|
808
|
-
|
809
|
-
|
740
|
+
proto = ip_proto(protonum)
|
741
|
+
return nil if proto.nil?
|
742
|
+
proto.reason
|
810
743
|
end
|
811
744
|
|
812
745
|
# Returns a Port::Service object for IP protocol +protonum+
|
813
746
|
def ip_service(protonum)
|
814
|
-
|
815
|
-
|
816
|
-
|
747
|
+
proto = ip_proto(protonum)
|
748
|
+
return nil if proto.nil?
|
749
|
+
proto.service
|
817
750
|
end
|
818
751
|
|
819
752
|
# Returns the state of IP protocol +protonum+
|
820
753
|
def ip_state(protonum)
|
821
|
-
|
822
|
-
|
823
|
-
|
754
|
+
proto = ip_proto(protonum)
|
755
|
+
return nil if proto.nil?
|
756
|
+
proto.state
|
824
757
|
end
|
825
758
|
|
826
759
|
# Returns the Script object for the specified host script +name+
|
827
760
|
def script(name)
|
828
|
-
@scripts.find
|
829
|
-
script.id == name
|
830
|
-
end
|
761
|
+
@scripts.find { |script| script.id == name }
|
831
762
|
end
|
832
763
|
|
833
764
|
# Returns an array of Script objects for each host script run, and
|
834
765
|
# passes them each to a block if given
|
835
766
|
def scripts
|
836
|
-
if block_given?
|
837
|
-
@scripts.each do |script|
|
838
|
-
yield script
|
839
|
-
end
|
840
|
-
end
|
767
|
+
@scripts.each { |script| yield script } if block_given?
|
841
768
|
|
842
769
|
@scripts
|
843
770
|
end
|
@@ -857,28 +784,6 @@ class Nmap::Parser::Host
|
|
857
784
|
parse(hostinfo)
|
858
785
|
end
|
859
786
|
|
860
|
-
# Convert a string like "22-25,80,110-900" into
|
861
|
-
# an array with all the uncondensed elements, e.g.
|
862
|
-
# [ 22, 23, 24, 25, 80, 110, 111 ... ]
|
863
|
-
def parsePortlist(ports)
|
864
|
-
list = []
|
865
|
-
|
866
|
-
# Build array from port specification
|
867
|
-
ports.split(/,/).each do |item|
|
868
|
-
start, stop = item.split(/-/).map { |p| p.to_i }
|
869
|
-
|
870
|
-
start ||= 0
|
871
|
-
stop ||= item.match(/-/) ? 65535 : start
|
872
|
-
|
873
|
-
start, stop = stop, start if stop < start
|
874
|
-
|
875
|
-
start.upto(stop) { |p| list << p }
|
876
|
-
end
|
877
|
-
|
878
|
-
# Sort, and remove dups and invalid ports
|
879
|
-
list.sort.uniq.delete_if { |p| p < 0 or p > 65535 }
|
880
|
-
end
|
881
|
-
|
882
787
|
def parseAddr(elem)
|
883
788
|
case elem.attributes['addrtype']
|
884
789
|
when "mac"
|
@@ -909,7 +814,7 @@ class Nmap::Parser::Host
|
|
909
814
|
return nil if ports.nil?
|
910
815
|
|
911
816
|
ports.each_element('port') do |port|
|
912
|
-
num = port.attributes['portid']
|
817
|
+
num = port.attributes['portid'].to_i
|
913
818
|
proto = port.attributes['protocol']
|
914
819
|
|
915
820
|
if proto == "tcp"
|
@@ -931,9 +836,7 @@ class Nmap::Parser::Host
|
|
931
836
|
ExtraPorts.new(e)
|
932
837
|
end
|
933
838
|
|
934
|
-
@extraports.sort!
|
935
|
-
x.count <=> y.count
|
936
|
-
end
|
839
|
+
@extraports.sort!
|
937
840
|
end
|
938
841
|
|
939
842
|
def parseScripts(scriptlist)
|
@@ -1091,19 +994,13 @@ class Nmap::Parser::Host::Port
|
|
1091
994
|
|
1092
995
|
# Returns the Script object with the specified +name+
|
1093
996
|
def script(name)
|
1094
|
-
@scripts.find
|
1095
|
-
script.id == name
|
1096
|
-
end
|
997
|
+
@scripts.find { |script| script.id == name }
|
1097
998
|
end
|
1098
999
|
|
1099
1000
|
# Returns an array of Script objects associated with this port, and
|
1100
1001
|
# passes them each to a block if one is given
|
1101
1002
|
def scripts
|
1102
|
-
if block_given?
|
1103
|
-
@scripts.each do |script|
|
1104
|
-
yield script
|
1105
|
-
end
|
1106
|
-
end
|
1003
|
+
@scripts.each { |script| yield script } if block_given?
|
1107
1004
|
|
1108
1005
|
@scripts
|
1109
1006
|
end
|
@@ -1160,15 +1057,16 @@ class Nmap::Parser::Host::ExtraPorts
|
|
1160
1057
|
# for each set of reasons, and passes them each to a block if one is
|
1161
1058
|
# given
|
1162
1059
|
def reasons
|
1163
|
-
if block_given?
|
1164
|
-
@reasons.each do |reason|
|
1165
|
-
yield reason
|
1166
|
-
end
|
1167
|
-
end
|
1060
|
+
@reasons.each { |reason| yield reason } if block_given?
|
1168
1061
|
|
1169
1062
|
@reasons
|
1170
1063
|
end
|
1171
1064
|
|
1065
|
+
# Compares the port counts
|
1066
|
+
def <=>(extraports)
|
1067
|
+
@count <=> extraports.count
|
1068
|
+
end
|
1069
|
+
|
1172
1070
|
private
|
1173
1071
|
|
1174
1072
|
def initialize(extraports)
|
@@ -1199,19 +1097,13 @@ class Nmap::Parser::Host::Traceroute
|
|
1199
1097
|
|
1200
1098
|
# Returns the Hop object for the given TTL
|
1201
1099
|
def hop(ttl)
|
1202
|
-
@hops.find
|
1203
|
-
h.ttl == ttl.to_i
|
1204
|
-
end
|
1100
|
+
@hops.find { |hop| hop.ttl == ttl.to_i }
|
1205
1101
|
end
|
1206
1102
|
|
1207
1103
|
# Returns an array of Hop objects, which are each a responsive hop,
|
1208
1104
|
# and passes them each to a block if one if given.
|
1209
|
-
def hops
|
1210
|
-
if block_given?
|
1211
|
-
@hops.each do |h|
|
1212
|
-
yield h
|
1213
|
-
end
|
1214
|
-
end
|
1105
|
+
def hops
|
1106
|
+
@hops.each { |hop| yield hop } if block_given?
|
1215
1107
|
|
1216
1108
|
@hops
|
1217
1109
|
end
|
@@ -1246,6 +1138,11 @@ class Nmap::Parser::Host::Traceroute::Hop
|
|
1246
1138
|
alias host hostname
|
1247
1139
|
alias ipaddr addr
|
1248
1140
|
|
1141
|
+
# Compares the TTLs
|
1142
|
+
def <=>(hop)
|
1143
|
+
@ttl <=> hop.ttl
|
1144
|
+
end
|
1145
|
+
|
1249
1146
|
private
|
1250
1147
|
|
1251
1148
|
def initialize(hop)
|
@@ -1337,11 +1234,7 @@ class Nmap::Parser::Host::OS
|
|
1337
1234
|
# Returns an array of OSClass objects, and passes them each to a
|
1338
1235
|
# block if one is given
|
1339
1236
|
def osclasses
|
1340
|
-
if block_given?
|
1341
|
-
@osclasses.each do |osclass|
|
1342
|
-
yield osclass
|
1343
|
-
end
|
1344
|
-
end
|
1237
|
+
@osclasses.each { |osclass| yield osclass } if block_given?
|
1345
1238
|
|
1346
1239
|
@osclasses
|
1347
1240
|
end
|
@@ -1349,11 +1242,7 @@ class Nmap::Parser::Host::OS
|
|
1349
1242
|
# Returns an array of OSMatch objects, and passes them each to a
|
1350
1243
|
# block if one is given
|
1351
1244
|
def osmatches
|
1352
|
-
if block_given?
|
1353
|
-
@osmatches.each do |osmatch|
|
1354
|
-
yield osmatch
|
1355
|
-
end
|
1356
|
-
end
|
1245
|
+
@osmatches.each { |osmatch| yield osmatch } if block_given?
|
1357
1246
|
|
1358
1247
|
@osmatches
|
1359
1248
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nmap-parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kris Katterjohn
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-02-08 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -26,6 +26,8 @@ files:
|
|
26
26
|
- LICENSE
|
27
27
|
- README
|
28
28
|
- lib/nmap/parser.rb
|
29
|
+
- examples/listopentcp.rb
|
30
|
+
- examples/services.rb
|
29
31
|
has_rdoc: true
|
30
32
|
homepage: http://rubynmap.sourceforge.net
|
31
33
|
post_install_message:
|