packetgen-plugin-smb 0.3.0 → 0.6.2

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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/specs.yml +28 -0
  3. data/.rubocop.yml +8 -1
  4. data/Gemfile +15 -3
  5. data/README.md +59 -3
  6. data/Rakefile +10 -4
  7. data/examples/llmnr-responder +110 -0
  8. data/examples/smb-responder +233 -0
  9. data/lib/packetgen-plugin-smb.rb +5 -2
  10. data/lib/packetgen/plugin/gssapi.rb +11 -6
  11. data/lib/packetgen/plugin/llmnr.rb +58 -0
  12. data/lib/packetgen/plugin/netbios.rb +19 -0
  13. data/lib/packetgen/plugin/netbios/datagram.rb +108 -0
  14. data/lib/packetgen/plugin/netbios/name.rb +64 -0
  15. data/lib/packetgen/plugin/netbios/session.rb +72 -0
  16. data/lib/packetgen/plugin/ntlm.rb +211 -0
  17. data/lib/packetgen/plugin/ntlm/authenticate.rb +197 -0
  18. data/lib/packetgen/plugin/ntlm/av_pair.rb +115 -0
  19. data/lib/packetgen/plugin/ntlm/challenge.rb +140 -0
  20. data/lib/packetgen/plugin/ntlm/negotiate.rb +127 -0
  21. data/lib/packetgen/plugin/ntlm/ntlmv2_response.rb +59 -0
  22. data/lib/packetgen/plugin/smb.rb +27 -15
  23. data/lib/packetgen/plugin/smb/blocks.rb +2 -4
  24. data/lib/packetgen/plugin/smb/browser.rb +8 -8
  25. data/lib/packetgen/plugin/smb/browser/domain_announcement.rb +2 -7
  26. data/lib/packetgen/plugin/smb/browser/host_announcement.rb +10 -7
  27. data/lib/packetgen/plugin/smb/browser/local_master_announcement.rb +2 -7
  28. data/lib/packetgen/plugin/smb/close.rb +2 -2
  29. data/lib/packetgen/plugin/smb/close/request.rb +3 -3
  30. data/lib/packetgen/plugin/smb/close/response.rb +3 -3
  31. data/lib/packetgen/plugin/smb/filetime.rb +30 -3
  32. data/lib/packetgen/plugin/smb/negotiate.rb +20 -0
  33. data/lib/packetgen/plugin/smb/negotiate/dialect.rb +39 -0
  34. data/lib/packetgen/plugin/smb/negotiate/request.rb +35 -0
  35. data/lib/packetgen/plugin/smb/negotiate/response.rb +29 -0
  36. data/lib/packetgen/plugin/smb/nt_create_and_x.rb +2 -2
  37. data/lib/packetgen/plugin/smb/ntcreateandx/request.rb +5 -5
  38. data/lib/packetgen/plugin/smb/ntcreateandx/response.rb +3 -3
  39. data/lib/packetgen/plugin/smb/string.rb +60 -23
  40. data/lib/packetgen/plugin/smb/trans.rb +2 -2
  41. data/lib/packetgen/plugin/smb/trans/request.rb +4 -4
  42. data/lib/packetgen/plugin/smb/trans/response.rb +3 -3
  43. data/lib/packetgen/plugin/smb2.rb +20 -9
  44. data/lib/packetgen/plugin/smb2/base.rb +5 -7
  45. data/lib/packetgen/plugin/smb2/error.rb +3 -4
  46. data/lib/packetgen/plugin/smb2/guid.rb +6 -4
  47. data/lib/packetgen/plugin/smb2/negotiate.rb +2 -2
  48. data/lib/packetgen/plugin/smb2/negotiate/context.rb +28 -27
  49. data/lib/packetgen/plugin/smb2/negotiate/request.rb +16 -12
  50. data/lib/packetgen/plugin/smb2/negotiate/response.rb +25 -14
  51. data/lib/packetgen/plugin/smb2/session_setup.rb +2 -2
  52. data/lib/packetgen/plugin/smb2/session_setup/request.rb +12 -7
  53. data/lib/packetgen/plugin/smb2/session_setup/response.rb +13 -8
  54. data/lib/packetgen/plugin/smb_version.rb +3 -1
  55. data/packetgen-plugin-smb.gemspec +10 -15
  56. metadata +28 -81
  57. data/.travis.yml +0 -12
