Skip to content

Commit 3e5d825

Browse files
authored
Merge pull request Pennyw0rth#473 from Pennyw0rth/neff-code-improvements
2 parents 110f61b + 6f7c4db commit 3e5d825

10 files changed

Lines changed: 39 additions & 26 deletions

File tree

nxc/connection.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,8 @@ def proto_flow(self):
229229
else:
230230
self.logger.debug("Created connection object")
231231
self.enum_host_info()
232-
if self.print_host_info() and (self.login() or (self.username == "" and self.password == "")):
232+
self.print_host_info()
233+
if self.login() or (self.username == "" and self.password == ""):
233234
if hasattr(self.args, "module") and self.args.module:
234235
self.load_modules()
235236
self.logger.debug("Calling modules")

nxc/protocols/ftp.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def proto_logger(self):
2424

2525
def proto_flow(self):
2626
self.proto_logger()
27-
if self.create_conn_obj() and self.enum_host_info() and self.print_host_info() and self.login():
27+
if self.create_conn_obj() and self.login():
2828
if hasattr(self.args, "module") and self.args.module:
2929
self.load_modules()
3030
self.logger.debug("Calling modules")
@@ -38,11 +38,9 @@ def enum_host_info(self):
3838
self.logger.debug(f"Welcome result: {welcome}")
3939
self.remote_version = welcome.split("220", 1)[1].strip() # strip out the extra space in the front
4040
self.logger.debug(f"Remote version: {self.remote_version}")
41-
return True
4241

4342
def print_host_info(self):
4443
self.logger.display(f"Banner: {self.remote_version}")
45-
return True
4644

4745
def create_conn_obj(self):
4846
self.conn = FTP()

nxc/protocols/ldap.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,6 @@ def print_host_info(self):
312312
smbv1 = colored(f"SMBv1:{self.smbv1}", host_info_colors[2], attrs=["bold"]) if self.smbv1 else colored(f"SMBv1:{self.smbv1}", host_info_colors[3], attrs=["bold"])
313313
self.logger.display(f"{self.server_os}{f' x{self.os_arch}' if self.os_arch else ''} (name:{self.hostname}) (domain:{self.targetDomain}) ({signing}) ({smbv1})")
314314
self.logger.extra["protocol"] = "LDAP"
315-
return True
316315

317316
def kerberos_login(self, domain, username, password="", ntlm_hash="", aesKey="", kdcHost="", useCache=False):
318317
self.username = username
@@ -694,7 +693,7 @@ def getUnixTime(self, t):
694693
t /= 10000000
695694
return t
696695

697-
def search(self, searchFilter, attributes, sizeLimit=0):
696+
def search(self, searchFilter, attributes, sizeLimit=0) -> list:
698697
try:
699698
if self.ldapConnection:
700699
self.logger.debug(f"Search Filter={searchFilter}")
@@ -714,8 +713,8 @@ def search(self, searchFilter, attributes, sizeLimit=0):
714713
e.getAnswers()
715714
else:
716715
self.logger.fail(e)
717-
return False
718-
return False
716+
return []
717+
return []
719718

