librex 0.0.6 → 0.0.7

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 (51) hide show
  1. data/README.md +3 -5
  2. data/Rakefile +26 -0
  3. data/lib/rex/compat.rb +1 -1
  4. data/lib/rex/exploitation/javascriptosdetect.rb +125 -62
  5. data/lib/rex/file.rb +15 -0
  6. data/lib/rex/io/stream.rb +1 -1
  7. data/lib/rex/parser/nmap_xml.rb +6 -0
  8. data/lib/rex/poly/block.rb +9 -0
  9. data/lib/rex/post/meterpreter/client.rb +0 -8
  10. data/lib/rex/post/meterpreter/extensions/priv/priv.rb +6 -0
  11. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +1 -1
  12. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_advapi32.rb +49 -35
  13. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_netapi32.rb +26 -0
  14. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb +9 -2
  15. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/util.rb +630 -0
  16. data/lib/rex/post/meterpreter/packet.rb +3 -1
  17. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +143 -57
  18. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +6 -0
  19. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +9 -3
  20. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +6 -4
  21. data/lib/rex/proto.rb +1 -0
  22. data/lib/rex/proto/dhcp/server.rb +4 -2
  23. data/lib/rex/proto/http/packet.rb +5 -6
  24. data/lib/rex/proto/ntlm.rb +7 -0
  25. data/lib/rex/proto/ntlm.rb.ut.rb +177 -0
  26. data/lib/rex/proto/ntlm/base.rb +326 -0
  27. data/lib/rex/proto/ntlm/constants.rb +74 -0
  28. data/lib/rex/proto/ntlm/crypt.rb +340 -0
  29. data/lib/rex/proto/ntlm/exceptions.rb +9 -0
  30. data/lib/rex/proto/ntlm/message.rb +533 -0
  31. data/lib/rex/proto/ntlm/utils.rb +358 -0
  32. data/lib/rex/proto/smb/client.rb +548 -86
  33. data/lib/rex/proto/smb/client.rb.ut.rb +4 -4
  34. data/lib/rex/proto/smb/constants.rb +7 -24
  35. data/lib/rex/proto/smb/crypt.rb +12 -71
  36. data/lib/rex/proto/smb/exceptions.rb +12 -0
  37. data/lib/rex/proto/smb/simpleclient.rb +17 -5
  38. data/lib/rex/proto/smb/utils.rb +3 -460
  39. data/lib/rex/proto/tftp/server.rb +2 -2
  40. data/lib/rex/script/base.rb +2 -2
  41. data/lib/rex/socket.rb +12 -0
  42. data/lib/rex/socket.rb.ut.rb +31 -10
  43. data/lib/rex/socket/ssl_tcp_server.rb.ut.rb +15 -5
  44. data/lib/rex/text.rb +55 -4
  45. data/lib/rex/ui/output.rb +0 -2
  46. data/lib/rex/ui/text/dispatcher_shell.rb +95 -10
  47. data/lib/rex/ui/text/output/buffer.rb +0 -4
  48. data/lib/rex/ui/text/shell.rb +8 -0
  49. data/lib/rex/ui/text/table.rb +21 -1
  50. metadata +15 -19
  51. data/lib/rex/proto/smb/crypt.rb.ut.rb +0 -20
