arp_scan 0.1.1 → 0.1.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 768a6997ecf0acffce32b3d52a16994e892b8f6fd93ec887613aebd478a6a86b
4
- data.tar.gz: d8c053296aae885d75e79b70a71d4e7264fdc3f5cf61c84d65b3019b89e56262
3
+ metadata.gz: e9acd4f2a06b8706a4991c24b6ed5ddce3e71f280440a1bfec82e2155c76375c
4
+ data.tar.gz: 26bef346fb5f6ee4f5c97dee98283c44b8b443fe7065e130ca9698c2ed569734
5
5
  SHA512:
6
- metadata.gz: 62d6e68337f32a52808e63dae880d09191b3b353c4338e4b05ee4349ed23572c594badb21af97a1336bba20dbad6b1d5aec23889acc16de63aa3e9e1ce8abbed
7
- data.tar.gz: af52cd4506b2a847041e296fbf9d2483a0fb23a2c5e520b45168850ef986105736be7e0512832a88b39390c218a7eb5df5e10d233566af9107f9a8c1b745ebf6
6
+ metadata.gz: 01af8e6a6a14daca95e60cc39ea2d529163019c48741bbcf0d70e527becd0b8c01ec43d9938b6e1e9c88efaa5ed36affce1fe6dd860df6dc0c1102c2652b99b4
7
+ data.tar.gz: 5665f838a56d966809fbeedc527efcbc9753677cc51847cacfe39af8b0177d8f54bcd95fd46fbbfa05b028026e433dee93f28da9bf019fe55dd409b554cd2db0
data/README.md CHANGED
@@ -7,23 +7,12 @@ Very simple wrapper for using and parsing output from `arp-scan`.
7
7
 
8
8
  You will need to make sure `arp-scan` is installed. See the arp-scan homepage at http://www.nta-monitor.com/tools/arp-scan/
9
9
 
