nmunch 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/nmunch/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Michael Henriksen"]
6
+ gem.email = ["michenriksen87@gmail.com"]
7
+ gem.description = %q{Nmunch is a passive network discovery tool that finds live network nodes by analyzing ARP and broadcast packets.}
8
+ gem.summary = %q{OM NOM NOM NOM}
9
+ gem.homepage = "https://github.com/michenriksen/nmunch"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "nmunch"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Nmunch::VERSION
17
+ gem.add_development_dependency('rspec')
18
+ gem.add_development_dependency('rake', '>= 0.9.2')
19
+ gem.add_dependency('methadone', '~> 1.2.3')
20
+ gem.add_dependency('pcap', '~> 0.7.7')
21
+ gem.add_dependency('paint')
22
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nmunch::Dissectors::Arp do
4
+ let(:arp_pcap_packet) do
5
+ packet = stub(Pcap::Packet)
6
+ packet.stub(:raw_data).and_return(ARP_PACKET_DATA)
7
+ packet.stub(:ip?).and_return(false)
8
+ packet
9
+ end
10
+
11
+ subject { Nmunch::Dissectors::Arp.new(arp_pcap_packet) }
12
+
13
+ describe '#ip_address' do
14
+ it 'returns correct IP address' do
15
+ subject.ip_address.should == '192.168.0.125'
16
+ end
17
+ end
18
+
19
+ describe '#mac_address' do
20
+ it 'returns correct MAC address' do
21
+ subject.mac_address.should == 'de:ad:be:ef:de:ad'
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nmunch::Dissectors::Base do
4
+ let(:arp_pcap_packet) do
5
+ packet = stub(Pcap::Packet)
6
+ packet.stub(:raw_data).and_return(ARP_PACKET_DATA)
7
+ packet.stub(:ip?).and_return(false)
8
+ packet
9
+ end
10
+
11
+ let(:ip_pcap_packet) do
12
+ packet = stub(Pcap::Packet)
13
+ packet.stub(:raw_data).and_return(IP_PACKET_DATA)
14
+ packet.stub(:ip?).and_return(true)
15
+ packet
16
+ end
17
+
18
+ subject { Nmunch::Dissectors::Base.new(arp_pcap_packet) }
19
+
20
+ describe '#pcap_packet' do
21
+ it 'returns pcap packet given in initializer' do
22
+ subject.pcap_packet.should == arp_pcap_packet
23
+ end
24
+ end
25
+
26
+ describe '#raw_data' do
27
+ it 'returns an array of bytes represented in HEX' do
28
+ subject.raw_data.should == ARP_PACKET_DATA.unpack('H*').first.scan(/.{2}/)
29
+ end
30
+ end
31
+
32
+ describe '.factory' do
33
+ context 'when given ARP packet' do
34
+ it 'returns an ARP dissector' do
35
+ Nmunch::Dissectors::Base.factory(arp_pcap_packet).should be_a(Nmunch::Dissectors::Arp)
36
+ end
37
+ end
38
+
39
+ context 'when given an IP packet' do
40
+ it 'returns an IP dissector' do
41
+ Nmunch::Dissectors::Base.factory(ip_pcap_packet).should be_a(Nmunch::Dissectors::Ip)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nmunch::Dissectors::Ip do
4
+ let(:ip_pcap_packet) do
5
+ packet = stub(Pcap::Packet)
6
+ packet.stub(:raw_data).and_return(IP_PACKET_DATA)
7
+ packet.stub(:ip?).and_return(true)
8
+ packet
9
+ end
10
+
11
+ subject { Nmunch::Dissectors::Ip.new(ip_pcap_packet) }
12
+
13
+ describe '#ip_address' do
14
+ it 'returns correct IP address' do
15
+ ip_pcap_packet.should_receive(:ip_src).and_return('192.168.0.125')
16
+ subject.ip_address.should == '192.168.0.125'
17
+ end
18
+ end
19
+
20
+ describe '#mac_address' do
21
+ it 'returns correct MAC address' do
22
+ subject.mac_address.should == 'de:ad:be:ef:de:ad'
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nmunch::MacOuiLookup do
4
+ context 'when given an Apple mac address' do
5
+ it 'returns Apple' do
6
+ Nmunch::MacOuiLookup.instance.lookup('58:b0:35:31:33:73').should == 'Apple'
7
+ end
8
+ end
9
+
10
+ context 'when given a Cisco mac address' do
11
+ it 'returns Cisco Systems' do
12
+ Nmunch::MacOuiLookup.instance.lookup('00:01:63:42:42:42').should == 'Cisco Systems'
13
+ end
14
+ end
15
+
16
+ context 'when given a mac address with an unknown prefix' do
17
+ it 'returns Unknown' do
18
+ Nmunch::MacOuiLookup.instance.lookup('de:ad:be:ef:de:ad').should == 'Unknown'
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nmunch::Node do
4
+ subject { Nmunch::Node.new(ip_address: '192.168.0.1', mac_address: 'de:ad:be:ef:de:ad') }
5
+
6
+ describe '#ip_address' do
7
+ it 'returns correct IP address' do
8
+ subject.ip_address.should == '192.168.0.1'
9
+ end
10
+ end
11
+
12
+ describe '#mac_address' do
13
+ it 'returns correct MAC address' do
14
+ subject.mac_address.should == 'de:ad:be:ef:de:ad'
15
+ end
16
+ end
17
+
18
+ describe '#meta_address?' do
19
+ context 'when IP is not a meta address' do
20
+ it 'returns false' do
21
+ subject.should_not be_meta_address
22
+ end
23
+ end
24
+
25
+ context 'when IP is a meta address' do
26
+ it 'returns true' do
27
+ subject.stub(:ip_address).and_return('0.0.0.0')
28
+ subject.should be_meta_address
29
+ end
30
+ end
31
+ end
32
+
33
+ describe '.create_from_dissector' do
34
+ let(:dissector) do
35
+ dissector = stub
36
+ dissector.stub(:ip_address).and_return('192.168.0.1')
37
+ dissector.stub(:mac_address).and_return('de:ad:be:ef:de:ad')
38
+ dissector
39
+ end
40
+ subject { Nmunch::Node.create_from_dissector(dissector) }
41
+
42
+ it 'returns a node' do
43
+ subject.should be_a(Nmunch::Node)
44
+ end
45
+
46
+ it 'has correct IP address' do
47
+ subject.ip_address.should == '192.168.0.1'
48
+ end
49
+
50
+ it 'has correct MAC address' do
51
+ subject.mac_address.should == 'de:ad:be:ef:de:ad'
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ class TestSubscriber
4
+ def process(node); end
5
+ end
6
+
7
+ describe Nmunch::Report do
8
+ let(:node) { Nmunch::Node.new(ip_address: '192.168.0.1', mac_address: 'de:ad:be:ef:de:ad') }
9
+ let(:options) { {interface: 'en1'} }
10
+ let(:subscriber) { TestSubscriber.new }
11
+ subject { Nmunch::Report.new(options) }
12
+
13
+ describe '#publish_node' do
14
+ before(:each) do
15
+ subject.register_subscriber(subscriber)
16
+ end
17
+
18
+ it 'delegates the node to the subscriber' do
19
+ subscriber.should_receive(:process).with(node)
20
+ subject.publish_node(node)
21
+ end
22
+
23
+ context 'when node has a meta address' do
24
+ it 'does not delegate node to subscribers' do
25
+ node.stub(:ip_address).and_return('0.0.0.0')
26
+ subscriber.should_not_receive(:process)
27
+ subject.publish_node(node)
28
+ end
29
+ end
30
+
31
+ context 'when node is already discovered' do
32
+ it 'does not delegate node to subscribers' do
33
+ subject.publish_node(node)
34
+ subscriber.should_not_receive(:process)
35
+ subject.publish_node(node)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nmunch::Subscribers::Base do
4
+ let(:options) { {interface: 'en1'} }
5
+ subject { Nmunch::Subscribers::Base.new(options) }
6
+
7
+ describe '.initialize' do
8
+ it 'assigns options to instance variable' do
9
+ subject.options.should == options
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nmunch::Subscribers::Stdout do
4
+ let(:node) { Nmunch::Node.new(ip_address: '192.168.0.1', mac_address: 'de:ad:be:ef:de:ad') }
5
+ let(:options) { {interface: 'en1'} }
6
+ subject { Nmunch::Subscribers::Stdout.new(options) }
7
+
8
+ describe '#process' do
9
+ it 'prints node details to STDOUT' do
10
+ output = capture_stdout { subject.process(node) }
11
+ output.should include('192.168.0.1')
12
+ output.should include('de:ad:be:ef:de:ad')
13
+ output.should include('Unknown')
14
+ end
15
+
16
+ context 'when --no-prefix-lookup option is set' do
17
+ it 'does not look up mac address prefix' do
18
+ options['no-prefix-lookup'] = true
19
+ output = capture_stdout { subject.process(node) }
20
+ output.should include('192.168.0.1')
21
+ output.should include('de:ad:be:ef:de:ad')
22
+ output.should_not include('Unknown')
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nmunch do
4
+ describe 'PCAP filter expression' do
5
+ it 'allows only ARP and broadcast packets' do
6
+ Nmunch::CAPTURE_FILTER.should == 'arp or broadcast'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,43 @@
1
+ require 'bundler'
2
+ begin
3
+ Bundler.setup(:default, :development)
4
+ rescue Bundler::BundlerError => e
5
+ $stderr.puts e.message
6
+ $stderr.puts 'Run `bundle install` to install missing gems'
7
+ exit e.status_code
8
+ end
9
+
10
+ require 'pcap'
11
+ require 'ipaddr'
12
+ require 'paint'
13
+ require 'nmunch'
14
+
15
+ RSpec.configure do |config|
16
+ config.filter_run :focus => true
17
+ config.run_all_when_everything_filtered = true
18
+ end
19
+
20
+ def capture_stdout
21
+ original_stdout = $stdout
22
+ $stdout = fake = StringIO.new
23
+ begin
24
+ yield
25
+ ensure
26
+ $stdout = original_stdout
27
+ end
28
+ fake.string
29
+ end
30
+
31
+ ARP_PACKET_DATA = "\xff\xff\xff\xff\xff\xff\xde\xad\xbe\xef\xde\xad\x08\x06\x00\x01" +
32
+ "\x08\x00\x06\x04\x00\x01\xde\xad\xbe\xef\xde\xad\xc0\xa8\x00\x7d" +
33
+ "\x00\x00\x00\x00\x00\x00\xc0\xa8\x00\x42"
34
+
35
+ IP_PACKET_DATA = "\x7b\x22\x68\x6f\x73\x74\xde\xad\xbe\xef\xde\xad\x20\x32\x36\x37" +
36
+ "\x35\x37\x32\x31\x31\x30\x2c\x20\x22\x76\x65\x72\x73\x69\x6f\x6e" +
37
+ "\x22\x3a\x20\x5b\x31\x2c\x20\x38\x5d\x2c\x20\x22\x64\x69\x73\x70" +
38
+ "\x6c\x61\x79\x6e\x61\x6d\x65\x22\x3a\x20\x22\x32\x36\x37\x35\x37" +
39
+ "\x32\x31\x31\x30\x22\x2c\x20\x22\x70\x6f\x72\x74\x22\x3a\x20\x31" +
40
+ "\x37\x35\x30\x30\x2c\x20\x22\x6e\x61\x6d\x65\x73\x70\x61\x63\x65" +
41
+ "\x73\x22\x3a\x20\x5b\x31\x34\x33\x30\x30\x33\x33\x37\x36\x2c\x20" +
42
+ "\x31\x31\x35\x36\x33\x34\x38\x35\x38\x2c\x20\x31\x31\x38\x39\x30" +
43
+ "\x36\x37\x30\x31\x5d\x7d"
metadata ADDED
@@ -0,0 +1,166 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nmunch
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Michael Henriksen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 0.9.2
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 0.9.2
46
+ - !ruby/object:Gem::Dependency
47
+ name: methadone
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 1.2.3
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 1.2.3
62
+ - !ruby/object:Gem::Dependency
63
+ name: pcap
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 0.7.7
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 0.7.7
78
+ - !ruby/object:Gem::Dependency
79
+ name: paint
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ description: Nmunch is a passive network discovery tool that finds live network nodes
95
+ by analyzing ARP and broadcast packets.
96
+ email:
97
+ - michenriksen87@gmail.com
98
+ executables:
99
+ - nmunch
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - .gitignore
104
+ - Gemfile
105
+ - Gemfile.lock
106
+ - LICENSE
107
+ - README.md
108
+ - Rakefile
109
+ - bin/nmunch
110
+ - lib/nmunch.rb
111
+ - lib/nmunch/dissectors/arp.rb
112
+ - lib/nmunch/dissectors/base.rb
113
+ - lib/nmunch/dissectors/ip.rb
114
+ - lib/nmunch/mac_oui_lookup.rb
115
+ - lib/nmunch/node.rb
116
+ - lib/nmunch/report.rb
117
+ - lib/nmunch/subscribers/base.rb
118
+ - lib/nmunch/subscribers/stdout.rb
119
+ - lib/nmunch/version.rb
120
+ - mac-prefixes.txt
121
+ - nmunch.gemspec
122
+ - spec/lib/nmunch/dissectors/arp_spec.rb
123
+ - spec/lib/nmunch/dissectors/base_spec.rb
124
+ - spec/lib/nmunch/dissectors/ip_spec.rb
125
+ - spec/lib/nmunch/mac_oui_lookup_spec.rb
126
+ - spec/lib/nmunch/node_spec.rb
127
+ - spec/lib/nmunch/report_spec.rb
128
+ - spec/lib/nmunch/subscribers/base_spec.rb
129
+ - spec/lib/nmunch/subscribers/stdout_spec.rb
130
+ - spec/lib/nmunch_spec.rb
131
+ - spec/spec_helper.rb
132
+ homepage: https://github.com/michenriksen/nmunch
133
+ licenses: []
134
+ post_install_message:
135
+ rdoc_options: []
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ! '>='
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ requirements: []
151
+ rubyforge_project:
152
+ rubygems_version: 1.8.24
153
+ signing_key:
154
+ specification_version: 3
155
+ summary: OM NOM NOM NOM
156
+ test_files:
157
+ - spec/lib/nmunch/dissectors/arp_spec.rb
158
+ - spec/lib/nmunch/dissectors/base_spec.rb
159
+ - spec/lib/nmunch/dissectors/ip_spec.rb
160
+ - spec/lib/nmunch/mac_oui_lookup_spec.rb
161
+ - spec/lib/nmunch/node_spec.rb
162
+ - spec/lib/nmunch/report_spec.rb
163
+ - spec/lib/nmunch/subscribers/base_spec.rb
164
+ - spec/lib/nmunch/subscribers/stdout_spec.rb
165
+ - spec/lib/nmunch_spec.rb
166
+ - spec/spec_helper.rb