Class: PacketGen::Plugin::NTLM

Inherits:
Types::Fields
  • Object
show all
Defined in:
lib/packetgen/plugin/ntlm.rb,
lib/packetgen/plugin/ntlm/av_pair.rb,
lib/packetgen/plugin/ntlm/challenge.rb,
lib/packetgen/plugin/ntlm/negotiate.rb,
lib/packetgen/plugin/ntlm/authenticate.rb,
lib/packetgen/plugin/ntlm/ntlmv2_response.rb

Overview

Base class for NTLM authentication protocol.

Author:

  • Sylvain Daubert

Direct Known Subclasses

Authenticate, Challenge, Negotiate

Defined Under Namespace

Classes: ArrayOfAvPair, Authenticate, AvPair, Challenge, Negotiate, Ntlmv2Response

Constant Summary collapse

AVPAIR_TYPES =

Known AvPair IDs

{
  'EOL' => 0,
  'ComputerName' => 1,
  'DomainName' => 2,
  'DnsComputerName' => 3,
  'DnsDomainName' => 4,
  'DnsTreeName' => 5,
  'Flags' => 6,
  'Timestamp' => 7,
  'SingleHost' => 8,
  'TargetName' => 9,
  'ChannelBindings' => 10
}.freeze
EOLAvPair =

EOL AVPAIR structure, with no value

PacketGen::Types::AbstractTLV.create(type_class: PacketGen::Types::Int16leEnum,
length_class: PacketGen::Types::Int16le)
TimestampAvPair =

Timestamp AVPAIR structure, with value of type SMB::Filetime.

PacketGen::Types::AbstractTLV.create(type_class: PacketGen::Types::Int16leEnum,
length_class: PacketGen::Types::Int16le,
value_class: SMB::Filetime)
Int32leAvPair =

Int32le AVPAIR structure, with value a Types::Int32le.

PacketGen::Types::AbstractTLV.create(type_class: PacketGen::Types::Int16leEnum,
length_class: PacketGen::Types::Int16le,
value_class: PacketGen::Types::Int32le)
StringAvPair =

String AVPAIR structure, with value a Types::String.

PacketGen::Types::AbstractTLV.create(type_class: PacketGen::Types::Int16leEnum,
length_class: PacketGen::Types::Int16le,
value_class: PacketGen::Types::String)
TYPES =

NTLM message types

{
  'negotiate' => 1,
  'challenge' => 2,
  'authenticate' => 3
}.freeze
SIGNATURE =

NTLM signature

"NTLMSSP\0"
VOID_VERSION =

void version

[0].pack('q').freeze
VOID_CHALLENGE =
VOID_VERSION

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ NTLM

This method is abstract.

This method is meaningful for PacketGen::Plugin::NTLM subclasses only.

Returns a new instance of NTLM.



130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/packetgen/plugin/ntlm.rb', line 130

def initialize(options={})
  super
  return if self.class.payload_fields.nil?

  self.class.payload_fields.each do |name, type_and_opt|
    type, options = type_and_opt
    content = if type.new.respond_to?(:unicode?)
                type.new(options.merge(unicode: unicode?))
              else
                type.new(options)
              end
    send(:"#{name}=", content)
  end
end

Class Attribute Details

.payload_fieldsHash

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Return fields defined in payload one.

Returns:

  • (Hash)


42
43
44
# File 'lib/packetgen/plugin/ntlm.rb', line 42

def payload_fields
  @payload_fields
end

Instance Attribute Details

#payloadString

Returns:

  • (String)


36
# File 'lib/packetgen/plugin/ntlm.rb', line 36

define_field :payload, PacketGen::Types::String

#signatureString

8-byte NTLM signature

Returns:

  • (String)


29
# File 'lib/packetgen/plugin/ntlm.rb', line 29

define_field :signature, PacketGen::Types::String, static_length: 8, default: SIGNATURE

#typeInteger

4-byte message type

Returns:

  • (Integer)


33
# File 'lib/packetgen/plugin/ntlm.rb', line 33

define_field :type, PacketGen::Types::Int32leEnum, enum: TYPES

Class Method Details

.define_in_payload(name, type = SMB::String, options = {}) ⇒ void

This method returns an undefined value.

Define a field in payload. Also add name_len, name_maxlen and name_offset fields.

Parameters:

  • name (Symbol)

    name of field.

  • type (Class, nil) (defaults to: SMB::String)

    type of name field.

  • options (Hash) (defaults to: {})

    type’s options needed at build time



117
118
119
120
121
122
123
124
125
126
# File 'lib/packetgen/plugin/ntlm.rb', line 117

def define_in_payload(name, type=SMB::String, options={})
  @payload_fields ||= {}
  @payload_fields[name] = [type, options]

  define_field_before :payload, :"#{name}_len", PacketGen::Types::Int16le
  define_field_before :payload, :"#{name}_maxlen", PacketGen::Types::Int16le
  define_field_before :payload, :"#{name}_offset", PacketGen::Types::Int32le

  attr_accessor name
