packetman 0.1.0 → 0.1.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 -1
- data/config/protocols.yml +28 -34
- data/lib/packetman.rb +0 -5
- data/lib/packetman/compose.rb +16 -20
- data/lib/packetman/config.rb +8 -30
- data/lib/packetman/config_methods.rb +4 -0
- data/lib/packetman/table.rb +1 -1
- data/lib/packetman/version.rb +1 -1
- metadata +3 -4
- data/packetman_notes +0 -156
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d3819b6864ab2d131bcd29e65c79a02123a1d4b4
|
4
|
+
data.tar.gz: 7de18ca9f2f368755393dbc6c0d3b4edfb34a019
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f70eb13025b20f23690c6d0b169bb165a7ea035597bd863a5bb1279711eb1f40f54fe393e0611715b980f460e5d899f2ddf92a8ce2806544d70f26d3cf0599e8
|
7
|
+
data.tar.gz: 3f2df4b4ee6be9f721195aa661b8ae91bf7aeccd77c8935fa6b51464c872e345206c103af7898342f102ddc55859ddb300642a5420b1e7831b24585f3b378dcb
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Advanced tcpdump and Wireshark capture generator.
|
4
4
|
|
5
|
-
[](https://codeclimate.com/github/jescholl/packetman) [](https://codeclimate.com/github/jescholl/packetman/coverage) [](https://circleci.com/gh/jescholl/packetman)
|
5
|
+
[](http://badge.fury.io/rb/packetman) [](https://codeclimate.com/github/jescholl/packetman) [](https://codeclimate.com/github/jescholl/packetman/coverage) [](https://circleci.com/gh/jescholl/packetman)
|
6
6
|
|
7
7
|
Packetman is a packet capture filter generator modeled after [Wireshark's String-Matching Capture Filter Generator](https://www.wireshark.org/tools/string-cf.html) but with a lot more features allowing much finer control over the packets you see.
|
8
8
|
|
data/config/protocols.yml
CHANGED
@@ -1,35 +1,29 @@
|
|
1
1
|
---
|
2
|
-
|
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
|
-
Type Specific Options: 32
|
31
|
-
application:
|
32
|
-
http:
|
33
|
-
transport_protocol: tcp
|
34
|
-
dns:
|
35
|
-
transport_protocol: tcp
|
2
|
+
tcp:
|
3
|
+
table:
|
4
|
+
Source Port: 16
|
5
|
+
Destination Port: 16
|
6
|
+
Sequence Number: 32
|
7
|
+
Acknowledgement Number: 32
|
8
|
+
Data Offset: 4
|
9
|
+
RESERVED: 3
|
10
|
+
ECN: 3
|
11
|
+
Control Bits: 6
|
12
|
+
Window: 16
|
13
|
+
Checksum: 16
|
14
|
+
Urgent Pointer: 16
|
15
|
+
Options and Padding: 32
|
16
|
+
payload_query: '((tcp[12:1] & 0xf0) >> 2)'
|
17
|
+
udp:
|
18
|
+
table:
|
19
|
+
Source Port: 16
|
20
|
+
Destination Port: 16
|
21
|
+
Length: 16
|
22
|
+
Checksum: 16
|
23
|
+
payload_query: 8
|
24
|
+
icmp:
|
25
|
+
table:
|
26
|
+
Type: 8
|
27
|
+
Code: 8
|
28
|
+
Checksum: 16
|
29
|
+
Type Specific Options: 32
|
data/lib/packetman.rb
CHANGED
data/lib/packetman/compose.rb
CHANGED
@@ -6,7 +6,7 @@ module Packetman
|
|
6
6
|
@input = input
|
7
7
|
@radix = radix
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
def desired_length
|
11
11
|
((@input.length + config.offset)/8.to_f).ceil*8 - config.offset
|
12
12
|
end
|
@@ -15,7 +15,7 @@ module Packetman
|
|
15
15
|
(radix.nil?) ? 8 : Math.log2(radix).to_i
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
18
|
+
def mask_bits
|
19
19
|
shift(@input.scan(/./).map{ |c| mask_chr(c) }.join)
|
20
20
|
end
|
21
21
|
|
@@ -27,7 +27,7 @@ module Packetman
|
|
27
27
|
input.ljust(desired_length, '0')
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
30
|
+
def search_bits
|
31
31
|
shift(@input.scan(/./).map{ |c| bin_chr(c) }.join)
|
32
32
|
end
|
33
33
|
|
@@ -54,20 +54,18 @@ module Packetman
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def mask_hex
|
57
|
-
hex_encode(
|
57
|
+
hex_encode(mask_bits)
|
58
58
|
end
|
59
59
|
|
60
60
|
def search_hex
|
61
|
-
hex_encode(
|
61
|
+
hex_encode(search_bits)
|
62
62
|
end
|
63
63
|
|
64
64
|
def hex_encode(bin_str)
|
65
|
-
bin_str.reverse.scan(/.{1,4}/).map{ |chunk| chunk.reverse.to_i(2).to_s(16) }.reverse.join.scan(/.{
|
65
|
+
bin_str.reverse.scan(/.{1,4}/).map{ |chunk| chunk.reverse.to_i(2).to_s(16) }.reverse.join.scan(/.{8}|.{4}|.{2}/).map{ |hex| hex.prepend('0x') }
|
66
66
|
end
|
67
67
|
|
68
|
-
def
|
69
|
-
return num.to_i(radix).to_s(radix).length * bit_density(radix) if radix
|
70
|
-
|
68
|
+
def bit_length(num)
|
71
69
|
case num
|
72
70
|
when /^0x/
|
73
71
|
$'.length * bit_density(16)
|
@@ -78,20 +76,18 @@ module Packetman
|
|
78
76
|
end
|
79
77
|
end
|
80
78
|
|
81
|
-
def start_byte(
|
82
|
-
|
79
|
+
def start_byte(bit_position)
|
80
|
+
[config.payload_query, (config.offset + bit_position)/8].compact.join(' + ')
|
83
81
|
end
|
84
82
|
|
85
|
-
def
|
86
|
-
|
87
|
-
|
88
|
-
search_hex.zip(mask_hex).each_with_index do |(hex_search, hex_mask),i|
|
89
|
-
search_bit_length = full_bit_length(hex_search)
|
90
|
-
clauses << "#{config.transport}[#{start_byte(position)}:#{search_bit_length/8}] & #{hex_mask} = #{hex_search}"
|
91
|
-
position += search_bit_length
|
92
|
-
end
|
83
|
+
def data_address(start_bit, bit_length)
|
84
|
+
"#{config.transport}[#{start_byte(start_bit)}:#{bit_length/8}]"
|
85
|
+
end
|
93
86
|
|
94
|
-
|
87
|
+
def to_s
|
88
|
+
search_hex.zip(mask_hex).map.with_index do |(search, mask),i|
|
89
|
+
"#{data_address(i*32, bit_length(search))} & #{mask} = #{search}"
|
90
|
+
end.join(' && ')
|
95
91
|
end
|
96
92
|
end
|
97
93
|
end
|
data/lib/packetman/config.rb
CHANGED
@@ -2,16 +2,12 @@ require 'optparse'
|
|
2
2
|
|
3
3
|
module Packetman
|
4
4
|
class Config
|
5
|
-
attr_accessor :transport, :application, :
|
5
|
+
attr_accessor :transport, :application, :use_bytes, :allow_wildcards, :radix, :start_with_transport
|
6
6
|
attr_writer :offset
|
7
7
|
|
8
8
|
def initialize
|
9
9
|
@transport = "tcp"
|
10
|
-
@application = "http"
|
11
10
|
@offset = 0
|
12
|
-
@offset_units = "bits"
|
13
|
-
@offset_type = "application"
|
14
|
-
@allow_wildcards = true
|
15
11
|
end
|
16
12
|
|
17
13
|
def protocols
|
@@ -19,17 +15,11 @@ module Packetman
|
|
19
15
|
end
|
20
16
|
|
21
17
|
def payload_query
|
22
|
-
|
23
|
-
when "application"
|
24
|
-
protocols['transport'][transport.to_s]['payload_query']
|
25
|
-
else
|
26
|
-
"0"
|
27
|
-
end
|
18
|
+
protocols[transport]['payload_query'] unless start_with_transport
|
28
19
|
end
|
29
20
|
|
30
21
|
def offset
|
31
|
-
|
32
|
-
when "bytes"
|
22
|
+
if use_bytes
|
33
23
|
@offset*8
|
34
24
|
else
|
35
25
|
@offset
|
@@ -39,14 +29,13 @@ module Packetman
|
|
39
29
|
def parse_opts
|
40
30
|
@opts ||= OptionParser.new do |opt|
|
41
31
|
opt.banner = "Usage: #{File.basename($PROGRAM_NAME)} [OPTIONS] FILTER_STRING"
|
42
|
-
opt.on("-
|
43
|
-
opt.on("-
|
44
|
-
#opt.on("-a", "--application [PROTO]", String, "Application Protocol (http|dns|icmp)") {|v| self.application = v }
|
32
|
+
opt.on("-p", "--protocol [PROTO]", protocols.keys, "Transport Protocol (#{protocols.keys.join(',')})") {|v| self.transport = v }
|
33
|
+
opt.on("-t", "--transport", "OFFSET starts at transport header instead of data payload") { |v| self.start_with_transport = v }
|
45
34
|
opt.on("-r", "--radix [RADIX]", Integer, "Treat FILTER_STRING as RADIX instead of String") {|v| self.radix = v; }
|
46
35
|
opt.on("-o", "--offset [OFFSET]", Integer, "Offset in bits") {|v| self.offset = v; }
|
47
|
-
opt.on("-b", "--byte-offset", "Use 8-bit bytes instead of bits for offset") { |v| self.
|
48
|
-
opt.on("-
|
49
|
-
opt.on("
|
36
|
+
opt.on("-b", "--byte-offset", "Use 8-bit bytes instead of bits for offset") { |v| self.use_bytes = v }
|
37
|
+
opt.on("-w", "--wildcards", "Allow '?' wildcards") { |v| self.allow_wildcards = v }
|
38
|
+
opt.on("-v", "--version", "Show version") { puts Packetman::VERSION; exit }
|
50
39
|
end
|
51
40
|
|
52
41
|
@opts.parse!
|
@@ -54,17 +43,6 @@ module Packetman
|
|
54
43
|
raise "Invalid command line arguments" if ARGV.size != 1
|
55
44
|
|
56
45
|
ARGV.pop
|
57
|
-
|
58
|
-
|
59
|
-
# if transport !~ /tcp|udp/i ||
|
60
|
-
# application !~ /http|dns|icmp/i
|
61
|
-
# raise "invalid options"
|
62
|
-
# end
|
63
|
-
#
|
64
|
-
# if offset_units == :bits
|
65
|
-
# offset /= 8.to_f
|
66
|
-
# offset_units = :octets
|
67
|
-
# end
|
68
46
|
end
|
69
47
|
|
70
48
|
end
|
data/lib/packetman/table.rb
CHANGED
@@ -44,7 +44,7 @@ module Packetman
|
|
44
44
|
def to_s
|
45
45
|
output = horizontal_bar + header_row + horizontal_bar
|
46
46
|
|
47
|
-
|
47
|
+
protocols[config.transport]['table'].each do |label, size|
|
48
48
|
output += sprintf "%s%.#{cell_size(size)}s", line_v, label.center(cell_size(size))
|
49
49
|
if output.split("\n").last.length == (table_width - 1)
|
50
50
|
output += line_v + "\n"
|
data/lib/packetman/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: packetman
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jason Scholl
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-11-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -110,7 +110,6 @@ files:
|
|
110
110
|
- lib/packetman/table.rb
|
111
111
|
- lib/packetman/version.rb
|
112
112
|
- packetman.gemspec
|
113
|
-
- packetman_notes
|
114
113
|
homepage: https://github.com/jescholl/packetman
|
115
114
|
licenses:
|
116
115
|
- MIT
|
@@ -131,7 +130,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
131
130
|
version: '0'
|
132
131
|
requirements: []
|
133
132
|
rubyforge_project:
|
134
|
-
rubygems_version: 2.4.5
|
133
|
+
rubygems_version: 2.4.5.1
|
135
134
|
signing_key:
|
136
135
|
specification_version: 4
|
137
136
|
summary: Advanced tcpdump and Wiresharp filter generator.
|
data/packetman_notes
DELETED
@@ -1,156 +0,0 @@
|
|
1
|
-
7a
|
2
|
-
1111010
|
3
|
-
|
4
|
-
#NOTE: I think this is wrong
|
5
|
-
# also, maybe I don't need to worry about the bits bing aligned on the byte, just on the bit, as long as it's what the user asked for
|
6
|
-
|
7
|
-
hex and string need to be 0 padded on the left
|
8
|
-
binary needs to fill to the right to hex encode, starting at the offset bit
|
9
|
-
|
10
|
-
Packetman.compose3("0b1111", 3)
|
11
|
-
1111
|
12
|
-
(fill right to ((4+3)/8.to_f).ceil*8 = 8 )
|
13
|
-
11110000
|
14
|
-
(shift mask and search >> 3)
|
15
|
-
00011110
|
16
|
-
00011110
|
17
|
-
(sample byte sequence)
|
18
|
-
00011111
|
19
|
-
|
20
|
-
Packetman.compose3("0b1111010", 3)
|
21
|
-
1111010
|
22
|
-
(fill right to ((7+3)/8.to_f).ceil*8 = 16)
|
23
|
-
11110100 00000000
|
24
|
-
(shift mask and search >> 3)
|
25
|
-
00011111 11000000
|
26
|
-
00011110 10000000
|
27
|
-
(sample byte sequence)
|
28
|
-
00011110 10101010
|
29
|
-
|
30
|
-
|
31
|
-
Packetman.compose3("0b1111010????????", 3)
|
32
|
-
1111010? ???????
|
33
|
-
(fill right to ((15+3)/8.to_f).ceil*8 = 24)
|
34
|
-
1111010? ???????0 00000000
|
35
|
-
(shift mask and search >> 3)
|
36
|
-
00011111 11000000 00000000
|
37
|
-
00011110 10000000 00000000
|
38
|
-
(sample byte sequence)
|
39
|
-
00011110 10101010 10101010
|
40
|
-
|
41
|
-
Packetman.compose3("0x123",3)
|
42
|
-
100100011
|
43
|
-
(left fill to 12 first, or manual right fill with 16-12)
|
44
|
-
(fill right to ((3*4)+3)/8.to_f).ceil*8 = 16)
|
45
|
-
00010010 00110000
|
46
|
-
(shift mask and search >> 3)
|
47
|
-
00000011 11111110
|
48
|
-
00000010 01000110
|
49
|
-
(sample byte sequence)
|
50
|
-
00000010 01000111
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
Packetman.compose3("0xa",3)
|
56
|
-
"((tcp[0:1] & 0xa) >> 1) = 0xa"
|
57
|
-
1010
|
58
|
-
(generate shifted mask)
|
59
|
-
00011110
|
60
|
-
(generate shifted search)
|
61
|
-
00010100
|
62
|
-
(sample byte sequence)
|
63
|
-
10010101
|
64
|
-
|
65
|
-
0b00011110 & 0b10010101 == 0x14
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
Packetman.compose3("0b001010010", 3)
|
73
|
-
"((tcp[0:2] & 0x1ff0) >> 4 = 0x52"
|
74
|
-
001010010
|
75
|
-
(generate shifted mask)
|
76
|
-
(turn preceding 0s to 1s)
|
77
|
-
(left shift (((binlen)+3)/8.to_f).ceil*8 - binlen - 3)
|
78
|
-
1111111110000
|
79
|
-
(generate shifted search - same as above)
|
80
|
-
0010100100000
|
81
|
-
(sample byte sequence)
|
82
|
-
0010100101010
|
83
|
-
|
84
|
-
0b0010100101010 & 1111111110000 == 0b0010100100000
|
85
|
-
|
86
|
-
|
87
|
-
Packetman.compose3("0b00??1010?111?00010101??10101010?????1010111110???111110101001111010101??????????10100101010100011???????", 5)
|
88
|
-
00??1010?111?00010101??10101010?????1010111110???111110101001111010101??????????10100101010100011???????
|
89
|
-
(generate search str - replace ?s with 0s)
|
90
|
-
00001010011100001010100101010100000010101111100001111101010011110101010000000000101001010101000110000000
|
91
|
-
(generate shifted mask)
|
92
|
-
(turn preceding 0s to 1s)
|
93
|
-
(left shift (((binlen)+5)/8.to_f).ceil*8 - binlen - 5)
|
94
|
-
11001111011101111111100111111110000011111111110001111111111111111111110000000000111111111111111110000000000
|
95
|
-
11001111011101111111100111111110000011111111110001111111111111111111110000000000111111111111111110000000
|
96
|
-
(generate shifted search - same as above)
|
97
|
-
00001010011100001010100101010100000010101111100001111101010011110101010000000000101001010101000110000000000
|
98
|
-
(sample byte sequence)
|
99
|
-
00011010011100001010111101010101100110101111100101111101010011110101010010101001101001010101000110110100101
|
100
|
-
|
101
|
-
00011010011100001010111101010101100110101111100101111101010011110101010010101001101001010101000110110100101 &
|
102
|
-
11001111011101111111100111111110000011111111110001111111111111111111110000000000111111111111111110000000000 ==
|
103
|
-
00001010011100001010100101010100000010101111100001111101010011110101010000000000101001010101000110000000000
|
104
|
-
|
105
|
-
|
106
|
-
# NOTE
|
107
|
-
|
108
|
-
instead of shifting the product of (mask & input), shift search
|
109
|
-
this makes the form
|
110
|
-
"tcp[0:1] & mask = shifted_search"
|
111
|
-
|
112
|
-
|
113
|
-
Packetman.compose3("0xa",1)
|
114
|
-
"((tcp[0:1] & 0x78) >> 3) = 0xa"
|
115
|
-
1010
|
116
|
-
(generate shifted mask)
|
117
|
-
(left shift (((hexlen*4)+1)/8.to_f).ceil*8 - hexlen*4 - 1)
|
118
|
-
(use length of mask to determine how much data to take)
|
119
|
-
01111000
|
120
|
-
(sample byte sequence)
|
121
|
-
11010101
|
122
|
-
|
123
|
-
(0b01111000 & 0b11010101) >> 3 == 0xa
|
124
|
-
|
125
|
-
|
126
|
-
Packetman.compose3("0x123", 3)
|
127
|
-
"((tcp[0:2] & 0x1ffe) >> 1) = 0x123"
|
128
|
-
100100011
|
129
|
-
(hex: left fill with 1s to hexlen*4)
|
130
|
-
111100100011
|
131
|
-
(generate shifted mask)
|
132
|
-
(left shift (((hexlen*4)+3)/8.to_f).ceil*8 - hexlen*4 - 3)
|
133
|
-
(use length of mask to determine how much data to take)
|
134
|
-
0001111111111110
|
135
|
-
(sample byte sequence)
|
136
|
-
1000001001000111
|
137
|
-
|
138
|
-
(0b1000001001000111 & 0b0001111111111110) >> 1 == 0x123
|
139
|
-
|
140
|
-
Packetman.compose3("abc", 3)
|
141
|
-
"((tcp[0:4] & 0x1fffffe0 >> 5) = 0x616263"
|
142
|
-
11000010110001001100011
|
143
|
-
(str: left fill with 1s to len*8)
|
144
|
-
111000010110001001100011
|
145
|
-
(generate shifted mask)
|
146
|
-
(left shift (((strlen*8)+3)/8.to_f).ceil*8 - strlen*8 - 3)
|
147
|
-
(use length of mask to determine how much data to take)
|
148
|
-
00011111 11111111 11111111 11100000
|
149
|
-
(sample byte sequence)
|
150
|
-
10101100 00101100 01001100 01110101
|
151
|
-
|
152
|
-
(0b10101100001011000100110001110101 & 0b00011111111111111111111111100000) >> 5 == 0b11000010110001001100011
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|