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,54 @@
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/converters/json'
22
+ require 'ronin/nmap/converters/csv'
23
+
24
+ module Ronin
25
+ module Nmap
26
+ #
27
+ # @api private
28
+ #
29
+ module Converters
30
+ # Mapping of formats to converter modules.
31
+ FORMATS = {
32
+ json: JSON,
33
+ csv: CSV
34
+ }
35
+
36
+ #
37
+ # Fetches the converter for the given format.
38
+ #
39
+ # @param [:json, :csv] format
40
+ #
41
+ # @return [Converters::JSON, Converters::CSV]
42
+ # The converter module.
43
+ #
44
+ # @raise [ArgumentError]
45
+ # The given format is unsupported.
46
+ #
47
+ def self.[](format)
48
+ FORMATS.fetch(format) do
49
+ raise(ArgumentError,"unsupported format: #{format.inspect}")
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,47 @@
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
+ module Ronin
22
+ module Nmap
23
+ #
24
+ # Base class for all {Ronin::Nmap} exceptions.
25
+ #
26
+ # @api public
27
+ #
28
+ class Exception < RuntimeError
29
+ end
30
+
31
+ #
32
+ # Indicates that the `nmap` command is not installed.
33
+ #
34
+ # @api public
35
+ #
36
+ class NotInstalled < Exception
37
+ end
38
+
39
+ #
40
+ # Indicates that an `nmap` scan failed.
41
+ #
42
+ # @api public
43
+ #
44
+ class ScanFailed < Exception
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,369 @@
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/db'
22
+ require 'nmap/xml'
23
+
24
+ module Ronin
25
+ module Nmap
26
+ #
27
+ # Handles importing a parsed nmap XML file into [ronin-db].
28
+ #
29
+ # [ronin-db]: https://github.com/ronin-rb/ronin-db#readme
30
+ #
31
+ # ## Examples
32
+ #
33
+ # require 'ronin/nmap/importer'
34
+ #
35
+ # Ronin::DB.connect
36
+ # Ronin::Nmap::Importer.import_file('scan.xml') do |record|
37
+ # puts "Imported #{record.inspect}!"
38
+ # end
39
+ #
40
+ module Importer
41
+ #
42
+ # Parses the nmap XML file and imports it's contents into the database.
43
+ #
44
+ # @param [String] path
45
+ # The path to the nmap XML file to parse and import.
46
+ #
47
+ # @yield [imported]
48
+ # If a block is given, it will be passed the imported database records.
49
+ #
50
+ # @yieldparam [Ronin::DB::IPAddress,
51
+ # Ronin::DB::MACAddress,
52
+ # Ronin::DB::HostName,
53
+ # Ronin::DB::Port,
54
+ # Ronin::DB::Service,
55
+ # Ronin::DB::OpenPort] imported
56
+ # An imported IP address, MAC address, host name, or open port.
57
+ #
58
+ # @return [Array<Ronin::DB::IPAddress>]
59
+ # If no block was given, then an Array of imported IP addresses will
60
+ # be returned.
61
+ #
62
+ def self.import_file(path,&block)
63
+ import(::Nmap::XML.open(path),&block)
64
+ end
65
+
66
+ #
67
+ # Imports the parsed nmap XML into the database.
68
+ #
69
+ # @param [::Nmap::XML] xml
70
+ # The parsed nmap XML document.
71
+ #
72
+ # @yield [imported]
73
+ # If a block is given, it will be passed the imported database records.
74
+ #
75
+ # @yieldparam [Ronin::DB::IPAddress,
76
+ # Ronin::DB::MACAddress,
77
+ # Ronin::DB::HostName,
78
+ # Ronin::DB::Port,
79
+ # Ronin::DB::Service,
80
+ # Ronin::DB::OpenPort] imported
81
+ # An imported IP address, MAC address, host name, or open port.
82
+ #
83
+ # @return [Array<Ronin::DB::IPAddress>]
84
+ # If no block was given, then an Array of imported IP addresses will
85
+ # be returned.
86
+ #
87
+ def self.import(xml,&block)
88
+ return enum_for(__method__,xml).to_a unless block
89
+
90
+ xml.each_up_host do |host|
91
+ import_host(host,&block)
92
+ end
93
+ end
94
+
95
+ #
96
+ # Imports an nmap host into the database.
97
+ #
98
+ # @yield [imported]
99
+ # If a block is given, it will be passed the imported database records.
100
+ #
101
+ # @yieldparam [Ronin::DB::IPAddress,
102
+ # Ronin::DB::MACAddress,
103
+ # Ronin::DB::HostName,
104
+ # Ronin::DB::Port,
105
+ # Ronin::DB::Service,
106
+ # Ronin::DB::OpenPort] imported
107
+ # An imported IP address, MAC address, host name, or open port.
108
+ #
109
+ # @param [::Nmap::XML::Host] host
110
+ #
111
+ # @return [Array<Ronin::DB::IPAddress>]
112
+ #
113
+ def self.import_host(host,&block)
114
+ imported_ip_addresses, = import_addresses(host,&block)
115
+ imported_hostnames = import_hostnames(host,&block)
116
+
117
+ # associate any imported host names with the imported IP addresses
118
+ imported_hostnames.each do |imported_hostname|
119
+ imported_ip_addresses.each do |imported_ip_address|
120
+ DB::HostNameIPAddress.transaction do
121
+ DB::HostNameIPAddress.find_or_create_by(
122
+ host_name: imported_hostname,
123
+ ip_address: imported_ip_address
124
+ )
125
+ end
126
+ end
127
+ end
128
+
129
+ host.each_open_port do |port|
130
+ imported_port, imported_service = import_port(port,&block)
131
+
132
+ # associate the imported port with the imported IP addresses
133
+ imported_ip_addresses.each do |imported_ip_address|
134
+ import_open_port(imported_ip_address,
135
+ imported_port,
136
+ imported_service,
137
+ &block)
138
+ end
139
+ end
140
+
141
+ return imported_ip_addresses
142
+ end
143
+
144
+ #
145
+ # Creates or updates an open port association between the imported IP
146
+ # address, imported port, and imported service.
147
+ #
148
+ # @param [Ronin::DB::IPAddress] imported_ip_address
149
+ #
150
+ # @param [Ronin::DB::Port] imported_port
151
+ #
152
+ # @param [Ronin::DB::Service] imported_service
153
+ #
154
+ # @return [Ronin::DB::OpenPort]
155
+ #
156
+ def self.import_open_port(imported_ip_address,
157
+ imported_port,
158
+ imported_service)
159
+ imported_open_port = DB::OpenPort.transaction do
160
+ DB::OpenPort.find_or_create_by(
161
+ ip_address: imported_ip_address,
162
+ port: imported_port,
163
+ service: imported_service
164
+ )
165
+ end
166
+
167
+ yield imported_open_port if block_given?
168
+ return imported_open_port
169
+ end
170
+
171
+ #
172
+ # Imports the host names for the scanned nmap host.
173
+ #
174
+ # @param [::Nmap::XML::Host] host
175
+ #
176
+ # @yield [imported]
177
+ # If a block is given, it will be passed the imported database records.
178
+ #
179
+ # @yieldparam [Ronin::DB::HostName] imported
180
+ # An imported host name.
181
+ #
182
+ # @return [Array<Ronin::DB::HostName>]
183
+ #
184
+ def self.import_hostnames(host)
185
+ host.each_hostname.map do |hostname|
186
+ imported_host_name = import_hostname(hostname)
187
+ yield imported_host_name if block_given?
188
+ imported_host_name
189
+ end
190
+ end
191
+
192
+ #
193
+ # Imports a hostname into the database.
194
+ #
195
+ # @param [::Nmap::XML::HostName] hostname
196
+ # The nmap XML hostname object to import.
197
+ #
198
+ # @return [Ronin::DB::HostName]
199
+ # The imported host name.
200
+ #
201
+ def self.import_hostname(hostname)
202
+ DB::HostName.transaction do
203
+ DB::HostName.find_or_import(hostname.name)
204
+ end
205
+ end
206
+
207
+ #
208
+ # Imports the addresses for a host.
209
+ #
210
+ # @param [::Nmap::XML::Host] host
211
+ #
212
+ # @yield [imported]
213
+ # If a block is given, it will be passed the imported database records.
214
+ #
215
+ # @yieldparam [Ronin::DB::IPAddress, Ronin::DB::MACAddress] imported
216
+ # An imported IP address or MAC address.
217
+ #
218
+ # @return [(Array<Ronin::DB::IPAddress>, Array<Ronin::DB::MACAddress>)]
219
+ # The imported IP addresses and MAC addresses.
220
+ #
221
+ def self.import_addresses(host,&block)
222
+ imported_ip_addresses = []
223
+ imported_mac_addresses = []
224
+
225
+ host.each_address do |address|
226
+ case (imported_address = import_address(address,&block))
227
+ when DB::IPAddress
228
+ imported_ip_addresses << imported_address
229
+ when DB::MACAddress
230
+ imported_mac_addresses << imported_address
231
+ end
232
+ end
233
+
234
+ # associate any imported MAC addresses with the imported IP addresses
235
+ imported_mac_addresses.each do |imported_mac_address|
236
+ imported_ip_addresses.each do |imported_ip_address|
237
+ DB::IPAddressMACAddress.transaction do
238
+ DB::IPAddressMACAddress.find_or_create_by(
239
+ mac_address: imported_mac_address,
240
+ ip_address: imported_ip_address
241
+ )
242
+ end
243
+ end
244
+ end
245
+
246
+ return imported_ip_addresses, imported_mac_addresses
247
+ end
248
+
249
+ #
250
+ # Imports and IP address or a MAC address into the database.
251
+ #
252
+ # @param [::Nmap::XML::Address] address
253
+ # The nmap XML address object.
254
+ #
255
+ # @yield [imported]
256
+ # If a block is given, it will be passed the imported address.
257
+ #
258
+ # @yieldparam [Ronin::DB::IPAddress, Ronin::DB::MACAddress] imported
259
+ # The imported IP address or MAC address record.
260
+ #
261
+ # @return [Ronin::DB::IPAddress, Ronin::DB::MACAddress]
262
+ # The imported IP address or MAC address.
263
+ #
264
+ def self.import_address(address,&block)
265
+ case address.type
266
+ when :ipv4, :ipv6 then import_ip_address(address,&block)
267
+ when :mac then import_mac_address(address,&block)
268
+ end
269
+ end
270
+
271
+ # Mapping of nmap XML IP address types to IP versions.
272
+ IP_VERSIONS = {
273
+ ipv4: 4,
274
+ ipv6: 6
275
+ }
276
+
277
+ #
278
+ # Imports an IP address into the database.
279
+ #
280
+ # @param [::Nmap::XML::Address] address
281
+ # The nmap XML IP address object.
282
+ #
283
+ # @yield [imported]
284
+ # If a block is given, it will be passed the imported IP address.
285
+ #
286
+ # @yieldparam [Ronin::DB::IPAddress] imported
287
+ # The imported IP address record.
288
+ #
289
+ # @return [Ronin::DB::IPAddress]
290
+ # The imported IP address.
291
+ #
292
+ def self.import_ip_address(address,&block)
293
+ imported_ip_address = DB::IPAddress.transaction do
294
+ DB::IPAddress.find_or_create_by(
295
+ version: IP_VERSIONS.fetch(address.type),
296
+ address: address.addr
297
+ )
298
+ end
299
+
300
+ yield imported_ip_address if block_given?
301
+ return imported_ip_address
302
+ end
303
+
304
+ #
305
+ # Imports an MAC address into the database.
306
+ #
307
+ # @param [::Nmap::XML::Address] address
308
+ # The nmap XML MAC address object.
309
+ #
310
+ # @yield [imported]
311
+ # If a block is given, it will be passed the imported MAC address
312
+ # reocrd.
313
+ #
314
+ # @yieldparam [Ronin::DB::MACAddress] imported
315
+ # The imported MAC address record.
316
+ #
317
+ # @return [Ronin::DB::MACAddress]
318
+ # The imported MAC address.
319
+ #
320
+ def self.import_mac_address(address,&block)
321
+ imported_mac_address = DB::MACAddress.transaction do
322
+ DB::MACAddress.find_or_import(address.addr)
323
+ end
324
+
325
+ yield imported_mac_address if block_given?
326
+ return imported_mac_address
327
+ end
328
+
329
+ #
330
+ # Import an nmap port.
331
+ #
332
+ # @param [::Nmap::XML::Port] port
333
+ # The nmap port.
334
+ #
335
+ # @yield [imported]
336
+ # If a block is given, it will be passed the imported database records.
337
+ #
338
+ # @yieldparam [Ronin::DB::Port, Ronin::DB::Service] imported
339
+ # An imported port or service.
340
+ #
341
+ # @return [Ronin::DB::Port, (Ronin::DB::Port, Ronin::DB::Service)]
342
+ # The imported port and optionally the imported service.
343
+ #
344
+ def self.import_port(port)
345
+ imported_port = DB::Port.transaction do
346
+ DB::Port.find_or_create_by(
347
+ protocol: port.protocol,
348
+ number: port.number
349
+ )
350
+ end
351
+
352
+ imported_service = if (service = port.service)
353
+ DB::Service.transaction do
354
+ DB::Service.find_or_create_by(
355
+ name: service.name
356
+ )
357
+ end
358
+ end
359
+
360
+ if block_given?
361
+ yield imported_port
362
+ yield imported_service if imported_service
363
+ end
364
+
365
+ return imported_port, imported_service
366
+ end
367
+ end
368
+ end
369
+ end
@@ -0,0 +1,28 @@
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
+ module Ronin
22
+ module Nmap
23
+ # Path to `ronin-nmap` root directory.
24
+ #
25
+ # @api private
26
+ ROOT = File.expand_path(File.join(__dir__,'..','..','..'))
27
+ end
28
+ end
@@ -0,0 +1,26 @@
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
+ module Ronin
22
+ module Nmap
23
+ # ronin-nmap version
24
+ VERSION = '0.1.0.rc1'
25
+ end
26
+ end