Skip to content

Commit aa9075e

Browse files
author
snowpeacock
committed
fix: override of exec method by default arg
1 parent c1780a1 commit aa9075e

3 files changed

Lines changed: 25 additions & 11 deletions

File tree

nxc/helpers/args.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from argparse import ArgumentDefaultsHelpFormatter, SUPPRESS, OPTIONAL, ZERO_OR_MORE
2+
from argparse import Action
23

34
class DisplayDefaultsNotNone(ArgumentDefaultsHelpFormatter):
45
def _get_help_string(self, action):
@@ -7,4 +8,18 @@ def _get_help_string(self, action):
78
defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
89
if (action.option_strings or action.nargs in defaulting_nargs) and action.default: # Only add default info if it's not None
910
help_string += " (default: %(default)s)" # NORUFF
10-
return help_string
11+
return help_string
12+
13+
14+
class DefaultTrackingAction(Action):
15+
def __init__(self, option_strings, dest, default=None, required=False, **kwargs):
16+
# Store the default value to check later
17+
self.default_value = default
18+
super().__init__(
19+
option_strings, dest, default=default, required=required, **kwargs
20+
)
21+
22+
def __call__(self, parser, namespace, values, option_string=None):
23+
# Set an attribute to track whether the value was explicitly set
24+
setattr(namespace, self.dest, values)
25+
setattr(namespace, f"{self.dest}_explicitly_set", True)

nxc/protocols/smb.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,7 @@ def gen_relay_list(self):
619619

620620
@requires_admin
621621
def execute(self, payload=None, get_output=False, methods=None):
622-
if self.args.exec_method:
622+
if getattr(self.args, "exec_method_explicitly_set", False):
623623
methods = [self.args.exec_method]
624624
if not methods:
625625
methods = ["wmiexec", "atexec", "smbexec", "mmcexec"]

nxc/protocols/smb/proto_args.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
from argparse import _StoreTrueAction
2-
from nxc.helpers.args import DisplayDefaultsNotNone
2+
from nxc.helpers.args import DisplayDefaultsNotNone, DefaultTrackingAction
33

44

55
def proto_args(parser, parents):
66
smb_parser = parser.add_parser("smb", help="own stuff using SMB", parents=parents, formatter_class=DisplayDefaultsNotNone)
77
smb_parser.add_argument("-H", "--hash", metavar="HASH", dest="hash", nargs="+", default=[], help="NTLM hash(es) or file(s) containing NTLM hashes")
8-
8+
99
delegate_arg = smb_parser.add_argument("--delegate", action="store", help="Impersonate user with S4U2Self + S4U2Proxy")
1010
self_delegate_arg = smb_parser.add_argument("--self", dest="no_s4u2proxy", action=get_conditional_action(_StoreTrueAction), make_required=[], help="Only do S4U2Self, no S4U2Proxy (use with delegate)")
11-
11+
1212
dgroup = smb_parser.add_mutually_exclusive_group()
1313
dgroup.add_argument("-d", "--domain", metavar="DOMAIN", dest="domain", type=str, help="domain to authenticate to")
1414
dgroup.add_argument("--local-auth", action="store_true", help="authenticate locally to each target")
15-
15+
1616
smb_parser.add_argument("--port", type=int, default=445, help="SMB port")
1717
smb_parser.add_argument("--share", metavar="SHARE", default="C$", help="specify a share")
1818
smb_parser.add_argument("--smb-server-port", default="445", help="specify a server port for SMB", type=int)
@@ -47,7 +47,7 @@ def proto_args(parser, parents):
4747
mapping_enum_group.add_argument("--local-groups", nargs="?", const="", metavar="GROUP", help="enumerate local groups, if a group is specified then its members are enumerated")
4848
mapping_enum_group.add_argument("--pass-pol", action="store_true", help="dump password policy")
4949
mapping_enum_group.add_argument("--rid-brute", nargs="?", type=int, const=4000, metavar="MAX_RID", help="enumerate users by bruteforcing RIDs")
50-
50+
5151
wmi_group = smb_parser.add_argument_group("WMI", "Options for WMI Queries")
5252
wmi_group.add_argument("--wmi", metavar="QUERY", type=str, help="issues the specified WMI query")
5353
wmi_group.add_argument("--wmi-namespace", metavar="NAMESPACE", default="root\\cimv2", help="WMI Namespace")
@@ -69,7 +69,7 @@ def proto_args(parser, parents):
6969
files_group.add_argument("--append-host", action="store_true", help="append the host to the get-file filename")
7070

7171
cmd_exec_group = smb_parser.add_argument_group("Command Execution", "Options for executing commands")
72-
cmd_exec_group.add_argument("--exec-method", choices={"wmiexec", "mmcexec", "smbexec", "atexec"}, default="wmiexec", help="method to execute the command. Ignored if in MSSQL mode")
72+
cmd_exec_group.add_argument("--exec-method", choices={"wmiexec", "mmcexec", "smbexec", "atexec"}, default="wmiexec", help="method to execute the command. Ignored if in MSSQL mode", action=DefaultTrackingAction)
7373
cmd_exec_group.add_argument("--dcom-timeout", help="DCOM connection timeout", type=int, default=5)
7474
cmd_exec_group.add_argument("--get-output-tries", help="Number of times atexec/smbexec/mmcexec tries to get results", type=int, default=10)
7575
cmd_exec_group.add_argument("--codec", default="utf-8", help="Set encoding used (codec) from the target's output. If errors are detected, run chcp.com at the target & map the result with https://docs.python.org/3/library/codecs.html#standard-encodings and then execute again with --codec and the corresponding codec")
@@ -78,15 +78,14 @@ def proto_args(parser, parents):
7878
cmd_exec_method_group = cmd_exec_group.add_mutually_exclusive_group()
7979
cmd_exec_method_group.add_argument("-x", metavar="COMMAND", dest="execute", help="execute the specified CMD command")
8080
cmd_exec_method_group.add_argument("-X", metavar="PS_COMMAND", dest="ps_execute", help="execute the specified PowerShell command")
81-
81+
8282
posh_group = smb_parser.add_argument_group("Powershell Obfuscation", "Options for PowerShell script obfuscation")
8383
posh_group.add_argument("--obfs", action="store_true", help="Obfuscate PowerShell scripts")
8484
posh_group.add_argument("--amsi-bypass", nargs=1, metavar="FILE", help="File with a custom AMSI bypass")
8585
posh_group.add_argument("--clear-obfscripts", action="store_true", help="Clear all cached obfuscated PowerShell scripts")
8686
posh_group.add_argument("--force-ps32", action="store_true", help="force PowerShell commands to run in a 32-bit process (may not apply to modules)")
8787
posh_group.add_argument("--no-encode", action="store_true", default=False, help="Do not encode the PowerShell command ran on target")
8888

89-
9089
return parser
9190

9291
def get_conditional_action(baseAction):
@@ -101,4 +100,4 @@ def __call__(self, parser, namespace, values, option_string=None):
101100
x.required = True
102101
super().__call__(parser, namespace, values, option_string)
103102

104-
return ConditionalAction
103+
return ConditionalAction

0 commit comments

Comments
 (0)