simple_capture 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +57 -0
- data/.ruby-version +1 -0
- data/LICENSE +21 -0
- data/README.md +14 -0
- data/Rakefile +8 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/simple_capture.rb +11 -0
- data/lib/simple_capture/capture.rb +92 -0
- data/lib/simple_capture/header/ehter_header.rb +70 -0
- data/lib/simple_capture/header/icmp_header.rb +76 -0
- data/lib/simple_capture/header/ipv4_header.rb +117 -0
- data/lib/simple_capture/packet.rb +18 -0
- data/lib/simple_capture/recv_message.rb +25 -0
- data/lib/simple_capture/string.rb +25 -0
- data/lib/simple_capture/version.rb +3 -0
- data/sample_run.rb +4 -0
- data/simple_capture.gemspec +36 -0
- metadata +64 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d8ab97c1d77026f80dc16f0e798a730078d52f9323b9038769c5d60c2385a1a3
|
4
|
+
data.tar.gz: 6fc14246c88e07be902c1dae27ec8ac268f6db4d6d144b414f5902f0ff0d1170
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c600259cbe23284c1ba1e27eac9430da64c841c4c0879b850ca8f7c092df0e711aec3335dc3fd827ed206c5df1b16b94c8bb9994a571ee9f32b0c669bec69ebf
|
7
|
+
data.tar.gz: 94b33abf943b6a48c13e23e1cc4423171427f15e001e384c8d279903429c3bb70ae03cb48b5ba2ecac63ac84fd0ffdf0058a4f55dedd3af06faf1d4e6a259bbf
|
data/.gitignore
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
|
13
|
+
# Used by dotenv library to load environment variables.
|
14
|
+
# .env
|
15
|
+
|
16
|
+
# Ignore Byebug command history file.
|
17
|
+
.byebug_history
|
18
|
+
|
19
|
+
## Specific to RubyMotion:
|
20
|
+
.dat*
|
21
|
+
.repl_history
|
22
|
+
build/
|
23
|
+
*.bridgesupport
|
24
|
+
build-iPhoneOS/
|
25
|
+
build-iPhoneSimulator/
|
26
|
+
|
27
|
+
## Specific to RubyMotion (use of CocoaPods):
|
28
|
+
#
|
29
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
30
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
31
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
32
|
+
#
|
33
|
+
# vendor/Pods/
|
34
|
+
|
35
|
+
## Documentation cache and generated files:
|
36
|
+
/.yardoc/
|
37
|
+
/_yardoc/
|
38
|
+
/doc/
|
39
|
+
/rdoc/
|
40
|
+
|
41
|
+
## Environment normalization:
|
42
|
+
/.bundle/
|
43
|
+
/vendor/bundle
|
44
|
+
/lib/bundler/man/
|
45
|
+
|
46
|
+
# for a library or gem, you might want to ignore these files since the code is
|
47
|
+
# intended to run in multiple environments; otherwise, check them in:
|
48
|
+
# Gemfile.lock
|
49
|
+
# .ruby-version
|
50
|
+
# .ruby-gemset
|
51
|
+
|
52
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
53
|
+
.rvmrc
|
54
|
+
|
55
|
+
# Used by RuboCop. Remote config files pulled in from inherit_from directive.
|
56
|
+
# .rubocop-https?--*
|
57
|
+
simple_capture.code-workspace
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.0.0
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2021 Akira kure
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "simple_capture"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require "irb"
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require_relative "simple_capture/version"
|
2
|
+
require_relative "simple_capture/capture"
|
3
|
+
require_relative "simple_capture/packet"
|
4
|
+
require_relative "simple_capture/string"
|
5
|
+
require_relative "simple_capture/recv_message"
|
6
|
+
require_relative "simple_capture/header/ehter_header"
|
7
|
+
require_relative "simple_capture/header/ipv4_header"
|
8
|
+
require_relative "simple_capture/header/icmp_header"
|
9
|
+
|
10
|
+
module SimpleCapture
|
11
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require "socket"
|
2
|
+
|
3
|
+
module SimpleCapture
|
4
|
+
class Capture
|
5
|
+
SOL_PACKET = 0x0107 # bits/socket.h
|
6
|
+
IFINDEX_SIZE = 0x0004 # sizeof(ifreq.ifr_ifindex) on 64bit
|
7
|
+
IFREQ_SIZE = 0x0028 # sizeof(ifreq) on 64bit
|
8
|
+
SIOCGIFINDEX = 0x8933 # bits/ioctls.h
|
9
|
+
PACKET_MR_PROMISC = 0x0001 # netpacket/packet.h
|
10
|
+
PACKET_MREQ_SIZE = 0x0010 # sizeof(packet_mreq) on 64bit
|
11
|
+
PACKET_ADD_MEMBERSHIP = 0x0001 # netpacket/packet.h
|
12
|
+
ETH_P_ALL = 768 # htons(ETH_P_ALL), linux/if_ether.h
|
13
|
+
|
14
|
+
# @param [String] interface_name
|
15
|
+
def initialize(interface_name)
|
16
|
+
@interface_name = interface_name
|
17
|
+
end
|
18
|
+
|
19
|
+
# Run Capture
|
20
|
+
def run
|
21
|
+
socket = generate_socket(@interface_name)
|
22
|
+
cap_loop(socket)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def cap_loop(socket)
|
28
|
+
while true
|
29
|
+
mesg, _ = socket.recvfrom(1500)
|
30
|
+
packet = RecvMessageHandler.new(mesg).to_packet
|
31
|
+
packet.dump
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def bind_if(socket, interface_name)
|
36
|
+
index_str = mr_ifindex(interface_name)
|
37
|
+
|
38
|
+
eth_p_all_hbo = [ ETH_P_ALL ].pack('S').unpack('S>').first
|
39
|
+
sll = [ Socket::AF_PACKET, eth_p_all_hbo, index_str ].pack('SS>a16')
|
40
|
+
socket.bind(sll)
|
41
|
+
end
|
42
|
+
|
43
|
+
# @return [Integer]
|
44
|
+
def if_name_to_index(if_name)
|
45
|
+
Socket.getifaddrs.find do |ifaddr|
|
46
|
+
ifaddr.name == if_name
|
47
|
+
end&.ifindex
|
48
|
+
end
|
49
|
+
|
50
|
+
def generate_socket(interface_name)
|
51
|
+
socket = Socket.new(Socket::AF_PACKET, Socket::SOCK_RAW, ETH_P_ALL)
|
52
|
+
bind_if(socket, interface_name)
|
53
|
+
socket_promiscuous(socket, interface_name)
|
54
|
+
socket
|
55
|
+
end
|
56
|
+
|
57
|
+
def mr_ifindex(if_name)
|
58
|
+
[[if_name_to_index(if_name)].pack("c")].pack("a4")
|
59
|
+
end
|
60
|
+
|
61
|
+
def mr_type
|
62
|
+
[PACKET_MR_PROMISC].pack("S")
|
63
|
+
end
|
64
|
+
|
65
|
+
def mr_alen
|
66
|
+
[0].pack("S")
|
67
|
+
end
|
68
|
+
|
69
|
+
def mr_address
|
70
|
+
[0].pack("C")*8
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# https://linuxjm.osdn.jp/html/LDP_man-pages/man7/packet.7.html
|
75
|
+
# struct packet_mreq {
|
76
|
+
# int mr_ifindex; 4Byte
|
77
|
+
# unsigned short mr_type; 2Byte
|
78
|
+
# unsigned short mr_alen; 2Byte
|
79
|
+
# unsigned char mr_address[8]; 1Byte * 8
|
80
|
+
#};
|
81
|
+
#
|
82
|
+
# @param [String]
|
83
|
+
# @return [String]
|
84
|
+
def mreq(interface)
|
85
|
+
mr_ifindex(interface) + mr_type + mr_alen + mr_address
|
86
|
+
end
|
87
|
+
|
88
|
+
def socket_promiscuous(socket, interface_name)
|
89
|
+
socket.setsockopt(SOL_PACKET, PACKET_ADD_MEMBERSHIP, mreq(interface_name))
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module SimpleCapture
|
2
|
+
class EtherHeader
|
3
|
+
IPv4 = 0x0800
|
4
|
+
|
5
|
+
attr_reader :dst_mac_address, :src_mac_address, :type
|
6
|
+
|
7
|
+
# @param [Array<Integer>] [10, 46, ...]
|
8
|
+
def initialize(bytes: nil)
|
9
|
+
# support 14Byte EhterHeader only now.
|
10
|
+
raise ArgumentError, "bytes's size must be 10Byte" unless bytes.size == 14
|
11
|
+
|
12
|
+
convert_bytes_to_headers(bytes) unless bytes.nil?
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [Boolean]
|
16
|
+
def upper_layer_protocol_ipv4?
|
17
|
+
type_hex = type.map { |byte| byte.to_s(16).rjust(2, "0") }
|
18
|
+
type_hex.join.to_i(16) == IPv4
|
19
|
+
end
|
20
|
+
|
21
|
+
# Print Header Info
|
22
|
+
def dump
|
23
|
+
puts "■ether header------------------------------".red
|
24
|
+
print_dst_mac_address
|
25
|
+
print_src_mac_address
|
26
|
+
print_type
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def convert_bytes_to_headers(bytes)
|
32
|
+
@dst_mac_address = bytes[0..5]
|
33
|
+
@src_mac_address = bytes[6..11]
|
34
|
+
@type = bytes[12..13]
|
35
|
+
end
|
36
|
+
|
37
|
+
def print_dst_mac_address
|
38
|
+
hex_dst_mac_address = dst_mac_address.map { |byte| byte.to_s(16) }
|
39
|
+
|
40
|
+
puts "dst_mac_address = #{hex_dst_mac_address[0]}:\
|
41
|
+
#{hex_dst_mac_address[1]}:\
|
42
|
+
#{hex_dst_mac_address[2]}:\
|
43
|
+
#{hex_dst_mac_address[3]}:\
|
44
|
+
#{hex_dst_mac_address[4]}:\
|
45
|
+
#{hex_dst_mac_address[5]}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def print_src_mac_address
|
49
|
+
hex_src_mac_address = src_mac_address.map { |byte| byte.to_s(16) }
|
50
|
+
|
51
|
+
puts "src_mac_address = #{hex_src_mac_address[0]}:\
|
52
|
+
#{hex_src_mac_address[1]}:\
|
53
|
+
#{hex_src_mac_address[2]}:\
|
54
|
+
#{hex_src_mac_address[3]}:\
|
55
|
+
#{hex_src_mac_address[4]}:\
|
56
|
+
#{hex_src_mac_address[5]}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def print_type
|
60
|
+
type_hex = type.map { |byte| byte.to_s(16).rjust(2, "0") }
|
61
|
+
type_hex_int = type_hex.join.to_i(16) # ["08", "00"]
|
62
|
+
protocol_display = if type_hex_int == IPv4
|
63
|
+
"IPv4"
|
64
|
+
else
|
65
|
+
"[UnKnown Protocol]"
|
66
|
+
end
|
67
|
+
puts "protocol = #{protocol_display}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module SimpleCapture
|
2
|
+
class ICMPHeader
|
3
|
+
attr_reader :type, :code, :checksum, :id, :seq_number, :data
|
4
|
+
|
5
|
+
# @param [Array<Integer>] [10, 46, ...]
|
6
|
+
def initialize(bytes: nil)
|
7
|
+
convert_bytes_to_header(bytes) unless bytes.nil?
|
8
|
+
end
|
9
|
+
|
10
|
+
def dump
|
11
|
+
puts "■icmp--------------------------------------".blue
|
12
|
+
print_checksum
|
13
|
+
print_code
|
14
|
+
print_type
|
15
|
+
print_id
|
16
|
+
print_seqnumber
|
17
|
+
print_data
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def print_checksum
|
23
|
+
puts "checksum = 0x#{combine_2bits_in_hex(checksum).to_s(16)}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def print_code
|
27
|
+
puts "code = #{code}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def print_data
|
31
|
+
puts "data = "
|
32
|
+
data.each_slice(10) do |data10|
|
33
|
+
data10.each { |data_| print "0x#{data_.to_s(16)} " }
|
34
|
+
puts "\n"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def print_id
|
39
|
+
if id
|
40
|
+
puts "id = 0x#{combine_2bits_in_hex(id).to_s(16)}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def print_seqnumber
|
45
|
+
if seq_number
|
46
|
+
puts "seq_number = 0x#{combine_2bits_in_hex(seq_number).to_s(16)}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def print_type
|
51
|
+
puts "type = #{type}"
|
52
|
+
end
|
53
|
+
|
54
|
+
# Combine 2 bits of numbers in hexadecimal
|
55
|
+
#
|
56
|
+
# @param [Array<Integer>] [0d80, 0d30]
|
57
|
+
# @return [Integer] 0x501e... 0d80 -> 0x50, 0d30 -> 0x1e
|
58
|
+
def combine_2bits_in_hex(bytes)
|
59
|
+
(bytes[0].to_s(16) + bytes[1].to_s(16)).to_i(16)
|
60
|
+
end
|
61
|
+
|
62
|
+
def convert_bytes_to_header(bytes)
|
63
|
+
@type = bytes[0]
|
64
|
+
@code = bytes[1]
|
65
|
+
@checksum = bytes[2..3]
|
66
|
+
|
67
|
+
if @type == 0 || 8
|
68
|
+
@id = bytes[4..5]
|
69
|
+
@seq_number = bytes[6..7]
|
70
|
+
@data = bytes[8..(bytes.size-1)]
|
71
|
+
else
|
72
|
+
@data = bytes[4..(bytes.size-1)]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
module SimpleCapture
|
2
|
+
class IPv4Header
|
3
|
+
ICMP = 1
|
4
|
+
|
5
|
+
attr_reader :version, :ihl, :type_of_service, :length, :id, :flags, :offset, :ttl,
|
6
|
+
:checksum, :src_addr, :dst_addr, :protocol
|
7
|
+
|
8
|
+
# @param [Array<Integer>] 各バイトの数値の配列、[10, 46, ...]
|
9
|
+
def initialize(bytes: nil)
|
10
|
+
# support 20Byte IPHeader only now.
|
11
|
+
raise ArgumentError, "bytes's size must be 20Byte" unless bytes.size == 20
|
12
|
+
|
13
|
+
convert_bytes_to_header(bytes) unless bytes.nil?
|
14
|
+
end
|
15
|
+
|
16
|
+
def dump
|
17
|
+
puts "■ipv4--------------------------------------".yellow
|
18
|
+
print_version
|
19
|
+
print_ihl
|
20
|
+
print_type_of_service
|
21
|
+
print_length
|
22
|
+
print_id
|
23
|
+
print_flags
|
24
|
+
print_offset
|
25
|
+
print_ttl
|
26
|
+
print_protocol
|
27
|
+
print_checksum
|
28
|
+
print_src_addr
|
29
|
+
print_dst_addr
|
30
|
+
end
|
31
|
+
|
32
|
+
def upper_layer_protocol_icmp?
|
33
|
+
protocol == ICMP
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# Combine 2 bits of numbers in hexadecimal
|
39
|
+
#
|
40
|
+
# @param [Array<Integer>] [0d80, 0d30]
|
41
|
+
# @return [Integer] 0x501e... 0d80 -> 0x50, 0d30 -> 0x1e
|
42
|
+
def combine_2bits_in_hex(bytes)
|
43
|
+
bytes_hex = bytes.map { |byte| byte.to_s(16).rjust(2, "0") }
|
44
|
+
bytes_hex.join.to_i(16)
|
45
|
+
|
46
|
+
# (bytes[0].to_s(16) + bytes[1].to_s(16)).to_i(16)
|
47
|
+
end
|
48
|
+
|
49
|
+
def convert_bytes_to_header(bytes)
|
50
|
+
@version = bytes[0][4, 4]
|
51
|
+
@ihl = bytes[0][0, 4]
|
52
|
+
@type_of_service = bytes[1]
|
53
|
+
@length = bytes[2..3]
|
54
|
+
@id = bytes[4..5]
|
55
|
+
bytes67 = combine_2bits_in_hex(bytes[6..7])
|
56
|
+
@flags = bytes67[0, 3]
|
57
|
+
@offset = bytes67[3, 13]
|
58
|
+
@ttl = bytes[8]
|
59
|
+
@protocol = bytes[9]
|
60
|
+
@checksum = bytes[10..11]
|
61
|
+
@src_addr = bytes[12..15]
|
62
|
+
@dst_addr = bytes[16..19]
|
63
|
+
end
|
64
|
+
|
65
|
+
def print_checksum
|
66
|
+
puts "checksum = 0x#{combine_2bits_in_hex(checksum).to_s(16)}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def print_dst_addr
|
70
|
+
puts "dst_addr = #{dst_addr}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def print_flags
|
74
|
+
puts "flags = #{flags}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def print_id
|
78
|
+
puts "id = 0x#{combine_2bits_in_hex(id).to_s(16)}\n"
|
79
|
+
end
|
80
|
+
|
81
|
+
def print_ihl
|
82
|
+
puts "ihl = #{ihl}"
|
83
|
+
end
|
84
|
+
|
85
|
+
def print_length
|
86
|
+
puts "length = 0x#{combine_2bits_in_hex(length).to_s(16)}"
|
87
|
+
end
|
88
|
+
|
89
|
+
def print_offset
|
90
|
+
puts "offset = #{offset}"
|
91
|
+
end
|
92
|
+
|
93
|
+
def print_protocol
|
94
|
+
if protocol == ICMP
|
95
|
+
puts "protocol = ICMP"
|
96
|
+
else
|
97
|
+
puts "protocol = [UnKnown Protocol]"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def print_src_addr
|
102
|
+
puts "src_addr = #{src_addr}"
|
103
|
+
end
|
104
|
+
|
105
|
+
def print_type_of_service
|
106
|
+
puts "type_of_service = #{type_of_service}"
|
107
|
+
end
|
108
|
+
|
109
|
+
def print_ttl
|
110
|
+
puts "ttl = #{ttl}"
|
111
|
+
end
|
112
|
+
|
113
|
+
def print_version
|
114
|
+
puts "version = #{version}"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module SimpleCapture
|
2
|
+
class Packet
|
3
|
+
|
4
|
+
# @param [Array] headers
|
5
|
+
def initialize(headers)
|
6
|
+
@headers = headers
|
7
|
+
end
|
8
|
+
|
9
|
+
def dump
|
10
|
+
puts "\n■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■".green
|
11
|
+
puts "Display Packet".green
|
12
|
+
puts "■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■".green
|
13
|
+
@headers.each do |header|
|
14
|
+
header.dump
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module SimpleCapture
|
2
|
+
class RecvMessageHandler
|
3
|
+
def initialize(mesg)
|
4
|
+
@mesg = mesg
|
5
|
+
end
|
6
|
+
|
7
|
+
# @return [Packet]
|
8
|
+
def to_packet
|
9
|
+
headers = []
|
10
|
+
ether = SimpleCapture::EtherHeader.new(bytes: @mesg.bytes[0..13])
|
11
|
+
headers.push(ether)
|
12
|
+
|
13
|
+
if ether.upper_layer_protocol_ipv4?
|
14
|
+
ip = SimpleCapture::IPv4Header.new(bytes: @mesg.bytes[14..33])
|
15
|
+
headers.push(ip)
|
16
|
+
if ip.upper_layer_protocol_icmp?
|
17
|
+
icmp = SimpleCapture::ICMPHeader.new(bytes: @mesg.bytes[34..(@mesg.bytes.size-1)])
|
18
|
+
headers.push(icmp)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
SimpleCapture::Packet.new(headers)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class String
|
2
|
+
def colorize(color_code)
|
3
|
+
"\e[#{color_code}m#{self}\e[0m"
|
4
|
+
end
|
5
|
+
|
6
|
+
def red
|
7
|
+
colorize(31)
|
8
|
+
end
|
9
|
+
|
10
|
+
def green
|
11
|
+
colorize(32)
|
12
|
+
end
|
13
|
+
|
14
|
+
def yellow
|
15
|
+
colorize(33)
|
16
|
+
end
|
17
|
+
|
18
|
+
def blue
|
19
|
+
colorize(34)
|
20
|
+
end
|
21
|
+
|
22
|
+
def pink
|
23
|
+
colorize(35)
|
24
|
+
end
|
25
|
+
end
|
data/sample_run.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/simple_capture/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "simple_capture"
|
7
|
+
spec.version = SimpleCapture::VERSION
|
8
|
+
spec.authors = ["Akira Kure"]
|
9
|
+
spec.email = ["kuredev@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = "Packet capture tool made only with Ruby."
|
12
|
+
spec.description = "Packet capture tool made only with Ruby."
|
13
|
+
spec.homepage = "https://github.com/kuredev/simple_capture"
|
14
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
15
|
+
|
16
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
17
|
+
|
18
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
19
|
+
spec.metadata["source_code_uri"] = "https://github.com/kuredev/simple_capture"
|
20
|
+
spec.metadata["changelog_uri"] = "https://github.com/kuredev/simple_capture"
|
21
|
+
|
22
|
+
# Specify which files should be added to the gem when it is released.
|
23
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
24
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
25
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
26
|
+
end
|
27
|
+
spec.bindir = "exe"
|
28
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
29
|
+
spec.require_paths = ["lib"]
|
30
|
+
|
31
|
+
# Uncomment to register a new dependency of your gem
|
32
|
+
# spec.add_dependency "example-gem", "~> 1.0"
|
33
|
+
|
34
|
+
# For more information and examples about making a new gem, checkout our
|
35
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple_capture
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Akira Kure
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-02-22 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Packet capture tool made only with Ruby.
|
14
|
+
email:
|
15
|
+
- kuredev@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- ".gitignore"
|
21
|
+
- ".ruby-version"
|
22
|
+
- LICENSE
|
23
|
+
- README.md
|
24
|
+
- Rakefile
|
25
|
+
- bin/console
|
26
|
+
- bin/setup
|
27
|
+
- lib/simple_capture.rb
|
28
|
+
- lib/simple_capture/capture.rb
|
29
|
+
- lib/simple_capture/header/ehter_header.rb
|
30
|
+
- lib/simple_capture/header/icmp_header.rb
|
31
|
+
- lib/simple_capture/header/ipv4_header.rb
|
32
|
+
- lib/simple_capture/packet.rb
|
33
|
+
- lib/simple_capture/recv_message.rb
|
34
|
+
- lib/simple_capture/string.rb
|
35
|
+
- lib/simple_capture/version.rb
|
36
|
+
- sample_run.rb
|
37
|
+
- simple_capture.gemspec
|
38
|
+
homepage: https://github.com/kuredev/simple_capture
|
39
|
+
licenses: []
|
40
|
+
metadata:
|
41
|
+
allowed_push_host: https://rubygems.org
|
42
|
+
homepage_uri: https://github.com/kuredev/simple_capture
|
43
|
+
source_code_uri: https://github.com/kuredev/simple_capture
|
44
|
+
changelog_uri: https://github.com/kuredev/simple_capture
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options: []
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 2.3.0
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
requirements: []
|
60
|
+
rubygems_version: 3.2.3
|
61
|
+
signing_key:
|
62
|
+
specification_version: 4
|
63
|
+
summary: Packet capture tool made only with Ruby.
|
64
|
+
test_files: []
|