ronin-nmap 0.1.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.document +4 -0
  3. data/.github/workflows/ruby.yml +47 -0
  4. data/.gitignore +14 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +15 -0
  7. data/.ruby-version +1 -0
  8. data/.yardopts +1 -0
  9. data/COPYING.txt +165 -0
  10. data/ChangeLog.md +10 -0
  11. data/Gemfile +42 -0
  12. data/README.md +238 -0
  13. data/Rakefile +43 -0
  14. data/bin/ronin-nmap +32 -0
  15. data/data/completions/ronin-nmap +79 -0
  16. data/data/templates/script.rb.erb +58 -0
  17. data/gemspec.yml +42 -0
  18. data/lib/ronin/nmap/cli/command.rb +40 -0
  19. data/lib/ronin/nmap/cli/commands/completion.rb +61 -0
  20. data/lib/ronin/nmap/cli/commands/convert.rb +108 -0
  21. data/lib/ronin/nmap/cli/commands/dump.rb +293 -0
  22. data/lib/ronin/nmap/cli/commands/grep.rb +378 -0
  23. data/lib/ronin/nmap/cli/commands/import.rb +79 -0
  24. data/lib/ronin/nmap/cli/commands/new.rb +226 -0
  25. data/lib/ronin/nmap/cli/commands/print.rb +133 -0
  26. data/lib/ronin/nmap/cli/commands/scan.rb +233 -0
  27. data/lib/ronin/nmap/cli/filtering_options.rb +355 -0
  28. data/lib/ronin/nmap/cli/importable.rb +68 -0
  29. data/lib/ronin/nmap/cli/port_list.rb +102 -0
  30. data/lib/ronin/nmap/cli.rb +50 -0
  31. data/lib/ronin/nmap/converter.rb +114 -0
  32. data/lib/ronin/nmap/converters/csv.rb +162 -0
  33. data/lib/ronin/nmap/converters/json.rb +562 -0
  34. data/lib/ronin/nmap/converters.rb +54 -0
  35. data/lib/ronin/nmap/exceptions.rb +47 -0
  36. data/lib/ronin/nmap/importer.rb +369 -0
  37. data/lib/ronin/nmap/root.rb +28 -0
  38. data/lib/ronin/nmap/version.rb +26 -0
  39. data/lib/ronin/nmap.rb +223 -0
  40. data/man/ronin-nmap-completion.1 +76 -0
  41. data/man/ronin-nmap-completion.1.md +78 -0
  42. data/man/ronin-nmap-convert.1 +33 -0
  43. data/man/ronin-nmap-convert.1.md +36 -0
  44. data/man/ronin-nmap-dump.1 +141 -0
  45. data/man/ronin-nmap-dump.1.md +119 -0
  46. data/man/ronin-nmap-grep.1 +33 -0
  47. data/man/ronin-nmap-grep.1.md +36 -0
  48. data/man/ronin-nmap-import.1 +52 -0
  49. data/man/ronin-nmap-import.1.md +57 -0
  50. data/man/ronin-nmap-new.1 +81 -0
  51. data/man/ronin-nmap-new.1.md +73 -0
  52. data/man/ronin-nmap-print.1 +61 -0
  53. data/man/ronin-nmap-print.1.md +63 -0
  54. data/man/ronin-nmap-scan.1 +86 -0
  55. data/man/ronin-nmap-scan.1.md +84 -0
  56. data/man/ronin-nmap.1 +58 -0
  57. data/man/ronin-nmap.1.md +57 -0
  58. data/ronin-nmap.gemspec +62 -0
  59. data/scripts/setup +161 -0
  60. metadata +168 -0
