librex 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
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