end

.define_negotiate_flagsvoid

This method returns an undefined value.

Define a flags field.



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/packetgen/plugin/ntlm.rb', line 58

def define_negotiate_flags
  define_field_before :payload, :flags, PacketGen::Types::Int32le
  define_bit_fields_on :flags, :flags_w, :flags_v, :flags_u, :flags_r13, 3,
                       :flags_t, :flags_r4, :flags_s, :flags_r,
                       :flags_r5, :flags_q, :flags_p, :flags_r6,
                       :flags_o, :flags_n, :flags_m, :flags_r7,
                       :flags_l, :flags_k, :flags_j, :flags_r8,
                       :flags_h, :flags_r9, :flags_g, :flags_f,
                       :flags_e, :flags_d, :flags_r10, :flags_c,
                       :flags_b, :flags_a
  alias_method :nego56?, :flags_w?
  alias_method :key_exch?, :flags_v?
  alias_method :nego128?, :flags_u?
  alias_method :version?, :flags_t?
  alias_method :target_info?, :flags_s?
  alias_method :non_nt_session_key?, :flags_r?
  alias_method :identify?, :flags_q?
  alias_method :ext_session_security?, :flags_p?
  alias_method :target_type_server?, :flags_o?
  alias_method :target_type_domain?, :flags_n?
  alias_method :always_sign?, :flags_m?
  alias_method :oem_workstation_supplied?, :flags_l?
  alias_method :oem_domain_supplied?, :flags_k?
  alias_method :anonymous?, :flags_j?
  alias_method :ntlm?, :flags_h?
  alias_method :lm_key?, :flags_g?
  alias_method :datagram?, :flags_f?
  alias_method :seal?, :flags_e?
  alias_method :sign?, :flags_d?
  alias_method :request_target?, :flags_c?
  alias_method :oem?, :flags_b?
  alias_method :unicode?, :flags_a?
  alias_method :old_flags_a=, :flags_a=
  alias_method :old_flags=, :flags=

  class_eval do
    def flags_a=(value)
      self.old_flags_a = value
      self.class.payload_fields.each do |name, _|
        attr = send(name)
        attr.unicode = value if attr.respond_to?(:unicode=)
      end

      value
    end

    def flags=(value)
      self.old_flags = value
      self.flags_a = value & 1
    end
  end
end

.read(str) ⇒ NTLM

Create a NTLM object from a binary string

Parameters:

  • str (String)

Returns:



47
48
49
50
51
52
53
54
# File 'lib/packetgen/plugin/ntlm.rb', line 47

def read(str)
  ntlm = self.new.read(str)
  type = TYPES.key(ntlm.type)
  return ntlm if type.nil?

  klass = NTLM.const_get(type.capitalize)
  klass.new.read(str)
end

Instance Method Details

#calc_lengthvoid

This method is abstract.

This class is meaningful for PacketGen::Plugin::NTLM subclasses only.

This method returns an undefined value.

Calculate and set len, maxlen and offset fields defined for fields in #payload.



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/packetgen/plugin/ntlm.rb', line 173

def calc_length
  return self if self.class.payload_fields.nil?

  previous_len = 0
  self.class.payload_fields.each do |name, _type_and_opt|
    send(:"#{name}_len=", 0)
    send(:"#{name}_offset=", offset_of(:payload) + previous_len)

    field = send(name)
    next unless field && !field.empty?

    length = field.respond_to?(:sz) ? field.sz : field.size
    send(:"#{name}_len=", length)
    send(:"#{name}_maxlen=", length)
    previous_len = length
  end
end

#read(str) ⇒ self

This method is abstract.

This class is meaningful for PacketGen::Plugin::NTLM subclasses only.

Populate object from a binary string

Parameters:

  • str (String)

Returns:

  • (self)


149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/packetgen/plugin/ntlm.rb', line 149

def read(str)
  super
  return self if self.class.payload_fields.nil?

  self.class.payload_fields.each do |name, type_and_opt|
    type, options = type_and_opt
    offset_in_payload = send(:"#{name}_offset") - offset_of(:payload)
    length = send(:"#{name}_len")
    content = if type.new.respond_to?(:unicode?)
                type.new(options.merge(unicode: unicode?))
              else
                type.new(options)
              end
    content.read(payload[offset_in_payload, length]) if length.positive?
    send(:"#{name}=", content)
  end

  self
end

#to_sString

This method is abstract.

This class is meaningful for PacketGen::Plugin::NTLM subclasses only.

Returns:

  • (String)


193
194
195
196
197
198
199
200
201
202
203
# File 'lib/packetgen/plugin/ntlm.rb', line 193

def to_s
  s = super
  return s if self.class.payload_fields.nil?

  self.class.payload_fields.each do |name, _type_and_opt|
    attr = send(name)
    attr.unicode = unicode? if attr.respond_to?(:unicode=)
    s << attr.to_s unless attr.nil? || send("#{name}_len").zero?
  end
  s
end