@@ -0,0 +1,79 @@
1
+ # ronin-nmap completion -*- shell-script -*-
2
+
3
+ # This bash completions script was generated by
4
+ # completely (https://github.com/dannyben/completely)
5
+ # Modifying it manually is not recommended
6
+
7
+ _ronin-nmap_completions_filter() {
8
+ local words="$1"
9
+ local cur=${COMP_WORDS[COMP_CWORD]}
10
+ local result=()
11
+
12
+ if [[ "${cur:0:1}" == "-" ]]; then
13
+ echo "$words"
14
+
15
+ else
16
+ for word in $words; do
17
+ [[ "${word:0:1}" != "-" ]] && result+=("$word")
18
+ done
19
+
20
+ echo "${result[*]}"
21
+
22
+ fi
23
+ }
24
+
25
+ _ronin-nmap_completions() {
26
+ local cur=${COMP_WORDS[COMP_CWORD]}
27
+ local compwords=("${COMP_WORDS[@]:1:$COMP_CWORD-1}")
28
+ local compline="${compwords[*]}"
29
+
30
+ case "$compline" in
31
+ 'new'*'--xml-file')
32
+ while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -A file -- "$cur" )
33
+ ;;
34
+
35
+ 'scan'*'--output')
36
+ while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -A file -- "$cur" )
37
+ ;;
38
+
39
+ 'completion'*)
40
+ while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_ronin-nmap_completions_filter "--print --install --uninstall")" -- "$cur" )
41
+ ;;
42
+
43
+ 'convert'*)
44
+ while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -A file -W "$(_ronin-nmap_completions_filter "--format -F")" -- "$cur" )
45
+ ;;
46
+
47
+ 'scan'*'-o')
48
+ while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -A file -- "$cur" )
49
+ ;;
50
+
51
+ 'import'*)
52
+ while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -A file -W "$(_ronin-nmap_completions_filter "--db --db-uri --db-file")" -- "$cur" )
53
+ ;;
54
+
55
+ 'print'*)
56
+ while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_ronin-nmap_completions_filter "--ip --ip-range --domain --with-os --with-ports --with-service --with-script --with-script-output --with-script-regex")" -- "$cur" )
57
+ ;;
58
+
59
+ 'dump'*)
60
+ while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_ronin-nmap_completions_filter "--print-ips --print-hosts --print-ip-ports --print-host-ports --print-uris --ip --ip-range --domain --with-os --with-ports --with-service --with-script --with-script-output --with-script-regex --ports -p --services")" -- "$cur" )
61
+ ;;
62
+
63
+ 'scan'*)
64
+ while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_ronin-nmap_completions_filter "--db --db-uri --db-file --sudo --output -o --output-format -F --import")" -- "$cur" )
65
+ ;;
66
+
67
+ 'new'*)
68
+ while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_ronin-nmap_completions_filter "--parser --scanner --printing --import --xml-file --syn-scan --ports -p --target")" -- "$cur" )
69
+ ;;
70
+
71
+ *)
72
+ while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_ronin-nmap_completions_filter "--version -V help completion convert dump grep import new print scan")" -- "$cur" )
73
+ ;;
74
+
75
+ esac
76
+ } &&
77
+ complete -F _ronin-nmap_completions ronin-nmap
78
+
79
+ # ex: filetype=sh
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'ronin/nmap'
4
+
5
+ <%- if @script_type == :parser -%>
6
+ <%- if @xml_file -%>
7
+ xml = Ronin::Nmap.parse(<%= @xml_file.inspect %>)
8
+ <%- else -%>
9
+ xml = Ronin::Nmap.parse(ARGV[0])
10
+ <%- end -%>
11
+ <%- else -%>
12
+ xml = Ronin::Nmap.scan do |nmap|
13
+ <%- if @xml_file -%>
14
+ nmap.xml_file = <%= @xml_file.inspect %>
15
+ <%- else -%>
16
+ # nmap.xml_file = "path/to/nmap.xml"
17
+ <%- end -%>
18
+ <%- if @syn_scan -%>
19
+ nmap.syn_scan = true
20
+ <%- else -%>
21
+ # nmap.syn_scan = true
22
+ <%- end -%>
23
+ <%- if @ports -%>
24
+ nmap.ports = <%= @ports.inspect %>
25
+ <%- else -%>
26
+ # nmap.ports = [22, 80, 443, 8000..9000]
27
+ <%- end -%>
28
+ <%- case @targets.length -%>
29
+ <%- when 0 -%>
30
+ nmap.targets = ARGV[0]
31
+ <%- when 1 -%>
32
+ nmap.targets = <%= @targets[0].inspect %>
33
+ <%- else -%>
34
+ nmap.targets = <%= @targets.inspect %>
35
+ <%- end -%>
36
+ end
37
+ <%- end -%>
38
+ <% if @features[:printing] -%>
39
+
40
+ xml.each_host do |host|
41
+ puts "[ #{host.ip} ]"
42
+
43
+ host.each_port do |port|
44
+ puts " #{port.number}/#{port.protocol}\t#{port.state}\t#{port.service}"
45
+
46
+ port.scripts.each do |id,script|
47
+ puts " [ #{id} ]"
48
+
49
+ script.output.each_line { |line| puts " #{line}" }
50
+ end
51
+ end
52
+ end
53
+ <%- end -%>
54
+ <%- if @features[:import] -%>
55
+
56
+ Ronin::DB.connect
57
+ Ronin::Nmap::Importer.import(xml)
58
+ <%- end -%>
data/gemspec.yml ADDED
@@ -0,0 +1,42 @@
1
+ name: ronin-nmap
2
+ summary: A Ruby library and CLI for working with nmap.
3
+ description: |
4
+ ronin-nmap is a Ruby library for working with nmap. ronin-nmap can parse
5
+ nmap XML, convert nmap XML into JSON or CSV, or import nmap XML into the
6
+ ronin-db database.
7
+
8
+ license: LGPL-3.0
9
+ authors: Postmodern
10
+ email: postmodern.mod3@gmail.com
11
+ homepage: https://ronin-rb.dev/
12
+ has_yard: true
13
+
14
+ metadata:
15
+ documentation_uri: https://ronin-rb.dev/docs/ronin-nmap
16
+ source_code_uri: https://github.com/ronin-rb/ronin-nmap
17
+ bug_tracker_uri: https://github.com/ronin-rb/ronin-nmap/issues
18
+ changelog_uri: https://github.com/ronin-rb/ronin-nmap/blob/main/ChangeLog.md
19
+ rubygems_mfa_required: 'true'
20
+
21
+ generated_files:
22
+ - data/completions/ronin-nmap
23
+ - man/ronin-nmap.1
24
+ - man/ronin-nmap-completion.1
25
+ - man/ronin-nmap-convert.1
26
+ - man/ronin-nmap-dump.1
27
+ - man/ronin-nmap-grep.1
28
+ - man/ronin-nmap-import.1
29
+ - man/ronin-nmap-new.1
30
+ - man/ronin-nmap-print.1
31
+ - man/ronin-nmap-scan.1
32
+
33
+ required_ruby_version: ">= 3.0.0"
34
+
35
+ dependencies:
36
+ ruby-nmap: ~> 1.0
37
+ # Ronin dependencies:
38
+ ronin-core: ~> 0.2.0.rc1
39
+ ronin-db: ~> 0.2.0.rc1
40
+
41
+ development_dependencies:
42
+ bundler: ~> 2.0
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-nmap - A Ruby library for automating nmap and importing nmap scans.
4
+ #
5
+ # Copyright (c) 2023-2024 Hal Brodigan (postmodern.mod3@gmail.com)
6
+ #
7
+ # ronin-nmap is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-nmap is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-nmap. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/nmap/root'
22
+
23
+ require 'ronin/core/cli/command'
24
+
25
+ module Ronin
26
+ module Nmap
27
+ class CLI
28
+ #
29
+ # Base class for all other `ronin-nmap` commands.
30
+ #
31
+ class Command < Core::CLI::Command
32
+
33
+ man_dir File.join(ROOT,'man')
34
+
35
+ bug_report_url 'https://github.com/ronin-rb/ronin-nmap/issues/new'
36
+
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-nmap - A Ruby library for automating nmap and importing nmap scans.
4
+ #
5
+ # Copyright (c) 2023-2024 Hal Brodigan (postmodern.mod3@gmail.com)
6
+ #
7
+ # ronin-nmap is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-nmap is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-nmap. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/nmap/root'
22
+ require 'ronin/core/cli/completion_command'
23
+
24
+ module Ronin
25
+ module Nmap
26
+ class CLI
27
+ module Commands
28
+ #
29
+ # Manages the shell completion rules for `ronin-nmap`.
30
+ #
31
+ # ## Usage
32
+ #
33
+ # ronin-nmap completion [options]
34
+ #
35
+ # ## Options
36
+ #
37
+ # --print Prints the shell completion file
38
+ # --install Installs the shell completion file
39
+ # --uninstall Uninstalls the shell completion file
40
+ # -h, --help Print help information
41
+ #
42
+ # ## Examples
43
+ #
44
+ # ronin-nmap completion --print
45
+ # ronin-nmap completion --install
46
+ # ronin-nmap completion --uninstall
47
+ #
48
+ class Completion < Core::CLI::CompletionCommand
49
+
50
+ completion_file File.join(ROOT,'data','completions','ronin-nmap')
51
+
52
+ man_dir File.join(ROOT,'man')
53
+ man_page 'ronin-nmap-completion.1'
54
+
55
+ description 'Manages the shell completion rules for ronin-nmap'
56
+
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-nmap - A Ruby library for automating nmap and importing nmap scans.
4
+ #
5
+ # Copyright (c) 2023-2024 Hal Brodigan (postmodern.mod3@gmail.com)
6
+ #
7
+ # ronin-nmap is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-nmap is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-nmap. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/nmap/cli/command'
22
+ require 'ronin/nmap/converter'
23
+
24
+ module Ronin
25
+ module Nmap
26
+ class CLI
27
+ module Commands
28
+ #
29
+ # Converts an nmap XML file to JSON or CSV.
30
+ #
31
+ # ## Usage
32
+ #
33
+ # ronin-nmap convert [--format json|csv] XML_FILE [OUTPUT_FILE]
34
+ #
35
+ # ## Option
36
+ #
37
+ # -F, --format json|csv The desired output format
38
+ # -h, --help Print help information
39
+ #
40
+ # ## Arguments
41
+ #
42
+ # XML_FILE The input XML file to parse
43
+ # OUTPUT_FILE The output file
44
+ #
45
+ class Convert < Command
46
+
47
+ usage '[--format json|csv] XML_FILE [OUTPUT_FILE]'
48
+
49
+ option :format, short: '-F',
50
+ value: {
51
+ type: [:json, :csv],
52
+ required: true
53
+ },
54
+ desc: 'The desired output format'
55
+
56
+ argument :xml_file, required: true,
57
+ desc: 'The input XML file to parse'
58
+
59
+ argument :output_file, required: false,
60
+ desc: 'The output file'
61
+
62
+ description "Converts an nmap XML file to JSON or CSV"
63
+
64
+ man_page 'ronin-nmap-convert.1'
65
+
66
+ # The desired output format.
67
+ #
68
+ # @return [:json, :csv, nil]
69
+ attr_reader :format
70
+
71
+ #
72
+ # Runs the `ronin-nmap convert` command.
73
+ #
74
+ # @param [String] xml_file
75
+ # The XML input file to parse.
76
+ #
77
+ # @param [String] output_file
78
+ # The output file to write to.
79
+ #
80
+ def run(xml_file,output_file=nil)
81
+ unless File.file?(xml_file)
82
+ print_error "no such file or directory: #{xml_file}"
83
+ exit(-1)
84
+ end
85
+
86
+ if output_file
87
+ if (format = options[:format])
88
+ Converter.convert_file(xml_file,output_file, format: format)
89
+ else
90
+ Converter.convert_file(xml_file,output_file)
91
+ end
92
+ else
93
+ unless (format = options[:format])
94
+ print_error "must specify a --format if no output file is given"
95
+ exit(-1)
96
+ end
97
+
98
+ xml = ::Nmap::XML.open(xml_file)
99
+
100
+ Converter.convert(xml,stdout, format: format)
101
+ end
102
+ end
103
+
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,293 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-nmap - A Ruby library for automating nmap and importing nmap scans.
4
+ #
5
+ # Copyright (c) 2023-2024 Hal Brodigan (postmodern.mod3@gmail.com)
6
+ #
7
+ # ronin-nmap is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-nmap is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-nmap. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/nmap/cli/command'
22
+ require 'ronin/nmap/cli/filtering_options'
23
+ require 'nmap/xml'
24
+
25
+ require 'set'
26
+
27
+ module Ronin
28
+ module Nmap
29
+ class CLI
30
+ module Commands
31
+ #
32
+ # Dumps the scanned ports from nmap XML file(s).
33
+ #
34
+ # ## Usage
35
+ #
36
+ # ronin-nmap dump [options] XML_FILE [...]
37
+ #
38
+ # ## Options
39
+ #
40
+ # --print-ips Print all IP addresses
41
+ # --print-hosts Print all hostnames
42
+ # --print-ip-ports Print IP:PORT pairs. (Default)
43
+ # --print-host-ports Print HOST:PORT pairs
44
+ # --print-uris Print URIs
45
+ # --ip IP Filters the targets by IP
46
+ # --ip-range CIDR Filter the targets by IP range
47
+ # --domain DOMAIN Filters the targets by domain
48
+ # --with-os OS Filters the targets by OS
49
+ # --with-ports {PORT | PORT1-PORT2},...
50
+ # Filter targets by port numbers
51
+ # --with-service SERVICE[,...] Filters targets by service
52
+ # --with-script SCRIPT[,...] Filters targets with the script
53
+ # --with-script-output STRING Filters targets containing the script output
54
+ # --with-script-regex /REGEX/ Filters targets containing the script output
55
+ # -p, --ports {PORT | PORT1-PORT2},...
56
+ # Filter targets by port numbers
57
+ # --services SERVICE[,...] Filters targets by service
58
+ # -h, --help Print help information
59
+ #
60
+ # ## Arguments
61
+ #
62
+ # XML_FILE ... The nmap XML file(s) to parse
63
+ #
64
+ # ## Examples
65
+ #
66
+ # ronin-nmap dump --print-ip-ports scan.xml
67
+ # ronin-nmap dump --print-ip-ports --ports 22,80,443 scan.xml
68
+ # ronin-nmap dump --print-host-ports scan.xml
69
+ # ronin-nmap dump --print-hosts --with-port 22 scan.xml
70
+ # ronin-nmap dump --print-uris scan.xml
71
+ #
72
+ class Dump < Command
73
+
74
+ usage '[options] XML_FILE [...]'
75
+
76
+ option :print_ips, desc: 'Print all IP addresses' do
77
+ @mode = :ips
78
+ end
79
+
80
+ option :print_hosts, desc: 'Print all hostnames' do
81
+ @mode = :hostnames
82
+ end
83
+
84
+ option :print_ip_ports, desc: 'Print IP:PORT pairs. (Default)' do
85
+ @mode = :ip_ports
86
+ end
87
+
88
+ option :print_host_ports, desc: 'Print HOST:PORT pairs' do
89
+ @mode = :host_ports
90
+ end
91
+
92
+ option :print_uris, desc: 'Print URIs' do
93
+ @mode = :uris
94
+ end
95
+
96
+ include FilteringOptions
97
+
98
+ option :ports, short: '-p',
99
+ value: {
100
+ type: /\A(?:\d+|\d+-\d+)(?:,(?:\d+|\d+-\d+))*\z/,
101
+ usage: '{PORT | PORT1-PORT2},...'
102
+ },
103
+ desc: 'Filter targets by port numbers' do |ports|
104
+ @ports << PortList.parse(ports)
105
+ end
106
+
107
+ option :services, value: {
108
+ type: /\A(?:[a-z]+[a-z0-9_+-]*)(?:,[a-z]+[a-z0-9_+-]*)*\z/,
109
+ usage: 'SERVICE[,...]'
110
+ },
111
+ desc: 'Filters targets by service' do |services|
112
+ @services.merge(services.split(','))
113
+ end
114
+
115
+ argument :xml_file, required: true,
116
+ repeats: true,
117
+ desc: 'The nmap XML file(s) to parse'
118
+
119
+ examples [
120
+ '--print-ip-ports scan.xml',
121
+ '--print-ip-ports --ports 22,80,443 scan.xml',
122
+ '--print-host-ports scan.xml',
123
+ '--print-hosts --with-port 22 scan.xml',
124
+ '--print-uris scan.xml'
125
+ ]
126
+
127
+ description 'Dumps the scanned ports from nmap XML file(s)'
128
+
129
+ man_page 'ronin-nmap-dump.1'
130
+
131
+ #
132
+ # Initializes the command.
133
+ #
134
+ # @param [Hash{Symbol => Object}] kwargs
135
+ # Additional keywords for the command.
136
+ #
137
+ def initialize(**kwargs)
138
+ super(**kwargs)
139
+
140
+ @mode = :ip_ports
141
+
142
+ @ports = Set.new
143
+ @services = Set.new
144
+ end
145
+
146
+ #
147
+ # Runs the `ronin-nmap dump` command.
148
+ #
149
+ # @param [Array<String>] xml_files
150
+ # The nmap XML files to parse.
151
+ #
152
+ def run(*xml_files)
153
+ xml_files.each do |xml_file|
154
+ xml = ::Nmap::XML.open(xml_file)
155
+
156
+ filter_targets(xml).each do |host|
157
+ print_target(host)
158
+ end
159
+ end
160
+ end
161
+
162
+ #
163
+ # Prints the targets.
164
+ #
165
+ # @param [::Nmap::XML::Host] host
166
+ #
167
+ def print_target(host)
168
+ case @mode
169
+ when :ips then print_ip(host)
170
+ when :hostnames then print_hostname(host)
171
+ when :ip_ports then print_ip_ports(host)
172
+ when :host_ports then print_host_ports(host)
173
+ when :uris then print_uris(host)
174
+ end
175
+ end
176
+
177
+ #
178
+ # Prints the IPs for the target.
179
+ #
180
+ # @param [::Nmap::XML::Host] host
181
+ #
182
+ def print_ip(host)
183
+ puts host.address
184
+ end
185
+
186
+ #
187
+ # Prints the host names for the target.
188
+ #
189
+ # @param [::Nmap::XML::Host] host
190
+ #
191
+ def print_hostnames(host)
192
+ if (hostname = host.hostname)
193
+ puts hostname
194
+ end
195
+ end
196
+
197
+ #
198
+ # Prints the `IP:PORT` pair for the target.
199
+ #
200
+ # @param [::Nmap::XML::Host] host
201
+ #
202
+ def print_ip_ports(host)
203
+ filter_ports(host).each do |port|
204
+ puts "#{host.address}:#{port.number}"
205
+ end
206
+ end
207
+
208
+ #
209
+ # Prints the `HOST:PORT` pair for the target.
210
+ #
211
+ # @param [::Nmap::XML::Host] host
212
+ #
213
+ def print_host_ports(host)
214
+ filter_ports(host).each do |port|
215
+ if (hostname = host.hostname)
216
+ puts "#{hostname}:#{port.number}"
217
+ end
218
+ end
219
+ end
220
+
221
+ #
222
+ # Prints the URIs for the target.
223
+ #
224
+ # @param [::Nmap::XML::Host] host
225
+ #
226
+ def print_uris(host)
227
+ filter_ports(host).each do |port|
228
+ if (port.service && port.service.name == 'http') ||
229
+ (port.number == 80)
230
+ puts URI::HTTP.build(
231
+ host: host.to_s,
232
+ port: port.number
233
+ )
234
+ elsif (port.service && port.service.name == 'https') ||
235
+ (port.number == 443)
236
+ puts URI::HTTPS.build(
237
+ host: host.to_s,
238
+ port: port.number
239
+ )
240
+ end
241
+ end
242
+ end
243
+
244
+ #
245
+ # @param [::Nmap::XML::Host] host
246
+ #
247
+ # @return [Enumerator::Lazy]
248
+ #
249
+ def filter_ports(host)
250
+ ports = host.each_open_port.lazy
251
+
252
+ unless @ports.empty?
253
+ ports = filter_ports_by_number(ports)
254
+ end
255
+
256
+ unless @services.empty?
257
+ ports = filter_ports_by_service(ports)
258
+ end
259
+
260
+ return ports
261
+ end
262
+
263
+ #
264
+ # @param [Enumerator::Lazy] ports
265
+ #
266
+ # @return [Enumerator::Lazy]
267
+ #
268
+ def filter_ports_by_number(ports)
269
+ ports.filter do |port|
270
+ @ports.any? do |port_list|
271
+ port_list.include?(port.number)
272
+ end
273
+ end
274
+ end
275
+
276
+ #
277
+ # @param [Enumerator::Lazy] ports
278
+ #
279
+ # @return [Enumerator::Lazy]
280
+ #
281
+ def filter_ports_by_service(ports)
282
+ ports.filter do |port|
283
+ if (service = port.service)
284
+ @services.include?(service.name)
285
+ end
286
+ end
287
+ end
288
+
289
+ end
290
+ end
291
+ end
292
+ end
293
+ end