packetfu 1.1.13.pre → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data/.github/ISSUE_TEMPLATE.md +29 -0
- data/.github/workflows/verify.yml +72 -0
- data/.travis.yml +10 -5
- data/LICENSE.txt +1 -1
- data/README.md +8 -8
- data/certs/todb.pem +25 -0
- data/examples/100kpackets.rb +2 -2
- data/examples/ackscan.rb +7 -6
- data/examples/pcap2pcapng.rb +2 -2
- data/examples/readpcap.rb +28 -0
- data/lib/packetfu/capture.rb +1 -1
- data/lib/packetfu/config.rb +2 -2
- data/lib/packetfu/inject.rb +1 -1
- data/lib/packetfu/packet.rb +6 -3
- data/lib/packetfu/pcap.rb +25 -25
- data/lib/packetfu/pcapng/file.rb +1 -1
- data/lib/packetfu/protos/arp.rb +1 -8
- data/lib/packetfu/protos/eth.rb +0 -7
- data/lib/packetfu/protos/hsrp.rb +0 -7
- data/lib/packetfu/protos/icmp/header.rb +7 -10
- data/lib/packetfu/protos/icmp.rb +0 -7
- data/lib/packetfu/protos/icmpv6.rb +4 -17
- data/lib/packetfu/protos/ip/header.rb +2 -2
- data/lib/packetfu/protos/ip/mixin.rb +9 -0
- data/lib/packetfu/protos/ip.rb +0 -8
- data/lib/packetfu/protos/ipv6/mixin.rb +12 -0
- data/lib/packetfu/protos/ipv6.rb +0 -7
- data/lib/packetfu/protos/lldp.rb +1 -8
- data/lib/packetfu/protos/tcp.rb +73 -30
- data/lib/packetfu/protos/udp/header.rb +4 -5
- data/lib/packetfu/protos/udp.rb +6 -18
- data/lib/packetfu/structfu.rb +1 -1
- data/lib/packetfu/version.rb +1 -1
- data/packetfu.gemspec +10 -18
- data/spec/arp_spec.rb +1 -1
- data/spec/capture_spec.rb +137 -0
- data/spec/eth_spec.rb +1 -1
- data/spec/icmp_spec.rb +1 -1
- data/spec/icmpv6_spec.rb +1 -1
- data/spec/inject_spec.rb +95 -0
- data/spec/ip_spec.rb +23 -1
- data/spec/packetfu_spec.rb +1 -1
- data/spec/pcap_spec.rb +3 -3
- data/spec/pcapng/file_spec.rb +1 -1
- data/spec/spec_helper.rb +4 -2
- data/spec/structfu_spec.rb +86 -82
- data/spec/tcp_spec.rb +155 -53
- data/test/sample-ipv6.pcap +0 -0
- data.tar.gz.sig +0 -0
- metadata +62 -57
- metadata.gz.sig +0 -0
- data/test/test_capture.rb +0 -58
- data/test/test_inject.rb +0 -31
- data/test/test_structfu.rb +0 -114
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 77ec54305b3731b49e42fb61ec238ff855af78840c94e0d6f35ea1626a221133
|
4
|
+
data.tar.gz: 6e64404182742b2d021a7e93b1153ec46b0bf5eb87fc0661236415ef76901087
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dfd80b4314dbdf87bf0fba9c1bc39d182eaf1c2d41f13e598a496c9d09fe18e9f546018764cd704018560acae5d74ed0da86269ec5a343e0ddfbbd6e134c2412
|
7
|
+
data.tar.gz: afb859db4f09d052906b5ffb17529e8e394b1131c217f1ca5f96659c3155fa6f4bf285a6cad5607b87c6740fc2179ce61d41d9815406be22693041c9d9a4aa12
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
@@ -0,0 +1,29 @@
|
|
1
|
+
## Steps to reproduce
|
2
|
+
|
3
|
+
How'd you do it?
|
4
|
+
|
5
|
+
1. ...
|
6
|
+
2. ...
|
7
|
+
|
8
|
+
If relevant, please attach relevant PoC code or PCAPs to help with speedy reproduction.
|
9
|
+
|
10
|
+
## Expected behavior
|
11
|
+
|
12
|
+
What should happen?
|
13
|
+
|
14
|
+
## Current behavior
|
15
|
+
|
16
|
+
What happens instead?
|
17
|
+
|
18
|
+
## System stuff
|
19
|
+
|
20
|
+
### Versions
|
21
|
+
|
22
|
+
- Ruby Version (ruby -v): FILL_ME_IN
|
23
|
+
- PacketFu Version (gem list|grep packetfu -or- git log -1): FILL_ME_IN
|
24
|
+
- OS Version: FILL_ME_IN
|
25
|
+
|
26
|
+
### I installed PacketFu from:
|
27
|
+
- [ ] Git Source
|
28
|
+
- [ ] Gem
|
29
|
+
|
@@ -0,0 +1,72 @@
|
|
1
|
+
name: Verify
|
2
|
+
|
3
|
+
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
|
4
|
+
permissions:
|
5
|
+
actions: none
|
6
|
+
checks: none
|
7
|
+
contents: none
|
8
|
+
deployments: none
|
9
|
+
id-token: none
|
10
|
+
issues: none
|
11
|
+
discussions: none
|
12
|
+
packages: none
|
13
|
+
pages: none
|
14
|
+
pull-requests: none
|
15
|
+
repository-projects: none
|
16
|
+
security-events: none
|
17
|
+
statuses: none
|
18
|
+
|
19
|
+
on:
|
20
|
+
push:
|
21
|
+
branches:
|
22
|
+
- '*'
|
23
|
+
pull_request:
|
24
|
+
branches:
|
25
|
+
- '*'
|
26
|
+
|
27
|
+
jobs:
|
28
|
+
verify:
|
29
|
+
strategy:
|
30
|
+
fail-fast: false
|
31
|
+
matrix:
|
32
|
+
os:
|
33
|
+
- macos-latest
|
34
|
+
- ubuntu-latest
|
35
|
+
ruby:
|
36
|
+
- '2.7'
|
37
|
+
- '3.0'
|
38
|
+
- '3.1'
|
39
|
+
- '3.2'
|
40
|
+
- '3.3.0-preview1'
|
41
|
+
runs-on: ${{ matrix.os }}
|
42
|
+
timeout-minutes: 25
|
43
|
+
|
44
|
+
name: ${{ matrix.os }} - Ruby ${{ matrix.ruby }}
|
45
|
+
|
46
|
+
env:
|
47
|
+
COVERALLS_SKIP: "true"
|
48
|
+
|
49
|
+
steps:
|
50
|
+
- name: Checkout code
|
51
|
+
uses: actions/checkout@v3
|
52
|
+
with:
|
53
|
+
fetch-depth: 0
|
54
|
+
|
55
|
+
- name: Install system dependencies (Linux)
|
56
|
+
if: runner.os == 'Linux'
|
57
|
+
run: |
|
58
|
+
sudo apt-get install libpcap-dev
|
59
|
+
|
60
|
+
- name: Setup Ruby
|
61
|
+
env:
|
62
|
+
BUNDLE_WITHOUT: "coverage development"
|
63
|
+
uses: ruby/setup-ruby@v1
|
64
|
+
with:
|
65
|
+
ruby-version: ${{ matrix.ruby }}
|
66
|
+
bundler-cache: false
|
67
|
+
|
68
|
+
- name: Run tests
|
69
|
+
run: |
|
70
|
+
bundle install
|
71
|
+
bundle exec rspec
|
72
|
+
|
data/.travis.yml
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# PacketFu
|
2
2
|
|
3
|
-
[![Build Status](https://secure.travis-ci.org/packetfu/packetfu.
|
4
|
-
[![Code Climate](https://codeclimate.com/github/packetfu/packetfu.
|
3
|
+
[![Build Status](https://secure.travis-ci.org/packetfu/packetfu.svg)](http://travis-ci.org/packetfu/packetfu)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/packetfu/packetfu.svg)](https://codeclimate.com/github/packetfu/packetfu)
|
5
5
|
[![Coverage Status](https://coveralls.io/repos/github/packetfu/packetfu/badge.svg?branch=master)](https://coveralls.io/github/packetfu/packetfu?branch=master)
|
6
6
|
|
7
7
|
A library for reading and writing packets to an interface or to a
|
@@ -93,7 +93,7 @@ Here's an example of creating a TCPPacket and sending it out on the wire:
|
|
93
93
|
tcp_urg 0 StructFu::Int16
|
94
94
|
tcp_opts PacketFu::TcpOptions
|
95
95
|
|
96
|
-
2.3.0 :003 > packet.
|
96
|
+
2.3.0 :003 > packet.ip_daddr = "8.8.8.8"
|
97
97
|
=> "8.8.8.8"
|
98
98
|
2.3.0 :004 > packet.tcp_dst = 53
|
99
99
|
=> 53
|
@@ -113,13 +113,13 @@ Capture from an interface with show_live or whatever.
|
|
113
113
|
|
114
114
|
This project is integrated with travis-ci and is regularly tested to work with the following rubies:
|
115
115
|
|
116
|
-
-
|
117
|
-
- 2.2.3
|
118
|
-
- 2.3.0
|
116
|
+
To checkout the current build status and what rubies we're currently supporting, click [here](https://travis-ci.org/packetfu/packetfu).
|
119
117
|
|
120
|
-
|
118
|
+
## Supported OSs
|
121
119
|
|
122
|
-
|
120
|
+
This project is designed for use on Linux (Ubuntu|RHEL|BSD primarily) and OSX platforms and it is the intention of the PacketFu team to support those OSs to ensure PacketFu runs on them. That said, PacketFu can and has been known to run on Windows as well as other unix-style platforms, but it's not actively supported in the sense that we may help from the community to help fill that gap. If that is something you are interested in helping with, we welcome your support.
|
121
|
+
|
122
|
+
## Authors
|
123
123
|
|
124
124
|
PacketFu is maintained primarily by Tod Beardsley todb@packetfu.com and
|
125
125
|
Jonathan Claudius claudijd@yahoo.com, with help from Open Source Land.
|
data/certs/todb.pem
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIENDCCApygAwIBAgIBATANBgkqhkiG9w0BAQsFADAiMSAwHgYDVQQDDBd0b2Ri
|
3
|
+
L0RDPXBhY2tldGZ1L0RDPWNvbTAeFw0yMzA2MjcwMDExMjdaFw0yNDA2MjYwMDEx
|
4
|
+
MjdaMCIxIDAeBgNVBAMMF3RvZGIvREM9cGFja2V0ZnUvREM9Y29tMIIBojANBgkq
|
5
|
+
hkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAyz2+nfp+Vv+JVHrJMy5Ck3qWBkiZmE0w
|
6
|
+
7bR1I/bNXrCtv75l1GxTdRAoxKcXpXyC8elJQ9PEjEEDtdGBYQ13BKcQbDJ36etD
|
7
|
+
wjbhRs5SBXgIilJAiR3i/cVnNoNJKOpiJZPufkOpag7Sg8Ze+cWbsc0gYN9nyCmz
|
8
|
+
LYwWDC6Ji0KgJFw5YxFvIxVeOx86Ccfd64Wsa3EhkZd6fOpDE3029GWDqZwZTBIX
|
9
|
+
RzJP4M7QZHZjq3gbHgSKFCFv0MqsjnQzUhPyB/U27c/n+wfRzZNx4Y1eRVm7gwPP
|
10
|
+
LJDzt6mvtlXqc6pQ1NsR9hv3sieFLZDDPU1AaWiOAckIKcVoXB8sGnuFMczMW97o
|
11
|
+
OZLfqfZUAN6LSY939T2sCyOcGhjxZIQbXtn/R/RAJ7UTfJld9UdthKm1W/f0cjwW
|
12
|
+
yqoVsFL+nda6xfta9EnRqqFLOJqyX/wwA2cPO9B8EyM8vFEE8AG8wLu1tF3ggoMg
|
13
|
+
rKut/WQADc3ymKAtsr9bOWajj7bIQVJnAgMBAAGjdTBzMAkGA1UdEwQCMAAwCwYD
|
14
|
+
VR0PBAQDAgSwMB0GA1UdDgQWBBR2kf7ATPt3O7Lpc0uyyCiow3P88DAcBgNVHREE
|
15
|
+
FTATgRF0b2RiQHBhY2tldGZ1LmNvbTAcBgNVHRIEFTATgRF0b2RiQHBhY2tldGZ1
|
16
|
+
LmNvbTANBgkqhkiG9w0BAQsFAAOCAYEAZMp8nY7WzGOPO6TrAlZg37D3s3Rcm0/z
|
17
|
+
6DBzFcY4F5CF3xq1Z/DZ3JwhjILaHPAZTvVT4uj91K4BYh/QgteS52C+O/9qsZ25
|
18
|
+
L3Ocu4Yp+aU40KpjW+IjlzgTS3E21pCBrBTgT7NuTHmTmoNmHfE6Gbbig3a68C9z
|
19
|
+
LcXj2RaEQuhOKrq5vw/0AV34wRieClM/oW8kWAKJDQ8/WEocHQpO1K/dhQ9hHNir
|
20
|
+
lMpjKXsWuxdAZPyvNj15w9fw5a4gZgW26P4VBNJUD/iCe7QYhwXrhdhxf+cygW2A
|
21
|
+
gBCt2UC6yISUDFiajyTw8cTJB1UyfLIADS4hiOEShx7hvVee444bgmOA99C+YuzT
|
22
|
+
FFUt9KVtWsXKD0R6GBvbAUW4/LjmXCCM+Z3uWo1Ph6zljlNHz6/tg+SB7DVgsI3i
|
23
|
+
XuSkzAmFsPisZ7uZk/7gJVlmyaqIxdrPVt9ZOTeSc/8pgSoRurHEJ7KlUXv4kcYM
|
24
|
+
F3a8dA5tl/TC0vkHlCtghhLuD46SlAmH
|
25
|
+
-----END CERTIFICATE-----
|
data/examples/100kpackets.rb
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
# reading and writing packets to and from pcap files.
|
6
6
|
|
7
7
|
# Usage:
|
8
|
-
# ruby examples/100kpackets.rb
|
8
|
+
# ruby examples/100kpackets.rb
|
9
9
|
|
10
10
|
# Path setting slight of hand:
|
11
11
|
$: << File.expand_path("../../lib", __FILE__)
|
@@ -13,7 +13,7 @@ require 'packetfu'
|
|
13
13
|
|
14
14
|
puts "Generating packets... (#{Time.now.utc})"
|
15
15
|
|
16
|
-
File.unlink("/tmp/out.pcap") if File.
|
16
|
+
File.unlink("/tmp/out.pcap") if File.exist? "/tmp/out.pcap"
|
17
17
|
start_time = Time.now.utc
|
18
18
|
count = 0
|
19
19
|
|
data/examples/ackscan.rb
CHANGED
@@ -31,12 +31,13 @@ def gen_packets
|
|
31
31
|
pkt.tcp_dst=81
|
32
32
|
pkt_array = []
|
33
33
|
256.times do |i|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
34
|
+
oa = PacketFu::IPHeader.octet_array(pkt.ip_dst)[0,3] + ["#{i}"]
|
35
|
+
pkt.ip_dst = IPAddr.new(oa.join '.').to_i
|
36
|
+
pkt.tcp_src = rand(5000 - 1025) + 1025
|
37
|
+
pkt.recalc
|
38
|
+
pkt_array << pkt.to_s
|
39
|
+
end
|
40
|
+
pkt_array
|
40
41
|
end
|
41
42
|
|
42
43
|
do_scan
|
data/examples/pcap2pcapng.rb
CHANGED
@@ -9,11 +9,11 @@ require 'packetfu'
|
|
9
9
|
pcap_filename = ARGV[0].chomp
|
10
10
|
pcapng_filename = ARGV[1].chomp
|
11
11
|
|
12
|
-
unless File.
|
12
|
+
unless File.exist?(pcap_filename)
|
13
13
|
puts "PCAP input file #{pcap_filename} could not be found"
|
14
14
|
end
|
15
15
|
|
16
|
-
if File.
|
16
|
+
if File.exist?(pcapng_filename)
|
17
17
|
puts "PCAP-NG output file #{pcap_filename} already exists"
|
18
18
|
puts "Do you wish to overwrite the file? (Y/N, Default = N)"
|
19
19
|
STDOUT.flush
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Usage:
|
3
|
+
# rvmsudo ruby examples/readpcap.rb test.pcap test.pcap
|
4
|
+
|
5
|
+
# Path setting slight of hand:
|
6
|
+
$: << File.expand_path("../../lib", __FILE__)
|
7
|
+
|
8
|
+
require 'packetfu'
|
9
|
+
include PacketFu
|
10
|
+
|
11
|
+
pcap_filename = ARGV[0] || 'test/sample.pcap'
|
12
|
+
|
13
|
+
unless File.exist?(pcap_filename)
|
14
|
+
puts "PCAP input file '#{pcap_filename}' could not be found"
|
15
|
+
exit 1
|
16
|
+
end
|
17
|
+
|
18
|
+
puts "Loaded: PacketFu v#{PacketFu.version}"
|
19
|
+
|
20
|
+
puts "Reading PCAP to packet array from #{File.expand_path(pcap_filename)}"
|
21
|
+
packet_array = PacketFu::PcapFile.file_to_array(pcap_filename)
|
22
|
+
|
23
|
+
packet_array.each do |pkt|
|
24
|
+
packet = PacketFu::Packet.parse(pkt)
|
25
|
+
|
26
|
+
# Do some stuff here (really any thing you want)
|
27
|
+
puts packet.class
|
28
|
+
end
|
data/lib/packetfu/capture.rb
CHANGED
@@ -32,7 +32,7 @@ module PacketFu
|
|
32
32
|
def initialize(args={})
|
33
33
|
@array = [] # Where the packet array goes.
|
34
34
|
@stream = [] # Where the stream goes.
|
35
|
-
@iface = (args[:iface] || ENV['IFACE'] ||
|
35
|
+
@iface = (args[:iface] || ENV['IFACE'] || PacketFu::Utils.default_int || "lo").to_s
|
36
36
|
@snaplen = args[:snaplen] || 0xffff
|
37
37
|
@promisc = args[:promisc] || false # Sensible for some Intel wifi cards
|
38
38
|
@timeout = args[:timeout] || 1
|
data/lib/packetfu/config.rb
CHANGED
@@ -34,7 +34,7 @@ module PacketFu
|
|
34
34
|
|
35
35
|
def initialize(args={})
|
36
36
|
if Process.euid.zero?
|
37
|
-
@iface = args[:iface] || ENV['IFACE'] || Pcap.lookupdev || "lo"
|
37
|
+
@iface = args[:iface] || ENV['IFACE'] || Pcap.lookupdev || "lo"
|
38
38
|
end
|
39
39
|
@pcapfile = "/tmp/out.pcap"
|
40
40
|
args.each_pair { |k,v| self.instance_variable_set(("@#{k}"),v) }
|
@@ -43,7 +43,7 @@ module PacketFu
|
|
43
43
|
# Returns all instance variables as a hash (including custom variables set at initialization).
|
44
44
|
def config(arg=nil)
|
45
45
|
if arg
|
46
|
-
arg.each_pair {|k,v| self.instance_variable_set(("@" + k.to_s).
|
46
|
+
arg.each_pair {|k,v| self.instance_variable_set(("@" + k.to_s).to_sym, v)}
|
47
47
|
else
|
48
48
|
config_hash = {}
|
49
49
|
self.instance_variables.each do |v|
|
data/lib/packetfu/inject.rb
CHANGED
@@ -11,7 +11,7 @@ module PacketFu
|
|
11
11
|
def initialize(args={})
|
12
12
|
@array = [] # Where the packet array goes.
|
13
13
|
@stream = [] # Where the stream goes.
|
14
|
-
@iface = args[:iface] || ENV['IFACE'] ||
|
14
|
+
@iface = args[:iface] || ENV['IFACE'] || PacketFu::Utils.default_int || "lo"
|
15
15
|
@snaplen = args[:snaplen] || 0xffff
|
16
16
|
@promisc = args[:promisc] || false # Sensible for some Intel wifi cards
|
17
17
|
@timeout = args[:timeout] || 1
|
data/lib/packetfu/packet.rb
CHANGED
@@ -95,7 +95,7 @@ module PacketFu
|
|
95
95
|
filename ||= 'out.pcap'
|
96
96
|
mode = mode.to_s[0,1] + "b"
|
97
97
|
raise ArgumentError, "Unknown mode: #{mode.to_s}" unless mode =~ /^[wa]/
|
98
|
-
if(mode == 'w' || !(File.
|
98
|
+
if(mode == 'w' || !(File.exist?(filename)))
|
99
99
|
data = [PcapHeader.new, self.to_pcap].map {|x| x.to_s}.join
|
100
100
|
else
|
101
101
|
data = self.to_pcap
|
@@ -163,12 +163,15 @@ module PacketFu
|
|
163
163
|
# to be transmuted into a packet, as well as args. This superclass method is merely
|
164
164
|
# concerned with handling args common to many packet formats (namely, fixing packets
|
165
165
|
# on the fly)
|
166
|
-
def read(args={})
|
166
|
+
def read(str=nil, args={})
|
167
|
+
raise "Cannot parse `#{str}'" unless self.class.can_parse?(str)
|
168
|
+
@eth_header.read(str)
|
167
169
|
if args[:fix] || args[:recalc]
|
168
170
|
ip_recalc(:ip_sum) if self.is_ip?
|
169
171
|
recalc(:tcp) if self.is_tcp?
|
170
172
|
recalc(:udp) if self.is_udp?
|
171
173
|
end
|
174
|
+
self
|
172
175
|
end
|
173
176
|
|
174
177
|
# Packets are bundles of lots of objects, so copying them
|
@@ -294,7 +297,7 @@ module PacketFu
|
|
294
297
|
def hexify(str)
|
295
298
|
str.force_encoding(Encoding::BINARY) if str.respond_to? :force_encoding
|
296
299
|
hexascii_lines = str.to_s.unpack("H*")[0].scan(/.{1,32}/)
|
297
|
-
regex = Regexp.new('[\x00-\x1f\x7f-\xff]'
|
300
|
+
regex = Regexp.new('[\x00-\x1f\x7f-\xff]'.force_encoding('ASCII-8BIT'), Regexp::NOENCODING)
|
298
301
|
chars = str.to_s.gsub(regex,'.')
|
299
302
|
chars_lines = chars.scan(/.{1,16}/)
|
300
303
|
ret = []
|
data/lib/packetfu/pcap.rb
CHANGED
@@ -6,7 +6,7 @@ module StructFu
|
|
6
6
|
# Set the endianness for the various Int classes. Takes either :little or :big.
|
7
7
|
def set_endianness(e=nil)
|
8
8
|
unless [:little, :big].include? e
|
9
|
-
raise ArgumentError, "Unknown endianness for #{self.class}"
|
9
|
+
raise ArgumentError, "Unknown endianness for #{self.class}"
|
10
10
|
end
|
11
11
|
@int64 = e == :little ? Int64le : Int64be
|
12
12
|
@int32 = e == :little ? Int32le : Int32be
|
@@ -26,11 +26,11 @@ end
|
|
26
26
|
module PacketFu
|
27
27
|
|
28
28
|
# PcapHeader represents the header portion of a libpcap file (the packets
|
29
|
-
# themselves are in the PcapPackets array). See
|
29
|
+
# themselves are in the PcapPackets array). See
|
30
30
|
# http://wiki.wireshark.org/Development/LibpcapFileFormat for details.
|
31
31
|
#
|
32
32
|
# Depending on the endianness (set with :endian), elements are either
|
33
|
-
# :little endian or :big endian.
|
33
|
+
# :little endian or :big endian.
|
34
34
|
#
|
35
35
|
# ==== PcapHeader Definition
|
36
36
|
#
|
@@ -52,13 +52,13 @@ module PacketFu
|
|
52
52
|
|
53
53
|
def initialize(args={})
|
54
54
|
set_endianness(args[:endian] ||= :little)
|
55
|
-
init_fields(args)
|
56
|
-
super(args[:endian], args[:magic], args[:ver_major],
|
57
|
-
args[:ver_minor], args[:thiszone], args[:sigfigs],
|
55
|
+
init_fields(args)
|
56
|
+
super(args[:endian], args[:magic], args[:ver_major],
|
57
|
+
args[:ver_minor], args[:thiszone], args[:sigfigs],
|
58
58
|
args[:snaplen], args[:network])
|
59
59
|
end
|
60
|
-
|
61
|
-
# Called by initialize to set the initial fields.
|
60
|
+
|
61
|
+
# Called by initialize to set the initial fields.
|
62
62
|
def init_fields(args={})
|
63
63
|
args[:magic] = @int32.new(args[:magic] || PcapHeader::MAGIC_INT32)
|
64
64
|
args[:ver_major] = @int16.new(args[:ver_major] || 2)
|
@@ -82,7 +82,7 @@ module PacketFu
|
|
82
82
|
force_binary(str)
|
83
83
|
return self if str.nil?
|
84
84
|
str.force_encoding(Encoding::BINARY) if str.respond_to? :force_encoding
|
85
|
-
if str[0,4] == self[:magic].to_s
|
85
|
+
if str[0,4] == self[:magic].to_s
|
86
86
|
self[:magic].read str[0,4]
|
87
87
|
self[:ver_major].read str[4,2]
|
88
88
|
self[:ver_minor].read str[6,2]
|
@@ -114,7 +114,7 @@ module PacketFu
|
|
114
114
|
super(args[:endian], args[:sec], args[:usec])
|
115
115
|
end
|
116
116
|
|
117
|
-
# Called by initialize to set the initial fields.
|
117
|
+
# Called by initialize to set the initial fields.
|
118
118
|
def init_fields(args={})
|
119
119
|
args[:sec] = @int32.new(args[:sec])
|
120
120
|
args[:usec] = @int32.new(args[:usec])
|
@@ -156,7 +156,7 @@ module PacketFu
|
|
156
156
|
args[:orig_len], args[:data])
|
157
157
|
end
|
158
158
|
|
159
|
-
# Called by initialize to set the initial fields.
|
159
|
+
# Called by initialize to set the initial fields.
|
160
160
|
def init_fields(args={})
|
161
161
|
args[:timestamp] = Timestamp.new(:endian => args[:endian]).read(args[:timestamp])
|
162
162
|
args[:incl_len] = args[:incl_len].nil? ? @int32.new(args[:data].to_s.size) : @int32.new(args[:incl_len])
|
@@ -197,8 +197,8 @@ module PacketFu
|
|
197
197
|
str.force_encoding Encoding::BINARY if str.respond_to? :force_encoding
|
198
198
|
end
|
199
199
|
|
200
|
-
# Reads a string to populate the object. Note, this read takes in the
|
201
|
-
# whole pcap file, since we need to see the magic to know what
|
200
|
+
# Reads a string to populate the object. Note, this read takes in the
|
201
|
+
# whole pcap file, since we need to see the magic to know what
|
202
202
|
# endianness we're dealing with.
|
203
203
|
def read(str)
|
204
204
|
force_binary(str)
|
@@ -226,7 +226,7 @@ module PacketFu
|
|
226
226
|
|
227
227
|
end
|
228
228
|
|
229
|
-
# PcapFile is a complete libpcap file struct, made up of two elements, a
|
229
|
+
# PcapFile is a complete libpcap file struct, made up of two elements, a
|
230
230
|
# PcapHeader and PcapPackets.
|
231
231
|
#
|
232
232
|
# See http://wiki.wireshark.org/Development/LibpcapFileFormat
|
@@ -240,7 +240,7 @@ module PacketFu
|
|
240
240
|
|
241
241
|
class << self
|
242
242
|
|
243
|
-
# Takes a given file and returns an array of the packet bytes. Here
|
243
|
+
# Takes a given file and returns an array of the packet bytes. Here
|
244
244
|
# for backwards compatibilty.
|
245
245
|
def file_to_array(fname)
|
246
246
|
PcapFile.new.file_to_array(:f => fname)
|
@@ -248,9 +248,9 @@ module PacketFu
|
|
248
248
|
|
249
249
|
# Takes a given file name, and reads out the packets. If given a block,
|
250
250
|
# it will yield back a PcapPacket object per packet found.
|
251
|
-
def read(fname,&block)
|
251
|
+
def read(fname,&block)
|
252
252
|
file_header = PcapHeader.new
|
253
|
-
pcap_packets = PcapPackets.new
|
253
|
+
pcap_packets = PcapPackets.new
|
254
254
|
unless File.readable? fname
|
255
255
|
raise ArgumentError, "Cannot read file `#{fname}'"
|
256
256
|
end
|
@@ -279,13 +279,13 @@ module PacketFu
|
|
279
279
|
block ? packet_count : pcap_packets
|
280
280
|
end
|
281
281
|
|
282
|
-
# Takes a filename, and an optional block. If a block is given,
|
282
|
+
# Takes a filename, and an optional block. If a block is given,
|
283
283
|
# yield back the raw packet data from the given file. Otherwise,
|
284
284
|
# return an array of parsed packets.
|
285
285
|
def read_packet_bytes(fname,&block)
|
286
286
|
count = 0
|
287
287
|
packets = [] unless block
|
288
|
-
read(fname) do |packet|
|
288
|
+
read(fname) do |packet|
|
289
289
|
if block
|
290
290
|
count += 1
|
291
291
|
yield packet.data.to_s
|
@@ -296,7 +296,7 @@ module PacketFu
|
|
296
296
|
block ? count : packets
|
297
297
|
end
|
298
298
|
|
299
|
-
alias :file_to_array :read_packet_bytes
|
299
|
+
alias :file_to_array :read_packet_bytes
|
300
300
|
|
301
301
|
# Takes a filename, and an optional block. If a block is given,
|
302
302
|
# yield back parsed packets from the given file. Otherwise, return
|
@@ -307,7 +307,7 @@ module PacketFu
|
|
307
307
|
def read_packets(fname,&block)
|
308
308
|
count = 0
|
309
309
|
packets = [] unless block
|
310
|
-
read_packet_bytes(fname) do |packet|
|
310
|
+
read_packet_bytes(fname) do |packet|
|
311
311
|
if block
|
312
312
|
count += 1
|
313
313
|
yield Packet.parse(packet)
|
@@ -326,7 +326,7 @@ module PacketFu
|
|
326
326
|
super(args[:endian], args[:head], args[:body])
|
327
327
|
end
|
328
328
|
|
329
|
-
# Called by initialize to set the initial fields.
|
329
|
+
# Called by initialize to set the initial fields.
|
330
330
|
def init_fields(args={})
|
331
331
|
args[:head] = PcapHeader.new(:endian => args[:endian]).read(args[:head])
|
332
332
|
args[:body] = PcapPackets.new(:endian => args[:endian]).read(args[:body])
|
@@ -354,7 +354,7 @@ module PacketFu
|
|
354
354
|
|
355
355
|
# Clears the contents of the PcapFile prior to reading in a new string.
|
356
356
|
def read!(str)
|
357
|
-
clear
|
357
|
+
clear
|
358
358
|
force_binary(str)
|
359
359
|
self.read str
|
360
360
|
end
|
@@ -381,7 +381,7 @@ module PacketFu
|
|
381
381
|
|
382
382
|
# file_to_array() translates a libpcap file into an array of packets.
|
383
383
|
# Note that this strips out pcap timestamps -- if you'd like to retain
|
384
|
-
# timestamps and other libpcap file information, you will want to
|
384
|
+
# timestamps and other libpcap file information, you will want to
|
385
385
|
# use read() instead.
|
386
386
|
def file_to_array(args={})
|
387
387
|
filename = args[:filename] || args[:file] || args[:f]
|
@@ -469,7 +469,7 @@ module PacketFu
|
|
469
469
|
end
|
470
470
|
append = args[:append]
|
471
471
|
if append
|
472
|
-
if File.
|
472
|
+
if File.exist? filename
|
473
473
|
File.open(filename,'ab') {|file| file.write(self.body.to_s)}
|
474
474
|
else
|
475
475
|
File.open(filename,'wb') {|file| file.write(self.to_s)}
|
data/lib/packetfu/pcapng/file.rb
CHANGED
data/lib/packetfu/protos/arp.rb
CHANGED
@@ -44,13 +44,6 @@ module PacketFu
|
|
44
44
|
true
|
45
45
|
end
|
46
46
|
|
47
|
-
def read(str=nil,args={})
|
48
|
-
raise "Cannot parse `#{str}'" unless self.class.can_parse?(str)
|
49
|
-
@eth_header.read(str)
|
50
|
-
super(args)
|
51
|
-
self
|
52
|
-
end
|
53
|
-
|
54
47
|
def initialize(args={})
|
55
48
|
@eth_header = EthHeader.new(args).read(args[:eth])
|
56
49
|
@arp_header = ARPHeader.new(args).read(args[:arp])
|
@@ -59,7 +52,7 @@ module PacketFu
|
|
59
52
|
|
60
53
|
# Please send more flavors to todb+packetfu@planb-security.net.
|
61
54
|
# Most of these initial fingerprints come from one (1) sample.
|
62
|
-
case (args[:flavor].nil?) ? :nil : args[:flavor].to_s.downcase.
|
55
|
+
case (args[:flavor].nil?) ? :nil : args[:flavor].to_s.downcase.to_sym
|
63
56
|
when :windows; @arp_header.body = "\x00" * 64 # 64 bytes of padding
|
64
57
|
when :linux; @arp_header.body = "\x00" * 4 + # 32 bytes of padding
|
65
58
|
"\x00\x07\x5c\x14" + "\x00" * 4 +
|
data/lib/packetfu/protos/eth.rb
CHANGED
@@ -29,13 +29,6 @@ module PacketFu
|
|
29
29
|
true
|
30
30
|
end
|
31
31
|
|
32
|
-
def read(str=nil,args={})
|
33
|
-
raise "Cannot parse `#{str}'" unless self.class.can_parse?(str)
|
34
|
-
@eth_header.read(str)
|
35
|
-
super(args)
|
36
|
-
return self
|
37
|
-
end
|
38
|
-
|
39
32
|
# Does nothing, really, since there's no length or
|
40
33
|
# checksum to calculate for a straight Ethernet packet.
|
41
34
|
def recalc(args={})
|
data/lib/packetfu/protos/hsrp.rb
CHANGED
@@ -59,13 +59,6 @@ module PacketFu
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
-
def read(str=nil, args={})
|
63
|
-
raise "Cannot parse `#{str}'" unless self.class.can_parse?(str)
|
64
|
-
@eth_header.read(str)
|
65
|
-
super(args)
|
66
|
-
self
|
67
|
-
end
|
68
|
-
|
69
62
|
def initialize(args={})
|
70
63
|
@eth_header = EthHeader.new(args).read(args[:eth])
|
71
64
|
@ip_header = IPHeader.new(args).read(args[:ip])
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# -*- coding: binary -*-
|
2
2
|
module PacketFu
|
3
|
-
# ICMPHeader is a complete ICMP struct, used in ICMPPacket. ICMP is
|
3
|
+
# ICMPHeader is a complete ICMP struct, used in ICMPPacket. ICMP is
|
4
4
|
# typically used for network administration and connectivity testing.
|
5
5
|
#
|
6
|
-
# For more on ICMP packets, see
|
6
|
+
# For more on ICMP packets, see
|
7
7
|
# http://www.networksorcery.com/enp/protocol/icmp.htm
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# ==== Header Definition
|
10
10
|
#
|
11
11
|
# Int8 :icmp_type # Type
|
@@ -49,7 +49,7 @@ module PacketFu
|
|
49
49
|
def icmp_code=(i); typecast i; end
|
50
50
|
# Getter for the code.
|
51
51
|
def icmp_code; self[:icmp_code].to_i; end
|
52
|
-
# Setter for the checksum. Note, this is calculated automatically with
|
52
|
+
# Setter for the checksum. Note, this is calculated automatically with
|
53
53
|
# icmp_calc_sum.
|
54
54
|
def icmp_sum=(i); typecast i; end
|
55
55
|
# Getter for the checksum.
|
@@ -68,13 +68,10 @@ module PacketFu
|
|
68
68
|
checksum = 0xffff - checksum
|
69
69
|
checksum == 0 ? 0xffff : checksum
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
# Recalculates the calculatable fields for ICMP.
|
73
|
-
def icmp_recalc(arg
|
74
|
-
|
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
|
73
|
+
def icmp_recalc(arg = :all)
|
74
|
+
case arg.to_sym
|
78
75
|
when :icmp_sum
|
79
76
|
self.icmp_sum=icmp_calc_sum
|
80
77
|
when :all
|
data/lib/packetfu/protos/icmp.rb
CHANGED
@@ -50,13 +50,6 @@ module PacketFu
|
|
50
50
|
return true
|
51
51
|
end
|
52
52
|
|
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
|
-
|
60
53
|
def initialize(args={})
|
61
54
|
@eth_header = EthHeader.new(args).read(args[:eth])
|
62
55
|
@ip_header = IPHeader.new(args).read(args[:ip])
|