@@ -0,0 +1,358 @@
1
+ module Rex
2
+ module Proto
3
+ module NTLM
4
+ class Utils
5
+
6
+ #duplicate from lib/rex/proto/smb/utils cause we only need this fonction from Rex::Proto::SMB::Utils
7
+ # Convert a unix timestamp to a 64-bit signed server time
8
+ def self.time_unix_to_smb(unix_time)
9
+ t64 = (unix_time + 11644473600) * 10000000
10
+ thi = (t64 & 0xffffffff00000000) >> 32
11
+ tlo = (t64 & 0x00000000ffffffff)
12
+ return [thi, tlo]
13
+ end
14
+
15
+ #
16
+ # Prepends an ASN1 formatted length field to a piece of data
17
+ #
18
+ def self.asn1encode(str = '')
19
+ res = ''
20
+
21
+ # If the high bit of the first byte is 1, it contains the number of
22
+ # length bytes that follow
23
+
24
+ case str.length
25
+ when 0 .. 0x7F
26
+ res = [str.length].pack('C') + str
27
+ when 0x80 .. 0xFF
28
+ res = [0x81, str.length].pack('CC') + str
29
+ when 0x100 .. 0xFFFF
30
+ res = [0x82, str.length].pack('Cn') + str
31
+ when 0x10000 .. 0xffffff
32
+ res = [0x83, str.length >> 16, str.length & 0xFFFF].pack('CCn') + str
33
+ when 0x1000000 .. 0xffffffff
34
+ res = [0x84, str.length].pack('CN') + str
35
+ else
36
+ raise "ASN1 str too long"
37
+ end
38
+ return res
39
+ end
40
+
41
+ # GSS functions
42
+
43
+ # GSS BLOB usefull for SMB_NEGOCIATE_RESPONSE message
44
+ # mechTypes: 2 items :
45
+ # -MechType: 1.3.6.1.4.1.311.2.2.30 (SNMPv2-SMI::enterprises.311.2.2.30)
46
+ # -MechType: 1.3.6.1.4.1.311.2.2.10 (NTLMSSP - Microsoft NTLM Security Support Provider)
47
+ #
48
+ # this is the default on Win7
49
+ def self.make_simple_negotiate_secblob_resp
50
+ blob =
51
+ "\x60" + self.asn1encode(
52
+ "\x06" + self.asn1encode(
53
+ "\x2b\x06\x01\x05\x05\x02"
54
+ ) +
55
+ "\xa0" + self.asn1encode(
56
+ "\x30" + self.asn1encode(
57
+ "\xa0" + self.asn1encode(
58
+ "\x30" + self.asn1encode(
59
+ "\x06" + self.asn1encode(
60
+ "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
61
+ )
62
+ )
63
+ )
64
+ )
65
+ )
66
+ )
67
+
68
+ return blob
69
+ end
70
+
71
+ # GSS BLOB usefull for SMB_NEGOCIATE_RESPONSE message
72
+ # mechTypes: 4 items :
73
+ # MechType: 1.2.840.48018.1.2.2 (MS KRB5 - Microsoft Kerberos 5)
74
+ # MechType: 1.2.840.113554.1.2.2 (KRB5 - Kerberos 5)
75
+ # MechType: 1.2.840.113554.1.2.2.3 (KRB5 - Kerberos 5 - User to User)
76
+ # MechType: 1.3.6.1.4.1.311.2.2.10 (NTLMSSP - Microsoft NTLM Security Support Provider)
77
+ # mechListMIC:
78
+ # principal: account@domain
79
+ def self.make_negotiate_secblob_resp(account, domain)
80
+ blob =
81
+ "\x60" + self.asn1encode(
82
+ "\x06" + self.asn1encode(
83
+ "\x2b\x06\x01\x05\x05\x02"
84
+ ) +
85
+ "\xa0" + self.asn1encode(
86
+ "\x30" + self.asn1encode(
87
+ "\xa0" + self.asn1encode(
88
+ "\x30" + self.asn1encode(
89
+ "\x06" + self.asn1encode(
90
+ "\x2a\x86\x48\x82\xf7\x12\x01\x02\x02"
91
+ ) +
92
+ "\x06" + self.asn1encode(
93
+ "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"
94
+ ) +
95
+ "\x06" + self.asn1encode(
96
+ "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x03"
97
+ ) +
98
+ "\x06" + self.asn1encode(
99
+ "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
100
+ )
101
+ )
102
+ ) +
103
+ "\xa3" + self.asn1encode(
104
+ "\x30" + self.asn1encode(
105
+ "\xa0" + self.asn1encode(
106
+ "\x1b" + self.asn1encode(
107
+ account + '@' + domain
108
+ )
109
+ )
110
+ )
111
+ )
112
+ )
113
+ )
114
+ )
115
+
116
+ return blob
117
+ end
118
+
119
+
120
+ # GSS BLOB usefull for ntlmssp type 1 message
121
+ def self.make_ntlmssp_secblob_init(domain = 'WORKGROUP', name = 'WORKSTATION', flags=0x80201)
122
+ blob =
123
+ "\x60" + self.asn1encode(
124
+ "\x06" + self.asn1encode(
125
+ "\x2b\x06\x01\x05\x05\x02"
126
+ ) +
127
+ "\xa0" + self.asn1encode(
128
+ "\x30" + self.asn1encode(
129
+ "\xa0" + self.asn1encode(
130
+ "\x30" + self.asn1encode(
131
+ "\x06" + self.asn1encode(
132
+ "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
133
+ )
134
+ )
135
+ ) +
136
+ "\xa2" + self.asn1encode(
137
+ "\x04" + self.asn1encode(
138
+ "NTLMSSP\x00" +
139
+ [1, flags].pack('VV') +
140
+
141
+ [
142
+ domain.length, #length
143
+ domain.length, #max length
144
+ 32
145
+ ].pack('vvV') +
146
+
147
+ [
148
+ name.length, #length
149
+ name.length, #max length
150
+ domain.length + 32
151
+ ].pack('vvV') +
152
+
153
+ domain + name
154
+ )
155
+ )
156
+ )
157
+ )
158
+ )
159
+
160
+ return blob
161
+ end
162
+
163
+
164
+ # GSS BLOB usefull for ntlmssp type 2 message
165
+ def self.make_ntlmssp_secblob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
166
+
167
+ blob =
168
+ "\xa1" + self.asn1encode(
169
+ "\x30" + self.asn1encode(
170
+ "\xa0" + self.asn1encode(
171
+ "\x0a" + self.asn1encode(
172
+ "\x01"
173
+ )
174
+ ) +
175
+ "\xa1" + self.asn1encode(
176
+ "\x06" + self.asn1encode(
177
+ "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
178
+ )
179
+ ) +
180
+ "\xa2" + self.asn1encode(
181
+ "\x04" + self.asn1encode(
182
+ make_ntlmssp_blob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
183
+ )
184
+ )
185
+ )
186
+ )
187
+
188
+ return blob
189
+ end
190
+
191
+ # BLOB without GSS usefull for ntlm type 2 message
192
+ def self.make_ntlmssp_blob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
193
+
194
+ addr_list = ''
195
+ addr_list << [2, win_domain.length].pack('vv') + win_domain
196
+ addr_list << [1, win_name.length].pack('vv') + win_name
197
+ addr_list << [4, dns_domain.length].pack('vv') + dns_domain
198
+ addr_list << [3, dns_name.length].pack('vv') + dns_name
199
+ addr_list << [0, 0].pack('vv')
200
+
201
+ ptr = 0
202
+ blob = "NTLMSSP\x00" +
203
+ [2].pack('V') +
204
+ [
205
+ win_domain.length, # length
206
+ win_domain.length, # max length
207
+ (ptr += 48) # offset
208
+ ].pack('vvV') +
209
+ [ flags ].pack('V') +
210
+ chall +
211
+ "\x00\x00\x00\x00\x00\x00\x00\x00" +
212
+ [
213
+ addr_list.length, # length
214
+ addr_list.length, # max length
215
+ (ptr += win_domain.length)
216
+ ].pack('vvV') +
217
+ win_domain +
218
+ addr_list
219
+ return blob
220
+ end
221
+
222
+
223
+ # GSS BLOB Usefull for ntlmssp type 3 message
224
+ def self.make_ntlmssp_secblob_auth(domain, name, user, lm, ntlm, enc_session_key, flags = 0x080201)
225
+
226
+ lm ||= "\x00" * 24
227
+ ntlm ||= "\x00" * 24
228
+
229
+ domain_uni = Rex::Text.to_unicode(domain)
230
+ user_uni = Rex::Text.to_unicode(user)
231
+ name_uni = Rex::Text.to_unicode(name)
232
+ session = enc_session_key
233
+
234
+ ptr = 64
235
+ blob =
236
+ "\xa1" + self.asn1encode(
237
+ "\x30" + self.asn1encode(
238
+ "\xa2" + self.asn1encode(
239
+ "\x04" + self.asn1encode(
240
+
241
+ "NTLMSSP\x00" +
242
+ [ 3 ].pack('V') +
243
+
244
+ [ # Lan Manager Response
245
+ lm.length,
246
+ lm.length,
247
+ (ptr)
248
+ ].pack('vvV') +
249
+
250
+ [ # NTLM Manager Response
251
+ ntlm.length,
252
+ ntlm.length,
253
+ (ptr += lm.length)
254
+ ].pack('vvV') +
255
+
256
+ [ # Domain Name
257
+ domain_uni.length,
258
+ domain_uni.length,
259
+ (ptr += ntlm.length)
260
+ ].pack('vvV') +
261
+
262
+ [ # Username
263
+ user_uni.length,
264
+ user_uni.length,
265
+ (ptr += domain_uni.length)
266
+ ].pack('vvV') +
267
+
268
+ [ # Hostname
269
+ name_uni.length,
270
+ name_uni.length,
271
+ (ptr += user_uni.length)
272
+ ].pack('vvV') +
273
+
274
+ [ # Session Key (none)
275
+ session.length,
276
+ session.length,
277
+ (ptr += name_uni.length)
278
+ ].pack('vvV') +
279
+
280
+ [ flags ].pack('V') +
281
+
282
+ lm +
283
+ ntlm +
284
+ domain_uni +
285
+ user_uni +
286
+ name_uni +
287
+ session + "\x00"
288
+ )
289
+ )
290
+ )
291
+ )
292
+ return blob
293
+ end
294
+
295
+
296
+ # GSS BLOB Usefull for SMB Success
297
+ def self.make_ntlmv2_secblob_success
298
+ blob =
299
+ "\xa1" + self.asn1encode(
300
+ "\x30" + self.asn1encode(
301
+ "\xa0" + self.asn1encode(
302
+ "\x0a" + self.asn1encode(
303
+ "\x00"
304
+ )
305
+ )
306
+ )
307
+ )
308
+ return blob
309
+ end
310
+
311
+ # This function return an ntlmv2 client challenge
312
+ def self.make_ntlmv2_clientchallenge(win_domain, win_name, dns_domain, dns_name, client_challenge = nil, chall_MsvAvTimestamp = nil)
313
+
314
+ client_challenge ||= Rex::Text.rand_text(8)
315
+ # We have to set the timestamps here to the one in the challenge message from server if present
316
+ # If we don't do that, recent server like seven will send a STATUS_INVALID_PARAMETER error packet
317
+ timestamp = chall_MsvAvTimestamp != nil ? chall_MsvAvTimestamp : self.time_unix_to_smb(Time.now.to_i).reverse.pack("VV")
318
+ # Make those values unicode as requested
319
+ win_domain = Rex::Text.to_unicode(win_domain)
320
+ win_name = Rex::Text.to_unicode(win_name)
321
+ dns_domain = Rex::Text.to_unicode(dns_domain)
322
+ dns_name = Rex::Text.to_unicode(dns_name)
323
+ # Make the AV_PAIRs
324
+ addr_list = ''
325
+ addr_list << [2, win_domain.length].pack('vv') + win_domain
326
+ addr_list << [1, win_name.length].pack('vv') + win_name
327
+ addr_list << [4, dns_domain.length].pack('vv') + dns_domain
328
+ addr_list << [3, dns_name.length].pack('vv') + dns_name
329
+ addr_list << [7, 8].pack('vv') + timestamp
330
+
331
+ # MAY BE USEFUL FOR FUTURE
332
+ # Seven (client) add at least one more av that is of type MsAvRestrictions (8)
333
+ # maybe this will be usefull with future windows OSs but has no use at all for the moment afaik
334
+ # restriction_encoding = [48,0,0,0].pack("VVV") + # Size, Z4, IntegrityLevel, SubjectIntegrityLevel
335
+ # Rex::Text.rand_text(32) # MachineId generated on startup on win7 and above
336
+ # addr_list << [8, restriction_encoding.length].pack('vv') + restriction_encoding
337
+
338
+ # Seven (client) and maybe others versions also add an av of type MsvChannelBindings (10) but the hash is "\x00" * 16
339
+ # addr_list << [10, 16].pack('vv') + "\x00" * 16
340
+
341
+ # Seven and maybe other versions also add an av of type MsvAvTargetName(9) with value cifs/target(_ip)
342
+ # implementing it will necessary require knowing the target here, todo... :-/
343
+ # spn= Rex::Text.to_unicode("cifs/RHOST")
344
+ # addr_list << [9, spn.length].pack('vv') + spn
345
+
346
+ addr_list << [0, 0].pack('vv')
347
+ ntlm_clientchallenge = [1,1,0,0].pack("CCvV") + #RespType, HiRespType, Reserved1, Reserved2
348
+ timestamp + #Timestamp
349
+ client_challenge + #clientchallenge
350
+ [0].pack("V") + #Reserved3
351
+ addr_list + "\x00" * 4
352
+
353
+ end
354
+
355
+ end
356
+ end
357
+ end
358
+ end
@@ -8,8 +8,11 @@ require 'rex/struct2'
8
8
  require 'rex/proto/smb/constants'
