Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for "export" hive format + compute bootkey from class … #76

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion examples/registry-read.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,16 @@ def main():
walk_parser = subparsers.add_parser('walk', help='walks the registry from the name node down')
walk_parser.add_argument('-name', action='store', required=True, help='registry class name to start walking down from')

# Hive format
parser.add_argument('-format', action='store', choices=['save', 'export'], default='save',help="Hive format, either 'save' or 'export' (default: 'save')")

if len(sys.argv)==1:
parser.print_help()
sys.exit(1)

options = parser.parse_args()

reg = winregistry.Registry(options.hive)
reg = winregistry.Registry(options.hive,hiveFormat = options.format)

if options.action.upper() == 'ENUM_KEY':
print("[%s]" % options.name)
Expand Down
54 changes: 44 additions & 10 deletions examples/secretsdump.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,14 @@ def __init__(self, remoteName, username='', password='', domain='', options=None
self.__rodc = options.rodcNo
self.__systemHive = options.system
self.__bootkey = options.bootkey
self.__jdClass = options.lsa_jd
self.__skew1Class = options.lsa_skew1
self.__gbgClass = options.lsa_gbg
self.__dataClass = options.lsa_data
self.__securityHive = options.security
self.__securityHiveExport = options.security_export
self.__samHive = options.sam
self.__samHiveExport = options.sam_export
self.__ntdsFile = options.ntds
self.__skipSam = options.skip_sam
self.__skipSecurity = options.skip_security
Expand Down Expand Up @@ -170,6 +176,19 @@ def ldapConnect(self):
self.__aesKey, kdcHost=self.__kdcHost)
else:
raise

def getBootKey(self, jdClass, skew1Class, gbgClass, dataClass):
import binascii
bootKey = b''
tmpKey = jdClass.encode('utf-8') + skew1Class.encode('utf-8') + gbgClass.encode('utf-8') + dataClass.encode('utf-8')
transforms = [8, 5, 4, 2, 11, 9, 13, 3, 0, 6, 1, 12, 14, 10, 15, 7]
tmpKey = binascii.unhexlify(tmpKey)
for i in range(len(tmpKey)):
bootKey += tmpKey[transforms[i]:transforms[i] + 1]

logging.info('Target system bootKey: 0x%s' % binascii.hexlify(bootKey).decode('utf-8'))

return bootKey

def dump(self):
try:
Expand Down Expand Up @@ -217,10 +236,11 @@ def dump(self):
if self.__ntdsFile is not None:
# Let's grab target's configuration about LM Hashes storage
self.__noLMHash = localOperations.checkNoLMHashPolicy()
else:
elif self.__bootkey:
import binascii
bootKey = binascii.unhexlify(self.__bootkey)

elif self.__jdClass and self.__skew1Class and self.__gbgClass and self.__dataClass:
bootKey = self.getBootKey(self.__jdClass, self.__skew1Class, self.__gbgClass, self.__dataClass)
else:
self.__isRemote = True
bootKey = None
Expand Down Expand Up @@ -274,10 +294,14 @@ def dump(self):
try:
if self.__isRemote is True:
SAMFileName = self.__remoteOps.saveSAM()
else:
elif self.__samHive:
SAMFileName = self.__samHive
samFormat = "save"
elif self.__samHiveExport:
SAMFileName = self.__samHiveExport
samFormat = "export"

self.__SAMHashes = SAMHashes(SAMFileName, bootKey, isRemote = self.__isRemote)
self.__SAMHashes = SAMHashes(SAMFileName, bootKey, isRemote = self.__isRemote, format = samFormat)
self.__SAMHashes.dump()
if self.__outputFileName is not None:
self.__SAMHashes.export(self.__outputFileName)
Expand All @@ -288,11 +312,15 @@ def dump(self):
try:
if self.__isRemote is True:
SECURITYFileName = self.__remoteOps.saveSECURITY()
else:
elif self.__securityHive:
SECURITYFileName = self.__securityHive
securityFormat = "save"
elif self.__securityHiveExport:
SECURITYFileName = self.__securityHiveExport
securityFormat = "export"

