Files
2023-10-20 10:00:54 +02:00

135 lines
5.9 KiB
Python

#!/usr/bin/python3
# -*- coding: utf-8 -*-
#############################################################################
## ##
## This file is part of DPAPIck3 ##
## Windows DPAPI decryption & forensic toolkit ##
## ##
## ##
## Copyright (C) 2010, 2011 Cassidian SAS. All rights reserved. ##
## Copyright (C) 2023 Insecurity. All rights reserved. ##
## ##
## Author: Jean-Michel Picod <jmichel.p@gmail.com> ##
## Updated: Photubias <info@insecurity.be> ##
## ##
## This program is distributed under GPLv3 licence (see LICENCE.txt) ##
## ##
#############################################################################
from dpapick3 import probe, blob, masterkey
import argparse, base64, binascii
class GenericDecryptor(probe.DPAPIProbe):
def parse(self, data):
self.dpapiblob = blob.DPAPIBlob(data.remain())
def __getattr__(self, name):
return getattr(self.dpapiblob, name)
def __repr__(self):
s = ["Generic password decryptor"]
if self.dpapiblob is not None and self.dpapiblob.decrypted:
s.append(" password = %s" % self.cleartext)
s.append(" %r" % self.dpapiblob)
return "\n".join(s)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("--sid", metavar="SID", dest="sid")
parser.add_argument("--masterkey", required=True, metavar="DIRECTORY", dest="masterkeydir")
parser.add_argument("--credhist", required=False, metavar="FILE", dest="credhist")
parser.add_argument("--password", required=False, metavar="PASSWORD", dest="password")
parser.add_argument("--hash", required=False, metavar="PASSWORD", dest="hash")
parser.add_argument("--inputfile", required=False, metavar="FILE", dest="inputfile")
parser.add_argument("--base64file", required=False, metavar="FILE", dest="b64file")
parser.add_argument("--syskey", required=False, metavar="PASSWORD", dest="syskey", help="DPAPI_SYSTEM string. 01000000..., run lsasecrets.py")
parser.add_argument("--pkey", required=False, help="Private domain KEY", dest="pkey")
parser.add_argument("--entropy", required=False, help="Decrypt entropy, 0xaabb... or Base64", dest="entropy")
parser.add_argument("--debug", required=False, action="store_true",dest="debug")
#help="lines with base64-encoded password blobs")
options = parser.parse_args()
entropy = None
decrn = 0
if options.entropy:
if options.entropy[0:2] == "0x":
try:
entropy=binascii.unhexlify(options.entropy[2:])
except:
print("Error decoding entropy")
else:
try:
entropy = base64.b64decode(options.entropy)
print("Using entropy")
except:
print("Error decoding entropy")
if options.masterkeydir and options.credhist != None:
mkp = masterkey.MasterKeyPool()
mkp.loadDirectory(options.masterkeydir)
mkp.addCredhistFile(options.sid, options.credhist)
if options.masterkeydir and options.pkey:
mkp = masterkey.MasterKeyPool()
mkp.loadDirectory(options.masterkeydir)
decrn = mkp.try_domain(options.pkey)
if decrn > 0:
print("Decrypted: "+str(decrn))
if options.debug:
for mkl in mkp.keys.values(): #mkl - list with mk, mkbackup, mkdomain
for mk in mkl:
print(mk.guid)
if options.masterkeydir and options.password and options.sid:
mkp = masterkey.MasterKeyPool()
mkp.loadDirectory(options.masterkeydir)
decrn = mkp.try_credential(options.sid,options.password)
print("Decrypted masterkeys: "+str(decrn))
if options.masterkeydir and options.hash and options.sid:
mkp = masterkey.MasterKeyPool()
mkp.loadDirectory(options.masterkeydir)
options.hash = binascii.unhexlify(options.hash)
decrn = mkp.try_credential_hash(options.sid, options.hash)
print("Decrypted masterkeys: " + str(decrn))
if options.masterkeydir and options.syskey:
mkp = masterkey.MasterKeyPool()
mkp.loadDirectory(options.masterkeydir)
mkp.addSystemCredential(binascii.unhexlify(options.syskey))
decrn = mkp.try_credential_hash(None, None)
print("Decrypted masterkeys: " + str(decrn))
if decrn == 0:
print("No decrypted masterkeys ! ")
print("Exiting..")
exit()
if options.inputfile:
with open(options.inputfile, "rb") as file:
data=file.read()
probe = GenericDecryptor(data)
#if probe.try_decrypt_with_password(options.password, mkp, options.sid):
if probe.try_decrypt_with_hash(options.hash, mkp, options.sid, entropy=entropy):
print("Decrypted clear: %s" % probe.cleartext)
print("Decrypted hex: %s" % binascii.hexlify(probe.cleartext))
if options.b64file:
with open(options.b64file, 'r') as f:
lines = f.readlines()
for line in lines:
dline = base64.b64decode(line)
probe = GenericDecryptor(dline)
if options.debug: print(probe)
if probe.try_decrypt_with_password(options.password, mkp, options.sid, entropy=entropy):
print("Decrypted clear: %s" % probe.cleartext)
print("Decrypted hex: %s" % binascii.hexlify(probe.cleartext))
# vim:ts=4:expandtab:sw=4