@@ -1,15 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  # SMB FILETIME.
11
11
  # @author Sylvain Daubert
12
12
  class Filetime
13
+ include PacketGen::Types::Fieldable
14
+
13
15
  # Base time for SMB FILETIME.
14
16
  # This value also indicate no time.
15
17
  NO_TIME = Time.utc(1601).freeze
@@ -17,6 +19,17 @@ module PacketGen::Plugin
17
19
  # Numbers of 100ns in one second
18
20
  ONE_SEC = 10_000_000
19
21
 
22
+ # String to format time
23
+ FORMAT_TIME_STR = '%Y-%m-%d %H:%M:%S.%9N %Z'
24
+ # String to parse time
25
+ PARSE_TIME_STR = '%Y-%m-%d %H:%M:%S.%N %Z'
26
+
27
+ # Return a new Filetime object initialized to current time.
28
+ # @return [Filetime]
29
+ def self.now
30
+ new(time: Time.now.utc)
31
+ end
32
+
20
33
  # @param [Hash] options
21
34
  # @option options [Integer] :filetime
22
35
  # @option options [Time] :time
@@ -49,10 +62,24 @@ module PacketGen::Plugin
49
62
  if no_time?
50
63
  'no time'
51
64
  else
52
- @time.strftime("%Y-%m-%d %H:%M:%S.%9N %Z")
65
+ @time.strftime(FORMAT_TIME_STR)
53
66
  end
54
67
  end
55
68
 
69
+ # @return [self]
70
+ def from_human(str)
71
+ return self if str.nil?
72
+
73
+ @time = if str == 'no time'
74
+ Time.at(NO_TIME)
75
+ else
76
+ DateTime.strptime(str, PARSE_TIME_STR).to_time
77
+ end
78
+ @int.value = time2filetime
79
+
80
+ self
81
+ end
82
+
56
83
  # Get filetime integer value
57
84
  # @return [Integer]
