packetgen 3.2.0 → 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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/bin/pgconsole +3 -3
  4. data/lib/packetgen/header/arp.rb +24 -13
  5. data/lib/packetgen/header/asn1_base.rb +2 -2
  6. data/lib/packetgen/header/base.rb +1 -1
  7. data/lib/packetgen/header/dhcpv6/option.rb +11 -13
  8. data/lib/packetgen/header/dns/opt.rb +2 -2
  9. data/lib/packetgen/header/dns/rr.rb +61 -28
  10. data/lib/packetgen/header/dns.rb +13 -6
  11. data/lib/packetgen/header/dot11/management.rb +2 -5
  12. data/lib/packetgen/header/dot11.rb +1 -1
  13. data/lib/packetgen/header/eap.rb +1 -1
  14. data/lib/packetgen/header/eth.rb +1 -1
  15. data/lib/packetgen/header/http/response.rb +43 -23
  16. data/lib/packetgen/header/igmp.rb +1 -1
  17. data/lib/packetgen/header/ip/option.rb +2 -1
  18. data/lib/packetgen/header/ipv6/addr.rb +3 -0
  19. data/lib/packetgen/header/mdns.rb +19 -25
  20. data/lib/packetgen/header/mld.rb +1 -1
  21. data/lib/packetgen/header/ospfv2/lsa_header.rb +2 -4
  22. data/lib/packetgen/header/ospfv2.rb +1 -1
  23. data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +14 -5
  24. data/lib/packetgen/header/ospfv3/lsa.rb +1 -1
  25. data/lib/packetgen/header/ospfv3/lsa_header.rb +2 -4
  26. data/lib/packetgen/header/ospfv3.rb +1 -1
  27. data/lib/packetgen/header/snmp.rb +20 -14
  28. data/lib/packetgen/header/tcp/option.rb +1 -1
  29. data/lib/packetgen/header/tcp.rb +12 -5
  30. data/lib/packetgen/header/tftp.rb +15 -9
  31. data/lib/packetgen/inspect.rb +15 -9
  32. data/lib/packetgen/packet.rb +48 -2
  33. data/lib/packetgen/pcapng/file.rb +13 -13
  34. data/lib/packetgen/pcapng.rb +1 -0
  35. data/lib/packetgen/pcaprub_wrapper.rb +0 -4
  36. data/lib/packetgen/types/abstract_tlv.rb +1 -1
  37. data/lib/packetgen/types/array.rb +8 -1
  38. data/lib/packetgen/types/fields.rb +19 -19
  39. data/lib/packetgen/types/int.rb +7 -0
  40. data/lib/packetgen/types/oui.rb +1 -1
  41. data/lib/packetgen/types/tlv.rb +17 -9
  42. data/lib/packetgen/utils.rb +55 -21
  43. data/lib/packetgen/version.rb +1 -1
  44. data/lib/packetgen.rb +3 -3
  45. metadata +3 -3
@@ -16,10 +16,27 @@ 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 = {}
@@ -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,7 +72,7 @@ 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 2.
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={})
@@ -57,10 +89,10 @@ module PacketGen
57
89
  spa: Config.instance.ipaddr(iface),
58
90
  tpa: ipaddr)
59
91
 
60
- capture = Capture.new(iface: iface, timeout: timeout, max: 1,
61
- filter: "arp src #{ipaddr} and ether dst #{my_hwaddr}")
92
+ capture = Capture.new(iface: iface, timeout: timeout, max: 1, filter: ARP_FILTER % { ipaddr: ipaddr, hwaddr: my_hwaddr })
62
93
  cap_thread = Thread.new { capture.start }
63
94
 
95
+ sleep 0.1
64
96
  arp_pkt.to_w(iface)
65
97
  cap_thread.join
66
98
 
@@ -70,6 +102,7 @@ module PacketGen
70
102
  break pkt.arp.sha.to_s if pkt.arp.spa.to_s == ipaddr
71
103
  end
72
104
  end
105
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/AbcSize
73
106
 
74
107
  # Do ARP spoofing on given IP address. Call to this method blocks.
75
108
  # @note This method is provided for test purpose.
@@ -125,36 +158,37 @@ module PacketGen
125
158
  def self.mitm(target1, target2, options={})
126
159
  options = { iface: PacketGen.default_iface }.merge(options)
127
160
 
128
- mac1 = arp(target1)
129
- mac2 = arp(target2)
130
-
131
161
  spoofer = Utils::ARPSpoofer.new(options)
132
162
  spoofer.add target1, target2, options
133
163
  spoofer.add target2, target1, options
134
164
 
135
- my_mac = Config.instance.hwaddr(options[:iface])
136
- my_ip = Config.instance.ipaddr(options[:iface])
165
+ cfg = Config.instance
166
+ my_mac = cfg.hwaddr(options[:iface])
137
167
  capture = Capture.new(iface: options[:iface],
138
- filter: "((ip src #{target1} and not ip dst #{my_ip}) or" \
139
- " (ip src #{target2} and not ip dst #{my_ip}) or" \
140
- " (ip dst #{target1} and not ip src #{my_ip}) or" \
141
- " (ip dst #{target2} and not ip src #{my_ip}))" \
142
- " and ether dst #{my_mac}")
168
+ filter: MITM_FILTER % { target1: target1, target2: target2, local_ip: cfg.ipaddr(options[:iface]), local_mac: my_mac })
143
169
 
144
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
+
145
180
  capture.start do |pkt|
146
181
  modified_pkt = yield pkt
147
182
  iph = modified_pkt.ip
148
183
  l2 = modified_pkt.is?('Dot11') ? modified_pkt.dot11 : modified_pkt.eth
149
184
 
150
- if (iph.src == target1) || (iph.dst == target2)
151
- l2.dst = mac2
152
- elsif (iph.src == target2) || (iph.dst == target1)
153
- l2.dst = mac1
154
- else
155
- next
156
- end
157
- 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)
158
192
  end
159
193
  end
160
194
  end
@@ -10,5 +10,5 @@
10
10
  # @author Sylvain Daubert
11
11
  module PacketGen
12
12
  # PacketGen version
13
- VERSION = '3.2.0'
13
+ VERSION = '3.2.1'
14
14
  end
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
- "Try #{prev_hdr.class}.bind_layer(#{hdr.class}, " \
43
- "#{prev_hdr.method_name}_proto_field: " \
44
- "<value_for_#{hdr.method_name}>)"
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
 
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.2.0
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: 2021-04-20 00:00:00.000000000 Z
11
+ date: 2021-12-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: interfacez
@@ -260,7 +260,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
260
260
  requirements:
261
261
  - - ">="
262
262
  - !ruby/object:Gem::Version
263
- version: 2.4.0
263
+ version: 2.5.0
264
264
  required_rubygems_version: !ruby/object:Gem::Requirement
265
265
  requirements:
266
266
  - - ">="