10
- You'll also need superuser privileges to run `arp-scan`, you have have a few
11
- options but be sure to understand what you're doing before you do it:
12
-
13
- * Edit `/etc/sudoers` to allow user to run `arp-scan` as root without a
14
- password.
15
-
16
- `user host = (root) NOPASSWD: /usr/bin/arp-scan`
17
-
18
- * Set the SUID bit on the `arp-scan` bin:
19
-
20
- `sudo chmod u+s /usr/bin/arp-scan`
21
-
22
- * Run your Ruby code as root (I wouldn't do this)
23
-
24
- I use the SUID method but if you have other people logging into your machine you
25
- should probably go with the `/etc/sudoers` method.
10
+ `arp-scan` generally requires root privs to run. I use `setcap` to give it the
11
+ raw socket privs it needs so normal users can run it without sudo:
26
12
 
13
+ ```shell
14
+ sudo setcap cap_net_raw+ep /usr/bin/arp-scan
15
+ ```
27
16
 
28
17
  ## Notes
29
18
 
@@ -86,6 +75,20 @@ first_host.mac => '00:11:22:33:44:55'
86
75
  first_host.oui => "NIC Manufacturer"
87
76
  ```
88
77
 
78
+ ## Build the Gem
79
+
80
+ ```shell
81
+ bundle exec rake build
82
+ ```
83
+
84
+ This writes the packaged gem to `pkg/`.
85
+
86
+ ## Run the Tests
87
+
88
+ ```shell
89
+ bundle exec rake spec
90
+ ```
91
+
89
92
 
90
93
 
91
94
 
@@ -7,14 +7,23 @@ module ARPScan
7
7
  # delegates the parsing of the scan results to the ScanResultProcessor module.
8
8
  #
9
9
  module ARPScanner
10
+ # get array of file extensions, relevant for Windows
11
+ def self.exts
12
+ ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
13
+ end
14
+
15
+ # get array of paths
16
+ def self.paths
17
+ ENV['PATH'].split(File::PATH_SEPARATOR)
18
+ end
19
+
10
20
  # I got this method from: http://stackoverflow.com/questions/2108727
11
21
  # Cross-platform way of finding an executable in the $PATH.
12
22
  #
13
23
  # which('ruby') #=> /usr/bin/ruby
14
24
  #
15
25
  def self.which(cmd)
16
- exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
17
- ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
26
+ paths.each do |path|
18
27
  exts.each do |ext|
19
28
  exe = File.join(path, "#{cmd}#{ext}")
20
29
  return exe if File.executable?(exe) && !File.directory?(exe)
@@ -32,6 +41,6 @@ module ARPScan
32
41
  ScanResultProcessor.process(result_string, argument_string)
33
42
  end
34
43
 
35
- private_class_method :which
44
+ private_class_method :which, :exts, :paths
36
45
  end
37
46
  end
@@ -17,6 +17,14 @@ module ARPScan
17
17
  #
18
18
  attr_reader :datalink
19
19
 
20
+ # IP address of interface
21
+ #
22
+ attr_reader :ipv4
23
+
24
+ # MAC address of the interface
25
+ #
26
+ attr_reader :mac
27
+
20
28
  # `arp-scan` version number.
21
29
  #
22
30
  attr_reader :version
@@ -46,6 +54,8 @@ module ARPScan
46
54
  @hosts = hash[:hosts]
47
55
  @interface = hash[:interface]
48
56
  @datalink = hash[:datalink]
57
+ @ipv4 = hash[:ipv4]
58
+ @mac = hash[:mac]
49
59
  @version = hash[:version]
50
60
  @range_size = Integer(hash[:range_size])
51
61
  @scan_time = Float(hash[:scan_time])
@@ -74,6 +84,8 @@ module ARPScan
74
84
  { hosts: @hosts.map(&:to_hash),
75
85
  interface: @interface,
76
86
  datalink: @datalink,
87
+ ipv4: @ipv4,
88
+ mac: @mac,
77
89
  version: @version,
78
90
  range_size: @range_size,
79
91
  scan_time: @scan_time,
@@ -10,16 +10,24 @@ module ARPScan
10
10
  module ScanResultProcessor
11
11
  # Regex to capture IP address, MAC address, and OUI information
12
12
  #
13
- HOST_ENTRY_REGEX = /(\d+.\d+.\d+.\d+)\s(\w\w:\w\w:\w\w:\w\w:\w\w:\w\w)\s(.*)/.freeze
13
+ HOST_ENTRY_REGEX = /(\d+.\d+.\d+.\d+)\s(\w\w:\w\w:\w\w:\w\w:\w\w:\w\w)\s(.*)/
14
14
 
15
15
  # Regex to capture interface and datalink
16
16
  #
17
- INTERFACE_SUMMARY_REGEX = /Interface: (?<interface>.+), datalink type: (?<datalink>.*$)/.freeze
17
+ INTERFACE_SUMMARY_REGEX = /
18
+ ^Interface:\s+(?<interface>[^,\n]+),
19
+ (?:\s*datalink)?\s*type:\s*(?<datalink>[^\n,]+?)(?=,\s*MAC:|$)
20
+ (?:,\s*MAC:\s*(?<mac>[0-9A-Fa-f]{2}(?::[0-9A-Fa-f]{2}){5}))?
21
+ (?:,\s*IPv4:\s*(?<ipv4>(?:(?:25[0-5]|2[0-4]\d|1?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|1?\d?\d)))?
22
+ $
23
+ /x
24
+
25
+
18
26
 
19
27
  # Regex to capture arp-scan version, scan range size, scan time, scan rate,
20
28
  # and the number of responding hosts.
21
29
  #
22
- SCAN_SUMMARY_REGEX = %r{Ending arp-scan (?<version>.*): (?<range_size>.*) hosts scanned in (?<scan_time>.*) seconds \((?<scan_rate>.*) hosts/sec\). (?<reply_count>.*) responded}.freeze
30
+ SCAN_SUMMARY_REGEX = %r{Ending arp-scan (?<version>.*): (?<range_size>.*) hosts scanned in (?<scan_time>.*) seconds \((?<scan_rate>.*) hosts/sec\). (?<reply_count>.*) responded}
23
31
 
24
32
  # This method does the actual processing of the arp-scan result string. It
25
33
  # uses the Regexes to capture data then passes the results to ScanRepor.new
@@ -29,12 +37,14 @@ module ARPScan
29
37
  results = {}
30
38
  results[:hosts] = string.scan(HOST_ENTRY_REGEX).map { |entry| Host.new(*entry) }
31
39
  results[:interface],
32
- results[:datalink] = string.scan(INTERFACE_SUMMARY_REGEX)[0]
40
+ results[:datalink],
41
+ results[:mac],
42
+ results[:ipv4] = string.scan(INTERFACE_SUMMARY_REGEX)[0]
33
43
  results[:version],
34
- results[:range_size],
35
- results[:scan_time],
36
- results[:scan_rate],
37
- results[:reply_count] = string.scan(SCAN_SUMMARY_REGEX)[0]
44
+ results[:range_size],
45
+ results[:scan_time],
46
+ results[:scan_rate],
47
+ results[:reply_count] = string.scan(SCAN_SUMMARY_REGEX)[0]
38
48
  results[:arguments] = arguments
39
49
  ScanReport.new(results)
40
50
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ARPScan
4
- VERSION = '0.1.1'
4
+ VERSION = '0.1.3'
5
5
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arp_scan
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Rodrigues
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2021-07-11 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies: []
13
12
  description: Use the arp-scan utility from your ruby programs.
14
13
  email:
@@ -17,29 +16,18 @@ executables: []
17
16
  extensions: []
18
17
  extra_rdoc_files: []
19
18
  files:
20
- - Gemfile
21
- - Gemfile.lock
22
19
  - LICENSE.txt
23
20
  - README.md
24
- - arp_scan.gemspec
25
21
  - lib/arp_scan.rb
26
22
  - lib/arp_scan/arp_scanner.rb
27
23
  - lib/arp_scan/host.rb
28
24
  - lib/arp_scan/scan_report.rb
29
25
  - lib/arp_scan/scan_result_processor.rb
30
26
  - lib/arp_scan/version.rb
31
- - spec/arp_scan_spec.rb
32
- - spec/arp_scanner_spec.rb
33
- - spec/host_spec.rb
34
- - spec/scan_report_spec.rb
35
- - spec/scan_result_processor_spec.rb
36
- - spec/spec_helper.rb
37
- - spec/test_output.txt
38
27
  homepage: https://github.com/mikerodrigues/arp_scan
39
28
  licenses:
40
29
  - MIT
41
30
  metadata: {}
42
- post_install_message:
43
31
  rdoc_options: []
44
32
  require_paths:
45
33
  - lib
@@ -54,15 +42,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
54
42
  - !ruby/object:Gem::Version
55
43
  version: '0'
56
44
  requirements: []
57
- rubygems_version: 3.2.3
58
- signing_key:
45
+ rubygems_version: 3.7.1
59
46
  specification_version: 4
60
47
  summary: A ruby wrapper for the arp-scan utility.
61
- test_files:
62
- - spec/arp_scan_spec.rb
63
- - spec/arp_scanner_spec.rb
64
- - spec/host_spec.rb
65
- - spec/scan_report_spec.rb
66
- - spec/scan_result_processor_spec.rb
67
- - spec/spec_helper.rb
68
- - spec/test_output.txt
48
+ test_files: []
data/Gemfile DELETED
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source 'https://rubygems.org'
4
-
5
- group :test do
6
- gem 'rspec'
7
- gem 'rspec-support', '~>3.0.0'
8
- end
9
-
10
- # Specify your gem's dependencies in arp_scan.gemspec
11
- # gemspec
data/Gemfile.lock DELETED
@@ -1,26 +0,0 @@
1
- GEM
2
- remote: https://rubygems.org/
3
- specs:
4
- diff-lcs (1.4.4)
5
- rspec (3.0.0)
6
- rspec-core (~> 3.0.0)
7
- rspec-expectations (~> 3.0.0)
8
- rspec-mocks (~> 3.0.0)
9
- rspec-core (3.0.4)
10
- rspec-support (~> 3.0.0)
11
- rspec-expectations (3.0.4)
12
- diff-lcs (>= 1.2.0, < 2.0)
13
- rspec-support (~> 3.0.0)
14
- rspec-mocks (3.0.4)
15
- rspec-support (~> 3.0.0)
16
- rspec-support (3.0.4)
17
-
18
- PLATFORMS
19
- x86_64-linux
20
-
21
- DEPENDENCIES
22
- rspec
23
- rspec-support (~> 3.0.0)
24
-
25
- BUNDLED WITH
26
- 2.2.15
data/arp_scan.gemspec DELETED
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- lib = File.expand_path('lib', __dir__)
4
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require 'arp_scan/version'
6
-
7
- Gem::Specification.new do |spec|
8
- spec.name = 'arp_scan'
9
- spec.version = ARPScan::VERSION
10
- spec.authors = ['Michael Rodrigues']
11
- spec.email = ['mikebrodrigues@gmail.com']
12
- spec.summary = 'A ruby wrapper for the arp-scan utility.'
13
- spec.description = 'Use the arp-scan utility from your ruby programs.'
14
- spec.homepage = 'https://github.com/mikerodrigues/arp_scan'
15
- spec.license = 'MIT'
16
-
17
- spec.files = `git ls-files -z`.split("\x0")
18
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
- spec.require_paths = ['lib']
21
-
22
- end
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative './spec_helper.rb'
4
-
5
- RSpec.describe ARPScan do
6
- ARPScan('-l')
7
- it 'is a method' do
8
- expect(ARPScan.respond_to?('__send__')).to eq(true)
9
- end
10
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative './spec_helper'
4
-
5
- module ARPScan
6
- describe ARPScanner do
7
- describe '#scan' do
8
- it 'accepts arp-scan arguments as a string' do
9
- expect(ARPScanner.scan('-l').class).to eq(ScanReport)
10
- end
11
- end
12
- end
13
- end
data/spec/host_spec.rb DELETED
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative './spec_helper'
4
-
5
- module ARPScan
6
- describe Host do
7
- host = Host.new('10.0.0.1', '00:11:22:33:44:55', 'NIC Manufacturer')
8
-
9
- describe '#ip_addr' do
10
- it "returns the host's IP address" do
11
- expect(host.ip_addr).to eq('10.0.0.1')
12
- end
13
- end
14
-
15
- describe '#mac' do
16
- it "returns the host's MAC address" do
17
- expect(host.mac).to eq('00:11:22:33:44:55')
18
- end
19
- end
20
-
21
- describe '#oui' do
22
- it "returns the host's OUI information" do
23
- expect(host.oui).to eq('NIC Manufacturer')
24
- end
25
- end
26
- end
27
- end
@@ -1,76 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative './spec_helper'
4
-
5
- module ARPScan
6
- describe ScanReport do
7
- report_hash = {
8
- hosts: [Host.new('10.0.0.1', '00:11:22:33:44:55', 'NIC Manufacturer')],
9
- interface: 'eth0',
10
- datalink: 'EN10MB (Ethernet)',
11
- version: '1.8.1',
12
- range_size: 256,
13
- scan_time: 1.503,
14
- scan_rate: 170.33,
15
- reply_count: 1,
16
- arguments: '-l'
17
- }
18
-
19
- scan_report = ScanReport.new(report_hash)
20
-
21
- describe '#hosts' do
22
- it 'returns an Array of Host objects' do
23
- expect(scan_report.hosts.class).to eq(Array)
24
- expect(scan_report.hosts.first.class).to eq(Host)
25
- end
26
- end
27
-
28
- describe '#interface' do
29
- it 'returns the network interface used to scan' do
30
- expect(scan_report.interface).to eq('eth0')
31
- end
32
- end
33
-
34
- describe '#datalink' do
35
- it 'returns the datalink type of the network interface used to scan' do
36
- expect(scan_report.datalink).to eq('EN10MB (Ethernet)')
37
- end
38
- end
39
-
40
- describe '#version' do
41
- it 'returns the version of `arp-scan` used for the scan' do
42
- expect(scan_report.version).to eq('1.8.1')
43
- end
44
- end
45
-
46
- describe '#range_size' do
47
- it 'returns the size of the range of scanned IPs' do
48
- expect(scan_report.range_size).to eq(256)
49
- end
50
- end
51
-
52
- describe '#scan_time' do
53
- it 'returns the duration of the scan in seconds' do
54
- expect(scan_report.scan_time).to eq(1.503)
55
- end
56
- end
57
-
58
- describe '#scan_rate' do
59
- it 'returns the scan rate in hosts per second' do
60
- expect(scan_report.scan_rate).to eq(170.33)
61
- end
62
- end
63
-
64
- describe '#reply_count' do
65
- it 'returns the number of hosts that responded' do
66
- expect(scan_report.reply_count).to eq(1)
67
- end
68
- end
69
-
70
- describe '#arguments' do
71
- it 'returns the argument string used to scan' do
72
- expect(scan_report.arguments).to eq('-l')
73
- end
74
- end
75
- end
76
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative './spec_helper'
4
-
5
- module ARPScan
6
- describe ScanResultProcessor do
7
- argument_string = '-l'
8
- report_string = File.read './test_output.txt'
9
- report = ARPScan::ScanResultProcessor.process(report_string, argument_string)
10
-
11
- describe '#process' do
12
- it 'processes arp-scan output to create a ScanReport object' do
13
- expect(report.class).to eq(ARPScan::ScanReport)
14
- end
15
-
16
- it 'builds an array of Host objects' do
17
- expect(report.hosts[0].class).to eq(ARPScan::Host)
18
- end
19
-
20
- it 'parses the scan interface name' do
21
- expect(report.interface).to eq('eth0')
22
- end
23
-
24
- it 'parses the datalink type information' do
25
- expect(report.datalink).to eq('EN10MB (Ethernet)')
26
- end
27
-
28
- it 'parses the version of arp-scan that ran the scan' do
29
- expect(report.version).to eq('1.8.1')
30
- end
31
-
32
- it 'parses the number of hosts scanned' do
33
- expect(report.range_size).to eq(256)
34
- end
35
-
36
- it 'parses the duration of the scan in seconds' do
37
- expect(report.scan_time).to eq(1.494)
38
- end
39
-
40
- it 'parses the rate of the scan in hosts per second' do
41
- expect(report.scan_rate).to eq(171.35)
42
- end
43
-
44
- it 'parses the number of hosts that responded to the scan' do
45
- expect(report.reply_count).to eq(1)
46
- end
47
-
48
- it 'includes the argument string in the report' do
49
- expect(report.arguments).to eq('-l')
50
- end
51
- end
52
- end
53
- end
data/spec/spec_helper.rb DELETED
@@ -1,3 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require '../lib/arp_scan'
data/spec/test_output.txt DELETED
@@ -1,6 +0,0 @@
1
- Interface: eth0, datalink type: EN10MB (Ethernet)
2
- Starting arp-scan 1.8.1 with 256 hosts (http://www.nta-monitor.com/tools/arp-scan/)
3
- 10.0.0.1 00:11:22:33:44:55 NIC Manufacturer
4
-
5
- 1 packets received by filter, 0 packets dropped by kernel
6
- Ending arp-scan 1.8.1: 256 hosts scanned in 1.494 seconds (171.35 hosts/sec). 1 responded