packetfu 1.1.9 → 1.1.10
Sign up to get free protection for your applications and to get access to all the features.
- 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/lib/packetfu.rb +127 -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 +528 -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 +116 -116
- 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 +226 -217
- data/lib/packetfu/version.rb +41 -41
- data/packetfu.gemspec +2 -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 +4 -3
data/bench/octets.rb
CHANGED
@@ -8,15 +8,15 @@ IPV4_STR = "1.2.3.4"
|
|
8
8
|
|
9
9
|
iters = 50_000
|
10
10
|
Benchmark.bm do |bm|
|
11
|
-
|
12
|
-
|
11
|
+
bm.report("Octets.new.read(...) ") {iters.times {PacketFu::Octets.new.read(IPV4_RAW)}}
|
12
|
+
bm.report("Octets.new.read_quad(...) ") {iters.times {PacketFu::Octets.new.read_quad(IPV4_STR)}}
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
octets = PacketFu::Octets.new
|
15
|
+
bm.report("octets#read(...) ") {iters.times {octets.read(IPV4_RAW)}}
|
16
|
+
bm.report("octets#read_quad(...) ") {iters.times {octets.read_quad(IPV4_STR)}}
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
octets.read(IPV4_RAW)
|
19
|
+
bm.report("octets#to_x() ") {iters.times {octets.to_x}}
|
20
|
+
bm.report("octets#to_i() ") {iters.times {octets.to_i}}
|
21
|
+
bm.report("octets#to_s() ") {iters.times {octets.to_s}}
|
22
22
|
end
|
data/examples/100kpackets.rb
CHANGED
@@ -14,18 +14,18 @@ start_time = Time.now.utc
|
|
14
14
|
count = 0
|
15
15
|
|
16
16
|
100.times do
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
17
|
+
@pcaps = []
|
18
|
+
1000.times do
|
19
|
+
u = UDPPacket.new
|
20
|
+
u.ip_src = [rand(2**32-1)].pack("N")
|
21
|
+
u.ip_dst = [rand(2**32-1)].pack("N")
|
22
|
+
u.recalc
|
23
|
+
@pcaps << u
|
24
|
+
end
|
25
|
+
pfile = PcapFile.new
|
26
|
+
res = pfile.array_to_file(:filename => "/tmp/out.pcap", :array => @pcaps, :append => true)
|
27
|
+
count += res.last
|
28
|
+
puts "Wrote #{count} packets in #{Time.now.utc - start_time} seconds"
|
29
29
|
end
|
30
30
|
|
31
31
|
read_bytes_start = Time.now.utc
|
data/examples/ackscan.rb
CHANGED
@@ -10,25 +10,25 @@ require 'packetfu'
|
|
10
10
|
#cap = Capture.new(:iface=>'wlan0') # or whatever your interface is
|
11
11
|
# Run this on the third
|
12
12
|
def do_scan
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
puts "Generating packets..."
|
14
|
+
pkt_array = gen_packets.sort_by {rand}
|
15
|
+
puts "Dumping them on the wire..."
|
16
|
+
inj = PacketFu::Inject.new(:iface => ARGV[0])
|
17
|
+
inj.array_to_wire(:array=>pkt_array)
|
18
|
+
puts "Done!"
|
19
19
|
end
|
20
20
|
|
21
21
|
def gen_packets
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
22
|
+
config = PacketFu::Utils.whoami?(:iface=>ARGV[0])
|
23
|
+
pkt = PacketFu::TCPPacket.new(:config=>config, :flavor=>"Windows")
|
24
|
+
pkt.payload ="all I wanna do is ACK ACK ACK and a RST and take your money"
|
25
|
+
pkt.ip_daddr="209.85.165.0" # One of Google's networks
|
26
|
+
pkt.tcp_flags.ack=1
|
27
|
+
pkt.tcp_dst=81
|
28
|
+
pkt_array = []
|
29
|
+
256.times do |i|
|
30
|
+
pkt.ip_dst.o4=i
|
31
|
+
pkt.tcp_src = rand(5000 - 1025) + 1025
|
32
32
|
pkt.recalc
|
33
33
|
pkt_array << pkt.to_s
|
34
34
|
end
|
data/examples/arp.rb
CHANGED
@@ -9,11 +9,11 @@ require './examples' # For path setting slight-of-hand
|
|
9
9
|
require 'packetfu'
|
10
10
|
|
11
11
|
def usage
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
if ARGV[0].nil?
|
13
|
+
raise ArgumentError, "You need an IP address to start with."
|
14
|
+
elsif !Process.euid.zero?
|
15
|
+
raise SecurityError, "You need to be root to run this."
|
16
|
+
end
|
17
17
|
end
|
18
18
|
|
19
19
|
usage unless target_ip = ARGV[0] # Need a target IP.
|
@@ -24,36 +24,36 @@ $packetfu_default = PacketFu::Config.new(PacketFu::Utils.whoami?).config
|
|
24
24
|
|
25
25
|
def arp(target_ip)
|
26
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
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
27
|
+
arp_pkt = PacketFu::ARPPacket.new(:flavor => "Windows")
|
28
|
+
arp_pkt.eth_saddr = arp_pkt.arp_saddr_mac = $packetfu_default[:eth_saddr]
|
29
|
+
arp_pkt.eth_daddr = "ff:ff:ff:ff:ff:ff"
|
30
|
+
arp_pkt.arp_daddr_mac = "00:00:00:00:00:00"
|
31
|
+
|
32
|
+
arp_pkt.arp_saddr_ip = $packetfu_default[:ip_saddr]
|
33
|
+
arp_pkt.arp_daddr_ip = target_ip
|
34
|
+
|
35
|
+
# Stick the Capture object in its own thread.
|
36
|
+
|
37
|
+
cap_thread = Thread.new do
|
38
|
+
cap = PacketFu::Capture.new(:start => true,
|
39
|
+
:filter => "arp src #{target_ip} and ether dst #{arp_pkt.eth_saddr}")
|
40
|
+
arp_pkt.to_w # Shorthand for sending single packets to the default interface.
|
41
|
+
target_mac = nil
|
42
|
+
while target_mac.nil?
|
43
|
+
if cap.save > 0
|
44
|
+
arp_response = PacketFu::Packet.parse(cap.array[0])
|
45
|
+
target_mac = arp_response.arp_saddr_mac if arp_response.arp_saddr_ip = target_ip
|
46
|
+
end
|
47
|
+
sleep 0.1 # Check for a response ten times per second.
|
48
|
+
end
|
49
|
+
puts "#{target_ip} is-at #{target_mac}"
|
50
|
+
# That's all we need.
|
51
|
+
exit 0
|
52
|
+
end
|
53
|
+
|
54
|
+
# Timeout for cap_thread
|
55
|
+
sleep 3; puts "Oh noes! Couldn't get an arp out of #{target_ip}. Maybe it's not here."
|
56
|
+
exit 1
|
57
57
|
end
|
58
58
|
|
59
59
|
arp(target_ip)
|
data/examples/arphood.rb
CHANGED
@@ -11,20 +11,20 @@ require 'open-uri'
|
|
11
11
|
$oui_prefixes = {}
|
12
12
|
$arp_results = []
|
13
13
|
def build_oui_list
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
14
|
+
if ARGV[2].nil?
|
15
|
+
puts "Fetching the oui.txt from IEEE, it'll be a second. Avoid this with #{$0} [iface] [network] <filename>."
|
16
|
+
oui_file = open("http://standards.ieee.org/regauth/oui/oui.txt")
|
17
|
+
else
|
18
|
+
oui_file = File.open(ARGV[2], "rb")
|
19
|
+
end
|
20
|
+
oui_file.each do |oui_line|
|
21
|
+
maybe_oui = oui_line.scan(/^[0-9a-f]{2}\-[0-9a-f]{2}\-[0-9a-f]{2}/i)[0]
|
22
|
+
unless maybe_oui.nil?
|
23
|
+
oui_value = maybe_oui
|
24
|
+
oui_vendor = oui_line.split(/\(hex\)\s*/n)[1] || "PRIVATE"
|
25
|
+
$oui_prefixes[oui_value] = oui_vendor.chomp
|
26
|
+
end
|
27
|
+
end
|
28
28
|
end
|
29
29
|
|
30
30
|
build_oui_list
|
@@ -32,30 +32,30 @@ build_oui_list
|
|
32
32
|
$root_ok = true if Process.euid.zero?
|
33
33
|
|
34
34
|
def arp_everyone
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
35
|
+
my_net = PacketFu::Config.new(PacketFu::Utils.whoami?(:iface =>(ARGV[0] || 'wlan0')))
|
36
|
+
threads = []
|
37
|
+
network = ARGV[1] || "192.168.2"
|
38
|
+
print "Arping around..."
|
39
|
+
253.times do |i|
|
40
|
+
threads[i] = Thread.new do
|
41
|
+
this_host = network + ".#{i+1}"
|
42
|
+
print "."
|
43
|
+
colon_mac = PacketFu::Utils.arp(this_host,my_net.config)
|
44
|
+
unless colon_mac.nil?
|
45
|
+
hyphen_mac = colon_mac.tr(':','-').upcase[0,8]
|
46
|
+
else
|
47
|
+
hyphen_mac = colon_mac = "NOTHERE"
|
48
|
+
end
|
49
|
+
$arp_results << "%s : %s / %s" % [this_host,colon_mac,$oui_prefixes[hyphen_mac]]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
threads.each {|thr| thr.join}
|
53
53
|
end
|
54
54
|
|
55
55
|
if $root_ok
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
56
|
+
arp_everyone
|
57
|
+
puts "\n"
|
58
|
+
sleep 3
|
59
|
+
$arp_results.sort.each {|a| puts a unless a =~ /NOTHERE/}
|
60
60
|
end
|
61
61
|
|
data/examples/dissect_thinger.rb
CHANGED
@@ -14,10 +14,10 @@ include PacketFu
|
|
14
14
|
|
15
15
|
packets = PcapFile.file_to_array fname
|
16
16
|
packets.each do |packet|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
17
|
+
puts "_" * 75
|
18
|
+
puts packet.inspect
|
19
|
+
puts "_" * 75
|
20
|
+
pkt = Packet.parse(packet)
|
21
|
+
puts pkt.dissect
|
22
|
+
sleep sleep_interval
|
23
23
|
end
|
@@ -13,38 +13,38 @@ require './examples' # For path setting slight-of-hand
|
|
13
13
|
require 'packetfu'
|
14
14
|
|
15
15
|
def print_results(stats)
|
16
|
-
|
16
|
+
stats.each_pair { |k,v| puts "%-12s: %10d" % [k,v] }
|
17
17
|
end
|
18
18
|
|
19
19
|
# Takes a file name, parses the packets, and records the packet
|
20
20
|
# type based on its PacketFu class.
|
21
21
|
def count_packet_types(file)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
22
|
+
stats = {}
|
23
|
+
count = 0
|
24
|
+
elapsed = 0
|
25
|
+
start_time = Time.now
|
26
|
+
PacketFu::PcapFile.read_packets(file) do |pkt|
|
27
|
+
kind = pkt.proto.last.to_sym
|
28
|
+
stats[kind] ? stats[kind] += 1 : stats[kind] = 1
|
29
|
+
count += 1
|
30
|
+
elapsed = (Time.now - start_time).to_i
|
31
|
+
if count % 5_000 == 0
|
32
|
+
puts "After #{count} packets (#{elapsed} seconds elapsed):"
|
33
|
+
print_results(stats)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
puts "Final results for #{count} packets (#{elapsed} seconds elapsed):"
|
37
|
+
print_results(stats)
|
38
38
|
end
|
39
39
|
|
40
40
|
if File.readable?(infile = (ARGV[0] || 'in.pcap'))
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
title = "Packets by packet type in '#{infile}'"
|
42
|
+
puts "-" * title.size
|
43
|
+
puts title
|
44
|
+
puts "-" * title.size
|
45
|
+
count_packet_types(infile)
|
46
46
|
else
|
47
|
-
|
47
|
+
raise RuntimeError, "Need an infile, like so: #{$0} in.pcap"
|
48
48
|
end
|
49
49
|
|
50
50
|
|
data/examples/packetfu-shell.rb
CHANGED
@@ -49,12 +49,12 @@ require './examples'
|
|
49
49
|
require 'packetfu'
|
50
50
|
|
51
51
|
module PacketFu
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
52
|
+
def whoami?(args={})
|
53
|
+
Utils.whoami?(args)
|
54
|
+
end
|
55
|
+
def arp(arg)
|
56
|
+
Utils.arp(arg)
|
57
|
+
end
|
58
58
|
end
|
59
59
|
|
60
60
|
include PacketFu
|
@@ -64,7 +64,7 @@ include PacketFu
|
|
64
64
|
# http://jisho.org/words?jap=+%E3%83%91%E3%82%B1%E3%83%83%E3%83%88%E3%83%95&eng=&dict=edict
|
65
65
|
#
|
66
66
|
def packetfu_ascii_art
|
67
|
-
|
67
|
+
puts <<EOM
|
68
68
|
_______ _______ _______ _ _______ _________ _______
|
69
69
|
( ____ )( ___ )( ____ \\| \\ /\\( ____ \\\\__ __/( ____ \\|\\ /|
|
70
70
|
| ( )|| ( ) || ( \\/| \\ / /| ( \\/ ) ( | ( \\/| ) ( |
|
@@ -82,33 +82,33 @@ def packetfu_ascii_art
|
|
82
82
|
a mid-level packet manipulation library for ruby
|
83
83
|
|
84
84
|
EOM
|
85
|
-
|
85
|
+
end
|
86
86
|
|
87
87
|
@pcaprub_loaded = PacketFu.pcaprub_loaded?
|
88
88
|
# Displays a helpful banner.
|
89
89
|
def banner
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
90
|
+
packetfu_ascii_art
|
91
|
+
puts ">>> PacketFu Shell #{PacketFu.version}."
|
92
|
+
if Process.euid.zero? && @pcaprub_loaded
|
93
|
+
puts ">>> Use $packetfu_default.config for salient networking details."
|
94
|
+
print "IP: %-15s Mac: %s" % [$packetfu_default.ip_saddr, $packetfu_default.eth_saddr]
|
95
|
+
puts " Gateway: %s" % $packetfu_default.eth_daddr
|
96
|
+
print "Net: %-15s" % [Pcap.lookupnet($packetfu_default.iface)][0]
|
97
|
+
print " " * 13
|
98
|
+
puts "Iface: %s" % [($packetfu_default.iface)]
|
99
|
+
puts ">>> Packet capturing/injecting enabled."
|
100
|
+
else
|
101
|
+
print ">>> Packet capturing/injecting disabled. "
|
102
|
+
puts Process.euid.zero? ? "(no PcapRub)" : "(not root)"
|
103
|
+
end
|
104
|
+
puts "<>" * 36
|
105
105
|
end
|
106
106
|
|
107
107
|
# Silly wlan0 workaround
|
108
108
|
begin
|
109
|
-
|
109
|
+
$packetfu_default = PacketFu::Config.new(Utils.whoami?) if(@pcaprub_loaded && Process.euid.zero?)
|
110
110
|
rescue RuntimeError
|
111
|
-
|
111
|
+
$packetfu_default = PacketFu::Config.new(Utils.whoami?(:iface => 'wlan0')) if(@pcaprub_loaded && Process.euid.zero?)
|
112
112
|
end
|
113
113
|
|
114
114
|
banner
|
data/examples/simple-sniffer.rb
CHANGED
@@ -8,15 +8,15 @@ include PacketFu
|
|
8
8
|
iface = ARGV[0] || "eth0"
|
9
9
|
|
10
10
|
def sniff(iface)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
11
|
+
cap = Capture.new(:iface => iface, :start => true)
|
12
|
+
cap.stream.each do |p|
|
13
|
+
pkt = Packet.parse p
|
14
|
+
if pkt.is_ip?
|
15
|
+
next if pkt.ip_saddr == Utils.ifconfig(iface)[:ip_saddr]
|
16
|
+
packet_info = [pkt.ip_saddr, pkt.ip_daddr, pkt.size, pkt.proto.last]
|
17
|
+
puts "%-15s -> %-15s %-4d %s" % packet_info
|
18
|
+
end
|
19
|
+
end
|
20
20
|
end
|
21
21
|
|
22
22
|
sniff(iface)
|