packetfu 1.1.1 → 1.1.2

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 (71) hide show
  1. data/{README → README.rdoc} +2 -2
  2. metadata +58 -94
  3. data/INSTALL +0 -40
  4. data/LICENSE +0 -28
  5. data/examples/100kpackets.rb +0 -41
  6. data/examples/ackscan.rb +0 -38
  7. data/examples/arp.rb +0 -60
  8. data/examples/arphood.rb +0 -59
  9. data/examples/dissect_thinger.rb +0 -22
  10. data/examples/ethernet.rb +0 -10
  11. data/examples/examples.rb +0 -3
  12. data/examples/ids.rb +0 -4
  13. data/examples/idsv2.rb +0 -6
  14. data/examples/new-simple-stats.rb +0 -52
  15. data/examples/oui.txt +0 -84177
  16. data/examples/packetfu-shell.rb +0 -113
  17. data/examples/simple-sniffer.rb +0 -40
  18. data/examples/simple-stats.rb +0 -50
  19. data/examples/slammer.rb +0 -33
  20. data/examples/uniqpcap.rb +0 -15
  21. data/lib/packetfu.rb +0 -147
  22. data/lib/packetfu/capture.rb +0 -169
  23. data/lib/packetfu/config.rb +0 -58
  24. data/lib/packetfu/inject.rb +0 -65
  25. data/lib/packetfu/packet.rb +0 -533
  26. data/lib/packetfu/pcap.rb +0 -594
  27. data/lib/packetfu/protos/arp.rb +0 -268
  28. data/lib/packetfu/protos/eth.rb +0 -296
  29. data/lib/packetfu/protos/hsrp.rb +0 -206
  30. data/lib/packetfu/protos/icmp.rb +0 -179
  31. data/lib/packetfu/protos/invalid.rb +0 -55
  32. data/lib/packetfu/protos/ip.rb +0 -378
  33. data/lib/packetfu/protos/ipv6.rb +0 -250
  34. data/lib/packetfu/protos/tcp.rb +0 -1127
  35. data/lib/packetfu/protos/udp.rb +0 -240
  36. data/lib/packetfu/structfu.rb +0 -294
  37. data/lib/packetfu/utils.rb +0 -194
  38. data/lib/packetfu/version.rb +0 -50
  39. data/test/all_tests.rb +0 -41
  40. data/test/arp_test.pcap +0 -0
  41. data/test/eth_test.pcap +0 -0
  42. data/test/ethpacket_spec.rb +0 -74
  43. data/test/icmp_test.pcap +0 -0
  44. data/test/ip_test.pcap +0 -0
  45. data/test/packet_spec.rb +0 -73
  46. data/test/packet_subclasses_spec.rb +0 -13
  47. data/test/packetfu_spec.rb +0 -90
  48. data/test/ptest.rb +0 -16
  49. data/test/sample-ipv6.pcap +0 -0
  50. data/test/sample.pcap +0 -0
  51. data/test/sample2.pcap +0 -0
  52. data/test/sample_hsrp_pcapr.cap +0 -0
  53. data/test/structfu_spec.rb +0 -335
  54. data/test/tcp_spec.rb +0 -101
  55. data/test/tcp_test.pcap +0 -0
  56. data/test/test_arp.rb +0 -135
  57. data/test/test_eth.rb +0 -91
  58. data/test/test_hsrp.rb +0 -20
  59. data/test/test_icmp.rb +0 -54
  60. data/test/test_inject.rb +0 -31
  61. data/test/test_invalid.rb +0 -28
  62. data/test/test_ip.rb +0 -69
  63. data/test/test_ip6.rb +0 -68
  64. data/test/test_octets.rb +0 -37
  65. data/test/test_packet.rb +0 -174
  66. data/test/test_pcap.rb +0 -209
  67. data/test/test_structfu.rb +0 -112
  68. data/test/test_tcp.rb +0 -327
  69. data/test/test_udp.rb +0 -73
  70. data/test/udp_test.pcap +0 -0
  71. data/test/vlan-pcapr.cap +0 -0