9
9
  require 'rex/proto/smb/exceptions'
10
10
  require 'rex/proto/smb/evasions'
11
- require 'rex/proto/smb/crypt'
12
11
  require 'rex/proto/smb/utils'
12
+ require 'rex/proto/smb/crypt'
13
+ require 'rex/proto/ntlm/crypt'
14
+ require 'rex/proto/ntlm/constants'
15
+ require 'rex/proto/ntlm/utils'
13
16
 
14
17
 
15
18
  # Some short-hand class aliases
@@ -18,6 +21,9 @@ CRYPT = Rex::Proto::SMB::Crypt
18
21
  UTILS = Rex::Proto::SMB::Utils
19
22
  XCEPT = Rex::Proto::SMB::Exceptions
20
23
  EVADE = Rex::Proto::SMB::Evasions
24
+ NTLM_CRYPT = Rex::Proto::NTLM::Crypt
25
+ NTLM_CONST = Rex::Proto::NTLM::Constants
26
+ NTLM_UTILS = Rex::Proto::NTLM::Utils
21
27
 
22
28
  def initialize(socket)
23
29
  self.socket = socket
@@ -30,15 +36,28 @@ EVADE = Rex::Proto::SMB::Evasions
30
36
  self.read_timeout = 10
31
37
  self.evasion_opts = {
32
38
 
33
- # Padding is performed between packet headers and data
34
- 'pad_data' => EVADE::EVASION_NONE,
39
+ # Padding is performed between packet headers and data
40
+ 'pad_data' => EVADE::EVASION_NONE,
35
41
 
36
- # File path padding is performed on all open/create calls
37
- 'pad_file' => EVADE::EVASION_NONE,
42
+ # File path padding is performed on all open/create calls
43
+ 'pad_file' => EVADE::EVASION_NONE,
38
44
 
39
- # Modify the \PIPE\ string in trans_named_pipe calls
40
- 'obscure_trans_pipe' => EVADE::EVASION_NONE,
45
+ # Modify the \PIPE\ string in trans_named_pipe calls
46
+ 'obscure_trans_pipe' => EVADE::EVASION_NONE,
41
47
  }
48
+
49
+ self.verify_signature = false
50
+ self.use_ntlmv2 = false
51
+ self.usentlm2_session = true
52
+ self.send_lm = true
53
+ self.use_lanman_key = false
54
+ self.send_ntlm = true
55
+
56
+ # Signing
57
+ self.sequence_counter = 0
58
+ self.signing_key = ''
59
+ self.require_signing = false
60
+
42
61
  end
43
62
 
44
63
  # Read a SMB packet from the socket
@@ -73,7 +92,17 @@ EVADE = Rex::Proto::SMB::Evasions
73
92
  data << buff
74
93
  end
75
94
 
95
+ #signing
96
+ if self.require_signing && self.signing_key != ''
97
+ if self.verify_signature
98
+ raise XCEPT::IncorrectSigningError if not CRYPT::is_signature_correct?(self.signing_key,self.sequence_counter,data)
99
+ end
100
+ self.sequence_counter += 1
101
+ end
102
+
76
103
  return data
104
+
105
+
77
106
  end
78
107
 
79
108
  # Send a SMB packet down the socket
@@ -85,6 +114,12 @@ EVADE = Rex::Proto::SMB::Evasions
85
114
  size = 0
86
115
  wait = 0
87
116
 
117
+ #signing
118
+ if self.require_signing && self.signing_key != ''
119
+ data = CRYPT::sign_smb_packet(self.signing_key, self.sequence_counter, data)
120
+ self.sequence_counter += 1
121
+ end
122
+
88
123
  begin
89
124
  # Just send the packet and return
90
125
  if (size == 0 or size >= data.length)
@@ -121,7 +156,7 @@ EVADE = Rex::Proto::SMB::Evasions
121
156
  pkt = CONST::SMB_BASE_PKT.make_struct
122
157
  pkt.from_s(data)
123
158
  res = pkt
124
-
159
+
125
160
  begin
126
161
  case pkt['Payload']['SMB'].v['Command']
127
162
 
@@ -219,14 +254,14 @@ EVADE = Rex::Proto::SMB::Evasions
219
254
 
220
255
  # Process incoming SMB_COM_SESSION_SETUP_ANDX packets
221
256
  def smb_parse_session_setup(pkt, data)
222
- # Process NTLMv2 negotiate responses
257
+ # Process NTLMSSP negotiate responses
223
258
  if (pkt['Payload']['SMB'].v['WordCount'] == 4)
224
259
  res = CONST::SMB_SETUP_NTLMV2_RES_PKT.make_struct
225
260
  res.from_s(data)
226
261
  return res
227
262
  end
228
263
 
229
- # Process NTLMv1 and LANMAN responses
264
+ # Process LANMAN responses
230
265
  if (pkt['Payload']['SMB'].v['WordCount'] == 3)
231
266
  res = CONST::SMB_SETUP_RES_PKT.make_struct
232
267
  res.from_s(data)
@@ -436,7 +471,7 @@ EVADE = Rex::Proto::SMB::Evasions
436
471
  end
437
472
 
438
473
  # Negotiate a SMB dialect
439
- def negotiate(extended=true, do_recv = true)
474
+ def negotiate(smb_extended_security=true, do_recv = true)
440
475
 
441
476
  dialects = ['LANMAN1.0', 'LM1.2X002' ]
442
477
 
@@ -452,7 +487,7 @@ EVADE = Rex::Proto::SMB::Evasions
452
487
  pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NEGOTIATE
453
488
  pkt['Payload']['SMB'].v['Flags1'] = 0x18
454
489
 
455
- if(extended)
490
+ if(smb_extended_security)
456
491
  pkt['Payload']['SMB'].v['Flags2'] = 0x2801
457
492
  else
458
493
  pkt['Payload']['SMB'].v['Flags2'] = 0xc001
@@ -460,7 +495,7 @@ EVADE = Rex::Proto::SMB::Evasions
460
495
 
461
496
  pkt['Payload'].v['Payload'] = data
462
497
 
463
- ret = self.smb_send(pkt.to_s)
498
+ ret = self.smb_send(pkt.to_s, EVADE::EVASION_NONE)
464
499
  return ret if not do_recv
465
500
 
466
501
  ack = self.smb_recv_parse(CONST::SMB_COM_NEGOTIATE)
@@ -483,6 +518,11 @@ EVADE = Rex::Proto::SMB::Evasions
483
518
  # Set the security mode
484
519
  self.security_mode = ack['Payload'].v['SecurityMode']
485
520
 
521
+ #set require_signing
522
+ if (ack['Payload'].v['SecurityMode'] & 0x08 != 0)
523
+ self.require_signing = true
524
+ end
525
+
486
526
  # Set the challenge key