self.__LSASecrets = LSASecrets(SECURITYFileName, bootKey, self.__remoteOps,
isRemote=self.__isRemote, history=self.__history)
isRemote=self.__isRemote, history=self.__history, format = securityFormat)
self.__LSASecrets.dumpCachedHashes()
if self.__outputFileName is not None:
self.__LSASecrets.exportCached(self.__outputFileName)
Expand Down Expand Up @@ -400,8 +428,14 @@ def cleanup(self):
parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON')
parser.add_argument('-system', action='store', help='SYSTEM hive to parse')
parser.add_argument('-bootkey', action='store', help='bootkey for SYSTEM hive')
parser.add_argument('-security', action='store', help='SECURITY hive to parse')
parser.add_argument('-sam', action='store', help='SAM hive to parse')
parser.add_argument('-lsa-jd', action='store', help='Class name of HKLM\SYSTEM\CurrentControlSet\Control\Lsa\JD to compute the bootkey')
parser.add_argument('-lsa-skew1', action='store', help='Class name of HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Skew1 to compute the bootkey')
parser.add_argument('-lsa-gbg', action='store', help='Class name of HKLM\SYSTEM\CurrentControlSet\Control\Lsa\GBG to compute the bootkey')
parser.add_argument('-lsa-data', action='store', help='Class name of HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Data to compute the bootkey')
parser.add_argument('-security', action='store', help='SECURITY hive to parse in "save" format')
parser.add_argument('-security-export', action='store', help='SECURITY hive to parse in "export" format')
parser.add_argument('-sam', action='store', help='SAM hive to parse in "save" format')
parser.add_argument('-sam-export', action='store', help='SAM hive to parse in "export" format')
parser.add_argument('-ntds', action='store', help='NTDS.DIT file to parse')
parser.add_argument('-resumefile', action='store', help='resume file name to resume NTDS.DIT session dump (only '
'available to DRSUAPI approach). This file will also be used to keep updating the session\'s '
Expand Down Expand Up @@ -506,8 +540,8 @@ def cleanup(self):
sys.exit(1)

if remoteName.upper() == 'LOCAL' and username == '':
if options.system is None and options.bootkey is None:
logging.error('Either the SYSTEM hive or bootkey is required for local parsing, check help')
if options.system is None and options.bootkey is None and (options.lsa_jd is None or options.lsa_skew1 is None or options.lsa_gbg is None or options.lsa_data is None):
logging.error('Either the SYSTEM hive, bootkey or the LSA\'s class names is required for local parsing, check help')
sys.exit(1)
else:

Expand Down
12 changes: 6 additions & 6 deletions impacket/examples/secretsdump.py
Original file line number Diff line number Diff line change
Expand Up @@ -1293,10 +1293,10 @@ def decryptAES(key, value, iv=b'\x00'*16):


class OfflineRegistry:
def __init__(self, hiveFile = None, isRemote = False):
def __init__(self, hiveFile = None, isRemote = False, format = "save"):
self.__hiveFile = hiveFile
if self.__hiveFile is not None:
self.__registryHive = winregistry.Registry(self.__hiveFile, isRemote)
self.__registryHive = winregistry.Registry(self.__hiveFile, isRemote, format)

def enumKey(self, searchKey):
parentKey = self.__registryHive.findKey(searchKey)
Expand Down Expand Up @@ -1340,8 +1340,8 @@ def finish(self):
self.__registryHive.close()

class SAMHashes(OfflineRegistry):
def __init__(self, samFile, bootKey, isRemote = False, perSecretCallback = lambda secret: _print_helper(secret)):
OfflineRegistry.__init__(self, samFile, isRemote)
def __init__(self, samFile, bootKey, isRemote = False, format = "save", perSecretCallback = lambda secret: _print_helper(secret)):
OfflineRegistry.__init__(self, samFile, isRemote, format)
self.__samFile = samFile
self.__hashedBootKey = b''
self.__bootKey = bootKey
Expand Down Expand Up @@ -1488,9 +1488,9 @@ class SECRET_TYPE:
LSA_RAW = 2
LSA_KERBEROS = 3

def __init__(self, securityFile, bootKey, remoteOps=None, isRemote=False, history=False,
def __init__(self, securityFile, bootKey, remoteOps=None, isRemote=False, history=False, format = "save",
perSecretCallback=lambda secretType, secret: _print_helper(secret)):
OfflineRegistry.__init__(self, securityFile, isRemote)
OfflineRegistry.__init__(self, securityFile, isRemote, format)
self.__hashedBootKey = b''
self.__bootKey = bootKey
self.__LSAKey = b''
Expand Down
Loading