Merge branch 'main' into neff-add-shadow-creds

This commit is contained in:
Alex authored and GitHub committed 2026-08-23 13:08:41 +02:00
commit dfcbdb9fff
8 files changed
+37 -23

No files matched your search

+6 -2
View File
@@ -14,7 +14,7 @@ from socket import AF_UNSPEC, SOCK_DGRAM, IPPROTO_IP, AI_CANONNAME, getaddrinfo
from nxc.config import pwned_label
from nxc.helpers.logger import highlight
from nxc.loaders.moduleloader import ModuleLoader
from nxc.loaders.moduleloader import ModuleLoader, ModuleOptionsError
from nxc.logger import nxc_logger, NXCAdapter
from nxc.context import Context
from nxc.paths import NXC_PATH
@@ -604,5 +604,9 @@ class connection:
self.modules = []
for module_path in self.module_paths:
module = loader.init_module(module_path)
try:
module = loader.init_module(module_path)
except ModuleOptionsError as e:
self.logger.debug(f"Skipping module: {e}")
continue
self.modules.append(module)
+6 -1
View File
@@ -13,6 +13,10 @@ from nxc.logger import NXCAdapter
from nxc.paths import NXC_PATH
class ModuleOptionsError(Exception):
"""Raised when a module aborts the run from options() (returned False)."""
class ModuleLoader:
def __init__(self, args, db, logger):
self.args = args
@@ -100,7 +104,8 @@ class ModuleLoader:
key, value = option.split("=", 1)
module_options[str(key).upper()] = value
module.options(context, module_options)
if module.options(context, module_options) is False:
raise ModuleOptionsError(f"Module {module.name} aborted the run from options()")
return module
else:
self.logger.fail(f"Module {module.name.upper()} is not supported for protocol {self.args.protocol}")
+4 -4
View File
@@ -249,10 +249,10 @@ class NXCModule:
context.log.debug("There is a target specified!")
if isfile(module_options[option]):
try:
target_file = open(module_options[option]) # ruff: ignore[open-file-with-context-handler]
for line in target_file:
context.log.debug(f"Adding target from file: {line}")
self.targets.append((line.strip(), SEARCH_FILTERS[option]))
with open(module_options[option]) as target_file:
for line in target_file:
context.log.debug(f"Adding target from file: {line}")
self.targets.append((line.strip(), SEARCH_FILTERS[option]))
except Exception:
context.log.fail("The file doesn't exist or cannot be opened.")
else:
+1
View File
@@ -22,6 +22,7 @@ class NXCModule:
Module options get parsed here. Additionally, put the modules usage here as well
"""
# Put "No options available" in the docstring if there are no options for the module
# Return False to abort the run if options are invalid (log with context.log.fail first).
def on_login(self, context, connection):
"""Concurrent.
+8 -11
View File
@@ -126,20 +126,17 @@ class NXCModule:
except Exception as e:
context.log.fail(f"[OPSEC] Error deleting lsass.dmp file on share {self.share}: {e}")
h_in = open(self.dir_result + machine_name, "rb") # ruff: ignore[open-file-with-context-handler]
h_out = open(self.dir_result + machine_name + ".decode", "wb") # ruff: ignore[open-file-with-context-handler]
with open(self.dir_result + machine_name, "rb") as h_in, open(self.dir_result + machine_name + ".decode", "wb") as h_out:
bytes_in = bytearray(h_in.read())
bytes_in = bytearray(h_in.read())
bytes_in_len = len(bytes_in)
context.log.display(f"Deobfuscating, this might take a while (size: {len(bytes_in)} bytes)")
context.log.display(f"Deobfuscating, this might take a while (size: {bytes_in_len} bytes)")
chunks = [bytes_in[i: i + 1000000] for i in range(0, len(bytes_in), 1000000)]
for chunk in chunks:
for i in range(len(chunk)):
chunk[i] ^= 0x41
chunks = [bytes_in[i: i + 1000000] for i in range(0, bytes_in_len, 1000000)]
for chunk in chunks:
for i in range(len(chunk)):
chunk[i] ^= 0x41
h_out.write(bytes(chunk))
h_out.write(bytes(chunk))
with open(self.dir_result + machine_name + ".decode", "rb") as dump:
try:
+6 -2
View File
@@ -8,7 +8,7 @@ from nxc.parsers.nmap import parse_nmap_xml
from nxc.parsers.nessus import parse_nessus_file
from nxc.cli import gen_cli_args
from nxc.loaders.protocolloader import ProtocolLoader
from nxc.loaders.moduleloader import ModuleLoader
from nxc.loaders.moduleloader import ModuleLoader, ModuleOptionsError
from nxc.first_run import first_run_setup
from nxc.paths import NXC_PATH, WORKSPACE_DIR
from nxc.console import nxc_console
@@ -207,7 +207,11 @@ def main():
exit(1)
nxc_logger.debug(f"Loading module for sanity check {m} at path {modules[m]['path']}")
module = loader.init_module(modules[m]["path"])
try:
loader.init_module(modules[m]["path"])
except ModuleOptionsError as e:
nxc_logger.debug(f"Aborting run: {e}")
exit(1)
# Add modules paths to the protocol object so it can load them itself
proto_module_paths.append(modules[m]["path"])
+4 -2
View File
@@ -128,7 +128,8 @@ class ftp(connection):
# Check if the file exists
self.conn.size(filename)
# Attempt to download the file
self.conn.retrbinary(f"RETR {filename}", open(downloaded_file, "wb").write) # ruff: ignore[open-file-with-context-handler]
with open(downloaded_file, "wb") as f:
self.conn.retrbinary(f"RETR {filename}", f.write)
except error_perm as error_message:
self.logger.fail(f"Failed to download the file. Response: ({error_message})")
self.conn.close()
@@ -146,7 +147,8 @@ class ftp(connection):
def put_file(self, local_file, remote_file):
try:
# Attempt to upload the file
self.conn.storbinary(f"STOR {remote_file}", open(local_file, "rb")) # ruff: ignore[open-file-with-context-handler]
with open(local_file, "rb") as f:
self.conn.storbinary(f"STOR {remote_file}", f.read)
except error_perm as error_message:
self.logger.fail(f"Failed to upload file. Response: ({error_message})")
return False
+2 -1
View File
@@ -2314,7 +2314,8 @@ class smb(connection):
if self.args.pvk is not None:
try:
self.pvkbytes = open(self.args.pvk, "rb").read() # ruff: ignore[open-file-with-context-handler]
with open(self.args.pvk, "rb") as f:
self.pvkbytes = f.read()
self.logger.success(f"Loading domain backupkey from {self.args.pvk}")
except Exception as e:
self.logger.fail(str(e))