487
527
  if (ack['Payload'].v['EncryptionKey'] != nil)
488
528
  self.challenge_key = ack['Payload'].v['EncryptionKey']
@@ -530,15 +570,6 @@ EVADE = Rex::Proto::SMB::Evasions
530
570
  end
531
571
  self.system_zone = system_zone * 60
532
572
 
533
- # XXX: this is being commented out because ruby prior to 1.9.2 doesn't
534
- # seem to support representing non-utc or local times (eg, a time in
535
- # another timezone) If you know a way to do it in pre-1.9.2 please
536
- # tell us!
537
- =begin
538
- # Adjust the system_time object to reflect the remote timezone
539
- self.system_time = self.system_time.utc.localtime(system_zone)
540
- =end
541
-
542
573
  return ack
543
574
  end
544
575
 
@@ -547,15 +578,15 @@ EVADE = Rex::Proto::SMB::Evasions
547
578
  def session_setup(*args)
548
579
 
549
580
  if (self.dialect =~ /^(NT LANMAN 1.0|NT LM 0.12)$/)
550
-
551
-
581
+
552
582
  if (self.challenge_key)
553
- return self.session_setup_ntlmv1(*args)
583
+ return self.session_setup_no_ntlmssp(*args)
554
584
  end
555
585
 
556
586
  if ( self.extended_security )
557
- return self.session_setup_ntlmv2(*args)
587
+ return self.session_setup_with_ntlmssp(*args)
558
588
  end
589
+
559
590
  end
560
591
 
561
592
  return self.session_setup_clear(*args)
@@ -571,7 +602,14 @@ EVADE = Rex::Proto::SMB::Evasions
571
602
 
572
603
  pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_SESSION_SETUP_ANDX
573
604
  pkt['Payload']['SMB'].v['Flags1'] = 0x18
574
- pkt['Payload']['SMB'].v['Flags2'] = 0x2001
605
+ if self.require_signing
606
+ #ascii
607
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
608
+ else
609
+ #ascii
610
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
611
+ end
612
+
575
613
  pkt['Payload']['SMB'].v['WordCount'] = 10
576
614
  pkt['Payload'].v['AndX'] = 255
577
615
  pkt['Payload'].v['MaxBuff'] = 0xffdf
@@ -601,17 +639,36 @@ EVADE = Rex::Proto::SMB::Evasions
601
639
  return ack
602
640
  end
603
641
 
604
- # Authenticate using NTLMv1
605
- def session_setup_ntlmv1(user = '', pass = '', domain = '', do_recv = true)
642
+ # Authenticate without NTLMSSP
643
+ def session_setup_no_ntlmssp(user = '', pass = '', domain = '', do_recv = true)
606
644
 
645
+ # Requires a challenge key to have been seen during negotiation
607
646
  raise XCEPT::NTLM1MissingChallenge if not self.challenge_key
608
647
 
609
- if (pass.length == 65)
610
- hash_lm = CRYPT.e_p24( [ pass.upcase()[0,32] ].pack('H42'), self.challenge_key)
611
- hash_nt = CRYPT.e_p24( [ pass.upcase()[33,65] ].pack('H42'), self.challenge_key)
648
+ #
649
+ # We can not yet handle signing in this situation
650
+ # But instead of throwing an exception,we will disable signing, continue and hope for the best.
651
+ #
652
+
653
+ #raise XCEPT::SigningError if self.require_signing
654
+ self.require_signing = false if self.require_signing
655
+
656
+
657
+ if UTILS.is_pass_ntlm_hash?(pass)
658
+ arglm = {
659
+ :lm_hash => [ pass.upcase()[0,32] ].pack('H32'),
660
+ :challenge => self.challenge_key
661
+ }
662
+ hash_lm = NTLM_CRYPT::lm_response(arglm)
663
+
664
+ argntlm = {
665
+ :ntlm_hash => [ pass.upcase()[33,65] ].pack('H32'),
666
+ :challenge => self.challenge_key
667
+ }
668
+ hash_nt = NTLM_CRYPT::ntlm_response(argntlm)
612
669
  else
613
- hash_lm = pass.length > 0 ? CRYPT.lanman_des(pass, self.challenge_key) : ''
614
- hash_nt = pass.length > 0 ? CRYPT.ntlm_md4(pass, self.challenge_key) : ''
670
+ hash_lm = pass.length > 0 ? NTLM_CRYPT.lanman_des(pass, self.challenge_key) : ''
671
+ hash_nt = pass.length > 0 ? NTLM_CRYPT.ntlm_md4(pass, self.challenge_key) : ''
615
672
  end
616
673
 
617
674
  data = ''
@@ -660,8 +717,10 @@ EVADE = Rex::Proto::SMB::Evasions
660
717
  end
661
718
 
662
719
 
663
- # Authenticate using NTLMv1 with a precomputed hash pair
664
- def session_setup_ntlmv1_prehash(user, domain, hash_lm, hash_nt, do_recv = true)
720
+ # Authenticate without ntlmssp with a precomputed hash pair
721
+ def session_setup_no_ntlmssp_prehash(user, domain, hash_lm, hash_nt, do_recv = true)
722
+
723
+ raise XCEPT::NTLM2MissingChallenge if self.require_signing
665
724
 
666
725
  data = ''
667
726
  data << hash_lm
@@ -708,14 +767,40 @@ EVADE = Rex::Proto::SMB::Evasions
708
767
  return ack
709
768
  end
710
769
 
711
- # Authenticate using extended security negotiation (NTLMv2)
712
- def session_setup_ntlmv2(user = '', pass = '', domain = '', name = nil, do_recv = true)
770
+ # Authenticate using extended security negotiation
771
+ def session_setup_with_ntlmssp(user = '', pass = '', domain = '', name = nil, do_recv = true)
772
+
773
+ if require_signing
774
+ ntlmssp_flags = 0xe2088215
775
+ else
776
+
777
+ ntlmssp_flags = 0xa2080205
778
+ end
779
+
780
+ if self.usentlm2_session
781
+ if self.use_ntlmv2
782
+ #set Negotiate Target Info
783
+ ntlmssp_flags |= NTLM_CONST::NEGOTIATE_TARGET_INFO
784
+ end
785
+
786
+ else
787
+ #remove the ntlm2_session flag
788
+ ntlmssp_flags &= 0xfff7ffff
789
+ #set lanmanflag only when lm and ntlm are sent
790
+ if self.send_lm
791
+ ntlmssp_flags |= NTLM_CONST::NEGOTIATE_LMKEY if self.use_lanman_key
792
+ end
793
+ end
794
+
795
+ #we can also downgrade ntlm2_session when we send only lmv1
796
+ ntlmssp_flags &= 0xfff7ffff if self.usentlm2_session && (not self.use_ntlmv2) && (not self.send_ntlm)
797
+
713
798
 
714
799
  if (name == nil)
715
800
  name = Rex::Text.rand_text_alphanumeric(16)
716
801
  end
717
802
 
718
- blob = UTILS.make_ntlmv2_secblob_init(domain, name)
803
+ blob = NTLM_UTILS.make_ntlmssp_secblob_init(domain, name, ntlmssp_flags)
719
804
 
720
805
  native_data = ''
721
806
  native_data << self.native_os + "\x00"
@@ -726,26 +811,33 @@ EVADE = Rex::Proto::SMB::Evasions
726
811
 
727
812
  pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_SESSION_SETUP_ANDX
728
813
  pkt['Payload']['SMB'].v['Flags1'] = 0x18
729
- pkt['Payload']['SMB'].v['Flags2'] = 0x2801
814
+ if require_signing
815
+ #ascii
816
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
817
+ else
818
+ #ascii
819
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
820
+ end
730
821
  pkt['Payload']['SMB'].v['WordCount'] = 12
731
822
  pkt['Payload'].v['AndX'] = 255
732
823
  pkt['Payload'].v['MaxBuff'] = 0xffdf
733
824
  pkt['Payload'].v['MaxMPX'] = 2
