manual installed 3rd party tools
This commit is contained in:
179
usr/local/bin/framework/win32/lsasecrets.py
Normal file
179
usr/local/bin/framework/win32/lsasecrets.py
Normal file
@@ -0,0 +1,179 @@
|
||||
# This file is part of creddump.
|
||||
#
|
||||
# creddump is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# creddump is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with creddump. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# pylint: disable=missing-docstring
|
||||
|
||||
"""
|
||||
@author: Brendan Dolan-Gavitt
|
||||
@license: GNU General Public License 2.0 or later
|
||||
@contact: bdolangavitt@wesleyan.edu
|
||||
"""
|
||||
|
||||
from Crypto.Hash import MD5, SHA256
|
||||
from Crypto.Cipher import ARC4, DES, AES
|
||||
|
||||
from framework.win32.rawreg import get_root, open_key, subkeys, unpack
|
||||
from framework.addrspace import HiveFileAddressSpace
|
||||
from framework.win32.hashdump import get_bootkey, str_to_key
|
||||
|
||||
|
||||
def get_lsa_key(secaddr, bootkey, vista):
|
||||
root = get_root(secaddr)
|
||||
if not root:
|
||||
return None
|
||||
|
||||
if vista:
|
||||
enc_reg_key = open_key(root, ["Policy", "PolEKList"])
|
||||
else:
|
||||
enc_reg_key = open_key(root, ["Policy", "PolSecretEncryptionKey"])
|
||||
|
||||
if not enc_reg_key:
|
||||
return None
|
||||
|
||||
enc_reg_value = enc_reg_key.ValueList.List[0]
|
||||
if not enc_reg_value:
|
||||
return None
|
||||
|
||||
obf_lsa_key = secaddr.read(enc_reg_value.Data.value,
|
||||
enc_reg_value.DataLength.value)
|
||||
if not obf_lsa_key:
|
||||
return None
|
||||
|
||||
if not vista:
|
||||
md5 = MD5.new()
|
||||
md5.update(bootkey)
|
||||
for __ in range(1000):
|
||||
md5.update(obf_lsa_key[60:76])
|
||||
rc4key = md5.digest()
|
||||
rc4 = ARC4.new(rc4key)
|
||||
lsa_key = rc4.decrypt(obf_lsa_key[12:60])
|
||||
lsa_key = lsa_key[0x10:0x20]
|
||||
else:
|
||||
lsa_key = decrypt_aes(obf_lsa_key, bootkey)
|
||||
lsa_key = lsa_key[68:100]
|
||||
|
||||
return lsa_key
|
||||
|
||||
|
||||
def decrypt_secret(secret, key):
|
||||
"""Python implementation of SystemFunction005.
|
||||
|
||||
Decrypts a block of data with DES using given key.
|
||||
Note that key can be longer than 7 bytes."""
|
||||
decrypted_data = bytearray()
|
||||
j = 0 # key index
|
||||
for i in range(0, len(secret), 8):
|
||||
enc_block = secret[i:i + 8]
|
||||
block_key = key[j:j + 7]
|
||||
des_key = str_to_key(block_key)
|
||||
|
||||
des = DES.new(des_key, DES.MODE_ECB)
|
||||
decrypted_data += des.decrypt(enc_block)
|
||||
|
||||
j += 7
|
||||
if len(key[j:j + 7]) < 7:
|
||||
j = len(key[j:j + 7])
|
||||
|
||||
(dec_data_len,) = unpack("<L", decrypted_data[:4])
|
||||
return decrypted_data[8:8 + dec_data_len]
|
||||
|
||||
|
||||
def decrypt_aes(secret, key):
|
||||
sha = SHA256.new()
|
||||
sha.update(key)
|
||||
for _i in range(1, 1000 + 1):
|
||||
sha.update(secret[28:60])
|
||||
aeskey = sha.digest()
|
||||
|
||||
data = bytearray()
|
||||
for i in range(60, len(secret), 16):
|
||||
aes = AES.new(aeskey, AES.MODE_CBC, b"\x00" * 16)
|
||||
buf = secret[i: i + 16]
|
||||
if len(buf) < 16:
|
||||
buf += (16 - len(buf)) * b"\00"
|
||||
|
||||
data += aes.decrypt(buf)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def get_secret_by_name(secaddr, name, lsakey, vista):
|
||||
root = get_root(secaddr)
|
||||
if not root:
|
||||
return None
|
||||
|
||||
enc_secret_key = open_key(root, ["Policy", "Secrets", name, "CurrVal"])
|
||||
if not enc_secret_key:
|
||||
return None
|
||||
|
||||
enc_secret_value = enc_secret_key.ValueList.List[0]
|
||||
if not enc_secret_value:
|
||||
return None
|
||||
|
||||
enc_secret = secaddr.read(enc_secret_value.Data.value,
|
||||
enc_secret_value.DataLength.value)
|
||||
if not enc_secret:
|
||||
return None
|
||||
|
||||
if vista:
|
||||
secret = decrypt_aes(enc_secret, lsakey)
|
||||
else:
|
||||
secret = decrypt_secret(enc_secret[0xC:], lsakey)
|
||||
|
||||
return secret
|
||||
|
||||
|
||||
def get_secrets(sysaddr, secaddr, vista):
|
||||
root = get_root(secaddr)
|
||||
if not root:
|
||||
return None
|
||||
|
||||
bootkey = get_bootkey(sysaddr)
|
||||
lsakey = get_lsa_key(secaddr, bootkey, vista)
|
||||
|
||||
secrets_key = open_key(root, ["Policy", "Secrets"])
|
||||
if not secrets_key:
|
||||
return None
|
||||
|
||||
secrets = {}
|
||||
for key in subkeys(secrets_key):
|
||||
sec_val_key = open_key(key, ["CurrVal"])
|
||||
if not sec_val_key:
|
||||
continue
|
||||
|
||||
enc_secret_value = sec_val_key.ValueList.List[0]
|
||||
if not enc_secret_value:
|
||||
continue
|
||||
|
||||
enc_secret = secaddr.read(enc_secret_value.Data.value,
|
||||
enc_secret_value.DataLength.value)
|
||||
if not enc_secret:
|
||||
continue
|
||||
|
||||
if vista:
|
||||
secret = decrypt_aes(enc_secret, lsakey)
|
||||
else:
|
||||
secret = decrypt_secret(enc_secret[0xC:], lsakey)
|
||||
|
||||
secrets[key.Name] = secret
|
||||
|
||||
return secrets
|
||||
|
||||
|
||||
def get_file_secrets(sysfile, secfile, vista):
|
||||
sysaddr = HiveFileAddressSpace(sysfile)
|
||||
secaddr = HiveFileAddressSpace(secfile)
|
||||
|
||||
return get_secrets(sysaddr, secaddr, vista)
|
Reference in New Issue
Block a user