packetfu 1.1.8 → 1.1.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/README.rdoc +11 -12
  2. data/bench/octets.rb +9 -9
  3. data/examples/100kpackets.rb +13 -12
  4. data/examples/ackscan.rb +17 -16
  5. data/examples/arp.rb +36 -35
  6. data/examples/arphood.rb +37 -36
  7. data/examples/dissect_thinger.rb +7 -6
  8. data/examples/ethernet.rb +1 -0
  9. data/examples/examples.rb +1 -0
  10. data/examples/ifconfig.rb +1 -0
  11. data/examples/new-simple-stats.rb +24 -23
  12. data/examples/packetfu-shell.rb +26 -25
  13. data/examples/simple-sniffer.rb +10 -9
  14. data/examples/simple-stats.rb +24 -23
  15. data/examples/slammer.rb +4 -3
  16. data/lib/packetfu.rb +128 -127
  17. data/lib/packetfu/capture.rb +170 -169
  18. data/lib/packetfu/config.rb +53 -52
  19. data/lib/packetfu/inject.rb +57 -56
  20. data/lib/packetfu/packet.rb +529 -528
  21. data/lib/packetfu/pcap.rb +580 -579
  22. data/lib/packetfu/protos/arp.rb +91 -90
  23. data/lib/packetfu/protos/arp/header.rb +159 -158
  24. data/lib/packetfu/protos/arp/mixin.rb +37 -36
  25. data/lib/packetfu/protos/eth.rb +45 -44
  26. data/lib/packetfu/protos/eth/header.rb +244 -243
  27. data/lib/packetfu/protos/eth/mixin.rb +4 -3
  28. data/lib/packetfu/protos/hsrp.rb +70 -69
  29. data/lib/packetfu/protos/hsrp/header.rb +108 -107
  30. data/lib/packetfu/protos/hsrp/mixin.rb +30 -29
  31. data/lib/packetfu/protos/icmp.rb +72 -71
  32. data/lib/packetfu/protos/icmp/header.rb +83 -82
  33. data/lib/packetfu/protos/icmp/mixin.rb +15 -14
  34. data/lib/packetfu/protos/invalid.rb +50 -49
  35. data/lib/packetfu/protos/ip.rb +70 -69
  36. data/lib/packetfu/protos/ip/header.rb +292 -291
  37. data/lib/packetfu/protos/ip/mixin.rb +41 -40
  38. data/lib/packetfu/protos/ipv6.rb +51 -50
  39. data/lib/packetfu/protos/ipv6/header.rb +189 -188
  40. data/lib/packetfu/protos/ipv6/mixin.rb +30 -29
  41. data/lib/packetfu/protos/lldp.rb +3 -1
  42. data/lib/packetfu/protos/lldp/header.rb +1 -0
  43. data/lib/packetfu/protos/lldp/mixin.rb +1 -0
  44. data/lib/packetfu/protos/tcp.rb +177 -176
  45. data/lib/packetfu/protos/tcp/ecn.rb +36 -35
  46. data/lib/packetfu/protos/tcp/flags.rb +75 -74
  47. data/lib/packetfu/protos/tcp/header.rb +269 -268
  48. data/lib/packetfu/protos/tcp/hlen.rb +33 -32
  49. data/lib/packetfu/protos/tcp/mixin.rb +47 -46
  50. data/lib/packetfu/protos/tcp/option.rb +322 -321
  51. data/lib/packetfu/protos/tcp/options.rb +96 -95
  52. data/lib/packetfu/protos/tcp/reserved.rb +36 -35
  53. data/lib/packetfu/protos/udp.rb +117 -116
  54. data/lib/packetfu/protos/udp/header.rb +92 -91
  55. data/lib/packetfu/protos/udp/mixin.rb +4 -3
  56. data/lib/packetfu/structfu.rb +281 -280
  57. data/lib/packetfu/utils.rb +211 -208
  58. data/lib/packetfu/version.rb +42 -41
  59. data/packetfu.gemspec +1 -1
  60. data/spec/ethpacket_spec.rb +48 -48
  61. data/spec/packet_spec.rb +57 -57
  62. data/spec/packet_subclasses_spec.rb +8 -8
  63. data/spec/packetfu_spec.rb +59 -59
  64. data/spec/structfu_spec.rb +268 -268
  65. data/spec/tcp_spec.rb +75 -75
  66. data/test/all_tests.rb +13 -13
  67. data/test/func_lldp.rb +3 -3
  68. data/test/ptest.rb +2 -2
  69. data/test/test_arp.rb +116 -116
  70. data/test/test_capture.rb +45 -45
  71. data/test/test_eth.rb +68 -68
  72. data/test/test_hsrp.rb +9 -9
  73. data/test/test_icmp.rb +52 -52
  74. data/test/test_inject.rb +18 -18
  75. data/test/test_invalid.rb +16 -16
  76. data/test/test_ip.rb +36 -36
  77. data/test/test_ip6.rb +48 -48
  78. data/test/test_octets.rb +21 -21
  79. data/test/test_packet.rb +154 -154
  80. data/test/test_pcap.rb +170 -170
  81. data/test/test_structfu.rb +97 -97
  82. data/test/test_tcp.rb +320 -320
  83. data/test/test_udp.rb +76 -76
  84. metadata +2 -2