734
825
  pkt['Payload'].v['VCNum'] = 1
735
826
  pkt['Payload'].v['SecurityBlobLen'] = blob.length
736
- pkt['Payload'].v['Capabilities'] = 0x8000d05c
827
+ pkt['Payload'].v['Capabilities'] = 0x800000d4
737
828
  pkt['Payload'].v['SessionKey'] = self.session_id
738
829
  pkt['Payload'].v['Payload'] = blob + native_data
739
830
 
740
831
  ret = self.smb_send(pkt.to_s)
832
+
741
833
  return ret if not do_recv
742
834
 
743
835
  ack = self.smb_recv_parse(CONST::SMB_COM_SESSION_SETUP_ANDX, true)
744
836
 
745
837
 
746
- # The server doesn't know about NTLM_NEGOTIATE, try ntlmv1
838
+ # The server doesn't know about NTLM_NEGOTIATE
747
839
  if (ack['Payload']['SMB'].v['ErrorClass'] == 0x00020002)
748
- return session_setup_ntlmv1(user, pass, domain)
840
+ return session_setup_no_ntlmssp(user, pass, domain)
749
841
  end
750
842
 
751
843
  # Make sure the error code tells us to continue processing
@@ -782,62 +874,326 @@ EVADE = Rex::Proto::SMB::Evasions
782
874
  # Extract the address list from the blob
783
875
  alist_len,alist_mlen,alist_off = blob[cidx + 40, 8].unpack("vvV")
784
876
  alist_buf = blob[cidx + alist_off, alist_len]
785
-
877
+ chall_MsvAvTimestamp = nil
786
878
  while(alist_buf.length > 0)
787
879
  atype, alen = alist_buf.slice!(0,4).unpack('vv')
788
880
  break if atype == 0x00
789
881
  addr = alist_buf.slice!(0, alen)
790
882
  case atype
791
883
  when 1
884
+ #netbios name
792
885
  self.default_name = addr.gsub("\x00", '')
793
886
  when 2
887
+ #netbios domain
794
888
  self.default_domain = addr.gsub("\x00", '')
795
889
  when 3
890
+ #dns name
796
891
  self.dns_host_name = addr.gsub("\x00", '')
797
892
  when 4
893
+ #dns domain
798
894
  self.dns_domain_name = addr.gsub("\x00", '')
799
895
  when 5
800
- # unknown
896
+ #The FQDN of the forest.
897
+ when 6
898
+ #A 32-bit value indicating server or client configuration
801
899
  when 7
802
- # client time
900
+ #Client time
901
+ chall_MsvAvTimestamp = addr
902
+ when 8
903
+ #A Restriction_Encoding structure
904
+ when 9
905
+ #The SPN of the target server.
906
+ when 10
907
+ #A channel bindings hash.
803
908
  end
804
909
  end
910
+
911
+ #calculate the lm/ntlm response
912
+ resp_lm = "\x00" * 24
913
+ resp_ntlm = "\x00" * 24
805
914
 
806
-
807
- # Generate a random client-side challenge
808
915
  client_challenge = Rex::Text.rand_text(8)
916
+ ntlm_cli_challenge = ''
917
+ if self.send_ntlm #should be default
918
+ if self.usentlm2_session
919
+
920
+ if self.use_ntlmv2
921
+ # This is only a partial implementation, in some situation recent servers may send STATUS_INVALID_PARAMETER
922
+ # answer must then be somewhere in [MS-NLMP].pdf around 3.1.5.2.1 :-/
923
+ ntlm_cli_challenge = NTLM_UTILS::make_ntlmv2_clientchallenge(default_domain, default_name, dns_domain_name,
924
+ dns_host_name,client_challenge , chall_MsvAvTimestamp)
925
+ if UTILS.is_pass_ntlm_hash?(pass)
926
+ argntlm = {
927
+ :ntlmv2_hash => NTLM_CRYPT::ntlmv2_hash(
928
+ user,
929
+ [ pass.upcase()[33,65] ].pack('H32'),
930
+ domain,{:pass_is_hash => true}
931
+ ),
932
+ :challenge => self.challenge_key
933
+ }
934
+ else
935
+ argntlm = {
936
+ :ntlmv2_hash => NTLM_CRYPT::ntlmv2_hash(user, pass, domain),
937
+ :challenge => self.challenge_key
938
+ }
939
+ end
940
+
941
+ optntlm = { :nt_client_challenge => ntlm_cli_challenge}
942
+ ntlmv2_response = NTLM_CRYPT::ntlmv2_response(argntlm,optntlm)
943
+ resp_ntlm = ntlmv2_response
944
+
945
+ if self.send_lm
946
+ if UTILS.is_pass_ntlm_hash?(pass)
947
+ arglm = {
948
+ :ntlmv2_hash => NTLM_CRYPT::ntlmv2_hash(
949
+ user,
950
+ [ pass.upcase()[33,65] ].pack('H32'),
951
+ domain,{:pass_is_hash => true}
952
+ ),
953
+ :challenge => self.challenge_key
954
+ }
955
+ else
956
+ arglm = {
957
+ :ntlmv2_hash => NTLM_CRYPT::ntlmv2_hash(user,pass, domain),
958
+ :challenge => self.challenge_key
959
+ }
960
+ end
961
+
962
+ optlm = { :client_challenge => client_challenge }
963
+ resp_lm = NTLM_CRYPT::lmv2_response(arglm, optlm)
964
+ else
965
+ resp_lm = "\x00" * 24
966
+ end
967
+
968
+ else # ntlm2_session
969
+ if UTILS.is_pass_ntlm_hash?(pass)
970
+ argntlm = {
971
+ :ntlm_hash => [ pass.upcase()[33,65] ].pack('H32'),
972
+ :challenge => self.challenge_key
973
+ }
974
+ else
975
+ argntlm = {
976
+ :ntlm_hash => NTLM_CRYPT::ntlm_hash(pass),
977
+ :challenge => self.challenge_key
978
+ }
979
+ end
980
+
981
+ optntlm = { :client_challenge => client_challenge}
982
+ resp_ntlm = NTLM_CRYPT::ntlm2_session(argntlm,optntlm).join[24,24]
983
+
984
+ # Generate the fake LANMAN hash
985
+ resp_lm = client_challenge + ("\x00" * 16)
986
+ end
809
987
 