58
85
  def to_i
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is part of packetgen-plugin-smb.
4
+ # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
5
+ # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
6
+ # This program is published under MIT license.
7
+
8
+ module PacketGen::Plugin
9
+ class SMB
10
+ # Namespace for NEGOTIATE related classes
11
+ # @author Sylvain Daubert
12
+ module Negotiate; end
13
+ end
14
+ end
15
+
16
+ require_relative 'negotiate/dialect'
17
+ require_relative 'negotiate/request'
18
+ require_relative 'negotiate/response'
19
+
20
+ PacketGen::Plugin::SMB.bind_command 'negotiate'
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is part of packetgen-plugin-smb.
4
+ # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
5
+ # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
6
+ # This program is published under MIT license.
7
+
8
+ module PacketGen::Plugin
9
+ class SMB
10
+ module Negotiate
11
+ # A SMB_Dialect struct containing:
12
+ # * a 8-bit {#format} field, which should be set to 0x02,
13
+ # * a null-terminated string identifying a SMB dialect.
14
+ # @author Sylvain Daubert
15
+ class Dialect < PacketGen::Types::Fields
16
+ # @!attribute format
17
+ # 8-bit format. Should be +2+ to indicate a null-terminated string for
18
+ # {#dialect} field.
19
+ # @return [Integer]
20
+ define_field :format, PacketGen::Types::Int8, default: 2
21
+ # @!attribute dialect
22
+ # Null-terminated string identifying a SMB dialect.
23
+ # @return [String]
24
+ define_field :dialect,PacketGen::Types::CString
25
+
26
+ # @return [String]
27
+ def to_human
28
+ self[:dialect].to_human
29
+ end
30
+ end
31
+
32
+ # Specialized {PacketGen::Types::Array} to embed {Dialect Dialects}.
33
+ # @author Sylvain Daubert
34
+ class ArrayOfDialect < PacketGen::Types::Array
35
+ set_of Dialect
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is part of packetgen-plugin-smb.
4
+ # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
5
+ # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
6
+ # This program is published under MIT license.
7
+
8
+ module PacketGen::Plugin
9
+ class SMB
10
+ module Negotiate
11
+ # SMB Negotiation Request header.
12
+ #
13
+ # See also {Blocks}, as {Negotiate::Request} is a specialization of {Blocks#words}
14
+ # and {Blocks#bytes}.
15
+ # @author Sylvain Daubert
16
+ class Request < PacketGen::Header::Base
17
+ # @!attribute word_count
18
+ # The size, in 2-byte words, of the SMB command parameters. It should
19
+ # be +0+ setup_count+.
20
+ # @return [Integer]
21
+ define_field :word_count, PacketGen::Types::Int8, default: 0
22
+ # @!attribute byte_count
23
+ # @return [Integer]
24
+ define_field :byte_count, PacketGen::Types::Int16le
25
+ # @!attribute dialects
26
+ # @return [ArrayOfDialect]
27
+ define_field :dialects, ArrayOfDialect
28
+
29
+ def self.protocol_name
30
+ 'SMB::Negotiate::Request'
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is part of packetgen-plugin-smb.
4
+ # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
5
+ # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
6
+ # This program is published under MIT license.
7
+
8
+ module PacketGen::Plugin
9
+ class SMB
10
+ module Negotiate
11
+ # SMB Negotiation Response header.
12
+ #
13
+ # See also {Blocks}, as {Negotiate::Response} is a specialization of {Blocks#words}
14
+ # and {Blocks#bytes}.
15
+ # @author Sylvain Daubert
16
+ class Response < Blocks
17
+ # Get index of the dialect selected by the server from the list presented in the request.
18
+ # @return [Integer]
19
+ def dialect_index
20
+ words.first.to_i
21
+ end
22
+
23
+ def self.protocol_name
24
+ 'SMB::Negotiate::Response'
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  # Namespace for NT_CREATE_ANDX related classes
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  # Namespace for NT_CREATE_ANDX related classes
@@ -128,7 +128,7 @@ module PacketGen::Plugin
128
128
  # Padding before {#filename} to align it on 16-bit boundary. Only present
129
129
  # if {SMB#flags2_unicode?} is +true+.
130
130
  # @return [Integer]
131
- define_field :pad1, PacketGen::Types::Int8, optional: ->(h) { h.packet && h.packet.smb.flags2_unicode? }
131
+ define_field :pad1, PacketGen::Types::Int8, optional: ->(h) { h&.packet&.smb&.flags2_unicode? }
132
132
  # @!attribute filename
133
133
  # A string that represents the fully qualified name of the file
134
134
  # relative to the supplied TID
@@ -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
 
@@ -154,6 +154,6 @@ module PacketGen::Plugin
154
154
  self.byte_count = bcount
155
155
  end
156
156
  end
157
- end
157
+ end
158
158
  end
159
159
  end
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  # Namespace for NT_CREATE_ANDX related classes
@@ -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
 
@@ -1,28 +1,39 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
8
+ require 'forwardable'
7
9
 
8
10
  module PacketGen::Plugin
9
11
  class SMB
10
- # SMB strings (UTF-16 little-endian).
12
+ # SMB strings (UTF-16 little-endian or OEM).
11
13
  # @author Sylvain Daubert
12
- class String < PacketGen::Types::CString
13
- # @param [Boolean] value
14
+ class String
15
+ extend Forwardable
16
+ include PacketGen::Types::Fieldable
17
+
18
+ def_delegators :@string, :[], :length, :size, :inspect, :==, :<<,
19
+ :unpack, :force_encoding, :encoding, :index, :empty?,
20
+ :encode
21
+
22
+ # @return [::String]
23
+ attr_reader :string
24
+ # @param [Boolean] null_terminated
14
25
  # @return [Boolean]
15
- attr_writer :unicode
26
+ attr_writer :null_terminated
16
27
 
17
28
  # @param [Hash] options
18
- # @option options [Integer] :static_length set a static length for this string
19
29
  # @option options [Boolean] :unicode If +true+, string is encoded as a UTF-16