@@ -1,172 +1,173 @@
1
+ # -*- coding: binary -*-
1
2
  module PacketFu
2
3
 
3
- # The Capture class is used to construct PcapRub objects in order to collect
4
- # packets from an interface.
5
- #
6
- # This class requires PcapRub. In addition, you will need root (or root-like) privileges
7
- # in order to capture from the interface.
8
- #
9
- # Note, on some wireless cards, setting :promisc => true will disable capturing.
10
- #
11
- # == Example
12
- #
13
- # # Typical use
14
- # cap = PacketFu::Capture.new(:iface => 'eth0', :promisc => true)
15
- # cap.start
16
- # sleep 10
17
- # cap.save
18
- # first_packet = cap.array[0]
19
- #
20
- # # Tcpdump-like use
21
- # cap = PacketFu::Capture.new(:start => true)
22
- # cap.show_live(:save => true, :filter => 'tcp and not port 22')
23
- #
24
- # == See Also
25
- #
26
- # Read, Write
27
- class Capture
28
- attr_accessor :array, :stream # Leave these public and open.
29
- attr_reader :iface, :snaplen, :promisc, :timeout, :filter
30
-
31
- def initialize(args={})
32
- @array = [] # Where the packet array goes.
33
- @stream = [] # Where the stream goes.
34
- @iface = (args[:iface] || ENV['IFACE'] || Pcap.lookupdev || "lo").to_s
35
- @snaplen = args[:snaplen] || 0xffff
36
- @promisc = args[:promisc] || false # Sensible for some Intel wifi cards
37
- @timeout = args[:timeout] || 1
38
- @filter = args[:filter] || args[:bpf]
39
- setup_params(args)
40
- end
41
-
42
- # Used by new().
43
- def setup_params(args={})
44
- filter = args[:filter] || args[:bpf] || @filter
45
- start = args[:start] || false
46
- capture if start
47
- bpf(:filter=>filter) if filter
48
- end
49
-
50
- # capture() initializes the @stream varaible. Valid arguments are:
51
- #
52
- # :filter
53
- # Provide a bpf filter to enable for the capture. For example, 'ip and not tcp'
54
- # :start
55
- # When true, start capturing packets to the @stream variable. Defaults to true
56
- def capture(args={})
57
- if Process.euid.zero?
58
- filter = args[:filter] || args[:bpf] || @filter
59
- start = args[:start] || true
60
- if start
61
- begin
62
- @stream = Pcap.open_live(@iface,@snaplen,@promisc,@timeout)
63
- rescue RuntimeError
64
- $stderr.print "Are you sure you're root? Error: "
65
- raise
66
- end
67
- bpf(:filter=>filter) if filter
68
- else
69
- @stream = []
70
- end
71
- @stream
72
- else
73
- raise RuntimeError,"Not root, so can't capture packets. Error: "
74
- end
75
- end
76
-
77
- # start() is equivalent to capture().
78
- def start(args={})
79
- capture(args)
80
- end
81
-
82
- # clear() clears the @stream and @array variables, essentially starting the
83
- # capture session over. Valid arguments are:
84
- #
85
- # :array
86
- # If true, the @array is cleared.
87
- # :stream
88
- # If true, the @stream is cleared.
89
- def clear(args={})
90
- array = args[:array] || true
91
- stream = args[:stream] || true
92
- @array = [] if array
93
- @stream = [] if stream
94
- end
95
-
96
- # bpf() sets a bpf filter on a capture session. Valid arugments are:
97
- #
98
- # :filter
99
- # Provide a bpf filter to enable for the capture. For example, 'ip and not tcp'
100
- def bpf(args={})
101
- filter = args[:filter] || args[:bpf] || @filter
102
- capture if @stream.class == Array
103
- @stream.setfilter(filter) if filter
104
- @filter = filter
105
- end
106
-
107
- alias :filter :bpf
108
-
109
- # wire_to_array() saves a packet stream as an array of binary strings. From here,
110
- # packets may accessed by other functions. Note that the wire_to_array empties
111
- # the stream, so multiple calls will append new packets to @array.
112
- # Valid arguments are:
113
- #
114
- # :filter
115
- # Provide a bpf filter to apply to packets moving from @stream to @array.
116
- def wire_to_array(args={})
117
- filter = args[:filter] || args[:bpf] || @filter
118
- bpf(:filter=>filter) if filter
119
-
120
- while this_pkt = @stream.next
121
- @array << this_pkt
122
- end
123
- @array.size
124
- end
125
-
126
- # next() exposes the Stream object's next method to the outside world.
127
- def next
128
- return @stream.next
129
- end
130
-
131
- # w2a() is a equivalent to wire_to_array()
132
- def w2a(args={})
133
- wire_to_array(args)
134
- end
135
-
136
- # save() is a equivalent to wire_to_array()
137
- def save(args={})
138
- wire_to_array(args)
139
- end
140
-
141
- # show_live() is a method to capture packets and display peek() data to stdout. Valid arguments are:
142
- #
143
- # :filter
144
- # Provide a bpf filter to captured packets.
145
- # :save
146
- # Save the capture in @array
147
- # :verbose
148
- # TODO: Not implemented yet; do more than just peek() at the packets.
149
- # :quiet
150
- # TODO: Not implemented yet; do less than peek() at the packets.
151
- def show_live(args={})
152
- filter = args[:filter] || args[:bpf] || @filter
153
- save = args[:save]
154
- verbose = args[:verbose] || args[:v] || false
155
- quiet = args[:quiet] || args[:q] || false # Setting q and v doesn't make a lot of sense but hey.
156
-
157
- # Ensure the capture's started.
158
- if @stream.class == Array
159
- capture
160
- end
161
-
162
- @stream.setfilter(filter) if filter
163
- while true
164
- @stream.each do |pkt|
165
- puts Packet.parse(pkt).peek
166
- @array << pkt if args[:save]
167
- end
168
- end
169
- end
170
-
171
- end
4
+ # The Capture class is used to construct PcapRub objects in order to collect
5
+ # packets from an interface.
6
+ #
7
+ # This class requires PcapRub. In addition, you will need root (or root-like) privileges
8
+ # in order to capture from the interface.
9
+ #
10
+ # Note, on some wireless cards, setting :promisc => true will disable capturing.
11
+ #
12
+ # == Example
13
+ #
14
+ # # Typical use
15
+ # cap = PacketFu::Capture.new(:iface => 'eth0', :promisc => true)
16
+ # cap.start
17
+ # sleep 10
18
+ # cap.save
19
+ # first_packet = cap.array[0]
20
+ #
21
+ # # Tcpdump-like use
22
+ # cap = PacketFu::Capture.new(:start => true)
23
+ # cap.show_live(:save => true, :filter => 'tcp and not port 22')
24
+ #
25
+ # == See Also
26
+ #
27
+ # Read, Write
28
+ class Capture
29
+ attr_accessor :array, :stream # Leave these public and open.
30
+ attr_reader :iface, :snaplen, :promisc, :timeout, :filter
31
+
32
+ def initialize(args={})
33
+ @array = [] # Where the packet array goes.
34
+ @stream = [] # Where the stream goes.
35
+ @iface = (args[:iface] || ENV['IFACE'] || Pcap.lookupdev || "lo").to_s
36
+ @snaplen = args[:snaplen] || 0xffff
37
+ @promisc = args[:promisc] || false # Sensible for some Intel wifi cards
38
+ @timeout = args[:timeout] || 1
39
+ @filter = args[:filter] || args[:bpf]
40
+ setup_params(args)
41
+ end
42
+
43
+ # Used by new().
44
+ def setup_params(args={})
45
+ filter = args[:filter] || args[:bpf] || @filter
46
+ start = args[:start] || false
47
+ capture if start
48
+ bpf(:filter=>filter) if filter
49
+ end
50
+
51
+ # capture() initializes the @stream varaible. Valid arguments are:
52
+ #
53
+ # :filter
54
+ # Provide a bpf filter to enable for the capture. For example, 'ip and not tcp'
55
+ # :start
56
+ # When true, start capturing packets to the @stream variable. Defaults to true
57
+ def capture(args={})
58
+ if Process.euid.zero?
59
+ filter = args[:filter] || args[:bpf] || @filter
60
+ start = args[:start] || true
61
+ if start
62
+ begin
63
+ @stream = Pcap.open_live(@iface,@snaplen,@promisc,@timeout)
64
+ rescue RuntimeError
65
+ $stderr.print "Are you sure you're root? Error: "
66
+ raise
67
+ end
68
+ bpf(:filter=>filter) if filter
69
+ else
70
+ @stream = []
71
+ end
72
+ @stream
73
+ else
74
+ raise RuntimeError,"Not root, so can't capture packets. Error: "
75
+ end
76
+ end
77
+
78
+ # start() is equivalent to capture().
79
+ def start(args={})
80
+ capture(args)
81
+ end
82
+
83
+ # clear() clears the @stream and @array variables, essentially starting the
84
+ # capture session over. Valid arguments are:
85
+ #
86
+ # :array
87
+ # If true, the @array is cleared.
88
+ # :stream
89
+ # If true, the @stream is cleared.
90
+ def clear(args={})
91
+ array = args[:array] || true
92
+ stream = args[:stream] || true
93
+ @array = [] if array
94
+ @stream = [] if stream
95
+ end
96
+
97
+ # bpf() sets a bpf filter on a capture session. Valid arugments are:
98
+ #
99
+ # :filter
100
+ # Provide a bpf filter to enable for the capture. For example, 'ip and not tcp'
101
+ def bpf(args={})
102
+ filter = args[:filter] || args[:bpf] || @filter
103
+ capture if @stream.class == Array
104
+ @stream.setfilter(filter) if filter
105
+ @filter = filter
106
+ end
107
+
108
+ alias :filter :bpf
109
+
110
+ # wire_to_array() saves a packet stream as an array of binary strings. From here,
111
+ # packets may accessed by other functions. Note that the wire_to_array empties
112
+ # the stream, so multiple calls will append new packets to @array.
113
+ # Valid arguments are:
114
+ #
115
+ # :filter
116
+ # Provide a bpf filter to apply to packets moving from @stream to @array.
117
+ def wire_to_array(args={})
118
+ filter = args[:filter] || args[:bpf] || @filter
119
+ bpf(:filter=>filter) if filter
120
+
121
+ while this_pkt = @stream.next
122
+ @array << this_pkt
123
+ end
124
+ @array.size
125
+ end
126
+
127
+ # next() exposes the Stream object's next method to the outside world.
128
+ def next
129
+ return @stream.next
130
+ end
131
+
132
+ # w2a() is a equivalent to wire_to_array()
133
+ def w2a(args={})
134
+ wire_to_array(args)
135
+ end
136
+
137
+ # save() is a equivalent to wire_to_array()
138
+ def save(args={})
139
+ wire_to_array(args)
140
+ end
141
+
142
+ # show_live() is a method to capture packets and display peek() data to stdout. Valid arguments are:
143
+ #
144
+ # :filter
145
+ # Provide a bpf filter to captured packets.
146
+ # :save
147
+ # Save the capture in @array
148
+ # :verbose
149
+ # TODO: Not implemented yet; do more than just peek() at the packets.
150
+ # :quiet
151
+ # TODO: Not implemented yet; do less than peek() at the packets.
152
+ def show_live(args={})
153
+ filter = args[:filter] || args[:bpf] || @filter
154
+ save = args[:save]
155
+ verbose = args[:verbose] || args[:v] || false
156
+ quiet = args[:quiet] || args[:q] || false # Setting q and v doesn't make a lot of sense but hey.
157
+
158
+ # Ensure the capture's started.
159
+ if @stream.class == Array
160
+ capture
161
+ end
162
+
163
+ @stream.setfilter(filter) if filter
164
+ while true
165
+ @stream.each do |pkt|
166
+ puts Packet.parse(pkt).peek
167
+ @array << pkt if args[:save]
168
+ end
169
+ end
170
+ end
171
+
172
+ end
172
173
  end
