packetgen-plugin-smb 0.3.0 → 0.4.0

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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +0 -1
  3. data/Gemfile +0 -3
  4. data/README.md +18 -1
  5. data/lib/packetgen-plugin-smb.rb +1 -0
  6. data/lib/packetgen/plugin/gssapi.rb +3 -2
  7. data/lib/packetgen/plugin/netbios.rb +17 -0
  8. data/lib/packetgen/plugin/netbios/datagram.rb +108 -0
  9. data/lib/packetgen/plugin/netbios/name.rb +64 -0
  10. data/lib/packetgen/plugin/netbios/session.rb +71 -0
  11. data/lib/packetgen/plugin/smb.rb +2 -2
  12. data/lib/packetgen/plugin/smb/browser.rb +6 -6
  13. data/lib/packetgen/plugin/smb/browser/domain_announcement.rb +0 -5
  14. data/lib/packetgen/plugin/smb/browser/host_announcement.rb +8 -5
  15. data/lib/packetgen/plugin/smb/browser/local_master_announcement.rb +0 -5
  16. data/lib/packetgen/plugin/smb/close/request.rb +1 -1
  17. data/lib/packetgen/plugin/smb/close/response.rb +1 -1
  18. data/lib/packetgen/plugin/smb/filetime.rb +20 -1
  19. data/lib/packetgen/plugin/smb/ntcreateandx/request.rb +1 -1
  20. data/lib/packetgen/plugin/smb/ntcreateandx/response.rb +1 -1
  21. data/lib/packetgen/plugin/smb/trans/request.rb +1 -1
  22. data/lib/packetgen/plugin/smb/trans/response.rb +1 -1
  23. data/lib/packetgen/plugin/smb2.rb +7 -5
  24. data/lib/packetgen/plugin/smb2/negotiate/context.rb +12 -24
  25. data/lib/packetgen/plugin/smb2/negotiate/request.rb +6 -6
  26. data/lib/packetgen/plugin/smb2/negotiate/response.rb +7 -6
  27. data/lib/packetgen/plugin/smb2/session_setup/request.rb +1 -1
  28. data/lib/packetgen/plugin/smb2/session_setup/response.rb +1 -1
  29. data/lib/packetgen/plugin/smb_version.rb +1 -1
  30. data/packetgen-plugin-smb.gemspec +1 -1
  31. metadata +8 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cc233d3dcb94925757db9c4f5dde9647f97cce4d1e73001f3bbbcb41309ed435
4
- data.tar.gz: 50d2ebf353a37d073bae3f6f7458057e4db8a7f2b5c0932094e1820056ab2746
3
+ metadata.gz: f3f0164d4068b3b829fac802f5ce944c33bf86275fb90aa46150e57926a236f3
4
+ data.tar.gz: 001d57bf0ec000e0e738b25d1116ea0b73bc7a2c0de61b68e6c16ef75a130d4b
5
5
  SHA512:
6
- metadata.gz: 5862b573e7b9bba3826f10ef8e1ac8bbb34817e49f93338223ca5fbfcd0ad19cbeb65b64428fc1832c7603fe8a5a5cfc32cb6ac31d63c2e66de4a518ab89de6d
7
- data.tar.gz: bb9a3e27eb4c36e3b6197d6450bef4efd73af1e3a0849c07383ea32924d155e0e21f975f7c91b4092ba70cce3d03cb368f92d38311a1a6585c946b5c1462dae5
6
+ metadata.gz: 661c09099b29c3c747e5b4d1831b05fb3945123e1d5ff7aaabc053221c100ed1113fd04a72af5fdbc245a9d0789419f6b6fc1c8a37a558c64da53ef1b30c4e8e
7
+ data.tar.gz: 06b857556ca716b954a4fb935ec3e6e91ab2a0416442b31e3ad7e9eec7631fe33d6c3bb96814fd949fbffd2d58c97fc80fbbd18dd4b66cd5a603663f58169bb9
@@ -1,4 +1,3 @@
1
- TargetRubyVersion: 2.3
2
1
  Layout/SpaceAroundEqualsInParameterDefault:
3
2
  EnforcedStyle: no_space
4
3
  Lint/EmptyWhen:
data/Gemfile CHANGED
@@ -1,6 +1,3 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
-
5
- # Specify your gem's dependencies in packetgen-plugin-smb.gemspec
6
3
  gemspec
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))
@@ -8,5 +8,6 @@
8
8
  require 'packetgen'
