packetfu 1.1.8 → 1.1.9
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.
- data/README.rdoc +11 -12
- data/bench/octets.rb +9 -9
- data/examples/100kpackets.rb +13 -12
- data/examples/ackscan.rb +17 -16
- data/examples/arp.rb +36 -35
- data/examples/arphood.rb +37 -36
- data/examples/dissect_thinger.rb +7 -6
- data/examples/ethernet.rb +1 -0
- data/examples/examples.rb +1 -0
- data/examples/ifconfig.rb +1 -0
- data/examples/new-simple-stats.rb +24 -23
- data/examples/packetfu-shell.rb +26 -25
- data/examples/simple-sniffer.rb +10 -9
- data/examples/simple-stats.rb +24 -23
- data/examples/slammer.rb +4 -3
- data/lib/packetfu.rb +128 -127
- data/lib/packetfu/capture.rb +170 -169
- data/lib/packetfu/config.rb +53 -52
- data/lib/packetfu/inject.rb +57 -56
- data/lib/packetfu/packet.rb +529 -528
- data/lib/packetfu/pcap.rb +580 -579
- data/lib/packetfu/protos/arp.rb +91 -90
- data/lib/packetfu/protos/arp/header.rb +159 -158
- data/lib/packetfu/protos/arp/mixin.rb +37 -36
- data/lib/packetfu/protos/eth.rb +45 -44
- data/lib/packetfu/protos/eth/header.rb +244 -243
- data/lib/packetfu/protos/eth/mixin.rb +4 -3
- data/lib/packetfu/protos/hsrp.rb +70 -69
- data/lib/packetfu/protos/hsrp/header.rb +108 -107
- data/lib/packetfu/protos/hsrp/mixin.rb +30 -29
- data/lib/packetfu/protos/icmp.rb +72 -71
- data/lib/packetfu/protos/icmp/header.rb +83 -82
- data/lib/packetfu/protos/icmp/mixin.rb +15 -14
- data/lib/packetfu/protos/invalid.rb +50 -49
- data/lib/packetfu/protos/ip.rb +70 -69
- data/lib/packetfu/protos/ip/header.rb +292 -291
- data/lib/packetfu/protos/ip/mixin.rb +41 -40
- data/lib/packetfu/protos/ipv6.rb +51 -50
- data/lib/packetfu/protos/ipv6/header.rb +189 -188
- data/lib/packetfu/protos/ipv6/mixin.rb +30 -29
- data/lib/packetfu/protos/lldp.rb +3 -1
- data/lib/packetfu/protos/lldp/header.rb +1 -0
- data/lib/packetfu/protos/lldp/mixin.rb +1 -0
- data/lib/packetfu/protos/tcp.rb +177 -176
- data/lib/packetfu/protos/tcp/ecn.rb +36 -35
- data/lib/packetfu/protos/tcp/flags.rb +75 -74
- data/lib/packetfu/protos/tcp/header.rb +269 -268
- data/lib/packetfu/protos/tcp/hlen.rb +33 -32
- data/lib/packetfu/protos/tcp/mixin.rb +47 -46
- data/lib/packetfu/protos/tcp/option.rb +322 -321
- data/lib/packetfu/protos/tcp/options.rb +96 -95
- data/lib/packetfu/protos/tcp/reserved.rb +36 -35
- data/lib/packetfu/protos/udp.rb +117 -116
- data/lib/packetfu/protos/udp/header.rb +92 -91
- data/lib/packetfu/protos/udp/mixin.rb +4 -3
- data/lib/packetfu/structfu.rb +281 -280
- data/lib/packetfu/utils.rb +211 -208
- data/lib/packetfu/version.rb +42 -41
- data/packetfu.gemspec +1 -1
- data/spec/ethpacket_spec.rb +48 -48
- data/spec/packet_spec.rb +57 -57
- data/spec/packet_subclasses_spec.rb +8 -8
- data/spec/packetfu_spec.rb +59 -59
- data/spec/structfu_spec.rb +268 -268
- data/spec/tcp_spec.rb +75 -75
- data/test/all_tests.rb +13 -13
- data/test/func_lldp.rb +3 -3
- data/test/ptest.rb +2 -2
- data/test/test_arp.rb +116 -116
- data/test/test_capture.rb +45 -45
- data/test/test_eth.rb +68 -68
- data/test/test_hsrp.rb +9 -9
- data/test/test_icmp.rb +52 -52
- data/test/test_inject.rb +18 -18
- data/test/test_invalid.rb +16 -16
- data/test/test_ip.rb +36 -36
- data/test/test_ip6.rb +48 -48
- data/test/test_octets.rb +21 -21
- data/test/test_packet.rb +154 -154
- data/test/test_pcap.rb +170 -170
- data/test/test_structfu.rb +97 -97
- data/test/test_tcp.rb +320 -320
- data/test/test_udp.rb +76 -76
- metadata +2 -2
data/lib/packetfu/protos/icmp.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- coding: binary -*-
|
1
2
|
require 'packetfu/protos/eth/header'
|
2
3
|
require 'packetfu/protos/eth/mixin'
|
3
4
|
|
@@ -8,85 +9,85 @@ require 'packetfu/protos/icmp/header'
|
|
8
9
|
require 'packetfu/protos/icmp/mixin'
|
9
10
|
|
10
11
|
module PacketFu
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
12
|
+
# ICMPPacket is used to construct ICMP Packets. They contain an EthHeader, an IPHeader, and a ICMPHeader.
|
13
|
+
#
|
14
|
+
# == Example
|
15
|
+
#
|
16
|
+
# icmp_pkt.new
|
17
|
+
# icmp_pkt.icmp_type = 8
|
18
|
+
# icmp_pkt.icmp_code = 0
|
19
|
+
# icmp_pkt.payload = "ABC, easy as 123. As simple as do-re-mi. ABC, 123, baby, you and me!"
|
20
|
+
#
|
21
|
+
# icmp_pkt.ip_saddr="1.2.3.4"
|
22
|
+
# icmp_pkt.ip_daddr="5.6.7.8"
|
23
|
+
#
|
24
|
+
# icmp_pkt.recalc
|
25
|
+
# icmp_pkt.to_f('/tmp/icmp.pcap')
|
26
|
+
#
|
27
|
+
# == Parameters
|
28
|
+
#
|
29
|
+
# :eth
|
30
|
+
# A pre-generated EthHeader object.
|
31
|
+
# :ip
|
32
|
+
# A pre-generated IPHeader object.
|
33
|
+
# :flavor
|
34
|
+
# TODO: Sets the "flavor" of the ICMP packet. Pings, in particular, often betray their true
|
35
|
+
# OS.
|
36
|
+
# :config
|
37
|
+
# A hash of return address details, often the output of Utils.whoami?
|
38
|
+
class ICMPPacket < Packet
|
38
39
|
include ::PacketFu::EthHeaderMixin
|
39
40
|
include ::PacketFu::IPHeaderMixin
|
40
41
|
include ::PacketFu::ICMPHeaderMixin
|
41
42
|
|
42
|
-
|
43
|
+
attr_accessor :eth_header, :ip_header, :icmp_header
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
45
|
+
def self.can_parse?(str)
|
46
|
+
return false unless str.size >= 38
|
47
|
+
return false unless EthPacket.can_parse? str
|
48
|
+
return false unless IPPacket.can_parse? str
|
49
|
+
return false unless str[23,1] == "\x01"
|
50
|
+
return true
|
51
|
+
end
|
51
52
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
53
|
+
def read(str=nil, args={})
|
54
|
+
raise "Cannot parse `#{str}'" unless self.class.can_parse?(str)
|
55
|
+
@eth_header.read(str)
|
56
|
+
super(args)
|
57
|
+
self
|
58
|
+
end
|
58
59
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
60
|
+
def initialize(args={})
|
61
|
+
@eth_header = EthHeader.new(args).read(args[:eth])
|
62
|
+
@ip_header = IPHeader.new(args).read(args[:ip])
|
63
|
+
@ip_header.ip_proto = 1
|
64
|
+
@icmp_header = ICMPHeader.new(args).read(args[:icmp])
|
64
65
|
|
65
|
-
|
66
|
-
|
66
|
+
@ip_header.body = @icmp_header
|
67
|
+
@eth_header.body = @ip_header
|
67
68
|
|
68
|
-
|
69
|
-
|
70
|
-
|
69
|
+
@headers = [@eth_header, @ip_header, @icmp_header]
|
70
|
+
super
|
71
|
+
end
|
71
72
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
73
|
+
# Peek provides summary data on packet contents.
|
74
|
+
def peek_format
|
75
|
+
peek_data = ["IC "] # I is taken by IP
|
76
|
+
peek_data << "%-5d" % self.to_s.size
|
77
|
+
type = case self.icmp_type.to_i
|
78
|
+
when 8
|
79
|
+
"ping"
|
80
|
+
when 0
|
81
|
+
"pong"
|
82
|
+
else
|
83
|
+
"%02x-%02x" % [self.icmp_type, self.icmp_code]
|
84
|
+
end
|
85
|
+
peek_data << "%-21s" % "#{self.ip_saddr}:#{type}"
|
86
|
+
peek_data << "->"
|
87
|
+
peek_data << "%21s" % "#{self.ip_daddr}"
|
88
|
+
peek_data << "%23s" % "I:"
|
89
|
+
peek_data << "%04x" % self.ip_id
|
90
|
+
peek_data.join
|
91
|
+
end
|
92
|
+
end
|
92
93
|
end
|
@@ -1,93 +1,94 @@
|
|
1
|
+
# -*- coding: binary -*-
|
1
2
|
module PacketFu
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
3
|
+
# ICMPHeader is a complete ICMP struct, used in ICMPPacket. ICMP is
|
4
|
+
# typically used for network administration and connectivity testing.
|
5
|
+
#
|
6
|
+
# For more on ICMP packets, see
|
7
|
+
# http://www.networksorcery.com/enp/protocol/icmp.htm
|
8
|
+
#
|
9
|
+
# ==== Header Definition
|
10
|
+
#
|
11
|
+
# Int8 :icmp_type # Type
|
12
|
+
# Int8 :icmp_code # Code
|
13
|
+
# Int16 :icmp_sum Default: calculated # Checksum
|
14
|
+
# String :body
|
15
|
+
class ICMPHeader < Struct.new(:icmp_type, :icmp_code, :icmp_sum, :body)
|
15
16
|
|
16
|
-
|
17
|
+
include StructFu
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
19
|
+
def initialize(args={})
|
20
|
+
super(
|
21
|
+
Int8.new(args[:icmp_type]),
|
22
|
+
Int8.new(args[:icmp_code]),
|
23
|
+
Int16.new(args[:icmp_sum] || icmp_calc_sum),
|
24
|
+
StructFu::String.new.read(args[:body])
|
25
|
+
)
|
26
|
+
end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
# Returns the object in string form.
|
29
|
+
def to_s
|
30
|
+
self.to_a.map {|x| x.to_s}.join
|
31
|
+
end
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
33
|
+
# Reads a string to populate the object.
|
34
|
+
def read(str)
|
35
|
+
force_binary(str)
|
36
|
+
return self if str.nil?
|
37
|
+
self[:icmp_type].read(str[0,1])
|
38
|
+
self[:icmp_code].read(str[1,1])
|
39
|
+
self[:icmp_sum].read(str[2,2])
|
40
|
+
self[:body].read(str[4,str.size])
|
41
|
+
self
|
42
|
+
end
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
44
|
+
# Setter for the type.
|
45
|
+
def icmp_type=(i); typecast i; end
|
46
|
+
# Getter for the type.
|
47
|
+
def icmp_type; self[:icmp_type].to_i; end
|
48
|
+
# Setter for the code.
|
49
|
+
def icmp_code=(i); typecast i; end
|
50
|
+
# Getter for the code.
|
51
|
+
def icmp_code; self[:icmp_code].to_i; end
|
52
|
+
# Setter for the checksum. Note, this is calculated automatically with
|
53
|
+
# icmp_calc_sum.
|
54
|
+
def icmp_sum=(i); typecast i; end
|
55
|
+
# Getter for the checksum.
|
56
|
+
def icmp_sum; self[:icmp_sum].to_i; end
|
56
57
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
58
|
+
# Calculates and sets the checksum for the object.
|
59
|
+
def icmp_calc_sum
|
60
|
+
checksum = (icmp_type.to_i << 8) + icmp_code.to_i
|
61
|
+
chk_body = (body.to_s.size % 2 == 0 ? body.to_s : body.to_s + "\x00")
|
62
|
+
if 1.respond_to? :ord
|
63
|
+
chk_body.scan(/../).map { |x| (x[0].ord << 8) + x[1].ord }.each { |y| checksum += y }
|
64
|
+
else
|
65
|
+
chk_body.scan(/../).map { |x| (x[0] << 8) + x[1] }.each { |y| checksum += y }
|
66
|
+
end
|
67
|
+
checksum = checksum % 0xffff
|
68
|
+
checksum = 0xffff - checksum
|
69
|
+
checksum == 0 ? 0xffff : checksum
|
70
|
+
end
|
71
|
+
|
72
|
+
# Recalculates the calculatable fields for ICMP.
|
73
|
+
def icmp_recalc(arg=:all)
|
74
|
+
# How silly is this, you can't intern a symbol in ruby 1.8.7pl72?
|
75
|
+
# I'm this close to monkey patching Symbol so you can force it...
|
76
|
+
arg = arg.intern if arg.respond_to? :intern
|
77
|
+
case arg
|
78
|
+
when :icmp_sum
|
79
|
+
self.icmp_sum=icmp_calc_sum
|
80
|
+
when :all
|
81
|
+
self.icmp_sum=icmp_calc_sum
|
82
|
+
else
|
83
|
+
raise ArgumentError, "No such field `#{arg}'"
|
84
|
+
end
|
85
|
+
end
|
85
86
|
|
86
|
-
|
87
|
+
# Readability aliases
|
87
88
|
|
88
|
-
|
89
|
-
|
90
|
-
|
89
|
+
def icmp_sum_readable
|
90
|
+
"0x%04x" % icmp_sum
|
91
|
+
end
|
91
92
|
|
92
|
-
|
93
|
+
end
|
93
94
|
end
|
@@ -1,17 +1,18 @@
|
|
1
|
+
# -*- coding: binary -*-
|
1
2
|
module PacketFu
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
3
|
+
# This Mixin simplifies access to the ICMPHeaders. Mix this in with your
|
4
|
+
# packet interface, and it will add methods that essentially delegate to
|
5
|
+
# the 'icmp_header' method (assuming that it is a ICMPHeader object)
|
6
|
+
module ICMPHeaderMixin
|
7
|
+
def icmp_type=(v); self.icmp_header.icmp_type= v; end
|
8
|
+
def icmp_type; self.icmp_header.icmp_type; end
|
9
|
+
def icmp_code=(v); self.icmp_header.icmp_code= v; end
|
10
|
+
def icmp_code; self.icmp_header.icmp_code; end
|
11
|
+
def icmp_sum=(v); self.icmp_header.icmp_sum= v; end
|
12
|
+
def icmp_sum; self.icmp_header.icmp_sum; end
|
13
|
+
def icmp_calc_sum; self.icmp_header.icmp_calc_sum; end
|
14
|
+
def icmp_recalc(*v); self.icmp_header.icmp_recalc(*v); end
|
15
|
+
def icmp_sum_readable; self.icmp_header.icmp_sum_readable; end
|
16
|
+
end
|
16
17
|
end
|
17
18
|
|
@@ -1,54 +1,55 @@
|
|
1
|
+
# -*- coding: binary -*-
|
1
2
|
module PacketFu
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
4
|
+
# InvalidHeader catches all packets that we don't already have a Struct for,
|
5
|
+
# or for whatever reason, violates some basic packet rules for other packet
|
6
|
+
# types.
|
7
|
+
class InvalidHeader < Struct.new(:body)
|
8
|
+
include StructFu
|
9
|
+
|
10
|
+
def initialize(args={})
|
11
|
+
args[:body] ||= StructFu::String.new
|
12
|
+
super(args[:body])
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns the object in string form.
|
16
|
+
def to_s
|
17
|
+
self.to_a.map {|x| x.to_s}.join
|
18
|
+
end
|
19
|
+
|
20
|
+
# Reads a string to populate the object.
|
21
|
+
def read(str)
|
22
|
+
force_binary(str)
|
23
|
+
return self if str.nil?
|
24
|
+
self[:body].read str
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
# You probably don't want to write invalid packets on purpose.
|
31
|
+
class InvalidPacket < Packet
|
32
|
+
attr_accessor :invalid_header
|
33
|
+
|
34
|
+
# Any packet is potentially an invalid packet
|
35
|
+
def self.can_parse?(str)
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.layer
|
40
|
+
0
|
41
|
+
end
|
42
|
+
|
43
|
+
def read(str=nil,args={})
|
44
|
+
@invalid_header.read(str)
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
def initialize(args={})
|
49
|
+
@invalid_header = (args[:invalid] || InvalidHeader.new)
|
50
|
+
@headers = [@invalid_header]
|
51
|
+
end
|
52
|
+
end
|
52
53
|
|
53
54
|
end # module PacketFu
|
54
55
|
|