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.
- checksums.yaml +7 -0
- data/.document +4 -0
- data/.github/workflows/ruby.yml +47 -0
- data/.gitignore +14 -0
- data/.rspec +1 -0
- data/.rubocop.yml +15 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/COPYING.txt +165 -0
- data/ChangeLog.md +10 -0
- data/Gemfile +42 -0
- data/README.md +238 -0
- data/Rakefile +43 -0
- data/bin/ronin-nmap +32 -0
- data/data/completions/ronin-nmap +79 -0
- data/data/templates/script.rb.erb +58 -0
- data/gemspec.yml +42 -0
- data/lib/ronin/nmap/cli/command.rb +40 -0
- data/lib/ronin/nmap/cli/commands/completion.rb +61 -0
- data/lib/ronin/nmap/cli/commands/convert.rb +108 -0
- data/lib/ronin/nmap/cli/commands/dump.rb +293 -0
- data/lib/ronin/nmap/cli/commands/grep.rb +378 -0
- data/lib/ronin/nmap/cli/commands/import.rb +79 -0
- data/lib/ronin/nmap/cli/commands/new.rb +226 -0
- data/lib/ronin/nmap/cli/commands/print.rb +133 -0
- data/lib/ronin/nmap/cli/commands/scan.rb +233 -0
- data/lib/ronin/nmap/cli/filtering_options.rb +355 -0
- data/lib/ronin/nmap/cli/importable.rb +68 -0
- data/lib/ronin/nmap/cli/port_list.rb +102 -0
- data/lib/ronin/nmap/cli.rb +50 -0
- data/lib/ronin/nmap/converter.rb +114 -0
- data/lib/ronin/nmap/converters/csv.rb +162 -0
- data/lib/ronin/nmap/converters/json.rb +562 -0
- data/lib/ronin/nmap/converters.rb +54 -0
- data/lib/ronin/nmap/exceptions.rb +47 -0
- data/lib/ronin/nmap/importer.rb +369 -0
- data/lib/ronin/nmap/root.rb +28 -0
- data/lib/ronin/nmap/version.rb +26 -0
- data/lib/ronin/nmap.rb +223 -0
- data/man/ronin-nmap-completion.1 +76 -0
- data/man/ronin-nmap-completion.1.md +78 -0
- data/man/ronin-nmap-convert.1 +33 -0
- data/man/ronin-nmap-convert.1.md +36 -0
- data/man/ronin-nmap-dump.1 +141 -0
- data/man/ronin-nmap-dump.1.md +119 -0
- data/man/ronin-nmap-grep.1 +33 -0
- data/man/ronin-nmap-grep.1.md +36 -0
- data/man/ronin-nmap-import.1 +52 -0
- data/man/ronin-nmap-import.1.md +57 -0
- data/man/ronin-nmap-new.1 +81 -0
- data/man/ronin-nmap-new.1.md +73 -0
- data/man/ronin-nmap-print.1 +61 -0
- data/man/ronin-nmap-print.1.md +63 -0
- data/man/ronin-nmap-scan.1 +86 -0
- data/man/ronin-nmap-scan.1.md +84 -0
- data/man/ronin-nmap.1 +58 -0
- data/man/ronin-nmap.1.md +57 -0
- data/ronin-nmap.gemspec +62 -0
- data/scripts/setup +161 -0
- metadata +168 -0
@@ -0,0 +1,378 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-nmap - A Ruby library for automating nmap and importing nmap scans.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2023 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
|
+
|
23
|
+
require 'command_kit/colors'
|
24
|
+
require 'command_kit/printing/indent'
|
25
|
+
require 'nmap/xml'
|
26
|
+
|
27
|
+
module Ronin
|
28
|
+
module Nmap
|
29
|
+
class CLI
|
30
|
+
module Commands
|
31
|
+
#
|
32
|
+
# Parses and searches nmap XML file(s) for the pattern.
|
33
|
+
#
|
34
|
+
# ## Usage
|
35
|
+
#
|
36
|
+
# ronin-nmap grep [options] PATTERN XML_FILE [...]
|
37
|
+
#
|
38
|
+
# ## Options
|
39
|
+
#
|
40
|
+
# -h, --help Print help information
|
41
|
+
#
|
42
|
+
# ## Arguments
|
43
|
+
#
|
44
|
+
class Grep < Command
|
45
|
+
|
46
|
+
include CommandKit::Colors
|
47
|
+
include CommandKit::Printing::Indent
|
48
|
+
|
49
|
+
usage '[options] PATTERN XML_FILE [...]'
|
50
|
+
|
51
|
+
argument :pattern, required: true,
|
52
|
+
desc: 'The pattern to search for'
|
53
|
+
|
54
|
+
argument :xml_file, required: true,
|
55
|
+
repeats: true,
|
56
|
+
desc: 'The nmap XML file to search'
|
57
|
+
|
58
|
+
description 'Parses and searches nmap XML file(s) for the pattern'
|
59
|
+
|
60
|
+
man_page 'ronin-nmap-grep.1'
|
61
|
+
|
62
|
+
#
|
63
|
+
# Runs the `ronin-nmap grep` command.
|
64
|
+
#
|
65
|
+
# @param [String] pattern
|
66
|
+
# The pattern to search for.
|
67
|
+
#
|
68
|
+
# @param [Array<String>] xml_files
|
69
|
+
# The nmap `.xml` file(s) to grep.
|
70
|
+
#
|
71
|
+
def run(pattern,*xml_files)
|
72
|
+
xml_files.each do |xml_file|
|
73
|
+
unless File.file?(xml_file)
|
74
|
+
print_error "no such file or directory: #{xml_file}"
|
75
|
+
next
|
76
|
+
end
|
77
|
+
|
78
|
+
xml = ::Nmap::XML.open(xml_file)
|
79
|
+
hosts = grep_xml(xml,pattern)
|
80
|
+
|
81
|
+
highlight_hosts(hosts,pattern)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
# Searches the parsed nmap XML for the text pattern.
|
87
|
+
#
|
88
|
+
# @param [::Nmap::XML] xml
|
89
|
+
# The parsed nmap XML object.
|
90
|
+
#
|
91
|
+
# @param [String] pattern
|
92
|
+
# The text pattern to search for.
|
93
|
+
#
|
94
|
+
# @return [Enumerator::Lazy<::Nmap::XML::Host>]
|
95
|
+
# The nmap XML host objects that contain the text pattern.
|
96
|
+
#
|
97
|
+
def grep_xml(xml,pattern)
|
98
|
+
xml.each_up_host.lazy.filter do |host|
|
99
|
+
match_host(host,pattern)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
#
|
104
|
+
# Determines if the nmap XML host object contains the text pattern.
|
105
|
+
#
|
106
|
+
# @param [::Nmap::XML::Host] host
|
107
|
+
# The nmap XML host object to search.
|
108
|
+
#
|
109
|
+
# @param [String] pattern
|
110
|
+
# The text pattern to search for.
|
111
|
+
#
|
112
|
+
# @return [Boolean]
|
113
|
+
#
|
114
|
+
def match_host(host,pattern)
|
115
|
+
hostnames = host.each_hostname
|
116
|
+
open_ports = host.each_open_port
|
117
|
+
host_script = host.host_script
|
118
|
+
|
119
|
+
hostnames.any? { |hostname| match_hostname(hostname,pattern) } ||
|
120
|
+
open_ports.any? { |port| match_port(port,pattern) } ||
|
121
|
+
(host_script && match_scripts(host_script,pattern))
|
122
|
+
end
|
123
|
+
|
124
|
+
#
|
125
|
+
# Determines if the nmap XML hostname object contains the text
|
126
|
+
# pattern.
|
127
|
+
#
|
128
|
+
# @param [::Nmap::XML::Hostname] hostname
|
129
|
+
# The nmap XML hostname object to search.
|
130
|
+
#
|
131
|
+
# @param [String] pattern
|
132
|
+
# The text pattern to search for.
|
133
|
+
#
|
134
|
+
# @return [Boolean]
|
135
|
+
#
|
136
|
+
def match_hostname(hostname,pattern)
|
137
|
+
hostname.name.match(pattern)
|
138
|
+
end
|
139
|
+
|
140
|
+
#
|
141
|
+
# Determines if the nmap XML port object contains the text pattern.
|
142
|
+
#
|
143
|
+
# @param [::Nmap::XML::Port] port
|
144
|
+
# The nmap XML port object to search.
|
145
|
+
#
|
146
|
+
# @param [String] pattern
|
147
|
+
# The text pattern to search for.
|
148
|
+
#
|
149
|
+
# @return [Boolean]
|
150
|
+
#
|
151
|
+
def match_port(port,pattern)
|
152
|
+
match_scripts(port,pattern) || if (service = port.service)
|
153
|
+
match_service(service,pattern)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
#
|
158
|
+
# Determines if the nmap XML service object contains the text pattern.
|
159
|
+
#
|
160
|
+
# @param [::Nmap::XML::Service] service
|
161
|
+
# The nmap XML service object to search.
|
162
|
+
#
|
163
|
+
# @param [String] pattern
|
164
|
+
# The text pattern to search for.
|
165
|
+
#
|
166
|
+
# @return [Boolean]
|
167
|
+
#
|
168
|
+
def match_service(service,pattern)
|
169
|
+
product = service.product
|
170
|
+
version = service.version
|
171
|
+
extra_info = service.extra_info
|
172
|
+
|
173
|
+
service.name.match(pattern) ||
|
174
|
+
(product && product.match(pattern)) ||
|
175
|
+
(version && version.match(pattern)) ||
|
176
|
+
(extra_info && extra_info.match(pattern))
|
177
|
+
end
|
178
|
+
|
179
|
+
#
|
180
|
+
# Determines if the nmap XML scripts object contains the text pattern.
|
181
|
+
#
|
182
|
+
# @param [::Nmap::XML::Scripts] has_scripts
|
183
|
+
# The nmap XML object that includes `Nmap::XML::Scripts`.
|
184
|
+
#
|
185
|
+
# @param [String] pattern
|
186
|
+
# The text pattern to search for.
|
187
|
+
#
|
188
|
+
# @return [Boolean]
|
189
|
+
#
|
190
|
+
def match_scripts(has_scripts,pattern)
|
191
|
+
has_scripts.scripts.any? do |id,script|
|
192
|
+
match_script(script,pattern)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
#
|
197
|
+
# Determines if the nmap XML script object contains the text pattern.
|
198
|
+
#
|
199
|
+
# @param [::Nmap::XML::Script] script
|
200
|
+
# The nmap XML script object to search.
|
201
|
+
#
|
202
|
+
# @param [String] pattern
|
203
|
+
# The text pattern to search for.
|
204
|
+
#
|
205
|
+
# @return [Boolean]
|
206
|
+
#
|
207
|
+
def match_script(script,pattern)
|
208
|
+
script.id.match(pattern) || script.output.match(pattern)
|
209
|
+
end
|
210
|
+
|
211
|
+
#
|
212
|
+
# Prints the nmap hosts with the pattern highlighted in the output.
|
213
|
+
#
|
214
|
+
# @param [Enumerator::Lazy<::Nmap::XML::Host>] hosts
|
215
|
+
# The nmap hosts to print.
|
216
|
+
#
|
217
|
+
# @param [String] pattern
|
218
|
+
# The pattern to highlight in the output.
|
219
|
+
#
|
220
|
+
def highlight_hosts(hosts,pattern)
|
221
|
+
hosts.each do |host|
|
222
|
+
highlight_host(host,pattern)
|
223
|
+
puts
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
#
|
228
|
+
# Prints the nmap host with the pattern highlighted in the output.
|
229
|
+
#
|
230
|
+
# @param [::Nmap::XML::Host] host
|
231
|
+
# The nmap host to print.
|
232
|
+
#
|
233
|
+
# @param [String] pattern
|
234
|
+
# The text pattern to highlight in the output.
|
235
|
+
#
|
236
|
+
def highlight_host(host,pattern)
|
237
|
+
addresses = host.addresses
|
238
|
+
hostnames = host.hostnames
|
239
|
+
|
240
|
+
unless hostnames.empty?
|
241
|
+
puts "[ #{addresses.first} / #{highlight(hostnames.first,pattern)} ]"
|
242
|
+
else
|
243
|
+
puts "[ #{addresses.first} ]"
|
244
|
+
end
|
245
|
+
puts
|
246
|
+
|
247
|
+
indent do
|
248
|
+
if addresses.length > 1
|
249
|
+
puts "[ addresses ]"
|
250
|
+
puts
|
251
|
+
|
252
|
+
indent do
|
253
|
+
addresses.each do |address|
|
254
|
+
puts address
|
255
|
+
end
|
256
|
+
end
|
257
|
+
puts
|
258
|
+
end
|
259
|
+
|
260
|
+
if hostnames.length > 1
|
261
|
+
puts "[ hostnames ]"
|
262
|
+
puts
|
263
|
+
|
264
|
+
indent do
|
265
|
+
hostnames.each do |hostname|
|
266
|
+
puts highlight(hostname,pattern)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
puts
|
270
|
+
end
|
271
|
+
|
272
|
+
if (host_script = host.host_script)
|
273
|
+
puts "[ host scripts ]"
|
274
|
+
puts
|
275
|
+
|
276
|
+
indent do
|
277
|
+
highlight_scripts(host_script)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
puts "[ ports ]"
|
282
|
+
puts
|
283
|
+
|
284
|
+
indent do
|
285
|
+
host.each_open_port do |port|
|
286
|
+
highlight_port(port,pattern)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
#
|
293
|
+
# Prints the nmap port with the pattern highlighted in the output.
|
294
|
+
#
|
295
|
+
# @param [::Nmap::XML::Port] port
|
296
|
+
# The nmap XML port object to print.
|
297
|
+
#
|
298
|
+
# @param [String] pattern
|
299
|
+
# The text pattern to highlight in the output.
|
300
|
+
#
|
301
|
+
def highlight_port(port,pattern)
|
302
|
+
port_line = "#{port.number}/#{port.protocol}\t#{port.state}"
|
303
|
+
|
304
|
+
if (service = port.service)
|
305
|
+
port_line << "\t#{highlight(service,pattern)}"
|
306
|
+
|
307
|
+
if (extra_info = service.extra_info)
|
308
|
+
port_line << " #{highlight(extra_info,pattern)}"
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
puts port_line
|
313
|
+
|
314
|
+
unless port.scripts.empty?
|
315
|
+
puts
|
316
|
+
|
317
|
+
indent do
|
318
|
+
highlight_scripts(port,pattern)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
#
|
324
|
+
# Prints the nmap scripts with the pattern highlighted in the output.
|
325
|
+
#
|
326
|
+
# @param [::Nmap::XML::Scripts] has_scripts
|
327
|
+
# The nmap XML object that has scripts.
|
328
|
+
#
|
329
|
+
# @param [String] pattern
|
330
|
+
# The text pattern to highlight in the output.
|
331
|
+
#
|
332
|
+
def highlight_scripts(has_scripts,pattern)
|
333
|
+
has_scripts.scripts.each_value do |script|
|
334
|
+
highlight_script(script,pattern)
|
335
|
+
puts
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
#
|
340
|
+
# Prints the nmap script with the pattern highlighted in the output.
|
341
|
+
#
|
342
|
+
# @param [::Nmap::XML::Script] script
|
343
|
+
# The nmap XML script object to print.
|
344
|
+
#
|
345
|
+
# @param [String] pattern
|
346
|
+
# The text pattern to highlight in the output.
|
347
|
+
#
|
348
|
+
def highlight_script(script,pattern)
|
349
|
+
puts "#{highlight(script.id,pattern)}:"
|
350
|
+
|
351
|
+
indent do
|
352
|
+
script.output.strip.each_line do |line|
|
353
|
+
puts highlight(line,pattern)
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
#
|
359
|
+
# Highlights the pattern in the text.
|
360
|
+
#
|
361
|
+
# @param [String] text
|
362
|
+
# The text to modify.
|
363
|
+
#
|
364
|
+
# @param [String] pattern
|
365
|
+
# The pattern to highlight.
|
366
|
+
#
|
367
|
+
# @return [String]
|
368
|
+
# The modified text.
|
369
|
+
#
|
370
|
+
def highlight(text,pattern)
|
371
|
+
text.to_s.gsub(pattern,colors.bold(colors.red(pattern)))
|
372
|
+
end
|
373
|
+
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
@@ -0,0 +1,79 @@
|
|
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/importable'
|
23
|
+
require 'ronin/nmap/importer'
|
24
|
+
|
25
|
+
module Ronin
|
26
|
+
module Nmap
|
27
|
+
class CLI
|
28
|
+
module Commands
|
29
|
+
#
|
30
|
+
# The `ronin-nmap import` command.
|
31
|
+
#
|
32
|
+
# ## Usage
|
33
|
+
#
|
34
|
+
# ronin-nmap import [options] XML_FILE
|
35
|
+
#
|
36
|
+
# ## Options
|
37
|
+
#
|
38
|
+
# --db NAME The database to connect to (Default: default)
|
39
|
+
# --db-uri URI The database URI to connect to
|
40
|
+
# -h, --help Print help information
|
41
|
+
#
|
42
|
+
# ## Arguments
|
43
|
+
#
|
44
|
+
# XML_FILE The XML file to import
|
45
|
+
#
|
46
|
+
class Import < Command
|
47
|
+
|
48
|
+
include Importable
|
49
|
+
|
50
|
+
usage '[options] XML_FILE'
|
51
|
+
|
52
|
+
argument :xml_file, required: true,
|
53
|
+
desc: 'The XML file to import'
|
54
|
+
|
55
|
+
description 'Imports an nmap XML file into ronin-db'
|
56
|
+
|
57
|
+
man_page 'ronin-nmap-import.1'
|
58
|
+
|
59
|
+
#
|
60
|
+
# Runs the `ronin-nmap import` command.
|
61
|
+
#
|
62
|
+
# @param [String] xml_file
|
63
|
+
# The nmap XML file to import.
|
64
|
+
#
|
65
|
+
def run(xml_file)
|
66
|
+
unless File.file?(xml_file)
|
67
|
+
print_error "no such file or directory: #{xml_file}"
|
68
|
+
exit(1)
|
69
|
+
end
|
70
|
+
|
71
|
+
db_connect
|
72
|
+
import_file(xml_file)
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,226 @@
|
|
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/root'
|
23
|
+
|
24
|
+
require 'ronin/core/cli/generator'
|
25
|
+
|
26
|
+
module Ronin
|
27
|
+
module Nmap
|
28
|
+
class CLI
|
29
|
+
module Commands
|
30
|
+
#
|
31
|
+
# Generates a new nmap ruby script.
|
32
|
+
#
|
33
|
+
# ## Usage
|
34
|
+
#
|
35
|
+
# ronin-nmap new [options] FILE
|
36
|
+
#
|
37
|
+
# ## Options
|
38
|
+
#
|
39
|
+
# --parser Generate a nmap XML parser script
|
40
|
+
# --scanner Generate a nmap scanner script
|
41
|
+
# --printing Adds additional printing of the nmap scan data
|
42
|
+
# --import Also import the nmap XML scan data
|
43
|
+
# --xml-file XML_FILE Sets the XML file to write to or parse
|
44
|
+
# -p {PORT | [PORT1]-[PORT2]}[,...],
|
45
|
+
# --ports Sets the port range to scan
|
46
|
+
# --target TARGET Sets the targets to scan (Defaults: ARGV[0])
|
47
|
+
# -h, --help Print help information
|
48
|
+
#
|
49
|
+
# ## Arguments
|
50
|
+
#
|
51
|
+
# FILE The path to the new nmap ruby script.
|
52
|
+
#
|
53
|
+
# ## Examples
|
54
|
+
#
|
55
|
+
# ronin-nmap new scanner.rb --ports 22,80,443,8000-9000 --target example.com
|
56
|
+
# ronin-nmap new parser.rb --parser --xml-file path/to/nmap.xml --printing
|
57
|
+
#
|
58
|
+
class New < Command
|
59
|
+
|
60
|
+
include Core::CLI::Generator
|
61
|
+
|
62
|
+
template_dir File.join(ROOT,'data','templates')
|
63
|
+
|
64
|
+
usage '[options] FILE'
|
65
|
+
|
66
|
+
option :parser, desc: 'Generate a nmap XML parser script' do
|
67
|
+
@script_type = :parser
|
68
|
+
end
|
69
|
+
|
70
|
+
option :scanner, desc: 'Generate a nmap scanner script' do
|
71
|
+
@script_type = :scanner
|
72
|
+
end
|
73
|
+
|
74
|
+
option :printing, desc: 'Adds additional printing of the nmap scan data' do
|
75
|
+
@features[:printing] = true
|
76
|
+
end
|
77
|
+
|
78
|
+
option :import, desc: 'Also import the nmap XML scan data' do
|
79
|
+
@features[:import] = true
|
80
|
+
end
|
81
|
+
|
82
|
+
option :xml_file, value: {
|
83
|
+
type: String,
|
84
|
+
usage: 'XML_FILE'
|
85
|
+
},
|
86
|
+
desc: 'Sets the XML file to write to or parse' do |file|
|
87
|
+
@xml_file = file
|
88
|
+
end
|
89
|
+
|
90
|
+
option :syn_scan, desc: 'Enables SYN scanning' do
|
91
|
+
@syn_scan = true
|
92
|
+
end
|
93
|
+
|
94
|
+
option :ports, short: '-p',
|
95
|
+
value: {
|
96
|
+
type: String,
|
97
|
+
usage: '{PORT | [PORT1]-[PORT2]}[,...]'
|
98
|
+
},
|
99
|
+
desc: 'Sets the port range to scan' do |ports|
|
100
|
+
@ports = parse_port_range(ports)
|
101
|
+
rescue ArgumentError => error
|
102
|
+
raise(OptionParser::InvalidArgument,error.message)
|
103
|
+
end
|
104
|
+
|
105
|
+
option :target, value: {
|
106
|
+
type: String,
|
107
|
+
usage: 'TARGET'
|
108
|
+
},
|
109
|
+
desc: 'Sets the targets to scan (Defaults: ARGV[0])' do |target|
|
110
|
+
@targets << target
|
111
|
+
end
|
112
|
+
|
113
|
+
argument :path, desc: 'The path to the new nmap ruby script'
|
114
|
+
|
115
|
+
description 'Generates a new nmap ruby script'
|
116
|
+
|
117
|
+
man_page 'ronin-nmap-new.1'
|
118
|
+
|
119
|
+
examples [
|
120
|
+
"scanner.rb --ports 22,80,443,8000-9000 --target example.com",
|
121
|
+
"parser.rb --parser --xml-file path/to/nmap.xml --printing"
|
122
|
+
]
|
123
|
+
|
124
|
+
# The script type.
|
125
|
+
#
|
126
|
+
# @return [:scanner, :parser]
|
127
|
+
attr_reader :script_type
|
128
|
+
|
129
|
+
# The optioanl XML file to write to or parse.
|
130
|
+
#
|
131
|
+
# @return [String, nil]
|
132
|
+
attr_reader :xml_file
|
133
|
+
|
134
|
+
# Specifies whether to enable SYN scanning.
|
135
|
+
#
|
136
|
+
# @return [Boolean]
|
137
|
+
attr_reader :syn_scan
|
138
|
+
|
139
|
+
# The optional ports to scan.
|
140
|
+
#
|
141
|
+
# @return [Array<Integer, Range(Integer,Integer)>, "-", nil]
|
142
|
+
attr_reader :ports
|
143
|
+
|
144
|
+
# The targets to scan.
|
145
|
+
#
|
146
|
+
# @return [Array<String>]
|
147
|
+
attr_reader :targets
|
148
|
+
|
149
|
+
# Additional features.
|
150
|
+
#
|
151
|
+
# @return [Hash{Symbol => Boolean}]
|
152
|
+
attr_reader :features
|
153
|
+
|
154
|
+
#
|
155
|
+
# Initializes the `ronin-nmap new` command.
|
156
|
+
#
|
157
|
+
# @param [Hash{Symbol => Object}] kwargs
|
158
|
+
# Additional keyword arguments for the command.
|
159
|
+
#
|
160
|
+
def initialize(**kwargs)
|
161
|
+
super(**kwargs)
|
162
|
+
|
163
|
+
@script_type = :scanner
|
164
|
+
@targets = []
|
165
|
+
@features = {}
|
166
|
+
end
|
167
|
+
|
168
|
+
#
|
169
|
+
# Runs the `ronin-nmap new` command.
|
170
|
+
#
|
171
|
+
# @param [String] file
|
172
|
+
# The path to the new nmap ruby script.
|
173
|
+
#
|
174
|
+
def run(file)
|
175
|
+
@directory = File.dirname(file)
|
176
|
+
|
177
|
+
mkdir @directory unless File.directory?(@directory)
|
178
|
+
|
179
|
+
erb "script.rb.erb", file
|
180
|
+
chmod '+x', file
|
181
|
+
end
|
182
|
+
|
183
|
+
#
|
184
|
+
# Parses a port range.
|
185
|
+
#
|
186
|
+
# @param [String] ports
|
187
|
+
# The port range to parse.
|
188
|
+
#
|
189
|
+
# @return [Array<Integer, Range(Integer,Integer)>, "-"]
|
190
|
+
# The parsed port range.
|
191
|
+
#
|
192
|
+
# @raise [ArgumentError]
|
193
|
+
# An invalid port range was given.
|
194
|
+
#
|
195
|
+
def parse_port_range(ports)
|
196
|
+
case ports
|
197
|
+
when '-' then '-'
|
198
|
+
else
|
199
|
+
ports.split(',').map do |port|
|
200
|
+
case port
|
201
|
+
when /\A\d+-\d+\z/
|
202
|
+
start, stop = port.split('-',2)
|
203
|
+
|
204
|
+
(start.to_i..stop.to_i)
|
205
|
+
when /\A\d+-\z/
|
206
|
+
start = port.chomp('-')
|
207
|
+
|
208
|
+
(start.to_i..)
|
209
|
+
when /\A-\d+\z/
|
210
|
+
stop = port[1..]
|
211
|
+
|
212
|
+
(..stop.to_i)
|
213
|
+
when /\A\d+\z/
|
214
|
+
port.to_i
|
215
|
+
else
|
216
|
+
raise(ArgumentError,"invalid port range: #{ports.inspect}")
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|