packetgen 3.1.6 → 3.2.1
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.
- checksums.yaml +4 -4
- data/README.md +1 -2
- data/bin/pgconsole +3 -3
- data/lib/packetgen/capture.rb +5 -1
- data/lib/packetgen/header/arp.rb +24 -13
- data/lib/packetgen/header/asn1_base.rb +19 -9
- data/lib/packetgen/header/base.rb +1 -1
- data/lib/packetgen/header/dhcpv6/option.rb +11 -13
- data/lib/packetgen/header/dns/opt.rb +2 -2
- data/lib/packetgen/header/dns/rr.rb +61 -28
- data/lib/packetgen/header/dns.rb +13 -6
- data/lib/packetgen/header/dot11/data.rb +19 -29
- data/lib/packetgen/header/dot11/management.rb +2 -5
- data/lib/packetgen/header/dot11.rb +1 -1
- data/lib/packetgen/header/eap.rb +1 -1
- data/lib/packetgen/header/eth.rb +1 -1
- data/lib/packetgen/header/http/request.rb +5 -1
- data/lib/packetgen/header/http/response.rb +46 -20
- data/lib/packetgen/header/http/verbs.rb +1 -1
- data/lib/packetgen/header/igmp.rb +1 -1
- data/lib/packetgen/header/ip/option.rb +2 -1
- data/lib/packetgen/header/ipv6/addr.rb +3 -0
- data/lib/packetgen/header/mdns.rb +19 -25
- data/lib/packetgen/header/mld.rb +1 -1
- data/lib/packetgen/header/ospfv2/lsa.rb +7 -3
- data/lib/packetgen/header/ospfv2/lsa_header.rb +2 -4
- data/lib/packetgen/header/ospfv2.rb +1 -1
- data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +14 -5
- data/lib/packetgen/header/ospfv3/lsa.rb +8 -4
- data/lib/packetgen/header/ospfv3/lsa_header.rb +2 -4
- data/lib/packetgen/header/ospfv3.rb +1 -1
- data/lib/packetgen/header/snmp.rb +20 -14
- data/lib/packetgen/header/tcp/option.rb +1 -1
- data/lib/packetgen/header/tcp.rb +12 -5
- data/lib/packetgen/header/tftp.rb +15 -9
- data/lib/packetgen/inspect.rb +15 -9
- data/lib/packetgen/packet.rb +51 -5
- data/lib/packetgen/pcapng/file.rb +17 -15
- data/lib/packetgen/pcapng.rb +1 -0
- data/lib/packetgen/pcaprub_wrapper.rb +0 -4
- data/lib/packetgen/types/abstract_tlv.rb +1 -1
- data/lib/packetgen/types/array.rb +8 -1
- data/lib/packetgen/types/cstring.rb +20 -7
- data/lib/packetgen/types/fields.rb +19 -19
- data/lib/packetgen/types/int.rb +7 -0
- data/lib/packetgen/types/oui.rb +1 -1
- data/lib/packetgen/types/string.rb +16 -3
- data/lib/packetgen/types/tlv.rb +17 -9
- data/lib/packetgen/unknown_packet.rb +84 -0
- data/lib/packetgen/utils.rb +60 -27
- data/lib/packetgen/version.rb +1 -1
- data/lib/packetgen.rb +13 -4
- metadata +7 -7
@@ -62,7 +62,7 @@ module PacketGen
|
|
62
62
|
HUMAN_SEPARATOR = ','
|
63
63
|
|
64
64
|
# rubocop:disable Naming/AccessorMethodName
|
65
|
-
class <<self
|
65
|
+
class << self
|
66
66
|
# Get class set with {.set_of}.
|
67
67
|
# @return [Class]
|
68
68
|
# @since 3.0.0
|
@@ -154,6 +154,8 @@ module PacketGen
|
|
154
154
|
self
|
155
155
|
end
|
156
156
|
|
157
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
158
|
+
|
157
159
|
# Populate object from a string
|
158
160
|
# @param [String] str
|
159
161
|
# @return [self]
|
@@ -171,6 +173,7 @@ module PacketGen
|
|
171
173
|
end
|
172
174
|
self
|
173
175
|
end
|
176
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
174
177
|
|
175
178
|
# Get size in bytes
|
176
179
|
# @return [Integer]
|
@@ -228,18 +231,22 @@ module PacketGen
|
|
228
231
|
class ArrayOfInt8 < Array
|
229
232
|
set_of Int8
|
230
233
|
end
|
234
|
+
|
231
235
|
# Specialized array to handle serie of {Int16}.
|
232
236
|
class ArrayOfInt16 < Array
|
233
237
|
set_of Int16
|
234
238
|
end
|
239
|
+
|
235
240
|
# Specialized array to handle serie of {Int16le}.
|
236
241
|
class ArrayOfInt16le < Array
|
237
242
|
set_of Int16le
|
238
243
|
end
|
244
|
+
|
239
245
|
# Specialized array to handle serie of {Int32}.
|
240
246
|
class ArrayOfInt32 < Types::Array
|
241
247
|
set_of Types::Int32
|
242
248
|
end
|
249
|
+
|
243
250
|
# Specialized array to handle serie of {Int32le}.
|
244
251
|
class ArrayOfInt32le < Types::Array
|
245
252
|
set_of Types::Int32le
|
@@ -17,8 +17,9 @@ module PacketGen
|
|
17
17
|
extend Forwardable
|
18
18
|
include Fieldable
|
19
19
|
|
20
|
-
def_delegators :@string, :[], :length, :size, :inspect, :==,
|
21
|
-
:unpack, :force_encoding, :encoding, :index, :empty
|
20
|
+
def_delegators :@string, :[], :length, :size, :inspect, :==,
|
21
|
+
:unpack, :force_encoding, :encoding, :index, :empty?,
|
22
|
+
:encode, :slice, :slice!
|
22
23
|
|
23
24
|
# @return [::String]
|
24
25
|
attr_reader :string
|
@@ -28,7 +29,7 @@ module PacketGen
|
|
28
29
|
# @param [Hash] options
|
29
30
|
# @option options [Integer] :static_length set a static length for this string
|
30
31
|
def initialize(options={})
|
31
|
-
register_internal_string
|
32
|
+
register_internal_string(+'')
|
32
33
|
@static_length = options[:static_length]
|
33
34
|
end
|
34
35
|
|
@@ -37,9 +38,8 @@ module PacketGen
|
|
37
38
|
def read(str)
|
38
39
|
s = str.to_s
|
39
40
|
s = s[0, static_length] if static_length?
|
40
|
-
idx = s.index(0.chr)
|
41
|
-
s = s[0, idx] unless idx.nil?
|
42
41
|
register_internal_string s
|
42
|
+
remove_null_character
|
43
43
|
self
|
44
44
|
end
|
45
45
|
|
@@ -55,6 +55,15 @@ module PacketGen
|
|
55
55
|
PacketGen.force_binary(s)
|
56
56
|
end
|
57
57
|
|
58
|
+
# Append the given string to CString
|
59
|
+
# @param [#to_s] str
|
60
|
+
# @return [self]
|
61
|
+
def <<(str)
|
62
|
+
@string << str.to_s
|
63
|
+
remove_null_character
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
58
67
|
# @return [Integer]
|
59
68
|
def sz
|
60
69
|
if static_length?
|
@@ -80,8 +89,7 @@ module PacketGen
|
|
80
89
|
|
81
90
|
# @return [String]
|
82
91
|
def to_human
|
83
|
-
|
84
|
-
self[0, idx]
|
92
|
+
string
|
85
93
|
end
|
86
94
|
|
87
95
|
private
|
@@ -90,6 +98,11 @@ module PacketGen
|
|
90
98
|
@string = str
|
91
99
|
PacketGen.force_binary(@string)
|
92
100
|
end
|
101
|
+
|
102
|
+
def remove_null_character
|
103
|
+
idx = string.index(0.chr)
|
104
|
+
register_internal_string(string[0, idx]) unless idx.nil?
|
105
|
+
end
|
93
106
|
end
|
94
107
|
end
|
95
108
|
end
|
@@ -115,7 +115,7 @@ module PacketGen
|
|
115
115
|
# @private bit field definitions
|
116
116
|
@bit_fields = {}
|
117
117
|
|
118
|
-
class <<self
|
118
|
+
class << self
|
119
119
|
# Get field definitions for this class.
|
120
120
|
# @return [Hash]
|
121
121
|
# @since 3.1.0
|
@@ -282,7 +282,7 @@ module PacketGen
|
|
282
282
|
type = field_defs[attr].type
|
283
283
|
raise TypeError, "#{attr} is not a PacketGen::Types::Int" unless type < Types::Int
|
284
284
|
|
285
|
-
total_size = type.new.
|
285
|
+
total_size = type.new.nbits
|
286
286
|
idx = total_size - 1
|
287
287
|
|
288
288
|
until args.empty?
|
@@ -358,15 +358,15 @@ module PacketGen
|
|
358
358
|
clear_mask = compute_clear_mask(total_size, field_mask)
|
359
359
|
|
360
360
|
class_eval <<-METHODS
|
361
|
-
def #{name}?
|
362
|
-
val = (self[:#{attr}].to_i & #{field_mask}) >> #{shift}
|
363
|
-
val != 0
|
364
|
-
end
|
365
|
-
def #{name}=(v)
|
366
|
-
val = v ? 1 : 0
|
367
|
-
self[:#{attr}].value = self[:#{attr}].to_i & #{clear_mask}
|
368
|
-
self[:#{attr}].value |= val << #{shift}
|
369
|
-
end
|
361
|
+
def #{name}? # def bit?
|
362
|
+
val = (self[:#{attr}].to_i & #{field_mask}) >> #{shift} # val = (self[:attr}].to_i & 1}) >> 1
|
363
|
+
val != 0 # val != 0
|
364
|
+
end # end
|
365
|
+
def #{name}=(v) # def bit=(v)
|
366
|
+
val = v ? 1 : 0 # val = v ? 1 : 0
|
367
|
+
self[:#{attr}].value = self[:#{attr}].to_i & #{clear_mask} # self[:attr].value = self[:attr].to_i & 0xfffd
|
368
|
+
self[:#{attr}].value |= val << #{shift} # self[:attr].value |= val << 1
|
369
|
+
end # end
|
370
370
|
METHODS
|
371
371
|
end
|
372
372
|
|
@@ -375,13 +375,13 @@ module PacketGen
|
|
375
375
|
clear_mask = compute_clear_mask(total_size, field_mask)
|
376
376
|
|
377
377
|
class_eval <<-METHODS
|
378
|
-
def #{name}
|
379
|
-
(self[:#{attr}].to_i & #{field_mask}) >> #{shift}
|
380
|
-
end
|
381
|
-
def #{name}=(v)
|
382
|
-
self[:#{attr}].value = self[:#{attr}].to_i & #{clear_mask}
|
383
|
-
self[:#{attr}].value |= (v & #{2**size - 1}) << #{shift}
|
384
|
-
end
|
378
|
+
def #{name} # def multibit
|
379
|
+
(self[:#{attr}].to_i & #{field_mask}) >> #{shift} # (self[:attr].to_i & 6) >> 1
|
380
|
+
end # end
|
381
|
+
def #{name}=(v) # def multibit=(v)
|
382
|
+
self[:#{attr}].value = self[:#{attr}].to_i & #{clear_mask} # self[:attr].value = self[:attr].to_i & 0xfff9
|
383
|
+
self[:#{attr}].value |= (v & #{2**size - 1}) << #{shift} # self[:attr].value |= (v & 3) << 1
|
384
|
+
end # end
|
385
385
|
METHODS
|
386
386
|
end
|
387
387
|
|
@@ -523,7 +523,7 @@ module PacketGen
|
|
523
523
|
# Return object as a hash
|
524
524
|
# @return [Hash] keys: attributes, values: attribute values
|
525
525
|
def to_h
|
526
|
-
|
526
|
+
fields.map { |f| [f, @fields[f].to_human] }.to_h
|
527
527
|
end
|
528
528
|
|
529
529
|
# Get offset of given field in {Fields} structure.
|
data/lib/packetgen/types/int.rb
CHANGED
data/lib/packetgen/types/oui.rb
CHANGED
@@ -18,8 +18,9 @@ module PacketGen
|
|
18
18
|
include Fieldable
|
19
19
|
include LengthFrom
|
20
20
|
|
21
|
-
def_delegators :@string, :[], :to_s, :length, :size, :inspect, :==,
|
22
|
-
:unpack, :force_encoding, :encoding, :index, :empty
|
21
|
+
def_delegators :@string, :[], :to_s, :length, :size, :inspect, :==,
|
22
|
+
:unpack, :force_encoding, :encoding, :index, :empty?,
|
23
|
+
:encode, :slice, :slice!, :[]=
|
23
24
|
|
24
25
|
# @return [::String]
|
25
26
|
attr_reader :string
|
@@ -31,11 +32,15 @@ module PacketGen
|
|
31
32
|
# takes length when reading
|
32
33
|
# @option options [Integer] :static_length set a static length for this string
|
33
34
|
def initialize(options={})
|
34
|
-
register_internal_string
|
35
|
+
register_internal_string(+'')
|
35
36
|
initialize_length_from(options)
|
36
37
|
@static_length = options[:static_length]
|
37
38
|
end
|
38
39
|
|
40
|
+
def initialize_copy(_orig)
|
41
|
+
@string = @string.dup
|
42
|
+
end
|
43
|
+
|
39
44
|
# @param [::String] str
|
40
45
|
# @return [String] self
|
41
46
|
def read(str)
|
@@ -68,6 +73,14 @@ module PacketGen
|
|
68
73
|
inspect
|
69
74
|
end
|
70
75
|
|
76
|
+
# Append the given string to String
|
77
|
+
# @param [#to_s] str
|
78
|
+
# @return [self]
|
79
|
+
def <<(str)
|
80
|
+
@string << str.to_s
|
81
|
+
self
|
82
|
+
end
|
83
|
+
|
71
84
|
alias sz length
|
72
85
|
alias to_human to_s
|
73
86
|
alias from_human read
|
data/lib/packetgen/types/tlv.rb
CHANGED
@@ -56,12 +56,8 @@ module PacketGen
|
|
56
56
|
def initialize(options={})
|
57
57
|
Deprecation.deprecated_class(self.class, AbstractTLV)
|
58
58
|
super
|
59
|
-
|
60
|
-
|
61
|
-
self[:value] = options[:v].new if options[:v]
|
62
|
-
self.type = options[:type] if options[:type]
|
63
|
-
self.value = options[:value] if options[:value]
|
64
|
-
self.length = options[:length] if options[:length]
|
59
|
+
initialize_types(options)
|
60
|
+
initialize_values(options)
|
65
61
|
end
|
66
62
|
|
67
63
|
# Populate object from a binary string
|
@@ -137,9 +133,9 @@ module PacketGen
|
|
137
133
|
else
|
138
134
|
'%s'
|
139
135
|
end
|
140
|
-
|
141
|
-
"#{name} type:#{@typestr} length:#{
|
142
|
-
|
136
|
+
lenstr = "%-#{(2**self[:length].nbits - 1).to_s.size}u"
|
137
|
+
"#{name} type:#{@typestr} length:#{lenstr} value:#{value.inspect}" % [human_type,
|
138
|
+
length]
|
143
139
|
end
|
144
140
|
|
145
141
|
private
|
@@ -147,6 +143,18 @@ module PacketGen
|
|
147
143
|
def human_types?
|
148
144
|
self.class.const_defined? :TYPES
|
149
145
|
end
|
146
|
+
|
147
|
+
def initialize_types(options)
|
148
|
+
self[:type] = options[:t].new(self.type) if options[:t]
|
149
|
+
self[:length] = options[:l].new(self.length) if options[:l]
|
150
|
+
self[:value] = options[:v].new if options[:v]
|
151
|
+
end
|
152
|
+
|
153
|
+
def initialize_values(options)
|
154
|
+
self.type = options[:type] if options[:type]
|
155
|
+
self.value = options[:value] if options[:value]
|
156
|
+
self.length = options[:length] if options[:length]
|
157
|
+
end
|
150
158
|
end
|
151
159
|
end
|
152
160
|
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# This file is part of PacketGen
|
5
|
+
# See https://github.com/sdaubert/packetgen for more informations
|
6
|
+
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
7
|
+
# This program is published under MIT license.
|
8
|
+
|
9
|
+
module PacketGen
|
10
|
+
# Unknown packet, minimaly mimicking a {Packet}.
|
11
|
+
#
|
12
|
+
# An unknown packet is generated when capturing packets, and a packet cannot
|
13
|
+
# be parsed.
|
14
|
+
# @since 3.2.0
|
15
|
+
class UnknownPacket
|
16
|
+
# List of headers. Always empty
|
17
|
+
# @return [Array]
|
18
|
+
attr_reader :headers
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@headers = [].freeze
|
22
|
+
@binary_str = PacketGen.force_binary('')
|
23
|
+
end
|
24
|
+
|
25
|
+
# Unknown packet, so unknown protocol.
|
26
|
+
# @return [false]
|
27
|
+
def is?(_protocol)
|
28
|
+
false
|
29
|
+
end
|
30
|
+
|
31
|
+
# Get packet body
|
32
|
+
# @return [Types]
|
33
|
+
def body
|
34
|
+
@binary_str
|
35
|
+
end
|
36
|
+
alias to_s body
|
37
|
+
|
38
|
+
# Set packet body
|
39
|
+
# @param [String] str
|
40
|
+
# @return [void]
|
41
|
+
def body=(str)
|
42
|
+
@binary_str = PacketGen.force_binary(str)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Write packet to a PCapNG file on disk.
|
46
|
+
# @param [String] filename
|
47
|
+
# @return [Array] see return from {PcapNG::File#to_file}
|
48
|
+
# @see File
|
49
|
+
def to_f(filename)
|
50
|
+
PcapNG::File.new.read_array([self]).to_f(filename)
|
51
|
+
end
|
52
|
+
alias write to_f
|
53
|
+
|
54
|
+
# Read binary string
|
55
|
+
# @param [String] binary_string
|
56
|
+
# @return [self]
|
57
|
+
def parse(binary_str, _first_header: nil)
|
58
|
+
@binary_str = PacketGen.force_binary(binary_str)
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [String]
|
63
|
+
def inspect
|
64
|
+
# TODO
|
65
|
+
end
|
66
|
+
|
67
|
+
# equality if {#to_s} is equal
|
68
|
+
# @return [Boolean]
|
69
|
+
def ==(other)
|
70
|
+
to_s == other.to_s
|
71
|
+
end
|
72
|
+
|
73
|
+
# True only if +other+ is an {UnknownPacket} and +other == self+
|
74
|
+
# @return [Boolean]
|
75
|
+
def ===(other)
|
76
|
+
case other
|
77
|
+
when UnknwonPacket
|
78
|
+
self == other
|
79
|
+
else
|
80
|
+
false
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/packetgen/utils.rb
CHANGED
@@ -16,14 +16,31 @@ module PacketGen
|
|
16
16
|
# @author Sylvain Daubert
|
17
17
|
# @since 2.1.3
|
18
18
|
module Utils
|
19
|
+
# @private
|
20
|
+
ARP_FILTER = 'arp src %<ipaddr>s and ether dst %<hwaddr>s'
|
21
|
+
# @private
|
22
|
+
MITM_FILTER = '((ip src %<target1>s and not ip dst %<local_ip>s) or' \
|
23
|
+
' (ip src %<target2>s and not ip dst %<local_ip>s) or' \
|
24
|
+
' (ip dst %<target1>s and not ip src %<local_ip>s) or' \
|
25
|
+
' (ip dst %<target2>s and not ip src %<local_ip>s))' \
|
26
|
+
' and ether dst %<local_mac>s'
|
27
|
+
|
19
28
|
# Get local ARP cache
|
20
29
|
# @return [Hash] key: IP address, value: array containing MAC address and
|
21
30
|
# interface name
|
22
31
|
def self.arp_cache
|
32
|
+
return self.cache_from_arp_command if File.exist?('/usr/sbin/arp')
|
33
|
+
return self.cache_from_ip_command if File.exist?('/usr/bin/ip')
|
34
|
+
|
35
|
+
{}
|
36
|
+
end
|
37
|
+
|
38
|
+
# @private
|
39
|
+
def self.cache_from_arp_command
|
23
40
|
raw_cache = `/usr/sbin/arp -an`
|
24
41
|
|
25
42
|
cache = {}
|
26
|
-
raw_cache.split(
|
43
|
+
raw_cache.split("\n").each do |line|
|
27
44
|
match = line.match(/\((\d+\.\d+\.\d+\.\d+)\) at (([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2})(?: \[ether\])? on (\w+)/)
|
28
45
|
cache[match[1]] = [match[2], match[4]] if match
|
29
46
|
end
|
@@ -31,6 +48,21 @@ module PacketGen
|
|
31
48
|
cache
|
32
49
|
end
|
33
50
|
|
51
|
+
# @private
|
52
|
+
def self.cache_from_ip_command
|
53
|
+
raw_cache = `ip neigh`
|
54
|
+
|
55
|
+
cache = {}
|
56
|
+
raw_cache.split("\n").each do |line|
|
57
|
+
match = line.match(/^(\d+\.\d+\.\d+\.\d+) dev (\w+) lladdr (([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2})/)
|
58
|
+
cache[match[1]] = [match[3], match[2]] if match
|
59
|
+
end
|
60
|
+
|
61
|
+
cache
|
62
|
+
end
|
63
|
+
|
64
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize
|
65
|
+
|
34
66
|
# Get MAC address from an IP address, or nil if this IP address is unknown
|
35
67
|
# on local network.
|
36
68
|
# @param [String] ipaddr dotted-octet IP address
|
@@ -40,13 +72,13 @@ module PacketGen
|
|
40
72
|
# @option options [Boolean] :no_cache if +true+, do not query local ARP
|
41
73
|
# cache and always send an ARP request on wire. Default to +false+
|
42
74
|
# @option options [Integer] :timeout timeout in seconds before stopping
|
43
|
-
# request. Default to
|
75
|
+
# request. Default to 1.
|
44
76
|
# @return [String,nil]
|
45
77
|
# @raise [RuntimeError] user don't have permission to capture packets on network device.
|
46
78
|
def self.arp(ipaddr, options={})
|
47
79
|
unless options[:no_cache]
|
48
80
|
local_cache = self.arp_cache
|
49
|
-
return local_cache[ipaddr].first if local_cache.key?
|
81
|
+
return local_cache[ipaddr].first if local_cache.key?(ipaddr)
|
50
82
|
end
|
51
83
|
|
52
84
|
iface = options[:iface] || PacketGen.default_iface
|
@@ -54,14 +86,13 @@ module PacketGen
|
|
54
86
|
my_hwaddr = Config.instance.hwaddr(iface)
|
55
87
|
arp_pkt = Packet.gen('Eth', dst: 'ff:ff:ff:ff:ff:ff', src: my_hwaddr)
|
56
88
|
.add('ARP', sha: Config.instance.hwaddr(iface),
|
57
|
-
|
89
|
+
spa: Config.instance.ipaddr(iface),
|
90
|
+
tpa: ipaddr)
|
58
91
|
|
59
|
-
capture = Capture.new(iface: iface, timeout: timeout, max: 1,
|
60
|
-
|
61
|
-
cap_thread = Thread.new do
|
62
|
-
capture.start
|
63
|
-
end
|
92
|
+
capture = Capture.new(iface: iface, timeout: timeout, max: 1, filter: ARP_FILTER % { ipaddr: ipaddr, hwaddr: my_hwaddr })
|
93
|
+
cap_thread = Thread.new { capture.start }
|
64
94
|
|
95
|
+
sleep 0.1
|
65
96
|
arp_pkt.to_w(iface)
|
66
97
|
cap_thread.join
|
67
98
|
|
@@ -71,6 +102,7 @@ module PacketGen
|
|
71
102
|
break pkt.arp.sha.to_s if pkt.arp.spa.to_s == ipaddr
|
72
103
|
end
|
73
104
|
end
|
105
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/AbcSize
|
74
106
|
|
75
107
|
# Do ARP spoofing on given IP address. Call to this method blocks.
|
76
108
|
# @note This method is provided for test purpose.
|
@@ -126,36 +158,37 @@ module PacketGen
|
|
126
158
|
def self.mitm(target1, target2, options={})
|
127
159
|
options = { iface: PacketGen.default_iface }.merge(options)
|
128
160
|
|
129
|
-
mac1 = arp(target1)
|
130
|
-
mac2 = arp(target2)
|
131
|
-
|
132
161
|
spoofer = Utils::ARPSpoofer.new(options)
|
133
162
|
spoofer.add target1, target2, options
|
134
163
|
spoofer.add target2, target1, options
|
135
164
|
|
136
|
-
|
137
|
-
|
165
|
+
cfg = Config.instance
|
166
|
+
my_mac = cfg.hwaddr(options[:iface])
|
138
167
|
capture = Capture.new(iface: options[:iface],
|
139
|
-
filter:
|
140
|
-
" (ip src #{target2} and not ip dst #{my_ip}) or" \
|
141
|
-
" (ip dst #{target1} and not ip src #{my_ip}) or" \
|
142
|
-
" (ip dst #{target2} and not ip src #{my_ip}))" \
|
143
|
-
" and ether dst #{my_mac}")
|
168
|
+
filter: MITM_FILTER % { target1: target1, target2: target2, local_ip: cfg.ipaddr(options[:iface]), local_mac: my_mac })
|
144
169
|
|
145
170
|
spoofer.start_all
|
171
|
+
mitm_core(capture, target1, target2, my_mac, &proc)
|
172
|
+
spoofer.stop_all
|
173
|
+
end
|
174
|
+
|
175
|
+
# @private
|
176
|
+
def self.mitm_core(capture, target1, target2, my_mac)
|
177
|
+
mac1 = arp(target1)
|
178
|
+
mac2 = arp(target2)
|
179
|
+
|
146
180
|
capture.start do |pkt|
|
147
181
|
modified_pkt = yield pkt
|
148
182
|
iph = modified_pkt.ip
|
149
183
|
l2 = modified_pkt.is?('Dot11') ? modified_pkt.dot11 : modified_pkt.eth
|
150
184
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
modified_pkt.to_w(options[:iface])
|
185
|
+
l2.src = my_mac
|
186
|
+
l2.dst = if (iph.src == target1) || (iph.dst == target2)
|
187
|
+
mac2
|
188
|
+
else # (iph.src == target2) || (iph.dst == target1)
|
189
|
+
mac1
|
190
|
+
end
|
191
|
+
modified_pkt.to_w(capture.iface)
|
159
192
|
end
|
160
193
|
end
|
161
194
|
end
|
data/lib/packetgen/version.rb
CHANGED
data/lib/packetgen.rb
CHANGED
@@ -39,9 +39,9 @@ module PacketGen
|
|
39
39
|
|
40
40
|
def message
|
41
41
|
"#{prev_hdr.class} knowns no layer association with #{hdr.protocol_name}. " \
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
"Try #{prev_hdr.class}.bind_layer(#{hdr.class}, " \
|
43
|
+
"#{prev_hdr.method_name}_proto_field: " \
|
44
|
+
"<value_for_#{hdr.method_name}>)"
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
@@ -95,7 +95,15 @@ module PacketGen
|
|
95
95
|
# Get default network interface (ie. first non-loopback declared interface)
|
96
96
|
# @return [String]
|
97
97
|
def self.default_iface
|
98
|
-
|
98
|
+
return @default_iface if defined? @default_iface
|
99
|
+
|
100
|
+
@default_iface = Interfacez.raw_interface_addresses.each do |iface|
|
101
|
+
next unless iface.broadaddr
|
102
|
+
next unless Interfacez.ipv4_address_of(iface.name)
|
103
|
+
next unless Interfacez.ipv6_address_of(iface.name)
|
104
|
+
|
105
|
+
break iface.name
|
106
|
+
end
|
99
107
|
end
|
100
108
|
|
101
109
|
# Get loopback network interface
|
@@ -126,6 +134,7 @@ require 'packetgen/types'
|
|
126
134
|
require 'packetgen/pcapng'
|
127
135
|
require 'packetgen/pcap'
|
128
136
|
require 'packetgen/packet'
|
137
|
+
require 'packetgen/unknown_packet'
|
129
138
|
require 'packetgen/capture'
|
130
139
|
require 'packetgen/inject'
|
131
140
|
require 'packetgen/proto'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: packetgen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.1
|
4
|
+
version: 3.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sylvain Daubert
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-12-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: interfacez
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.
|
33
|
+
version: 0.12.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.
|
40
|
+
version: 0.12.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rasn1
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -233,6 +233,7 @@ files:
|
|
233
233
|
- lib/packetgen/types/oui.rb
|
234
234
|
- lib/packetgen/types/string.rb
|
235
235
|
- lib/packetgen/types/tlv.rb
|
236
|
+
- lib/packetgen/unknown_packet.rb
|
236
237
|
- lib/packetgen/utils.rb
|
237
238
|
- lib/packetgen/utils/arp_spoofer.rb
|
238
239
|
- lib/packetgen/version.rb
|
@@ -259,15 +260,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
259
260
|
requirements:
|
260
261
|
- - ">="
|
261
262
|
- !ruby/object:Gem::Version
|
262
|
-
version: 2.
|
263
|
+
version: 2.5.0
|
263
264
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
264
265
|
requirements:
|
265
266
|
- - ">="
|
266
267
|
- !ruby/object:Gem::Version
|
267
268
|
version: '0'
|
268
269
|
requirements: []
|
269
|
-
|
270
|
-
rubygems_version: 2.7.6.2
|
270
|
+
rubygems_version: 3.2.5
|
271
271
|
signing_key:
|
272
272
|
specification_version: 4
|
273
273
|
summary: Network packet generator and dissector
|