Skip to content

Commit 3ba663d

Browse files
authored
Merge branch 'Pennyw0rth:main' into main
2 parents 008eb6a + 413e5eb commit 3ba663d

11 files changed

Lines changed: 16 additions & 151 deletions

File tree

netexec.spec

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ a = Analysis(
3333
'impacket.ldap.ldap',
3434
'jwt',
3535
'nxc.connection',
36-
'nxc.servers.smb',
3736
'nxc.protocols.smb.wmiexec',
3837
'nxc.protocols.smb.atexec',
3938
'nxc.protocols.smb.smbexec',

nxc/cli.py

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
def gen_cli_args():
1818
setup_debug_logging()
19-
19+
2020
try:
2121
VERSION, COMMIT = importlib.metadata.version("netexec").split("+")
2222
DISTANCE, COMMIT = COMMIT.split(".")
@@ -26,28 +26,28 @@ def gen_cli_args():
2626
DISTANCE = ""
2727
CODENAME = "SmoothOperator"
2828
nxc_logger.debug(f"NXC VERSION: {VERSION} - {CODENAME} - {COMMIT} - {DISTANCE}")
29-
29+
3030
generic_parser = argparse.ArgumentParser(add_help=False, formatter_class=DisplayDefaultsNotNone)
3131
generic_group = generic_parser.add_argument_group("Generic", "Generic options for nxc across protocols")
3232
generic_group.add_argument("--version", action="store_true", help="Display nxc version")
3333
generic_group.add_argument("-t", "--threads", type=int, dest="threads", default=256, help="set how many concurrent threads to use")
3434
generic_group.add_argument("--timeout", default=None, type=int, help="max timeout in seconds of each thread")
3535
generic_group.add_argument("--jitter", metavar="INTERVAL", type=str, help="sets a random delay between each authentication")
36-
36+
3737
output_parser = argparse.ArgumentParser(add_help=False, formatter_class=DisplayDefaultsNotNone)
3838
output_group = output_parser.add_argument_group("Output", "Options to set verbosity levels and control output")
3939
output_group.add_argument("--verbose", action="store_true", help="enable verbose output")
4040
output_group.add_argument("--debug", action="store_true", help="enable debug level information")
4141
output_group.add_argument("--no-progress", action="store_true", help="do not displaying progress bar during scan")
4242
output_group.add_argument("--log", metavar="LOG", help="export result into a custom file")
43-
43+
4444
dns_parser = argparse.ArgumentParser(add_help=False, formatter_class=DisplayDefaultsNotNone)
4545
dns_group = dns_parser.add_argument_group("DNS")
4646
dns_group.add_argument("-6", dest="force_ipv6", action="store_true", help="Enable force IPv6")
4747
dns_group.add_argument("--dns-server", action="store", help="Specify DNS server (default: Use hosts file & System DNS)")
4848
dns_group.add_argument("--dns-tcp", action="store_true", help="Use TCP instead of UDP for DNS queries")
4949
dns_group.add_argument("--dns-timeout", action="store", type=int, default=3, help="DNS query timeout in seconds")
50-
50+
5151
parser = argparse.ArgumentParser(
5252
description=rf"""
5353
. .
@@ -107,12 +107,6 @@ def gen_cli_args():
107107
certificate_group.add_argument("--pfx-pass", metavar="PFXPASS", help="Password of the pfx certificate")
108108
certificate_group.add_argument("--pem-cert", metavar="PEMCERT", help="Use certificate authentication from PEM file")
109109
certificate_group.add_argument("--pem-key", metavar="PEMKEY", help="Private key for the PEM format")
110-
111-
server_group = std_parser.add_argument_group("Servers", "Options for nxc servers")
112-
server_group.add_argument("--server", choices={"http", "https"}, default="https", help="use the selected server")
113-
server_group.add_argument("--server-host", type=str, default="0.0.0.0", metavar="HOST", help="IP to bind the server to")
114-
server_group.add_argument("--server-port", metavar="PORT", type=int, help="start the server on the specified port")
115-
server_group.add_argument("--connectback-host", type=str, metavar="CHOST", help="IP for the remote system to connect back to")
116110

117111
p_loader = ProtocolLoader()
118112
protocols = p_loader.get_protocols()

nxc/connection.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -284,11 +284,6 @@ def call_modules(self):
284284
context = Context(self.db, module_logger, self.args)
285285
context.localip = self.local_ip
286286

287-
if hasattr(module, "on_request") or hasattr(module, "has_response"):
288-
self.logger.debug(f"Module {module.name} has on_request or has_response methods")
289-
self.server.connection = self
290-
self.server.context.localip = self.local_ip
291-
292287
if hasattr(module, "on_login"):
293288
self.logger.debug(f"Module {module.name} has on_login method")
294289
module.on_login(context, self)
@@ -297,10 +292,6 @@ def call_modules(self):
297292
self.logger.debug(f"Module {module.name} has on_admin_login method")
298293
module.on_admin_login(context, self)
299294

300-
if (not hasattr(module, "on_request") and not hasattr(module, "has_response")) and hasattr(module, "on_shutdown"):
301-
self.logger.debug(f"Module {module.name} has on_shutdown method")
302-
module.on_shutdown(context, self)
303-
304295
def inc_failed_login(self, username):
305296
global global_failed_logins
306297
global user_failed_logins

nxc/logger.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,6 @@ def format(self, msg, *args, **kwargs): # noqa: A003
118118
if len(self.extra) == 1 and ("module_name" in self.extra):
119119
return (f"{colored(self.extra['module_name'], 'cyan', attrs=['bold']):<64} {msg}", kwargs)
120120

121-
# If the logger is being called from nxcServer
122-
if len(self.extra) == 2 and ("module_name" in self.extra) and ("host" in self.extra):
123-
return (f"{colored(self.extra['module_name'], 'cyan', attrs=['bold']):<24} {self.extra['host']:<39} {msg}", kwargs)
124-
125121
# If the logger is being called from a protocol
126122
module_name = colored(self.extra["module_name"], "cyan", attrs=["bold"]) if "module_name" in self.extra else colored(self.extra["protocol"], "blue", attrs=["bold"])
127123

nxc/modules/example_module.py

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,3 @@ def on_admin_login(self, context, connection):
4848
Required if on_login is not present
4949
This gets called on each authenticated connection with Administrative privileges
5050
"""
51-
52-
def on_request(self, context, request):
53-
"""Optional.
54-
If the payload needs to retrieve additional files, add this function to the module
55-
"""
56-
57-
def on_response(self, context, response):
58-
"""Optional.
59-
If the payload sends back its output to our server, add this function to the module to handle its output
60-
"""
61-
62-
def on_shutdown(self, context, connection):
63-
"""Optional.
64-
Do something on shutdown
65-
"""

nxc/modules/wcc.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,6 @@ def on_admin_login(self, context, connection):
123123
self.results.setdefault(connection.host, {"checks": []})
124124
self.context = context
125125
HostChecker(context, connection).run()
126-
127-
def on_shutdown(self, context, connection):
128126
if self.output is not None:
129127
self.export_results()
130128

nxc/netexec.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,7 @@ def main():
9494
nxc_logger.error("KRB5CCNAME environment variable is not set")
9595
exit(1)
9696

97-
module_server = None
9897
targets = []
99-
server_port_dict = {"http": 80, "https": 443, "smb": 445}
10098

10199
if hasattr(args, "cred_id") and args.cred_id:
102100
for cred_id in args.cred_id:
@@ -203,13 +201,6 @@ def main():
203201
if ans.lower() not in ["y", "yes", ""]:
204202
exit(1)
205203

206-
if hasattr(module, "on_request") or hasattr(module, "has_response"):
207-
if hasattr(module, "required_server"):
208-
args.server = module.required_server
209-
210-
if not args.server_port:
211-
args.server_port = server_port_dict[args.server]
212-
213204
# Add modules paths to the protocol object so it can load them itself
214205
proto_module_paths.append(modules[m]["path"])
215206
protocol_object.module_paths = proto_module_paths
@@ -227,8 +218,6 @@ def main():
227218
except KeyboardInterrupt:
228219
nxc_logger.debug("Got keyboard interrupt")
229220
finally:
230-
if module_server:
231-
module_server.shutdown()
232221
db_engine.dispose()
233222

234223

nxc/protocols/ldap.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
)
2626
from impacket.krb5 import constants
2727
from impacket.krb5.kerberosv5 import getKerberosTGS, SessionKeyDecryptionError
28+
from impacket.krb5.ccache import CCache
2829
from impacket.krb5.types import Principal, KerberosException
2930
from impacket.ldap import ldap as ldap_impacket
3031
from impacket.ldap import ldaptypes
@@ -232,7 +233,6 @@ def get_ldap_username(self):
232233
def enum_host_info(self):
233234
self.hostname = self.target.split(".")[0].upper() if "." in self.target else self.target
234235
self.remoteName = self.target
235-
self.domain = self.targetDomain
236236

237237
ntlm_challenge = None
238238
bindRequest = ldapasn1_impacket.BindRequest()
@@ -250,6 +250,14 @@ def enum_host_info(self):
250250
ntlm_info = parse_challenge(ntlm_challenge)
251251
self.server_os = ntlm_info["os_version"]
252252

253+
if self.args.domain:
254+
self.domain = self.args.domain
255+
elif self.args.use_kcache: # Fixing domain trust, just pull the auth domain out of the ticket
256+
self.domain = CCache.parseFile()[0]
257+
self.username = CCache.parseFile()[1]
258+
else:
259+
self.domain = self.targetDomain
260+
253261
# using kdcHost is buggy on impacket when using trust relation between ad so we kdcHost must stay to none if targetdomain is not equal to domain
254262
if not self.kdcHost and self.domain and self.domain == self.targetDomain:
255263
result = self.resolver(self.domain)
@@ -276,15 +284,15 @@ def print_host_info(self):
276284
self.logger.display(f"{self.server_os} (name:{self.hostname}) (domain:{self.domain})")
277285

278286
def kerberos_login(self, domain, username, password="", ntlm_hash="", aesKey="", kdcHost="", useCache=False):
279-
self.username = username
287+
self.username = username if not self.username else self.username # With ccache we get the username from the ticket
280288
self.password = password
281289
self.domain = domain
282290
self.kdcHost = kdcHost
283291
self.aesKey = aesKey
284292

285293
lmhash = ""
286294
nthash = ""
287-
self.username = username
295+
288296
# This checks to see if we didn't provide the LM Hash
289297
if ntlm_hash.find(":") != -1:
290298
lmhash, nthash = ntlm_hash.split(":")

nxc/protocols/smb.py

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
from nxc.protocols.smb.dpapi import collect_masterkeys_from_target, get_domain_backup_key, upgrade_to_dploot_connection
4444
from nxc.protocols.smb.firefox import FirefoxCookie, FirefoxData, FirefoxTriage
4545
from nxc.protocols.smb.kerberos import kerberos_login_with_S4U
46-
from nxc.servers.smb import NXCSMBServer
4746
from nxc.protocols.smb.wmiexec import WMIEXEC
4847
from nxc.protocols.smb.atexec import TSCH_EXEC
4948
from nxc.protocols.smb.smbexec import SMBEXEC
@@ -65,14 +64,12 @@
6564

6665
from time import time, ctime
6766
from datetime import datetime
68-
from functools import wraps
6967
from traceback import format_exc
7068
import logging
7169
from termcolor import colored
7270
import contextlib
7371

7472
smb_share_name = gen_random_string(5).upper()
75-
smb_server = None
7673

7774
smb_error_status = [
7875
"STATUS_ACCOUNT_DISABLED",
@@ -103,50 +100,6 @@ def get_error_string(exception):
103100
else:
104101
return str(exception)
105102

106-
107-
def requires_smb_server(func):
108-
def _decorator(self, *args, **kwargs):
109-
global smb_server
110-
global smb_share_name
111-
112-
get_output = False
113-
payload = None
114-
methods = []
115-
116-
with contextlib.suppress(IndexError):
117-
payload = args[0]
118-
with contextlib.suppress(IndexError):
119-
get_output = args[1]
120-
with contextlib.suppress(IndexError):
121-
methods = args[2]
122-
123-
if "payload" in kwargs:
124-
payload = kwargs["payload"]
125-
if "get_output" in kwargs:
126-
get_output = kwargs["get_output"]
127-
if "methods" in kwargs:
128-
methods = kwargs["methods"]
129-
if not payload and self.args.execute and not self.args.no_output:
130-
get_output = True
131-
if (get_output or (methods and ("smbexec" in methods))) and not smb_server:
132-
self.logger.debug("Starting SMB server")
133-
smb_server = NXCSMBServer(
134-
self.nxc_logger,
135-
smb_share_name,
136-
listen_port=self.args.smb_server_port,
137-
verbose=self.args.verbose,
138-
)
139-
smb_server.start()
140-
141-
output = func(self, *args, **kwargs)
142-
if smb_server is not None:
143-
smb_server.shutdown()
144-
smb_server = None
145-
return output
146-
147-
return wraps(func)(_decorator)
148-
149-
150103
class smb(connection):
151104
def __init__(self, args, db, host):
152105
self.domain = None

nxc/servers/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)