packetgen-plugin-smb 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +0 -1
- data/Gemfile +0 -3
- data/README.md +18 -1
- data/lib/packetgen-plugin-smb.rb +1 -0
- data/lib/packetgen/plugin/gssapi.rb +3 -2
- data/lib/packetgen/plugin/netbios.rb +17 -0
- data/lib/packetgen/plugin/netbios/datagram.rb +108 -0
- data/lib/packetgen/plugin/netbios/name.rb +64 -0
- data/lib/packetgen/plugin/netbios/session.rb +71 -0
- data/lib/packetgen/plugin/smb.rb +2 -2
- data/lib/packetgen/plugin/smb/browser.rb +6 -6
- data/lib/packetgen/plugin/smb/browser/domain_announcement.rb +0 -5
- data/lib/packetgen/plugin/smb/browser/host_announcement.rb +8 -5
- data/lib/packetgen/plugin/smb/browser/local_master_announcement.rb +0 -5
- data/lib/packetgen/plugin/smb/close/request.rb +1 -1
- data/lib/packetgen/plugin/smb/close/response.rb +1 -1
- data/lib/packetgen/plugin/smb/filetime.rb +20 -1
- data/lib/packetgen/plugin/smb/ntcreateandx/request.rb +1 -1
- data/lib/packetgen/plugin/smb/ntcreateandx/response.rb +1 -1
- data/lib/packetgen/plugin/smb/trans/request.rb +1 -1
- data/lib/packetgen/plugin/smb/trans/response.rb +1 -1
- data/lib/packetgen/plugin/smb2.rb +7 -5
- data/lib/packetgen/plugin/smb2/negotiate/context.rb +12 -24
- data/lib/packetgen/plugin/smb2/negotiate/request.rb +6 -6
- data/lib/packetgen/plugin/smb2/negotiate/response.rb +7 -6
- data/lib/packetgen/plugin/smb2/session_setup/request.rb +1 -1
- data/lib/packetgen/plugin/smb2/session_setup/response.rb +1 -1
- data/lib/packetgen/plugin/smb_version.rb +1 -1
- data/packetgen-plugin-smb.gemspec +1 -1
- metadata +8 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3f0164d4068b3b829fac802f5ce944c33bf86275fb90aa46150e57926a236f3
|
4
|
+
data.tar.gz: 001d57bf0ec000e0e738b25d1116ea0b73bc7a2c0de61b68e6c16ef75a130d4b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 661c09099b29c3c747e5b4d1831b05fb3945123e1d5ff7aaabc053221c100ed1113fd04a72af5fdbc245a9d0789419f6b6fc1c8a37a558c64da53ef1b30c4e8e
|
7
|
+
data.tar.gz: 06b857556ca716b954a4fb935ec3e6e91ab2a0416442b31e3ad7e9eec7631fe33d6c3bb96814fd949fbffd2d58c97fc80fbbd18dd4b66cd5a603663f58169bb9
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -3,7 +3,20 @@
|
|
3
3
|
|
4
4
|
# Packetgen::Plugin::SMB
|
5
5
|
|
6
|
-
This is a plugin for [PacketGen gem](https://github.com/sdaubert/packetgen). It adds some support for SMB protocol suite
|
6
|
+
This is a plugin for [PacketGen gem](https://github.com/sdaubert/packetgen). It adds some support for SMB protocol suite:
|
7
|
+
|
8
|
+
* SMB:
|
9
|
+
* SMB common header,
|
10
|
+
* Close command,
|
11
|
+
* NtCreateAndX command,
|
12
|
+
* Trans command,
|
13
|
+
* Browser subprotocol,
|
14
|
+
* SMB2:
|
15
|
+
* SMB2 common header (support 2.x and 3.x dialects),
|
16
|
+
* Negotiate command,
|
17
|
+
* SessionSetup command,
|
18
|
+
* GSSAPI, used to transport negotiation over SMB2 commands.
|
19
|
+
|
7
20
|
|
8
21
|
## Installation
|
9
22
|
|
@@ -25,6 +38,10 @@ Or install it yourself as:
|
|
25
38
|
|
26
39
|
TODO
|
27
40
|
|
41
|
+
## See also
|
42
|
+
|
43
|
+
API documentation: http://www.rubydoc.info/gems/packetgen-plugin-smb
|
44
|
+
|
28
45
|
## License
|
29
46
|
|
30
47
|
MIT License (see [LICENSE](https://github.com/sdaubert/packetgen-plugin-smb/blob/master/LICENSE))
|
data/lib/packetgen-plugin-smb.rb
CHANGED
@@ -86,7 +86,7 @@ module PacketGen::Plugin
|
|
86
86
|
'accept-incomplete' => 1,
|
87
87
|
'reject' => 2,
|
88
88
|
'request-mic' => 3
|
89
|
-
}
|
89
|
+
}.freeze
|
90
90
|
sequence :token, explicit: 1, class: :context, constructed: true,
|
91
91
|
content: [enumerated(:negstate, enum: NEG_STATES, explicit: 0, class: :context, constructed: true, optional: true),
|
92
92
|
objectid(:supported_mech, explicit: 1, class: :context, constructed: true, optional: true),
|
@@ -106,8 +106,9 @@ module PacketGen::Plugin
|
|
106
106
|
def initialize(args={})
|
107
107
|
token = args.delete(:token)
|
108
108
|
super
|
109
|
-
self[:gssapi].chosen =
|
109
|
+
self[:gssapi].chosen = token == :init ? 0 : 1
|
110
110
|
end
|
111
|
+
|
111
112
|
# Populate Object from +str+
|
112
113
|
# @param [String] str
|
113
114
|
# @return [self]
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# This file is part of PacketGen
|
2
|
+
# See https://github.com/sdaubert/packetgen-plugin-smb for more informations
|
3
|
+
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
5
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PacketGen::Plugin
|
9
|
+
# Module to group all NetBIOS headers
|
10
|
+
# @author Sylvain Daubert
|
11
|
+
module NetBIOS
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
require_relative 'netbios/name'
|
16
|
+
require_relative 'netbios/session'
|
17
|
+
require_relative 'netbios/datagram'
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# This file is part of PacketGen
|
2
|
+
# See https://github.com/sdaubert/packetgen-plugin-smb for more informations
|
3
|
+
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
5
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PacketGen::Plugin
|
9
|
+
# Module to group all NetBIOS headers
|
10
|
+
# @author Sylvain Daubert
|
11
|
+
module NetBIOS
|
12
|
+
# NetBIOS Session Service messages.
|
13
|
+
# @author Sylvain Daubert
|
14
|
+
class Datagram < PacketGen::Header::Base
|
15
|
+
# Give protocol name
|
16
|
+
# @return [String]
|
17
|
+
def self.protocol_name
|
18
|
+
'NetBIOS::Datagram'
|
19
|
+
end
|
20
|
+
|
21
|
+
# Port number for NetBIOS Session Service over TCP
|
22
|
+
UDP_PORT = 138
|
23
|
+
|
24
|
+
# Datagram packet types
|
25
|
+
TYPES = {
|
26
|
+
'direct_unique' => 0x10,
|
27
|
+
'direct_group' => 0x11,
|
28
|
+
'broadcast' => 0x12,
|
29
|
+
'error' => 0x13,
|
30
|
+
'query_request' => 0x14,
|
31
|
+
'positive_query_resp' => 0x15,
|
32
|
+
'negative_query_resp' => 0x16,
|
33
|
+
}.freeze
|
34
|
+
|
35
|
+
# @!attribute type
|
36
|
+
# 8-bit session packet type
|
37
|
+
# @return [Integer]
|
38
|
+
define_field :type, PacketGen::Types::Int8Enum, enum: TYPES
|
39
|
+
# @!attribute flags
|
40
|
+
# 8-bit flags
|
41
|
+
# @return [Integer]
|
42
|
+
define_field :flags, PacketGen::Types::Int8
|
43
|
+
# @!attribute dgm_id
|
44
|
+
# 16-bit next transaction ID for datagrams
|
45
|
+
# @return [Integer]
|
46
|
+
define_field :dgm_id, PacketGen::Types::Int16
|
47
|
+
# @!attribute src_ip
|
48
|
+
# Source IP address
|
49
|
+
# @return [IP::Addr]
|
50
|
+
define_field :src_ip, PacketGen::Header::IP::Addr
|
51
|
+
# @!attribute src_port
|
52
|
+
# Source port
|
53
|
+
# @return [IP::Addr]
|
54
|
+
define_field :src_port, PacketGen::Types::Int16
|
55
|
+
# @!attribute dgm_length
|
56
|
+
# Length of data + second level of encoded names. Not present in error datagram.
|
57
|
+
# @return [Integer]
|
58
|
+
define_field :dgm_length, PacketGen::Types::Int16, optional: ->(h) { h.type != 0x13 }
|
59
|
+
# @!attribute packet_offset
|
60
|
+
# Not present in error datagram.
|
61
|
+
# @return [Integer]
|
62
|
+
define_field :packet_offset, PacketGen::Types::Int16, optional: ->(h) { h.type != 0x13 }
|
63
|
+
# @!attribute error_code
|
64
|
+
# Error code. Only present in error datagrams.
|
65
|
+
# @return [Integer]
|
66
|
+
define_field :error_code, PacketGen::Types::Int16, optional: ->(h) { h.type == 0x13 }
|
67
|
+
# @!attribute src_name
|
68
|
+
# NetBIOS source name. Only present in direct_unique, direct_group and broadcast datagrams.
|
69
|
+
# @return []
|
70
|
+
define_field :src_name, Name, default: '', optional: ->(h) { (h.type >= 0x10) && (h.type <= 0x12) }
|
71
|
+
# @!attribute dst_name
|
72
|
+
# NetBIOS destination name. Present in all but error datagrams.
|
73
|
+
# @return []
|
74
|
+
define_field :dst_name, Name, default: '', optional: ->(h) { h.type != 0x13 }
|
75
|
+
# @!attribute body
|
76
|
+
# User data. Ony present in direct_unique, direct_group and broadcast datagrams.
|
77
|
+
# @return [String]
|
78
|
+
define_field :body, PacketGen::Types::String, optional: ->(h) { (h.type >= 0x10) && (h.type <= 0x12) }
|
79
|
+
|
80
|
+
# @!attribute :rsv
|
81
|
+
# 4-bit rsv field. 4 upper bits of {#flags}
|
82
|
+
# @return [Integer]
|
83
|
+
# @!attribute :snt
|
84
|
+
# 2-bit SNT (Source end-Node Type) field from {#flags}.
|
85
|
+
# @return [Integer]
|
86
|
+
# @!attribute f
|
87
|
+
# First packet flag. If set then this is first
|
88
|
+
# (and possibly only) fragment of NetBIOS datagram.
|
89
|
+
# @return [Boolean]
|
90
|
+
# @!attribute m
|
91
|
+
# More flag. If set then more NetBIOS datagram
|
92
|
+
# fragments follow.
|
93
|
+
# @return [Boolean]
|
94
|
+
define_bit_fields_on :flags, :rsv, 4, :snt, 2, :f, :m
|
95
|
+
|
96
|
+
# Compute and set {#dgm_length} field
|
97
|
+
# @return [Integer] calculated length
|
98
|
+
def calc_length
|
99
|
+
length = self[:body].sz
|
100
|
+
length += self[:src_name].sz if present?(:src_name)
|
101
|
+
length += self[:dst_name].sz if present?(:dst_name)
|
102
|
+
self.dgm_length = length
|
103
|
+
end
|
104
|
+
end
|
105
|
+
PacketGen::Header.add_class Datagram
|
106
|
+
PacketGen::Header::UDP.bind Datagram, dport: Datagram::UDP_PORT, sport: Datagram::UDP_PORT
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# This file is part of PacketGen
|
2
|
+
# See https://github.com/sdaubert/packetgen-plugin-smb for more informations
|
3
|
+
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
5
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PacketGen::Plugin
|
9
|
+
# Module to group all NetBIOS headers
|
10
|
+
# @author Sylvain Daubert
|
11
|
+
module NetBIOS
|
12
|
+
# NetBIOS Name.
|
13
|
+
# @author Sylvain Daubert
|
14
|
+
class Name < PacketGen::Header::DNS::Name
|
15
|
+
# Size, in bytes, of an encoded NetBIOS name
|
16
|
+
ENCODED_NAME_SIZE = 32
|
17
|
+
|
18
|
+
# Read a NetBIOS name from a string
|
19
|
+
# @param [String] str
|
20
|
+
# @return [Name] self
|
21
|
+
def from_human(str)
|
22
|
+
clear
|
23
|
+
return self if str.nil?
|
24
|
+
|
25
|
+
encoded_name = encode_name(str)
|
26
|
+
super(encoded_name)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Get a human readable string
|
30
|
+
# @return [String]
|
31
|
+
def to_human
|
32
|
+
encoded_name = super
|
33
|
+
decode_name(encoded_name)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def encode_name(name)
|
39
|
+
basename, *scope_id = name.split('.')
|
40
|
+
basename = '' if basename.nil?
|
41
|
+
scope_id = scope_id.join('.')
|
42
|
+
encoded_name = +''
|
43
|
+
basename.each_byte do |byte|
|
44
|
+
a = (byte >> 4) + 0x41
|
45
|
+
b = (byte & 0xf) + 0x41
|
46
|
+
encoded_name << [a, b].pack('C2')
|
47
|
+
end
|
48
|
+
encoded_name << 'CA' * ((ENCODED_NAME_SIZE - encoded_name.size) / 2) if encoded_name.size < ENCODED_NAME_SIZE
|
49
|
+
encoded_name << ".#{scope_id}" if scope_id
|
50
|
+
encoded_name
|
51
|
+
end
|
52
|
+
|
53
|
+
def decode_name(encoded_name)
|
54
|
+
name = +''
|
55
|
+
encoded_name.partition('.').first.scan(/../).map do |duo|
|
56
|
+
a = (duo[0].ord - 0x41) & 0xf
|
57
|
+
b = (duo[1].ord - 0x41) & 0xf
|
58
|
+
name << (a << 4 | b).chr
|
59
|
+
end
|
60
|
+
name.strip
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# This file is part of PacketGen
|
2
|
+
# See https://github.com/sdaubert/packetgen-plugin-smb for more informations
|
3
|
+
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
5
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PacketGen::Plugin
|
9
|
+
# Module to group all NetBIOS headers
|
10
|
+
# @author Sylvain Daubert
|
11
|
+
module NetBIOS
|
12
|
+
# NetBIOS Session Service messages.
|
13
|
+
# @author Sylvain Daubert
|
14
|
+
class Session < PacketGen::Header::Base
|
15
|
+
# Give protocol name
|
16
|
+
# @return [String]
|
17
|
+
def self.protocol_name
|
18
|
+
'NetBIOS::Session'
|
19
|
+
end
|
20
|
+
|
21
|
+
# Port number for NetBIOS Session Service over TCP
|
22
|
+
TCP_PORT = 139
|
23
|
+
# Port number for NetBIOS Session Service over TCP (mainly used yb {SMB2})
|
24
|
+
TCP_PORT2 = 445
|
25
|
+
|
26
|
+
# Session packet types
|
27
|
+
TYPES = {
|
28
|
+
'message' => 0,
|
29
|
+
'request' => 0x81,
|
30
|
+
'positive_response' => 0x82,
|
31
|
+
'negative_response' => 0x83,
|
32
|
+
'retarget_response' => 0x84,
|
33
|
+
'keep_alive' => 0x85,
|
34
|
+
}.freeze
|
35
|
+
|
36
|
+
# @!attribute type
|
37
|
+
# 8-bit session packet type
|
38
|
+
# @return [Integer]
|
39
|
+
define_field :type, PacketGen::Types::Int8Enum, enum: TYPES
|
40
|
+
# @!attribute length
|
41
|
+
# 17-bit session packet length
|
42
|
+
# @return [Integer]
|
43
|
+
define_field :length, PacketGen::Types::Int24
|
44
|
+
# @!attribute body
|
45
|
+
# @return [String]
|
46
|
+
define_field :body, PacketGen::Types::String
|
47
|
+
|
48
|
+
# Compute and set {#length} field
|
49
|
+
# @return [Integer] calculated length
|
50
|
+
def calc_length
|
51
|
+
PacketGen::Header::Base.calculate_and_set_length(self, header_in_size: false)
|
52
|
+
end
|
53
|
+
|
54
|
+
# @api private
|
55
|
+
# @note This method is used internally by PacketGen and should not be
|
56
|
+
# directly called
|
57
|
+
# @since 2.7.0 Set TCP sport according to bindings, only if sport is 0.
|
58
|
+
# Needed by new bind API.
|
59
|
+
def added_to_packet(packet)
|
60
|
+
return unless packet.is? 'TCP'
|
61
|
+
return unless packet.tcp.sport.zero?
|
62
|
+
packet.tcp.sport = TCP_PORT
|
63
|
+
end
|
64
|
+
end
|
65
|
+
PacketGen::Header.add_class Session
|
66
|
+
PacketGen::Header::TCP.bind Session, dport: Session::TCP_PORT
|
67
|
+
PacketGen::Header::TCP.bind Session, sport: Session::TCP_PORT
|
68
|
+
PacketGen::Header::TCP.bind Session, dport: Session::TCP_PORT2
|
69
|
+
PacketGen::Header::TCP.bind Session, sport: Session::TCP_PORT2
|
70
|
+
end
|
71
|
+
end
|
data/lib/packetgen/plugin/smb.rb
CHANGED
@@ -190,8 +190,8 @@ module PacketGen::Plugin
|
|
190
190
|
end
|
191
191
|
end
|
192
192
|
PacketGen::Header.add_class SMB
|
193
|
-
|
194
|
-
|
193
|
+
NetBIOS::Session.bind SMB, body: ->(val) { val.nil? ? SMB::MARKER : val[0..3] == SMB::MARKER }
|
194
|
+
NetBIOS::Datagram.bind SMB, body: ->(val) { val.nil? ? SMB::MARKER : val[0..3] == SMB::MARKER }
|
195
195
|
end
|
196
196
|
|
197
197
|
require_relative 'smb/string'
|
@@ -11,6 +11,12 @@ module PacketGen::Plugin
|
|
11
11
|
# See subclasses.
|
12
12
|
# @author Sylvain Daubert
|
13
13
|
class Browser < PacketGen::Header::Base
|
14
|
+
# Give protocol name for this class
|
15
|
+
# @return [String]
|
16
|
+
def self.protocol_name
|
17
|
+
'SMB::Browser'
|
18
|
+
end
|
19
|
+
|
14
20
|
OPCODES = {
|
15
21
|
'HostAnnouncement' => 1,
|
16
22
|
'HostAnnouncementReq' => 2,
|
@@ -57,12 +63,6 @@ module PacketGen::Plugin
|
|
57
63
|
end
|
58
64
|
end
|
59
65
|
|
60
|
-
# Give protocol name for this class
|
61
|
-
# @return [String]
|
62
|
-
def protocol_name
|
63
|
-
'SMB::Browser'
|
64
|
-
end
|
65
|
-
|
66
66
|
# Callback called when a Browser header is added to a packet.
|
67
67
|
# Here, add +#smb_browser+ method as a shortcut to existing
|
68
68
|
# +#smb_browser_*+ method.
|
@@ -20,11 +20,6 @@ module PacketGen::Plugin
|
|
20
20
|
alias browser_conf_ver_min os_ver_min
|
21
21
|
alias machine_group server_name
|
22
22
|
alias local_master_name comment
|
23
|
-
|
24
|
-
# @return [String]
|
25
|
-
def protocol_name
|
26
|
-
'SMB::Browser::DomainAnnouncement'
|
27
|
-
end
|
28
23
|
end
|
29
24
|
PacketGen::Header.add_class DomainAnnouncement
|
30
25
|
SMB::Trans::Request.bind DomainAnnouncement, name: '\\MAILSLOT\\BROWSE', body: ->(v) { v[0] == OPCODES['DomainAnnouncement'] }
|
@@ -14,6 +14,14 @@ module PacketGen::Plugin
|
|
14
14
|
# specify the types of resources and services it supports.
|
15
15
|
# @author Sylvain Daubert
|
16
16
|
class HostAnnouncement < Browser
|
17
|
+
# @return [String]
|
18
|
+
def self.protocol_name
|
19
|
+
return @protocol_name if @protocol_name
|
20
|
+
|
21
|
+
basename = to_s.sub(/^.*::/, '')
|
22
|
+
@protocol_name = "SMB::Browser::#{basename}"
|
23
|
+
end
|
24
|
+
|
17
25
|
remove_field :body
|
18
26
|
update_field :opcode, default: 1
|
19
27
|
# @!attribute update_count
|
@@ -58,11 +66,6 @@ module PacketGen::Plugin
|
|
58
66
|
# Null-terminated ASCII string.
|
59
67
|
# @return [String]
|
60
68
|
define_field :comment, PacketGen::Types::CString
|
61
|
-
|
62
|
-
# @return [String]
|
63
|
-
def protocol_name
|
64
|
-
'SMB::Browser::HostAnnouncement'
|
65
|
-
end
|
66
69
|
end
|
67
70
|
PacketGen::Header.add_class HostAnnouncement
|
68
71
|
SMB::Trans::Request.bind HostAnnouncement, name: '\\MAILSLOT\\BROWSE', body: ->(v) { v[0] == OPCODES['HostAnnouncement'] }
|
@@ -15,11 +15,6 @@ module PacketGen::Plugin
|
|
15
15
|
# @author Sylvain Daubert
|
16
16
|
class LocalMasterAnnouncement < HostAnnouncement
|
17
17
|
update_field :opcode, default: 15
|
18
|
-
|
19
|
-
# @return [String]
|
20
|
-
def protocol_name
|
21
|
-
'SMB::Browser::LocalMasterAnnouncement'
|
22
|
-
end
|
23
18
|
end
|
24
19
|
PacketGen::Header.add_class LocalMasterAnnouncement
|
25
20
|
SMB::Trans::Request.bind LocalMasterAnnouncement, name: '\\MAILSLOT\\BROWSE', body: ->(v) { v[0] == OPCODES['LocalMasterAnnouncement'] }
|
@@ -17,6 +17,11 @@ module PacketGen::Plugin
|
|
17
17
|
# Numbers of 100ns in one second
|
18
18
|
ONE_SEC = 10_000_000
|
19
19
|
|
20
|
+
# String to format time
|
21
|
+
FORMAT_TIME_STR = '%Y-%m-%d %H:%M:%S.%9N %Z'
|
22
|
+
# String to parse time
|
23
|
+
PARSE_TIME_STR = '%Y-%m-%d %H:%M:%S.%N %Z'
|
24
|
+
|
20
25
|
# @param [Hash] options
|
21
26
|
# @option options [Integer] :filetime
|
22
27
|
# @option options [Time] :time
|
@@ -49,10 +54,24 @@ module PacketGen::Plugin
|
|
49
54
|
if no_time?
|
50
55
|
'no time'
|
51
56
|
else
|
52
|
-
@time.strftime(
|
57
|
+
@time.strftime(FORMAT_TIME_STR)
|
53
58
|
end
|
54
59
|
end
|
55
60
|
|
61
|
+
# @return [self]
|
62
|
+
def from_human(str)
|
63
|
+
return self if str.nil?
|
64
|
+
|
65
|
+
@time = if str == 'no time'
|
66
|
+
Time.at(NO_TIME)
|
67
|
+
else
|
68
|
+
DateTime.strptime(str, PARSE_TIME_STR).to_time
|
69
|
+
end
|
70
|
+
@int.value = time2filetime
|
71
|
+
|
72
|
+
self
|
73
|
+
end
|
74
|
+
|
56
75
|
# Get filetime integer value
|
57
76
|
# @return [Integer]
|
58
77
|
def to_i
|
@@ -148,6 +148,12 @@ module PacketGen::Plugin
|
|
148
148
|
self.bind kresponse, command: SMB2::COMMANDS[command], flags: ->(v) { v.nil? ? 0 : (v & 1 == 1) }
|
149
149
|
end
|
150
150
|
|
151
|
+
# Invert {#flags_response?}
|
152
|
+
# @return [self]
|
153
|
+
def reply!
|
154
|
+
self.flags_response = !flags_response?
|
155
|
+
end
|
156
|
+
|
151
157
|
# @return [String]
|
152
158
|
def inspect
|
153
159
|
super do |attr|
|
@@ -166,13 +172,9 @@ module PacketGen::Plugin
|
|
166
172
|
end
|
167
173
|
end
|
168
174
|
end
|
169
|
-
# TODO: move this in netbios file when packetgen3 will be out
|
170
|
-
PacketGen::Header::TCP.bind PacketGen::Header::NetBIOS::Session, dport: 445
|
171
|
-
PacketGen::Header::TCP.bind PacketGen::Header::NetBIOS::Session, sport: 445
|
172
175
|
|
173
176
|
PacketGen::Header.add_class SMB2
|
174
|
-
|
175
|
-
PacketGen::Header::NetBIOS::Datagram.bind SMB2, body: ->(val) { val.nil? ? SMB2::MARKER : val[0..3] == SMB2::MARKER }
|
177
|
+
NetBIOS::Session.bind SMB2, body: ->(val) { val.nil? ? SMB2::MARKER : val[0..3] == SMB2::MARKER }
|
176
178
|
end
|
177
179
|
|
178
180
|
require_relative 'smb2/base'
|
@@ -47,31 +47,11 @@ module PacketGen::Plugin
|
|
47
47
|
# @!attribute pad
|
48
48
|
# Padding to align next context on a 8-byte offset
|
49
49
|
# @return [String]
|
50
|
-
define_field :pad, PacketGen::Types::String, builder: ->(h, t) { t.new(length_from: -> {
|
50
|
+
define_field :pad, PacketGen::Types::String, builder: ->(h, t) { t.new(length_from: -> { (8 - (h.offset_of(:data) + h.data_length) % 8) % 8 }) }
|
51
51
|
|
52
52
|
# @private
|
53
53
|
alias old_read read
|
54
54
|
|
55
|
-
# Populate object from a binary string
|
56
|
-
# @param [String] str
|
57
|
-
# @return [Context]
|
58
|
-
def read(str)
|
59
|
-
return self if str.nil?
|
60
|
-
if self.instance_of? Context
|
61
|
-
self[:type].read str[0, 2]
|
62
|
-
name = TYPES.key(type)
|
63
|
-
return old_read(str) if name.nil?
|
64
|
-
|
65
|
-
klassname = name.downcase.capitalize.gsub(/_(\w)/) { $1.upcase }
|
66
|
-
return old_read(str) unless Negotiate.const_defined? klassname
|
67
|
-
|
68
|
-
klass = Negotiate.const_get(klassname)
|
69
|
-
klass.new.read str
|
70
|
-
else
|
71
|
-
old_read str
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
55
|
# Get human-readable type
|
76
56
|
# @return [String]
|
77
57
|
def human_type
|
@@ -104,7 +84,7 @@ module PacketGen::Plugin
|
|
104
84
|
# Salt value for hash
|
105
85
|
# @return [String]
|
106
86
|
define_field_before :pad, :salt, PacketGen::Types::String, builder: ->(h, t) { t.new(length_from: h[:salt_length]) }
|
107
|
-
update_field :pad, builder: ->(h, t) { t.new(length_from: -> {
|
87
|
+
update_field :pad, builder: ->(h, t) { t.new(length_from: -> { (8 - (h.offset_of(:salt) + h.salt_length) % 8) % 8 }) }
|
108
88
|
end
|
109
89
|
|
110
90
|
class EncryptionCap < Context
|
@@ -118,14 +98,22 @@ module PacketGen::Plugin
|
|
118
98
|
# algorithms
|
119
99
|
# @return [PacketGen::Types::ArrayOfInt16le]
|
120
100
|
define_field_before :pad, :ciphers, PacketGen::Types::ArrayOfInt16le, builder: ->(h, t) { t.new(counter: h[:hash_alg_count]) }
|
121
|
-
update_field :pad, builder: ->(h, t) { t.new(length_from: -> {
|
101
|
+
update_field :pad, builder: ->(h, t) { t.new(length_from: -> { (8 - (h.offset_of(:cipher_count) + h[:cipher_count].sz) % 8) % 8 }) }
|
122
102
|
end
|
123
103
|
|
124
104
|
# Array of {Context}
|
125
105
|
# @author Sylvain Daubert
|
126
106
|
class ArrayOfContext < PacketGen::Types::Array
|
127
107
|
set_of Context
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def real_type(ctx)
|
112
|
+
name = Context::TYPES.key(ctx.type)
|
113
|
+
klassname = name.downcase.capitalize.gsub(/_(\w)/) { $1.upcase }
|
114
|
+
Negotiate.const_defined?(klassname) ? Negotiate.const_get(klassname) : ctx.class
|
115
|
+
end
|
128
116
|
end
|
129
117
|
end
|
130
118
|
end
|
131
|
-
end
|
119
|
+
end
|
@@ -124,6 +124,12 @@ module PacketGen::Plugin
|
|
124
124
|
# @return [ArrayOfContext]
|
125
125
|
define_field :context_list, ArrayOfContext, builder: ->(h, t) { t.new(counter: h[:context_count]) }
|
126
126
|
|
127
|
+
# Protocol name
|
128
|
+
# @return [String]
|
129
|
+
def self.protocol_name
|
130
|
+
'SMB2::Negotiate::Request'
|
131
|
+
end
|
132
|
+
|
127
133
|
# @return [String]
|
128
134
|
def inspect
|
129
135
|
super do |attr|
|
@@ -154,12 +160,6 @@ module PacketGen::Plugin
|
|
154
160
|
def calc_length
|
155
161
|
self.context_offset = SMB2.new.sz + offset_of(:context_list)
|
156
162
|
end
|
157
|
-
|
158
|
-
# Protocol name
|
159
|
-
# @return [String]
|
160
|
-
def protocol_name
|
161
|
-
'SMB2::Negotiate::Request'
|
162
|
-
end
|
163
163
|
end
|
164
164
|
end
|
165
165
|
end
|
@@ -152,10 +152,17 @@ module PacketGen::Plugin
|
|
152
152
|
# @return [ArrayOfContext]
|
153
153
|
define_field :context_list, ArrayOfContext, builder: ->(h, t) { t.new(counter: h[:context_count]) }
|
154
154
|
|
155
|
+
# Protocol name
|
156
|
+
# @return [String]
|
157
|
+
def self.protocol_name
|
158
|
+
'SMB2::Negotiate::Response'
|
159
|
+
end
|
160
|
+
|
155
161
|
# @return [String]
|
156
162
|
def inspect
|
157
163
|
super do |attr|
|
158
164
|
next unless attr == :capabilities
|
165
|
+
|
159
166
|
value = bits_on(attr).reject { |_, v| v > 1 }
|
160
167
|
.keys
|
161
168
|
.select { |b| send("#{b}?") }
|
@@ -178,12 +185,6 @@ module PacketGen::Plugin
|
|
178
185
|
self.buffer_length = buffer.sz
|
179
186
|
context_list.each { |ctx| ctx.calc_length if ctx.respond_to? :calc_length }
|
180
187
|
end
|
181
|
-
|
182
|
-
# Protocol name
|
183
|
-
# @return [String]
|
184
|
-
def protocol_name
|
185
|
-
'SMB2::Negotiate::Response'
|
186
|
-
end
|
187
188
|
end
|
188
189
|
end
|
189
190
|
end
|
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
|
20
20
|
spec.required_ruby_version = '>= 2.3.0'
|
21
21
|
|
22
|
-
spec.add_dependency 'packetgen', '~>
|
22
|
+
spec.add_dependency 'packetgen', '~>3.0'
|
23
23
|
spec.add_dependency 'rasn1', '~>0.6', '>= 0.6.7'
|
24
24
|
|
25
25
|
spec.add_development_dependency 'bundler', '~> 1.16'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: packetgen-plugin-smb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sylvain Daubert
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-10-
|
11
|
+
date: 2018-10-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: packetgen
|
@@ -16,20 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
20
|
-
- - ">="
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: 2.8.7
|
19
|
+
version: '3.0'
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
24
|
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version: '
|
30
|
-
- - ">="
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: 2.8.7
|
26
|
+
version: '3.0'
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
28
|
name: rasn1
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,6 +130,10 @@ files:
|
|
136
130
|
- Rakefile
|
137
131
|
- lib/packetgen-plugin-smb.rb
|
138
132
|
- lib/packetgen/plugin/gssapi.rb
|
133
|
+
- lib/packetgen/plugin/netbios.rb
|
134
|
+
- lib/packetgen/plugin/netbios/datagram.rb
|
135
|
+
- lib/packetgen/plugin/netbios/name.rb
|
136
|
+
- lib/packetgen/plugin/netbios/session.rb
|
139
137
|
- lib/packetgen/plugin/smb.rb
|
140
138
|
- lib/packetgen/plugin/smb/blocks.rb
|
141
139
|
- lib/packetgen/plugin/smb/browser.rb
|