810
- # Generate the nonce
811
- nonce = CRYPT.md5_hash(self.challenge_key + client_challenge)
812
-
813
- # Generate the NTLM hash
814
- if (pass.length == 65)
815
- resp_ntlm = CRYPT.e_p24( [ pass.upcase()[33,65] ].pack('H42'), nonce[0, 8])
816
- else
817
- resp_ntlm = CRYPT.ntlm_md4(pass, nonce[0, 8])
818
- end
988
+ else # we use lmv1/ntlmv1
989
+ if UTILS.is_pass_ntlm_hash?(pass)
990
+ argntlm = {
991
+ :ntlm_hash => [ pass.upcase()[33,65] ].pack('H32'),
992
+ :challenge => self.challenge_key
993
+ }
994
+ else
995
+ argntlm = {
996
+ :ntlm_hash => NTLM_CRYPT::ntlm_hash(pass),
997
+ :challenge => self.challenge_key
998
+ }
999
+ end
1000
+
1001
+ resp_ntlm = NTLM_CRYPT::ntlm_response(argntlm)
1002
+ if self.send_lm
1003
+ if UTILS.is_pass_ntlm_hash?(pass)
1004
+ arglm = {
1005
+ :lm_hash => [ pass.upcase()[0,32] ].pack('H32'),
1006
+ :challenge => self.challenge_key
1007
+ }
1008
+ else
1009
+ arglm = {
1010
+ :lm_hash => NTLM_CRYPT::lm_hash(pass),
1011
+ :challenge => self.challenge_key
1012
+ }
1013
+ end
1014
+ resp_lm = NTLM_CRYPT::lm_response(arglm)
1015
+ else
1016
+ #when windows does not send lm in ntlmv1 type response,
1017
+ # it gives lm response the same value as ntlm response
1018
+ resp_lm = resp_ntlm
1019
+ end
1020
+ end
1021
+ else #send_ntlm = false
1022
+ #lmv2
1023
+ if self.usentlm2_session && self.use_ntlmv2
1024
+ if UTILS.is_pass_ntlm_hash?(pass)
1025
+ arglm = {
1026
+ :ntlmv2_hash => NTLM_CRYPT::ntlmv2_hash(
1027
+ user,
1028
+ [ pass.upcase()[33,65] ].pack('H32'),
1029
+ domain,{:pass_is_hash => true}
1030
+ ),
1031
+ :challenge => self.challenge_key
1032
+ }
1033
+ else
1034
+ arglm = {
1035
+ :ntlmv2_hash => NTLM_CRYPT::ntlmv2_hash(user,pass, domain),
1036
+ :challenge => self.challenge_key
1037
+ }
1038
+ end
1039
+ optlm = { :client_challenge => client_challenge }
1040
+ resp_lm = NTLM_CRYPT::lmv2_response(arglm, optlm)
1041
+ else
1042
+ if UTILS.is_pass_ntlm_hash?(pass)
1043
+ arglm = {
1044
+ :lm_hash => [ pass.upcase()[0,32] ].pack('H32'),
1045
+ :challenge => self.challenge_key
1046
+ }
1047
+ else
1048
+ arglm = {
1049
+ :lm_hash => NTLM_CRYPT::lm_hash(pass),
1050
+ :challenge => self.challenge_key
1051
+ }
1052
+ end
1053
+ resp_lm = NTLM_CRYPT::lm_response(arglm)
1054
+ end
1055
+ resp_ntlm = ""
1056
+ end
1057
+
1058
+
1059
+ # Create the sessionkey (aka signing key, aka mackey) and encrypted session key
1060
+ # Server will decide for key_size and key_exchange
1061
+ enc_session_key = ''
1062
+ if self.require_signing
1063
+
1064
+ server_ntlmssp_flags = blob[cidx + 20, 4].unpack("V")[0]
1065
+ # Set default key size and key exchange values
1066
+ key_size = 40
1067
+ key_exchange = false
1068
+ # Remove ntlmssp.negotiate56
1069
+ ntlmssp_flags &= 0x7fffffff
1070
+ # Remove ntlmssp.negotiatekeyexch
1071
+ ntlmssp_flags &= 0xbfffffff
1072
+ # Remove ntlmssp.negotiate128
1073
+ ntlmssp_flags &= 0xdfffffff
1074
+ # Check the keyexchange
1075
+ if server_ntlmssp_flags & NTLM_CONST::NEGOTIATE_KEY_EXCH != 0 then
1076
+ key_exchange = true
1077
+ ntlmssp_flags |= NTLM_CONST::NEGOTIATE_KEY_EXCH
1078
+ end
1079
+ # Check 128bits
1080
+ if server_ntlmssp_flags & NTLM_CONST::NEGOTIATE_128 != 0 then
1081
+ key_size = 128
1082
+ ntlmssp_flags |= NTLM_CONST::NEGOTIATE_128
1083
+ ntlmssp_flags |= NTLM_CONST::NEGOTIATE_56
1084
+ # Check 56bits
1085
+ else
1086
+ if server_ntlmssp_flags & NTLM_CONST::NEGOTIATE_56 != 0 then
1087
+ key_size = 56
1088
+ ntlmssp_flags |= NTLM_CONST::NEGOTIATE_56
1089
+ end
1090
+ end
819
1091
 
820
- # Generate the fake LANMAN hash
821
- resp_lmv2 = client_challenge + ("\x00" * 16)
1092
+ # Generate the user session key
1093
+ lanman_weak = false
1094
+
1095
+ if self.send_ntlm # Should be default
1096
+ if self.usentlm2_session
1097
+ if self.use_ntlmv2
1098
+ if UTILS.is_pass_ntlm_hash?(pass)
1099
+ user_session_key = NTLM_CRYPT::ntlmv2_user_session_key(user,
1100
+ [ pass.upcase()[33,65] ].pack('H32'),
1101
+ domain,
1102
+ self.challenge_key, ntlm_cli_challenge,
1103
+ {:pass_is_hash => true})
1104
+ else
1105
+ user_session_key = NTLM_CRYPT::ntlmv2_user_session_key(user, pass, domain,
1106
+ self.challenge_key, ntlm_cli_challenge)
1107
+ end
1108
+ else
1109
+ if UTILS.is_pass_ntlm_hash?(pass)
1110
+ user_session_key = NTLM_CRYPT::ntlm2_session_user_session_key([ pass.upcase()[33,65] ].pack('H32'),
1111
+ self.challenge_key,
1112
+ client_challenge,
1113
+ {:pass_is_hash => true})
1114
+ else
1115
+ user_session_key = NTLM_CRYPT::ntlm2_session_user_session_key(pass, self.challenge_key,
1116
+ client_challenge)
1117
+ end
1118
+ end
1119
+ else # lmv1/ntlmv1
1120
+ if self.send_lm
1121
+ if self.use_lanman_key
1122
+ if UTILS.is_pass_ntlm_hash?(pass)
1123
+ user_session_key = NTLM_CRYPT::lanman_session_key([ pass.upcase()[0,32] ].pack('H32'),
1124
+ self.challenge_key,
1125
+ {:pass_is_hash => true})
1126
+ else
1127
+ user_session_key = NTLM_CRYPT::lanman_session_key(pass, self.challenge_key)
1128
+ end
1129
+ lanman_weak = true
1130
+ else
1131
+ if UTILS.is_pass_ntlm_hash?(pass)
1132
+ user_session_key = NTLM_CRYPT::ntlmv1_user_session_key([ pass.upcase()[33,65] ].pack('H32'),
1133
+ {:pass_is_hash => true})
1134
+ else
1135
+ user_session_key = NTLM_CRYPT::ntlmv1_user_session_key(pass)
1136
+ end
1137
+
1138
+ end
1139
+ end
1140
+ end
1141
+ else
1142
+ if self.usentlm2_session && self.use_ntlmv2
1143
+ if UTILS.is_pass_ntlm_hash?(pass)
1144
+ user_session_key = NTLM_CRYPT::lmv2_user_session_key(user, [ pass.upcase()[33,65] ].pack('H32'),
1145
+ domain,
1146
+ self.challenge_key, client_challenge,
1147
+ {:pass_is_hash => true})
1148
+ else
1149
+ user_session_key = NTLM_CRYPT::lmv2_user_session_key(user, pass, domain,
1150
+ self.challenge_key, client_challenge)
1151
+ end
1152
+ else
1153
+ if UTILS.is_pass_ntlm_hash?(pass)
1154
+ user_session_key = NTLM_CRYPT::lmv1_user_session_key([ pass.upcase()[0,32] ].pack('H32'),
1155
+ {:pass_is_hash => true})
1156
+ else
1157
+ user_session_key = NTLM_CRYPT::lmv1_user_session_key(pass)
1158
+ end
1159
+ end
1160
+ end
822
1161
 
823
- # Create the ntlmv2 security blob data
824
- blob = UTILS.make_ntlmv2_secblob_auth(domain, name, user, resp_lmv2, resp_ntlm)
1162
+ user_session_key = NTLM_CRYPT::make_weak_sessionkey(user_session_key,key_size, lanman_weak)
1163
+ self.sequence_counter = 0
1164
+ # Sessionkey and encrypted session key
1165
+ if key_exchange
1166
+ self.signing_key = Rex::Text.rand_text(16)
1167
+ enc_session_key = NTLM_CRYPT::encrypt_sessionkey(self.signing_key, user_session_key)
1168
+ else
1169
+ self.signing_key = user_session_key
1170
+ end
1171
+
1172
+ end
1173
+ # Create the security blob data
1174
+ blob = NTLM_UTILS.make_ntlmssp_secblob_auth(domain, name, user, resp_lm, resp_ntlm, enc_session_key, ntlmssp_flags)
825
1175
 