9
9
  require_relative 'packetgen/plugin/smb_version'
10
10
  require_relative 'packetgen/plugin/gssapi'
11
+ require_relative 'packetgen/plugin/netbios'
11
12
  require_relative 'packetgen/plugin/smb'
12
13
  require_relative 'packetgen/plugin/smb2'
@@ -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 = (token == :init) ? 0 : 1
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
@@ -190,8 +190,8 @@ module PacketGen::Plugin
190
190
  end
191
191
  end
192
192
  PacketGen::Header.add_class SMB
193
- PacketGen::Header::NetBIOS::Session.bind SMB, body: ->(val) { val.nil? ? SMB::MARKER : val[0..3] == SMB::MARKER }
194
- PacketGen::Header::NetBIOS::Datagram.bind SMB, body: ->(val) { val.nil? ? SMB::MARKER : val[0..3] == SMB::MARKER }
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'] }
@@ -36,7 +36,7 @@ module PacketGen::Plugin
36
36
 
37
37
  # Give protocol name for this class
38
38
  # @return [String]
39
- def protocol_name
39
+ def self.protocol_name
40
40
  'SMB::Close::Request'
41
41
  end
42
42
  end
@@ -27,7 +27,7 @@ module PacketGen::Plugin
27
27
 
28
28
  # Give protocol name for this class
29
29
  # @return [String]
30
- def protocol_name
30
+ def self.protocol_name
31
31
  'SMB::Close::Response'
32
32
  end
33
33
  end
@@ -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("%Y-%m-%d %H:%M:%S.%9N %Z")
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
@@ -141,7 +141,7 @@ module PacketGen::Plugin
141
141
 
142
142
  # Give protocol name for this class
143
143
  # @return [String]
144
- def protocol_name
144
+ def self.protocol_name
145
145
  'SMB::NtCreateAndX::Request'
146
146
  end
147
147
 
@@ -101,7 +101,7 @@ module PacketGen::Plugin
101
101
 
102
102
  # Give protocol name for this class
103
103
  # @return [String]
104
- def protocol_name
104
+ def self.protocol_name
105
105
  'SMB::NtCreateAndX::Response'
106
106
  end
107
107
 
@@ -112,7 +112,7 @@ module PacketGen::Plugin
112
112
 
113
113
  # Give protocol name for this class
114
114
  # @return [String]
115
- def protocol_name
115
+ def self.protocol_name
116
116
  'SMB::Trans::Request'
117
117
  end
118
118
  end
@@ -85,7 +85,7 @@ module PacketGen::Plugin
85
85
 
86
86
  # Give protocol name for this class
87
87
  # @return [String]
88
- def protocol_name
88
+ def self.protocol_name
89
89
  'SMB::Trans::Response'
90
90
  end
91
91
  end
@@ -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
- PacketGen::Header::NetBIOS::Session.bind SMB2, body: ->(val) { val.nil? ? SMB2::MARKER : val[0..3] == SMB2::MARKER }
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: -> { v = 8 - (h.offset_of(:data) + h.data_length) % 8; v == 8 ? 0 : v }) }
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: -> { v = 8 - (h.offset_of(:salt) + h.salt_length) % 8; v == 8 ? 0 : v }) }
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: -> { v = 8 - (h.offset_of(:cipher_count) + h[:cipher_count].sz) % 8; v == 8 ? 0 : v }) }
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
@@ -89,7 +89,7 @@ module PacketGen::Plugin
89
89
 
90
90
  # Protocol name
91
91
  # @return [String]
92
- def protocol_name
92
+ def self.protocol_name
93
93
  'SMB2::SessionSetup::Request'
94
94
  end
95
95
  end
@@ -60,7 +60,7 @@ module PacketGen::Plugin
60
60
 
61
61
  # Protocol name
62
62
  # @return [String]
63
- def protocol_name
63
+ def self.protocol_name
64
64
  'SMB2::SessionSetup::Response'
65
65
  end
66
66
  end
@@ -1,5 +1,5 @@
1
1
  module PacketGen
2
2
  module Plugin
3
- SMB_VERSION = "0.3.0"
3
+ SMB_VERSION = "0.4.0"
4
4
  end
5
5
  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', '~>2.8', '>= 2.8.7'
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.3.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-18 00:00:00.000000000 Z
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: '2.8'
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: '2.8'
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