ronin-nmap 0.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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