826
1176
  pkt = CONST::SMB_SETUP_NTLMV2_PKT.make_struct
827
1177
  self.smb_defaults(pkt['Payload']['SMB'])
828
1178
 
829
1179
  pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_SESSION_SETUP_ANDX
830
1180
  pkt['Payload']['SMB'].v['Flags1'] = 0x18
831
- pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1181
+ if self.require_signing
1182
+ #ascii
1183
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1184
+ else
1185
+ #ascii
1186
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1187
+ end
832
1188
  pkt['Payload']['SMB'].v['WordCount'] = 12
833
1189
  pkt['Payload']['SMB'].v['UserID'] = temp_user_id
834
1190
  pkt['Payload'].v['AndX'] = 255
835
1191
  pkt['Payload'].v['MaxBuff'] = 0xffdf
836
1192
  pkt['Payload'].v['MaxMPX'] = 2
837
1193
  pkt['Payload'].v['VCNum'] = 1
838
- pkt['Payload'].v['SecurityBlobLen'] = blob.length
839
1194
  pkt['Payload'].v['Capabilities'] = 0x8000d05c
840
1195
  pkt['Payload'].v['SessionKey'] = self.session_id
1196
+ pkt['Payload'].v['SecurityBlobLen'] = blob.length
841
1197
  pkt['Payload'].v['Payload'] = blob + native_data
842
1198
 
843
1199
  # NOTE: if do_recv is set to false, we cant reach here...
@@ -847,8 +1203,13 @@ EVADE = Rex::Proto::SMB::Evasions
847
1203
 
848
1204
  # Make sure that authentication succeeded
849
1205
  if (ack['Payload']['SMB'].v['ErrorClass'] != 0)
1206
+
850
1207
  if (user.length == 0)
851
- return self.session_setup_ntlmv1(user, pass, domain)
1208
+ # Ensure that signing is disabled when we hit this corner case
1209
+ self.require_signing = false
1210
+
1211
+ # Fall back to the non-ntlmssp authentication method
1212
+ return self.session_setup_no_ntlmssp(user, pass, domain)
852
1213
  end
853
1214
 
854
1215
  failure = XCEPT::ErrorCode.new
@@ -869,7 +1230,7 @@ EVADE = Rex::Proto::SMB::Evasions
869
1230
 
870
1231
 
871
1232
  # An exploit helper function for sending arbitrary SPNEGO blobs
872
- def session_setup_ntlmv2_blob(blob = '', do_recv = true)
1233
+ def session_setup_with_ntlmssp_blob(blob = '', do_recv = true)
873
1234
  native_data = ''
874
1235
  native_data << self.native_os + "\x00"
875
1236
  native_data << self.native_lm + "\x00"
@@ -898,14 +1259,14 @@ EVADE = Rex::Proto::SMB::Evasions
898
1259
  end
899
1260
 
900
1261
 
901
- # Authenticate using extended security negotiation (NTLMv2), but stop half-way, using the temporary ID
902
- def session_setup_ntlmv2_temp(domain = '', name = nil, do_recv = true)
1262
+ # Authenticate using extended security negotiation (NTLMSSP), but stop half-way, using the temporary ID
1263
+ def session_setup_with_ntlmssp_temp(domain = '', name = nil, do_recv = true)
903
1264
 
904
1265
  if (name == nil)
905
1266
  name = Rex::Text.rand_text_alphanumeric(16)
906
1267
  end
907
1268
 
908
- blob = UTILS.make_ntlmv2_secblob_init(domain, name)
1269
+ blob = NTLM_UTILS.make_ntlmssp_secblob_init(domain, name)
909
1270
 
910
1271
  native_data = ''
911
1272
  native_data << self.native_os + "\x00"
@@ -934,7 +1295,7 @@ EVADE = Rex::Proto::SMB::Evasions
934
1295
 
935
1296
  # The server doesn't know about NTLM_NEGOTIATE, try ntlmv1
936
1297
  if (ack['Payload']['SMB'].v['ErrorClass'] == 0x00020002)
937
- return session_setup_ntlmv1(user, pass, domain)
1298
+ return session_setup_no_ntlmssp(user, pass, domain)
938
1299
  end
939
1300
 
940
1301
  # Make sure the error code tells us to continue processing
@@ -981,7 +1342,14 @@ EVADE = Rex::Proto::SMB::Evasions
981
1342
 
982
1343
  pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_TREE_CONNECT_ANDX
983
1344
  pkt['Payload']['SMB'].v['Flags1'] = 0x18
984
- pkt['Payload']['SMB'].v['Flags2'] = 0x2001
1345
+ if self.require_signing
1346
+ #ascii
1347
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1348
+ else
1349
+ #ascii
1350
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1351
+ end
1352
+
985
1353
  pkt['Payload']['SMB'].v['WordCount'] = 4
986
1354
  pkt['Payload'].v['AndX'] = 255
987
1355
  pkt['Payload'].v['PasswordLen'] = pass.length + 1
@@ -1008,7 +1376,14 @@ EVADE = Rex::Proto::SMB::Evasions
1008
1376
 
1009
1377
  pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_TREE_DISCONNECT
1010
1378
  pkt['Payload']['SMB'].v['Flags1'] = 0x18
1011
- pkt['Payload']['SMB'].v['Flags2'] = 0x2001
1379
+ if self.require_signing
1380
+ #ascii
1381
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1382
+ else
1383
+ #ascii
1384
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1385
+ end
1386
+
1012
1387
  pkt['Payload']['SMB'].v['WordCount'] = 0
1013
1388
  pkt['Payload']['SMB'].v['TreeID'] = tree_id
1014
1389
 
@@ -1037,7 +1412,14 @@ EVADE = Rex::Proto::SMB::Evasions
1037
1412
 
1038
1413
  pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NT_CREATE_ANDX
1039
1414
  pkt['Payload']['SMB'].v['Flags1'] = 0x18
1040
- pkt['Payload']['SMB'].v['Flags2'] = 0x2001
1415
+ if self.require_signing
1416
+ #ascii
1417
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1418
+ else
1419
+ #ascii
1420
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1421
+ end
1422
+
1041
1423
  pkt['Payload']['SMB'].v['WordCount'] = 24
1042
1424
 
1043
1425
  pkt['Payload'].v['AndX'] = 255
@@ -1071,7 +1453,14 @@ EVADE = Rex::Proto::SMB::Evasions
1071
1453
 
1072
1454
  pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_DELETE
1073
1455
  pkt['Payload']['SMB'].v['Flags1'] = 0x18
1074
- pkt['Payload']['SMB'].v['Flags2'] = 0x2001
1456
+ if self.require_signing
1457
+ #ascii
1458
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1459
+ else
1460
+ #ascii
1461
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1462
+ end
1463
+
1075
1464
  pkt['Payload']['SMB'].v['TreeID'] = tree_id
1076
1465
  pkt['Payload']['SMB'].v['WordCount'] = 1
1077
1466
 
@@ -1095,7 +1484,14 @@ EVADE = Rex::Proto::SMB::Evasions
1095
1484
 
1096
1485
  pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_OPEN_ANDX
1097
1486
  pkt['Payload']['SMB'].v['Flags1'] = 0x18
1098
- pkt['Payload']['SMB'].v['Flags2'] = 0x2001
1487
+ if self.require_signing
1488
+ #ascii
1489
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1490
+ else
1491
+ #ascii
1492
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1493
+ end
1494
+
1099
1495
  pkt['Payload']['SMB'].v['WordCount'] = 15
1100
1496
 
1101
1497
  pkt['Payload'].v['AndX'] = 255
@@ -1125,7 +1521,14 @@ EVADE = Rex::Proto::SMB::Evasions
1125
1521
 
1126
1522
  pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_CLOSE
1127
1523
  pkt['Payload']['SMB'].v['Flags1'] = 0x18
1128
- pkt['Payload']['SMB'].v['Flags2'] = 0x2001
1524
+ if self.require_signing
1525
+ #ascii
1526
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1527
+ else
1528
+ #ascii
1529
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1530
+ end
1531
+
1129
1532
  pkt['Payload']['SMB'].v['TreeID'] = tree_id