@@ -1,194 +0,0 @@
1
- require 'singleton'
2
- module PacketFu
3
-
4
- # Utils is a collection of various and sundry network utilities that are useful for packet
5
- # manipulation.
6
- class Utils
7
-
8
- # Returns the MAC address of an IP address, or nil if it's not responsive to arp. Takes
9
- # a dotted-octect notation of the target IP address, as well as a number of parameters:
10
- #
11
- # === Parameters
12
- # :eth_saddr
13
- # Source MAC address. Defaults to "00:00:00:00:00:00".
14
- # :ip_saddr
15
- # Source IP address. Defaults to "0.0.0.0"
16
- # :flavor
17
- # The flavor of the ARP request. Defaults to :none.
18
- # :timeout
19
- # Timeout in seconds. Defaults to 3.
20
- #
21
- # === Example
22
- # PacketFu::Utils::arp("192.168.1.1") #=> "00:18:39:01:33:70"
23
- # PacketFu::Utils::arp("192.168.1.1", :timeout => 5, :flavor => :hp_deskjet)
24
- #
25
- # === Warning
26
- #
27
- # It goes without saying, spewing forged ARP packets on your network is a great way to really
28
- # irritate your co-workers.
29
- def self.arp(target_ip,args={})
30
- iface = args[:iface] || :eth0
31
- args[:config] ||= whoami?(:iface => iface)
32
- arp_pkt = PacketFu::ARPPacket.new(:flavor => (args[:flavor] || :none), :config => args[:config])
33
- arp_pkt.eth_daddr = "ff:ff:ff:ff:ff:ff"
34
- arp_pkt.arp_daddr_mac = "00:00:00:00:00:00"
35
- arp_pkt.arp_daddr_ip = target_ip
36
- # Stick the Capture object in its own thread.
37
- cap_thread = Thread.new do
38
- target_mac = nil
39
- cap = PacketFu::Capture.new(:iface => iface, :start => true,
40
- :filter => "arp src #{target_ip} and ether dst #{arp_pkt.eth_saddr}")
41
- arp_pkt.to_w(iface) # Shorthand for sending single packets to the default interface.
42
- timeout = 0
43
- while target_mac.nil? && timeout <= (args[:timeout] || 3)
44
- if cap.save > 0
45
- arp_response = PacketFu::Packet.parse(cap.array[0])
46
- target_mac = arp_response.arp_saddr_mac if arp_response.arp_saddr_ip = target_ip
47
- end
48
- timeout += 0.1
49
- sleep 0.1 # Check for a response ten times per second.
50
- end
51
- target_mac
52
- end # cap_thread
53
- cap_thread.value
54
- end
55
-
56
- # Discovers the local IP and Ethernet address, which is useful for writing
57
- # packets you expect to get a response to. Note, this is a noisy
58
- # operation; a UDP packet is generated and dropped on to the default (or named)
59
- # interface, and then captured (which means you need to be root to do this).
60
- #
61
- # whoami? returns a hash of :eth_saddr, :eth_src, :ip_saddr, :ip_src,
62
- # :ip_src_bin, :eth_dst, and :eth_daddr (the last two are usually suitable
63
- # for a gateway mac address). It's most useful as an argument to
64
- # PacketFu::Config.new, or as an argument to the many Packet constructors.
65
- #
66
- # Note that if you have multiple interfaces with the same route (such as when
67
- # wlan0 and eth0 are associated to the same network), the "first" one
68
- # according to Pcap.lookupdev will be used, regardless of which :iface you
69
- # pick.
70
- #
71
- # === Parameters
72
- # :iface => "eth0"
73
- # An interface to listen for packets on. Note that since we rely on the OS to send the probe packet,
74
- # you will need to specify a target which will use this interface.
75
- # :target => "1.2.3.4"
76
- # A target IP address. By default, a packet will be sent to a random address in the 177/8 network.
77
- # Since this network is IANA reserved (for now), this network should be handled by your default gateway
78
- # and default interface.
79
- def self.whoami?(args={})
80
- unless args.kind_of? Hash
81
- raise ArgumentError, "Argument to `whoami?' must be a Hash"
82
- end
83
- if args[:iface].to_s =~ /^lo/ # Linux loopback more or less. Need a switch for windows loopback, too.
84
- dst_host = "127.0.0.1"
85
- else
86
- dst_host = (args[:target] || IPAddr.new((rand(16777216) + 2969567232), Socket::AF_INET).to_s)
87
- end
88
-
89
- dst_port = rand(0xffff-1024)+1024
90
- msg = "PacketFu whoami? packet #{(Time.now.to_i + rand(0xffffff)+1)}"
91
- iface = (args[:iface] || ENV['IFACE'] || Pcap.lookupdev || :lo ).to_s
92
- cap = PacketFu::Capture.new(:iface => iface, :promisc => false, :start => true, :filter => "udp and dst host #{dst_host} and dst port #{dst_port}")
93
- udp_sock = UDPSocket.new
94
- udp_sock.send(msg,0,dst_host,dst_port)
95
- udp_sock = nil
96
- cap.save
97
- pkt = Packet.parse(cap.array[0]) unless cap.save.zero?
98
- timeout = 0
99
- while timeout < 1 # Sometimes packet generation can be a little pokey.
100
- if pkt
101
- timeout = 1.1 # Cancel the timeout
102
- if pkt.payload == msg
103
- my_data = {
104
- :iface => (args[:iface] || ENV['IFACE'] || Pcap.lookupdev || "lo").to_s,
105
- :pcapfile => args[:pcapfile] || "/tmp/out.pcap",
106
- :eth_saddr => pkt.eth_saddr,
107
- :eth_src => pkt.eth_src.to_s,
108
- :ip_saddr => pkt.ip_saddr,
109
- :ip_src => pkt.ip_src,
110
- :ip_src_bin => [pkt.ip_src].pack("N"),
111
- :eth_dst => pkt.eth_dst.to_s,
112
- :eth_daddr => pkt.eth_daddr
113
- }
114
- else raise SecurityError,
115
- "whoami() packet doesn't match sent data. Something fishy's going on."
116
- end
117
- else
118
- sleep 0.1; timeout += 0.1
119
- cap.save
120
- pkt = Packet.parse(cap.array[0]) unless cap.save.zero?
121
- end
122
- raise SocketError, "Didn't receive the whomi() packet, can't automatically configure." if !pkt
123
- cap = nil
124
- end
125
- my_data
126
- end
127
-
128
- # This is a brute-force approach at trying to find a suitable interface with an IP address.
129
- def self.lookupdev
130
- # XXX cycle through eth0-9 and wlan0-9, and if a cap start throws a RuntimeErorr (and we're
131
- # root), it's not a good interface. Boy, really ought to fix lookupdev directly with another
132
- # method that returns an array rather than just the first candidate.
133
- end
134
-
135
- # Handles ifconfig for various (okay, one) platforms. Mac guys, fix this and submit a patch!
136
- # Will have Windows done shortly.
137
- #
138
- # Takes an argument (either string or symbol) of the interface to look up, and
139
- # returns a hash which contains at least the :iface element, and if configured,
140
- # these additional elements:
141
- #
142
- # :eth_saddr # A human readable MAC address
143
- # :eth_src # A packed MAC address
144
- # :ip_saddr # A dotted-quad string IPv4 address
145
- # :ip_src # A packed IPv4 address
146
- # :ip4_obj # An IPAddr object with bitmask
147
- # :ip6_saddr # A colon-delimited hex IPv6 address, with bitmask
148
- # :ip6_obj # An IPAddr object with bitmask
149
- #
150
- # === Example
151
- # PacketFu::Utils.ifconfig :wlan0 # Not associated yet
152
- # #=> {:eth_saddr=>"00:1d:e0:73:9d:ff", :eth_src=>"\000\035\340s\235\377", :iface=>"wlan0"}
153
- # PacketFu::Utils.ifconfig("eth0") # Takes 'eth0' as default
154
- # #=> {:eth_saddr=>"00:1c:23:35:70:3b", :eth_src=>"\000\034#5p;", :ip_saddr=>"10.10.10.9", :ip4_obj=>#<IPAddr: IPv4:10.10.10.0/255.255.254.0>, :ip_src=>"\n\n\n\t", :iface=>"eth0", :ip6_saddr=>"fe80::21c:23ff:fe35:703b/64", :ip6_obj=>#<IPAddr: IPv6:fe80:0000:0000:0000:0000:0000:0000:0000/ffff:ffff:ffff:ffff:0000:0000:0000:0000>}
155
- # PacketFu::Utils.ifconfig :lo
156
- # #=> {:ip_saddr=>"127.0.0.1", :ip4_obj=>#<IPAddr: IPv4:127.0.0.0/255.0.0.0>, :ip_src=>"\177\000\000\001", :iface=>"lo", :ip6_saddr=>"::1/128", :ip6_obj=>#<IPAddr: IPv6:0000:0000:0000:0000:0000:0000:0000:0001/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>}
157
- def self.ifconfig(iface='eth0')
158
- ret = {}
159
- iface = iface.to_s.scan(/[0-9A-Za-z]/).join # Sanitizing input, no spaces, semicolons, etc.
160
- case RUBY_PLATFORM
161
- when /linux/i
162
- ifconfig_data = %x[ifconfig #{iface}]
163
- if ifconfig_data =~ /#{iface}/i
164
- ifconfig_data = ifconfig_data.split(/[\s]*\n[\s]*/)
165
- else
166
- raise ArgumentError, "Cannot ifconfig #{iface}"
167
- end
168
- real_iface = ifconfig_data.first
169
- ret[:iface] = real_iface.split.first.downcase
170
- if real_iface =~ /[\s]HWaddr[\s]+([0-9a-fA-F:]{17})/i
171
- ret[:eth_saddr] = $1.downcase
172
- ret[:eth_src] = EthHeader.mac2str(ret[:eth_saddr])
173
- end
174
- ifconfig_data.each do |s|
175
- case s
176
- when /inet addr:[\s]*([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(.*Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+))?/i
177
- ret[:ip_saddr] = $1
178
- ret[:ip_src] = [IPAddr.new($1).to_i].pack("N")
179
- ret[:ip4_obj] = IPAddr.new($1)
180
- ret[:ip4_obj] = ret[:ip4_obj].mask($3) if $3
181
- when /inet6 addr:[\s]*([0-9a-fA-F:\x2f]+)/
182
- ret[:ip6_saddr] = $1
183
- ret[:ip6_obj] = IPAddr.new($1)
184
- end
185
- end
186
- end # linux
187
- ret
188
- end
189
-
190
- end
191
-
192
- end
193
-
194
- # vim: nowrap sw=2 sts=0 ts=2 ff=unix ft=ruby
@@ -1,50 +0,0 @@
1
- module PacketFu
2
-
3
- # Check the repo's for version release histories
4
- VERSION = "1.1.1" # Fixes for 1.8
5
-
6
- # Returns PacketFu::VERSION
7
- def self.version
8
- VERSION
9
- end
10
-
11
- # Returns a version string in a binary format for easy comparisons.
12
- def self.binarize_version(str)
13
- if(str.respond_to?(:split) && str =~ /^[0-9]+(\.([0-9]+)(\.[0-9]+)?)?\..+$/)
14
- bin_major,bin_minor,bin_teeny = str.split(/\x2e/).map {|x| x.to_i}
15
- bin_version = (bin_major.to_i << 16) + (bin_minor.to_i << 8) + bin_teeny.to_i
16
- else
17
- raise ArgumentError, "Compare version malformed. Should be \x22x.y.z\x22"
18
- end
19
- end
20
-
21
- # Returns true if the version is equal to or greater than the compare version.
22
- # If the current version of PacketFu is "0.3.1" for example:
23
- #
24
- # PacketFu.at_least? "0" # => true
25
- # PacketFu.at_least? "0.2.9" # => true
26
- # PacketFu.at_least? "0.3" # => true
27
- # PacketFu.at_least? "1" # => true after 1.0's release
28
- # PacketFu.at_least? "1.12" # => false
29
- # PacketFu.at_least? "2" # => false
30
- def self.at_least?(str)
31
- this_version = binarize_version(self.version)
32
- ask_version = binarize_version(str)
33
- this_version >= ask_version
34
- end
35
-
36
- # Returns true if the current version is older than the compare version.
37
- def self.older_than?(str)
38
- return false if str == self.version
39
- this_version = binarize_version(self.version)
40
- ask_version = binarize_version(str)
41
- this_version < ask_version
42
- end
43
-
44
- # Returns true if the current version is newer than the compare version.
45
- def self.newer_than?(str)
46
- return false if str == self.version
47
- !self.older_than?(str)
48
- end
49
-
50
- end
data/test/all_tests.rb DELETED
@@ -1,41 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #
3
- # Tested on:
4
- #
5
- # ruby-1.9.3-head [ x86_64 ]
6
- # ruby-1.9.1-p378 [ x86_64 ]
7
- # ruby-1.8.6-p399 [ x86_64 ]
8
- # ruby-1.8.7-p334 [ x86_64 ]
9
- # ruby-1.9.2-p180 [ x86_64 ]
10
-
11
- # Okay so the regular test/unit stuff screws up some of my
12
- # meta magic. I need to move these over to spec and see
13
- # if they're any better. In the meantime, behold my
14
- # ghetto test exec()'er. It all passes with this,
15
- # so I'm just going to go ahead and assume the testing
16
- # methodolgy is flawed. TODO: rewrite all this for spec
17
- # and incidentally get the gem to test like it's supposed
18
- # to.
19
-
20
- $:.unshift File.expand_path(File.dirname(__FILE__) + "/../lib/")
21
- require 'packetfu'
22
- puts "Testing PacketFu v#{PacketFu::VERSION}"
23
- dir = Dir.new(File.dirname(__FILE__))
24
-
25
- dir.each { |file|
26
- next unless File.file? file
27
- next unless file[/^test_.*rb$/]
28
- next if file == $0
29
- puts "Running #{file}..."
30
- cmd = %x{ruby #{file}}
31
- if cmd[/ 0 failures/] && cmd[/ 0 errors/]
32
- puts "#{file}: All passed"
33
- else
34
- puts "File: #{file} had failures or errors:"
35
- puts "-" * 80
36
- puts cmd
37
- puts "-" * 80
38
- end
39
- }
40
-
41
- # vim: nowrap sw=2 sts=0 ts=2 ff=unix ft=ruby
data/test/arp_test.pcap DELETED
Binary file
data/test/eth_test.pcap DELETED
Binary file
@@ -1,74 +0,0 @@
1
- $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
2
- require 'packetfu'
3
-
4
- include PacketFu
5
-
6
- describe EthPacket, "when read from a pcap file" do
7
-
8
- before :all do
9
- parsed_packets = PcapFile.read_packets(File.join(".","sample.pcap"))
10
- @eth_packet = parsed_packets.first
11
- end
12
-
13
- context "is a regular ethernet packet" do
14
-
15
- subject { @eth_packet }
16
-
17
- it "should be an EthPacket kind of packet" do
18
- subject.should be_kind_of EthPacket
19
- end
20
-
21
- it "should have a dest mac address" do
22
- subject.eth_daddr.should == "00:03:2f:1a:74:de"
23
- end
24
-
25
- it "should have a source mac address" do
26
- subject.eth_saddr.should == "00:1b:11:51:b7:ce"
27
- end
28
-
29
- its(:size) { should == 78 }
30
-
31
- it "should have a payload in its first header" do
32
- subject.headers.first.body.should_not be_nil
33
- end
34
-
35
- context "an EthPacket's first header" do
36
-
37
- subject { @eth_packet.headers.first }
38
-
39
- it "should be 64 bytes" do
40
- subject.body.sz.should == 64
41
- end
42
-
43
- context "EthHeader struct members" do
44
- if RUBY_VERSION =~ /^1\.8/
45
- its(:members) { should include :eth_dst.to_s }
46
- its(:members) { should include :eth_src.to_s }
47
- its(:members) { should include :eth_proto.to_s }
48
- its(:members) { should include :body.to_s }
49
- else
50
- its(:members) { should include :eth_dst }
51
- its(:members) { should include :eth_src }
52
- its(:members) { should include :eth_proto }
53
- its(:members) { should include :body }
54
- end
55
- end
56
-
57
- end
58
-
59
- end
60
-
61
- context "isn't a regular Ethernet packet" do
62
-
63
- subject {
64
- parsed_packets = PcapFile.read_packets(File.join(".","vlan-pcapr.cap"))
65
- parsed_packets.first
66
- }
67
-
68
- it "should not be an EthPacket" do
69
- subject.should_not be_kind_of EthPacket
70
- end
71
-
72
- end
73
-
74
- end
data/test/icmp_test.pcap DELETED
Binary file
data/test/ip_test.pcap DELETED
Binary file
data/test/packet_spec.rb DELETED
@@ -1,73 +0,0 @@
1
- $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
2
- require 'packetfu'
3
-
4
- describe PacketFu::Packet, "abstract packet class behavior" do
5
-
6
- before(:all) do
7
- class PacketFu::FooPacket < PacketFu::Packet; end
8
- class PacketFu::BarPacket < PacketFu::Packet; end
9
- end
10
-
11
- it "should not be instantiated" do
12
- expect { PacketFu::Packet.new }.to raise_error(NoMethodError)
13
- end
14
-
15
- it "should allow subclasses to instantiate" do
16
- expect { PacketFu::FooPacket.new }. to be
17
- PacketFu.packet_classes.include?(PacketFu::FooPacket).should be_true
18
- end
19
-
20
- it "should register packet classes with PacketFu" do
21
- PacketFu.packet_classes {should include(FooPacket) }
22
- PacketFu.packet_classes {should include(BarPacket) }
23
- end
24
-
25
- it "should disallow badly named subclasses" do
26
- expect {
27
- class PacketFu::PacketNot < PacketFu::Packet
28
- end
29
- }.to raise_error
30
- PacketFu.packet_classes.include?(PacketFu::PacketNot).should be_false
31
- PacketFu.packet_classes {should_not include(PacketNot) }
32
- end
33
-
34
- before(:each) do
35
- @tcp_packet = PacketFu::TCPPacket.new
36
- @tcp_packet.ip_saddr = "10.10.10.10"
37
- end
38
-
39
- it "should shallow copy with dup()" do
40
- p2 = @tcp_packet.dup
41
- p2.ip_saddr = "20.20.20.20"
42
- p2.ip_saddr.should == @tcp_packet.ip_saddr
43
- p2.headers[1].object_id.should == @tcp_packet.headers[1].object_id
44
- end
45
-
46
- it "should deep copy with clone()" do
47
- p3 = @tcp_packet.clone
48
- p3.ip_saddr = "30.30.30.30"
49
- p3.ip_saddr.should_not == @tcp_packet.ip_saddr
50
- p3.headers[1].object_id.should_not == @tcp_packet.headers[1].object_id
51
- end
52
-
53
- it "should have senisble equality" do
54
- p4 = @tcp_packet.dup
55
- p4.should == @tcp_packet
56
- p5 = @tcp_packet.clone
57
- p5.should == @tcp_packet
58
- end
59
-
60
- # It's actually kinda hard to manually create identical TCP packets
61
- it "should be possible to manually create identical packets" do
62
- p6 = @tcp_packet.clone
63
- p6.should == @tcp_packet
64
- p7 = PacketFu::TCPPacket.new
65
- p7.ip_saddr = p6.ip_saddr
66
- p7.ip_id = p6.ip_id
67
- p7.tcp_seq = p6.tcp_seq
68
- p7.tcp_src = p6.tcp_src
69
- p7.tcp_sum = p6.tcp_sum
70
- p7.should == p6
71
- end
72
-
73
- end
@@ -1,13 +0,0 @@
1
- $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
2
- require 'packetfu'
3
-
4
- PacketFu.packet_classes.each do |pclass|
5
- describe pclass, "peek format" do
6
- it "will display sensible peek information" do
7
- p = pclass.new
8
- p.respond_to?(:peek).should be_true
9
- p.peek.size.should be_<=(80), p.peek.inspect
10
- p.peek.should match(/^[A-Z0-9?]../)
11
- end
12
- end
13
- end