@@ -1,58 +1,59 @@
1
+ # -*- coding: binary -*-
1
2
  module PacketFu
2
3
 
3
- # The Config class holds various bits of useful default information
4
- # for packet creation. If initialized without arguments, @iface will be
5
- # set to ENV['IFACE'] or Pcap.lookupdev (or lo), and the @pcapfile will
6
- # be set to "/tmp/out.pcap" # (yes, it's Linux-biased, sorry, fixing
7
- # this is a TODO.)
8
- #
9
- # Any number of instance variables can be passed in to the intialize function (as a
10
- # hash), though only the expected network-related variables will be readable and
11
- # writeable directly.
12
- #
13
- # == Examples
14
- #
15
- # PacketFu::Config.new(:ip_saddr => "1.2.3.4").ip_saddr #=> "1.2.3.4"
16
- # PacketFu::Config.new(:foo=>"bar").foo #=> NomethodError: undefined method `foo'...
17
- #
18
- # The config() function, however, does provide access to custom variables:
19
- #
20
- # PacketFu::Config.new(:foo=>"bar").config[:foo] #=> "bar"
21
- # obj = PacketFu::Config.new(:foo=>"bar")
22
- # obj.config(:baz => "bat")
23
- # obj.config #=> {:iface=>"eth0", :baz=>"bat", :pcapfile=>"/tmp/out.pcap", :foo=>"bar"}
24
- class Config
25
- attr_accessor :eth_saddr, # The discovered eth_saddr
26
- :eth_daddr, # The discovered eth_daddr (ie, the gateway)
27
- :eth_src, # The discovered eth_src in binary form.
28
- :eth_dst, # The discovered eth_dst (gateway) in binary form.
29
- :ip_saddr, # The discovered ip_saddr
30
- :ip_src, # The discovered ip_src in binary form.
31
- :iface, # The declared interface.
32
- :pcapfile # A declared default file to write to.
33
-
34
- def initialize(args={})
35
- if Process.euid.zero?
36
- @iface = args[:iface] || ENV['IFACE'] || Pcap.lookupdev || "lo"
37
- end
38
- @pcapfile = "/tmp/out.pcap"
39
- args.each_pair { |k,v| self.instance_variable_set(("@#{k}"),v) }
40
- end
4
+ # The Config class holds various bits of useful default information
5
+ # for packet creation. If initialized without arguments, @iface will be
6
+ # set to ENV['IFACE'] or Pcap.lookupdev (or lo), and the @pcapfile will
7
+ # be set to "/tmp/out.pcap" # (yes, it's Linux-biased, sorry, fixing
8
+ # this is a TODO.)
9
+ #
10
+ # Any number of instance variables can be passed in to the intialize function (as a
11
+ # hash), though only the expected network-related variables will be readable and
12
+ # writeable directly.
13
+ #
14
+ # == Examples
15
+ #
16
+ # PacketFu::Config.new(:ip_saddr => "1.2.3.4").ip_saddr #=> "1.2.3.4"
17
+ # PacketFu::Config.new(:foo=>"bar").foo #=> NomethodError: undefined method `foo'...
18
+ #
19
+ # The config() function, however, does provide access to custom variables:
20
+ #
21
+ # PacketFu::Config.new(:foo=>"bar").config[:foo] #=> "bar"
22
+ # obj = PacketFu::Config.new(:foo=>"bar")
23
+ # obj.config(:baz => "bat")
24
+ # obj.config #=> {:iface=>"eth0", :baz=>"bat", :pcapfile=>"/tmp/out.pcap", :foo=>"bar"}
25
+ class Config
26
+ attr_accessor :eth_saddr, # The discovered eth_saddr
27
+ :eth_daddr, # The discovered eth_daddr (ie, the gateway)
28
+ :eth_src, # The discovered eth_src in binary form.
29
+ :eth_dst, # The discovered eth_dst (gateway) in binary form.
30
+ :ip_saddr, # The discovered ip_saddr
31
+ :ip_src, # The discovered ip_src in binary form.
32
+ :iface, # The declared interface.
33
+ :pcapfile # A declared default file to write to.
34
+
35
+ def initialize(args={})
36
+ if Process.euid.zero?
37
+ @iface = args[:iface] || ENV['IFACE'] || Pcap.lookupdev || "lo"
38
+ end
39
+ @pcapfile = "/tmp/out.pcap"
40
+ args.each_pair { |k,v| self.instance_variable_set(("@#{k}"),v) }
41
+ end
41
42
 
42
- # Returns all instance variables as a hash (including custom variables set at initialization).
43
- def config(arg=nil)
44
- if arg
45
- arg.each_pair {|k,v| self.instance_variable_set(("@" + k.to_s).intern, v)}
46
- else
47
- config_hash = {}
48
- self.instance_variables.each do |v|
49
- key = v.to_s.gsub(/^@/,"").to_sym
50
- config_hash[key] = self.instance_variable_get(v)
51
- end
52
- config_hash
53
- end
54
- end
43
+ # Returns all instance variables as a hash (including custom variables set at initialization).
44
+ def config(arg=nil)
45
+ if arg
46
+ arg.each_pair {|k,v| self.instance_variable_set(("@" + k.to_s).intern, v)}
47
+ else
48
+ config_hash = {}
49
+ self.instance_variables.each do |v|
50
+ key = v.to_s.gsub(/^@/,"").to_sym
51
+ config_hash[key] = self.instance_variable_get(v)
52
+ end
53
+ config_hash
54
+ end
55
+ end
55
56
 
56
- end
57
+ end
57
58
 
58
59
  end