1130
1533
  pkt['Payload']['SMB'].v['WordCount'] = 3
1131
1534
 
@@ -1140,10 +1543,8 @@ EVADE = Rex::Proto::SMB::Evasions
1140
1543
  return ack
1141
1544
  end
1142
1545
 
1143
-
1144
1546
  # Writes data to an open file handle
1145
1547
  def write(file_id = self.last_file_id, offset = 0, data = '', do_recv = true)
1146
-
1147
1548
  pkt = CONST::SMB_WRITE_PKT.make_struct
1148
1549
  self.smb_defaults(pkt['Payload']['SMB'])
1149
1550
 
@@ -1153,7 +1554,14 @@ EVADE = Rex::Proto::SMB::Evasions
1153
1554
 
1154
1555
  pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_WRITE_ANDX
1155
1556
  pkt['Payload']['SMB'].v['Flags1'] = 0x18
1156
- pkt['Payload']['SMB'].v['Flags2'] = 0x2001
1557
+ if self.require_signing
1558
+ #ascii
1559
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2805
1560
+ else
1561
+ #ascii
1562
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1563
+ end
1564
+
1157
1565
  pkt['Payload']['SMB'].v['WordCount'] = 14
1158
1566
 
1159
1567
  pkt['Payload'].v['AndX'] = 255
@@ -1184,7 +1592,14 @@ EVADE = Rex::Proto::SMB::Evasions
1184
1592
 
1185
1593
  pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_READ_ANDX
1186
1594
  pkt['Payload']['SMB'].v['Flags1'] = 0x18
1187
- pkt['Payload']['SMB'].v['Flags2'] = 0x2001
1595
+ if self.require_signing
1596
+ #ascii
1597
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1598
+ else
1599
+ #ascii
1600
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1601
+ end
1602
+
1188
1603
  pkt['Payload']['SMB'].v['WordCount'] = 10
1189
1604
 
1190
1605
  pkt['Payload'].v['AndX'] = 255
@@ -1272,7 +1687,14 @@ EVADE = Rex::Proto::SMB::Evasions
1272
1687
 
1273
1688
  pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_TRANSACTION
1274
1689
  pkt['Payload']['SMB'].v['Flags1'] = 0x18
1275
- pkt['Payload']['SMB'].v['Flags2'] = 0x2001
1690
+ if self.require_signing
1691
+ #ascii
1692
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1693
+ else
1694
+ #ascii
1695
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1696
+ end
1697
+
1276
1698
  pkt['Payload']['SMB'].v['WordCount'] = 14 + setup_count
1277
1699
 
1278
1700
  pkt['Payload'].v['ParamCountTotal'] = param.length
@@ -1343,7 +1765,14 @@ EVADE = Rex::Proto::SMB::Evasions
1343
1765
 
1344
1766
  pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_TRANSACTION
1345
1767
  pkt['Payload']['SMB'].v['Flags1'] = 0x18
1346
- pkt['Payload']['SMB'].v['Flags2'] = 0x2001
1768
+ if self.require_signing
1769
+ #ascii
1770
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1771
+ else
1772
+ #ascii
1773
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1774
+ end
1775
+
1347
1776
  pkt['Payload']['SMB'].v['WordCount'] = 14 + setup_count
1348
1777
 
1349
1778
  pkt['Payload'].v['ParamCountTotal'] = param.length
@@ -1406,7 +1835,14 @@ EVADE = Rex::Proto::SMB::Evasions
1406
1835
 
1407
1836
  pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_TRANSACTION
1408
1837
  pkt['Payload']['SMB'].v['Flags1'] = 0x18
1409
- pkt['Payload']['SMB'].v['Flags2'] = 0x2001
1838
+ if self.require_signing
1839
+ #ascii
1840
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1841
+ else
1842
+ #ascii
1843
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1844
+ end
1845
+
1410
1846
  pkt['Payload']['SMB'].v['WordCount'] = 14 + setup_count
1411
1847
 
1412
1848
  pkt['Payload'].v['ParamCountTotal'] = param.length
@@ -1449,7 +1885,14 @@ EVADE = Rex::Proto::SMB::Evasions
1449
1885
 
1450
1886
  pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_TRANSACTION2
1451
1887
  pkt['Payload']['SMB'].v['Flags1'] = 0x18
1452
- pkt['Payload']['SMB'].v['Flags2'] = 0x2001
1888
+ if self.require_signing
1889
+ #ascii
1890
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1891
+ else
1892
+ #ascii
1893
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1894
+ end
1895
+
1453
1896
  pkt['Payload']['SMB'].v['WordCount'] = 14 + setup_count
1454
1897
 
1455
1898
  pkt['Payload'].v['ParamCountTotal'] = param.length
@@ -1488,7 +1931,14 @@ EVADE = Rex::Proto::SMB::Evasions
1488
1931
 
1489
1932
  pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NT_TRANSACT
1490
1933
  pkt['Payload']['SMB'].v['Flags1'] = 0x18
1491
- pkt['Payload']['SMB'].v['Flags2'] = 0x2001
1934
+ if self.require_signing
1935
+ #ascii
1936
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1937
+ else
1938
+ #ascii
1939
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1940
+ end
1941
+
1492
1942
  pkt['Payload']['SMB'].v['WordCount'] = 19 + setup_count
1493
1943
 
1494
1944
  pkt['Payload'].v['ParamCountTotal'] = param.length
@@ -1526,7 +1976,14 @@ EVADE = Rex::Proto::SMB::Evasions
1526
1976
 
1527
1977
  pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NT_TRANSACT_SECONDARY
1528
1978
  pkt['Payload']['SMB'].v['Flags1'] = 0x18
1529
- pkt['Payload']['SMB'].v['Flags2'] = 0x2001
1979
+ if self.require_signing
1980
+ #ascii
1981
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1982
+ else
1983
+ #ascii
1984
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1985
+ end
1986
+
1530
1987
  pkt['Payload']['SMB'].v['WordCount'] = 18
1531
1988
 
1532
1989
  pkt['Payload'].v['ParamCountTotal'] = param.length
@@ -1757,7 +2214,8 @@ EVADE = Rex::Proto::SMB::Evasions
1757
2214
 
1758
2215
  # public read/write methods
1759
2216
  attr_accessor :native_os, :native_lm, :encrypt_passwords, :extended_security, :read_timeout, :evasion_opts
1760
- attr_accessor :system_time, :system_zone
2217
+ attr_accessor :verify_signature, :use_ntlmv2, :usentlm2_session, :send_lm, :use_lanman_key, :send_ntlm
2218
+ attr_accessor :system_time, :system_zone
1761
2219
 
1762
2220
  # public read methods
1763
2221
  attr_reader :dialect, :session_id, :challenge_key, :peer_native_lm, :peer_native_os
@@ -1765,6 +2223,8 @@ EVADE = Rex::Proto::SMB::Evasions
1765
2223
  attr_reader :multiplex_id, :last_tree_id, :last_file_id, :process_id, :last_search_id
1766
2224
  attr_reader :dns_host_name, :dns_domain_name
1767
2225
  attr_reader :security_mode, :server_guid
2226
+ #signing related
2227
+ attr_reader :sequence_counter,:signing_key, :require_signing
1768
2228
 
1769
2229
  # private methods
1770
2230
  attr_writer :dialect, :session_id, :challenge_key, :peer_native_lm, :peer_native_os
@@ -1772,6 +2232,8 @@ EVADE = Rex::Proto::SMB::Evasions
1772
2232
  attr_writer :dns_host_name, :dns_domain_name
1773
2233
  attr_writer :multiplex_id, :last_tree_id, :last_file_id, :process_id, :last_search_id
1774
2234
  attr_writer :security_mode, :server_guid
2235
+ #signing related
2236
+ attr_writer :sequence_counter,:signing_key, :require_signing
1775
2237
 
1776
2238
  attr_accessor :socket
1777
2239