20
30
  # unicode string. If +false+, string is encode in ASCII. Defaults to +true+.
31
+ # @option options [Boolean] :null_terminated If +true+, string is null-terminated.
32
+ # If +false+, string is not null-terminated. Defaults to +true+.
21
33
  def initialize(options={})
22
- super
23
34
  @unicode = options.key?(:unicode) ? options[:unicode] : true
24
- self.encode!('UTF-16LE') if @unicode
25
- self.encode!('ASCII-8BIT') unless @unicode
35
+ @null_terminated = options.key?(:null_terminated) ? options[:null_terminated] : true
36
+ @string = +''.encode(self_encoding)
26
37
  end
27
38
 
28
39
  # @return [Boolean]
@@ -30,6 +41,19 @@ module PacketGen::Plugin
30
41
  @unicode
31
42
  end
32
43
 
44
+ # @param [Boolean] bool
45
+ # @return [Boolean]
46
+ def unicode=(bool)
47
+ @unicode = bool
48
+ @string.force_encoding(self_encoding)
49
+ bool
50
+ end
51
+
52
+ # @return [Boolean]
53
+ def null_terminated?
54
+ @null_terminated
55
+ end
56
+
33
57
  # @param [::String] str
34
58
  # @return [String] self
35
59
  def read(str)
@@ -37,34 +61,47 @@ module PacketGen::Plugin
37
61
 
38
62
  str2 = case str.encoding
39
63
  when Encoding::BINARY
40
- binidx = nil
41
- 0.step(to: str.size, by: 2) do |i|
42
- binidx = i if str[i, 2] == binary_terminator
43
- end
44
- s = if binidx.nil?
45
- str
46
- else
47
- str[0, binidx]
48
- end
49
- s.force_encoding(self_encoding)
64
+ str.dup.force_encoding(self_encoding)
50
65
  else
51
66
  str.encode(self_encoding)
52
67
  end
53
- str2 = str2[0, @static_length / 2] if @static_length.is_a? Integer
54
68
  idx = str2.index(+"\x00".encode(self_encoding))
55
69
  str2 = str2[0, idx] unless idx.nil?
56
- self.replace str2
70
+ @string = str2
57
71
  self
58
72
  end
59
73
 
74
+ # @return [String]
75
+ def to_s
76
+ str = string.dup.force_encoding('BINARY')
77
+ return str unless null_terminated?
78
+
79
+ str << binary_terminator.force_encoding('BINARY')
80
+ end
81
+
82
+ # Populate String from a human readable (ie UTF-8) string
83
+ # @param [String] str
84
+ # @return [self]
85
+ def from_human(str)
86
+ return self if str.nil?
87
+
88
+ @string = str.encode(self_encoding)
89
+ self
90
+ end
91
+
92
+ # @return [String]
93
+ def to_human
94
+ string.encode('UTF-8')
95
+ end
96
+
60
97
  private
61
98
 
62
99
  def self_encoding
63
- @unicode ? Encoding::UTF_16LE : Encoding:: ASCII_8BIT
100
+ @unicode ? Encoding::UTF_16LE : Encoding::ASCII_8BIT
64
101
  end
65
102
 
66
103
  def binary_terminator
67
- @unicode ? "\x00\x00" : "\x00"
104
+ [0].pack('C').encode(self_encoding)
68
105
  end
69
106
  end
70
107
  end
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  # Namespace for TRANS related classes
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  module Trans
@@ -96,7 +96,7 @@ module PacketGen::Plugin
96
96
  # 8-bit optional padding to align {#name} on a 2-byte boundary. Only present
97
97
  # if {SMB#flags2_unicode?} is +true+.
98
98
  # @return [Integer]
99
- define_field :padname, PacketGen::Types::Int8, optional: ->(h) { h.packet && h.packet.smb.flags2_unicode? }
99
+ define_field :padname, PacketGen::Types::Int8, optional: ->(h) { h&.packet&.smb&.flags2_unicode? }
100
100
  # @!attribute name
101
101
  # Pathname of the mailslot or named pipe.
102
102
  # @return [String]
@@ -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
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  module Trans
@@ -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