packetfu 1.1.10 → 1.1.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +2 -0
- data/.gitignore +3 -0
- data/.travis.yml +8 -0
- data/CONTRIBUTING.md +47 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +1 -1
- data/README.rdoc +35 -30
- data/Rakefile +4 -4
- data/bench/octets.rb +9 -9
- data/examples/100kpackets.rb +12 -12
- data/examples/ackscan.rb +16 -16
- data/examples/arp.rb +35 -35
- data/examples/arphood.rb +36 -36
- data/examples/dissect_thinger.rb +6 -6
- data/examples/new-simple-stats.rb +23 -23
- data/examples/packetfu-shell.rb +25 -25
- data/examples/simple-sniffer.rb +9 -9
- data/examples/simple-stats.rb +23 -23
- data/examples/slammer.rb +3 -3
- data/gem-public_cert.pem +21 -0
- data/lib/packetfu.rb +149 -127
- data/lib/packetfu/capture.rb +169 -169
- data/lib/packetfu/config.rb +52 -52
- data/lib/packetfu/inject.rb +56 -56
- data/lib/packetfu/packet.rb +531 -528
- data/lib/packetfu/pcap.rb +579 -579
- data/lib/packetfu/protos/arp.rb +90 -90
- data/lib/packetfu/protos/arp/header.rb +158 -158
- data/lib/packetfu/protos/arp/mixin.rb +36 -36
- data/lib/packetfu/protos/eth.rb +44 -44
- data/lib/packetfu/protos/eth/header.rb +243 -243
- data/lib/packetfu/protos/eth/mixin.rb +3 -3
- data/lib/packetfu/protos/hsrp.rb +69 -69
- data/lib/packetfu/protos/hsrp/header.rb +107 -107
- data/lib/packetfu/protos/hsrp/mixin.rb +29 -29
- data/lib/packetfu/protos/icmp.rb +71 -71
- data/lib/packetfu/protos/icmp/header.rb +82 -82
- data/lib/packetfu/protos/icmp/mixin.rb +14 -14
- data/lib/packetfu/protos/invalid.rb +49 -49
- data/lib/packetfu/protos/ip.rb +69 -69
- data/lib/packetfu/protos/ip/header.rb +291 -291
- data/lib/packetfu/protos/ip/mixin.rb +40 -40
- data/lib/packetfu/protos/ipv6.rb +50 -50
- data/lib/packetfu/protos/ipv6/header.rb +188 -188
- data/lib/packetfu/protos/ipv6/mixin.rb +29 -29
- data/lib/packetfu/protos/tcp.rb +176 -176
- data/lib/packetfu/protos/tcp/ecn.rb +35 -35
- data/lib/packetfu/protos/tcp/flags.rb +74 -74
- data/lib/packetfu/protos/tcp/header.rb +268 -268
- data/lib/packetfu/protos/tcp/hlen.rb +32 -32
- data/lib/packetfu/protos/tcp/mixin.rb +46 -46
- data/lib/packetfu/protos/tcp/option.rb +321 -321
- data/lib/packetfu/protos/tcp/options.rb +95 -95
- data/lib/packetfu/protos/tcp/reserved.rb +35 -35
- data/lib/packetfu/protos/udp.rb +159 -123
- data/lib/packetfu/protos/udp/header.rb +91 -91
- data/lib/packetfu/protos/udp/mixin.rb +3 -3
- data/lib/packetfu/structfu.rb +280 -280
- data/lib/packetfu/utils.rb +292 -225
- data/lib/packetfu/version.rb +41 -41
- data/packetfu.gemspec +14 -3
- data/spec/arp_spec.rb +191 -0
- data/spec/eth_spec.rb +148 -0
- data/spec/icmp_spec.rb +97 -0
- data/spec/ip_spec.rb +78 -0
- data/spec/ipv6_spec.rb +81 -0
- data/spec/packet_spec.rb +61 -59
- data/spec/packet_subclasses_spec.rb +9 -10
- data/spec/packetfu_spec.rb +55 -62
- data/spec/sample3.pcap +0 -0
- data/spec/spec_helper.rb +44 -0
- data/spec/structfu_spec.rb +270 -271
- data/spec/tcp_spec.rb +76 -77
- data/spec/udp_spec.rb +32 -0
- data/spec/utils_spec.rb +95 -0
- data/test/all_tests.rb +14 -17
- data/test/func_lldp.rb +3 -3
- data/test/ptest.rb +2 -2
- data/test/test_capture.rb +45 -45
- data/test/test_eth.rb +70 -68
- data/test/test_hsrp.rb +9 -9
- data/test/test_inject.rb +18 -18
- data/test/test_invalid.rb +16 -16
- data/test/test_octets.rb +23 -21
- data/test/test_packet.rb +156 -154
- data/test/test_pcap.rb +172 -170
- data/test/test_structfu.rb +99 -97
- data/test/test_tcp.rb +322 -320
- data/test/test_udp.rb +78 -76
- metadata +108 -44
- metadata.gz.sig +2 -0
- data/spec/ethpacket_spec.rb +0 -74
- data/test/test_arp.rb +0 -135
- data/test/test_icmp.rb +0 -62
- data/test/test_ip.rb +0 -50
- data/test/test_ip6.rb +0 -68
data/lib/packetfu/protos/icmp.rb
CHANGED
@@ -9,85 +9,85 @@ require 'packetfu/protos/icmp/header'
|
|
9
9
|
require 'packetfu/protos/icmp/mixin'
|
10
10
|
|
11
11
|
module PacketFu
|
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
|
-
|
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
|
39
39
|
include ::PacketFu::EthHeaderMixin
|
40
40
|
include ::PacketFu::IPHeaderMixin
|
41
41
|
include ::PacketFu::ICMPHeaderMixin
|
42
42
|
|
43
|
-
|
43
|
+
attr_accessor :eth_header, :ip_header, :icmp_header
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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
|
52
52
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
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
|
59
59
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
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])
|
65
65
|
|
66
|
-
|
67
|
-
|
66
|
+
@ip_header.body = @icmp_header
|
67
|
+
@eth_header.body = @ip_header
|
68
68
|
|
69
|
-
|
70
|
-
|
71
|
-
|
69
|
+
@headers = [@eth_header, @ip_header, @icmp_header]
|
70
|
+
super
|
71
|
+
end
|
72
72
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
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
|
93
93
|
end
|
@@ -1,94 +1,94 @@
|
|
1
1
|
# -*- coding: binary -*-
|
2
2
|
module PacketFu
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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)
|
16
16
|
|
17
|
-
|
17
|
+
include StructFu
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
# Returns the object in string form.
|
29
|
+
def to_s
|
30
|
+
self.to_a.map {|x| x.to_s}.join
|
31
|
+
end
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
43
43
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
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
|
-
|
85
|
-
|
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.split("").each_slice(2).map { |x| (x[0].ord << 8) + x[1].ord }.each { |y| checksum += y }
|
64
|
+
else
|
65
|
+
chk_body.split("").each_slice(2).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
|
86
86
|
|
87
|
-
|
87
|
+
# Readability aliases
|
88
88
|
|
89
|
-
|
90
|
-
|
91
|
-
|
89
|
+
def icmp_sum_readable
|
90
|
+
"0x%04x" % icmp_sum
|
91
|
+
end
|
92
92
|
|
93
|
-
|
93
|
+
end
|
94
94
|
end
|
@@ -1,18 +1,18 @@
|
|
1
1
|
# -*- coding: binary -*-
|
2
2
|
module PacketFu
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
17
17
|
end
|
18
18
|
|
@@ -1,55 +1,55 @@
|
|
1
1
|
# -*- coding: binary -*-
|
2
2
|
module PacketFu
|
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
|
-
|
52
|
-
|
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
|
53
53
|
|
54
54
|
end # module PacketFu
|
55
55
|
|