Skip to content

Commit b387260

Browse files
authored
Merge pull request Pennyw0rth#438 from snowpeacock/fix_module_execution_method
Bugfix : exec-method specified in module file is not used
2 parents 0da04dd + dca1d08 commit b387260

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
@@ -648,7 +648,7 @@ def execute(self, payload=None, get_output=False, methods=None) -> str:
648648
-------
649649
str: The output of the command
650650
"""
651-
if self.args.exec_method:
651+
if getattr(self.args, "exec_method_explicitly_set", False):
652652
methods = [self.args.exec_method]
653653
if not methods:
654654
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)
@@ -49,7 +49,7 @@ def proto_args(parser, parents):
4949
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")
5050
mapping_enum_group.add_argument("--pass-pol", action="store_true", help="dump password policy")
5151
mapping_enum_group.add_argument("--rid-brute", nargs="?", type=int, const=4000, metavar="MAX_RID", help="enumerate users by bruteforcing RIDs")
52-
52+
5353
wmi_group = smb_parser.add_argument_group("WMI", "Options for WMI Queries")
5454
wmi_group.add_argument("--wmi", metavar="QUERY", type=str, help="issues the specified WMI query")
5555
wmi_group.add_argument("--wmi-namespace", metavar="NAMESPACE", default="root\\cimv2", help="WMI Namespace")
@@ -71,7 +71,7 @@ def proto_args(parser, parents):
7171
files_group.add_argument("--append-host", action="store_true", help="append the host to the get-file filename")
7272

7373
cmd_exec_group = smb_parser.add_argument_group("Command Execution", "Options for executing commands")
74-
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")
74+
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)
7575
cmd_exec_group.add_argument("--dcom-timeout", help="DCOM connection timeout", type=int, default=5)
7676
cmd_exec_group.add_argument("--get-output-tries", help="Number of times atexec/smbexec/mmcexec tries to get results", type=int, default=10)
7777
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")
@@ -80,15 +80,14 @@ def proto_args(parser, parents):
8080
cmd_exec_method_group = cmd_exec_group.add_mutually_exclusive_group()
8181
cmd_exec_method_group.add_argument("-x", metavar="COMMAND", dest="execute", help="execute the specified CMD command")
8282
cmd_exec_method_group.add_argument("-X", metavar="PS_COMMAND", dest="ps_execute", help="execute the specified PowerShell command")
83-
83+
8484
posh_group = smb_parser.add_argument_group("Powershell Obfuscation", "Options for PowerShell script obfuscation")
8585
posh_group.add_argument("--obfs", action="store_true", help="Obfuscate PowerShell scripts")
8686
posh_group.add_argument("--amsi-bypass", nargs=1, metavar="FILE", help="File with a custom AMSI bypass")
8787
posh_group.add_argument("--clear-obfscripts", action="store_true", help="Clear all cached obfuscated PowerShell scripts")
8888
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)")
8989
posh_group.add_argument("--no-encode", action="store_true", default=False, help="Do not encode the PowerShell command ran on target")
9090

91-
9291
return parser
9392

9493
def get_conditional_action(baseAction):
@@ -103,4 +102,4 @@ def __call__(self, parser, namespace, values, option_string=None):
103102
x.required = True
104103
super().__call__(parser, namespace, values, option_string)
105104

106-
return ConditionalAction
105+
return ConditionalAction

0 commit comments

Comments
 (0)