720719
def users(self):
721720
"""

nxc/protocols/mssql.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ def enum_host_info(self):
141141

142142
def print_host_info(self):
143143
self.logger.display(f"{self.server_os} (name:{self.hostname}) (domain:{self.targetDomain})")
144-
return True
145144

146145
@reconnect_mssql
147146
def kerberos_login(

nxc/protocols/nfs.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ def enum_host_info(self):
6969

7070
def print_host_info(self):
7171
self.logger.display(f"Target supported NFS versions: ({', '.join(str(x) for x in self.nfs_versions)})")
72-
return True
7372

7473
def disconnect(self):
7574
"""Disconnect mount and portmap if they are connected"""

nxc/protocols/rdp.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,6 @@ def __init__(self, args, db, host):
8181

8282
connection.__init__(self, args, db, host)
8383

84-
# def proto_flow(self):
85-
# if self.create_conn_obj():
86-
# if self.login() or (self.username == '' and self.password == ''):
87-
# if hasattr(self.args, 'module') and self.args.module:
88-
8984
def proto_logger(self):
9085
import platform
9186
if platform.python_version() in ["3.11.5", "3.11.6", "3.12.0"]:
@@ -112,7 +107,6 @@ def print_host_info(self):
112107
self.logger.display(f"Probably old, doesn't not support HYBRID or HYBRID_EX ({nla})")
113108
else:
114109
self.logger.display(f"{self.server_os} (name:{self.hostname}) (domain:{self.domain}) ({nla})")
115-
return True
116110

117111
def create_conn_obj(self):
118112
self.target = RDPTarget(ip=self.host, domain="FAKE", port=self.port, timeout=self.args.rdp_timeout)

nxc/protocols/smb.py

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,6 @@ def print_host_info(self):
312312
signing = colored(f"signing:{self.signing}", host_info_colors[0], attrs=["bold"]) if self.signing else colored(f"signing:{self.signing}", host_info_colors[1], attrs=["bold"])
313313
smbv1 = colored(f"SMBv1:{self.smbv1}", host_info_colors[2], attrs=["bold"]) if self.smbv1 else colored(f"SMBv1:{self.smbv1}", host_info_colors[3], attrs=["bold"])
314314
self.logger.display(f"{self.server_os}{f' x{self.os_arch}' if self.os_arch else ''} (name:{self.hostname}) (domain:{self.targetDomain}) ({signing}) ({smbv1})")
315-
return True
316315

317316
def kerberos_login(self, domain, username, password="", ntlm_hash="", aesKey="", kdcHost="", useCache=False):
318317
self.logger.debug(f"KDC set to: {kdcHost}")
@@ -619,7 +618,20 @@ def gen_relay_list(self):
619618
relay_list.write(self.host + "\n")
620619

621620
@requires_admin
622-
def execute(self, payload=None, get_output=False, methods=None):
621+
def execute(self, payload=None, get_output=False, methods=None) -> str:
622+
"""
623+
Executes a command on the target host using CMD.exe and the specified method(s).
624+
625+
Args:
626+
----
627+
payload (str): The command to execute
628+
get_output (bool): Whether to get the output of the command (can be useful for AV evasion)
629+
methods (list): The method(s) to use for command execution
630+
631+
Returns:
632+
-------
633+
str: The output of the command
634+
"""
623635
if self.args.exec_method:
624636
methods = [self.args.exec_method]
625637
if not methods:
@@ -753,7 +765,7 @@ def execute(self, payload=None, get_output=False, methods=None):
753765

754766
if "This script contains malicious content" in output:
755767
self.logger.fail("Command execution blocked by AMSI")
756-
return None
768+
return ""
757769

758770
if (self.args.execute or self.args.ps_execute):
759771
self.logger.success(f"Executed command via {current_method}")
@@ -764,14 +776,29 @@ def execute(self, payload=None, get_output=False, methods=None):
764776
return output
765777
else:
766778
self.logger.fail(f"Execute command failed with {current_method}")
767-
return False
779+
return ""
768780

769781
@requires_admin
770-
def ps_execute(self, payload=None, get_output=False, methods=None, force_ps32=False, obfs=False, encode=False):
782+
def ps_execute(self, payload=None, get_output=False, methods=None, force_ps32=False, obfs=False, encode=False) -> list:
783+
"""
784+
Wrapper for executing a PowerShell command on the target host. This still uses the execute() method internally, but
785+
creates a PowerShell command together with possible AMSI bypasses and other options.
786+
787+
Args:
788+
----
789+
payload (str): The PowerShell command to execute OR the path to a file containing PowerShell commands
790+
get_output (bool): Whether to get the output of the command (can be useful for AV evasion)
791+
methods (list): The method(s) to use for command execution
792+
force_ps32 (bool): Whether to force 32-bit PowerShell
793+
794+
Returns:
795+
-------
796+
list: A list containing the lines of the output of the command
797+
"""
771798
payload = self.args.ps_execute if not payload and self.args.ps_execute else payload
772799
if not payload:
773800
self.logger.error("No command to execute specified!")
774-
return None
801+
return []
775802

776803
response = []
777804
obfs = obfs if obfs else self.args.obfs

nxc/protocols/ssh.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ def proto_logger(self):
5555

5656
def print_host_info(self):
5757
self.logger.display(self.remote_version if self.remote_version != "Unknown SSH Version" else f"{self.remote_version}, skipping...")
58-
return True
5958

6059
def enum_host_info(self):
6160
if self.conn._transport.remote_version:

nxc/protocols/winrm.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,6 @@ def print_host_info(self):
7272
self.logger.extra["port"] = self.port
7373
self.logger.display(f"{self.server_os} (name:{self.hostname}) (domain:{self.targetDomain})")
7474

75-
return True
76-
7775
def create_conn_obj(self):
7876
if self.is_link_local_ipv6:
7977
self.logger.fail("winrm not support link-local ipv6, exiting...")

nxc/protocols/wmi.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,6 @@ def print_host_info(self):
146146
self.logger.extra["protocol"] = "RPC"
147147
self.logger.extra["port"] = "135"
148148
self.logger.display(f"{self.server_os} (name:{self.hostname}) (domain:{self.targetDomain})")
149-
return True
150149

151150
def check_if_admin(self):
152151
try:

0 commit comments

Comments
 (0)