Skip to content

Commit f021cde

Browse files
refactor(args): change Authentication to its own arg section and show defaults if set and not None/empty/etc
1 parent e16a66a commit f021cde

2 files changed

Lines changed: 45 additions & 30 deletions

File tree

nxc/cli.py

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from nxc.paths import NXC_PATH
1010
from nxc.loaders.protocolloader import ProtocolLoader
1111
from nxc.helpers.logger import highlight
12+
from nxc.helpers.args import DisplayDefaultsNotNone
1213
from nxc.logger import nxc_logger, setup_debug_logging
1314
import importlib.metadata
1415

@@ -25,13 +26,13 @@ def gen_cli_args():
2526
nxc_logger.debug(f"NXC VERSION: {VERSION} - {CODENAME} - {COMMIT}")
2627

2728
generic_parser = argparse.ArgumentParser(add_help=False)
28-
generic_group = generic_parser.add_argument_group("Generic Options", "Generic options for nxc across protocols")
29-
generic_group.add_argument("-t", "--threads", type=int, dest="threads", default=256, help="set how many concurrent threads to use (default: 256)")
30-
generic_group.add_argument("--timeout", default=None, type=int, help="max timeout in seconds of each thread (default: None)")
31-
generic_group.add_argument("--jitter", metavar="INTERVAL", type=str, help="sets a random delay between each authentication (default: None)")
29+
generic_group = generic_parser.add_argument_group("Generic", "Generic options for nxc across protocols")
30+
generic_group.add_argument("-t", "--threads", type=int, dest="threads", default=256, help="set how many concurrent threads to use")
31+
generic_group.add_argument("--timeout", default=None, type=int, help="max timeout in seconds of each thread")
32+
generic_group.add_argument("--jitter", metavar="INTERVAL", type=str, help="sets a random delay between each authentication")
3233

3334
output_parser = argparse.ArgumentParser(add_help=False)
34-
output_group = output_parser.add_argument_group("Output Options", "Options to set verbosity levels and control output")
35+
output_group = output_parser.add_argument_group("Output", "Options to set verbosity levels and control output")
3536
output_group.add_argument("--verbose", action="store_true", help="enable verbose output")
3637
output_group.add_argument("--debug", action="store_true", help="enable debug level information")
3738
output_group.add_argument("--no-progress", action="store_true", help="do not displaying progress bar during scan")
@@ -64,36 +65,40 @@ def gen_cli_args():
6465
parser.add_argument("--version", action="store_true", help="Display nxc version")
6566

6667
# we do module arg parsing here so we can reference the module_list attribute below
67-
module_parser = argparse.ArgumentParser(add_help=False)
68-
mgroup = module_parser.add_mutually_exclusive_group()
68+
module_parser = argparse.ArgumentParser(add_help=False, formatter_class=DisplayDefaultsNotNone)
69+
mgroup = module_parser.add_argument_group("Modules", "Options for nxc modules")
6970
mgroup.add_argument("-M", "--module", choices=get_module_names(), action="append", metavar="MODULE", help="module to use")
70-
module_parser.add_argument("-o", metavar="MODULE_OPTION", nargs="+", default=[], dest="module_options", help="module options")
71-
module_parser.add_argument("-L", "--list-modules", action="store_true", help="list available modules")
72-
module_parser.add_argument("--options", dest="show_module_options", action="store_true", help="display module options")
73-
module_parser.add_argument("--server", choices={"http", "https"}, default="https", help="use the selected server (default: https)")
74-
module_parser.add_argument("--server-host", type=str, default="0.0.0.0", metavar="HOST", help="IP to bind the server to (default: 0.0.0.0)")
75-
module_parser.add_argument("--server-port", metavar="PORT", type=int, help="start the server on the specified port")
76-
module_parser.add_argument("--connectback-host", type=str, metavar="CHOST", help="IP for the remote system to connect back to (default: same as server-host)")
71+
mgroup.add_argument("-o", metavar="MODULE_OPTION", nargs="+", default=[], dest="module_options", help="module options")
72+
mgroup.add_argument("-L", "--list-modules", action="store_true", help="list available modules")
73+
mgroup.add_argument("--options", dest="show_module_options", action="store_true", help="display module options")
7774

7875
subparsers = parser.add_subparsers(title="Available Protocols", dest="protocol")
7976

80-
std_parser = argparse.ArgumentParser(add_help=False, parents=[generic_parser, output_parser])
77+
std_parser = argparse.ArgumentParser(add_help=False, parents=[generic_parser, output_parser], formatter_class=DisplayDefaultsNotNone)
8178
std_parser.add_argument("target", nargs="+" if not (module_parser.parse_known_args()[0].list_modules or module_parser.parse_known_args()[0].show_module_options) else "*", type=str, help="the target IP(s), range(s), CIDR(s), hostname(s), FQDN(s), file(s) containing a list of targets, NMap XML or .Nessus file(s)")
82-
std_parser.add_argument("-id", metavar="CRED_ID", nargs="+", default=[], type=str, dest="cred_id", help="database credential ID(s) to use for authentication")
83-
std_parser.add_argument("-u", metavar="USERNAME", dest="username", nargs="+", default=[], help="username(s) or file(s) containing usernames")
84-
std_parser.add_argument("-p", metavar="PASSWORD", dest="password", nargs="+", default=[], help="password(s) or file(s) containing passwords")
85-
std_parser.add_argument("--ignore-pw-decoding", action="store_true", help="Ignore non UTF-8 characters when decoding the password file")
86-
std_parser.add_argument("-k", "--kerberos", action="store_true", help="Use Kerberos authentication")
87-
std_parser.add_argument("--no-bruteforce", action="store_true", help="No spray when using file for username and password (user1 => password1, user2 => password2")
88-
std_parser.add_argument("--continue-on-success", action="store_true", help="continues authentication attempts even after successes")
89-
std_parser.add_argument("--use-kcache", action="store_true", help="Use Kerberos authentication from ccache file (KRB5CCNAME)")
90-
std_parser.add_argument("--aesKey", metavar="AESKEY", nargs="+", help="AES key to use for Kerberos Authentication (128 or 256 bits)")
91-
std_parser.add_argument("--kdcHost", metavar="KDCHOST", help="FQDN of the domain controller. If omitted it will use the domain part (FQDN) specified in the target parameter")
92-
93-
fail_group = std_parser.add_mutually_exclusive_group()
94-
fail_group.add_argument("--gfail-limit", metavar="LIMIT", type=int, help="max number of global failed login attempts")
95-
fail_group.add_argument("--ufail-limit", metavar="LIMIT", type=int, help="max number of failed login attempts per username")
96-
fail_group.add_argument("--fail-limit", metavar="LIMIT", type=int, help="max number of failed login attempts per host")
79+
80+
credential_group = std_parser.add_argument_group("Authentication", "Options for authenticating")
81+
credential_group.add_argument("-u", metavar="USERNAME", dest="username", nargs="+", default=[], help="username(s) or file(s) containing usernames")
82+
credential_group.add_argument("-p", metavar="PASSWORD", dest="password", nargs="+", default=[], help="password(s) or file(s) containing passwords")
83+
credential_group.add_argument("-id", metavar="CRED_ID", nargs="+", default=[], type=str, dest="cred_id", help="database credential ID(s) to use for authentication")
84+
credential_group.add_argument("--ignore-pw-decoding", action="store_true", help="Ignore non UTF-8 characters when decoding the password file")
85+
credential_group.add_argument("--no-bruteforce", action="store_true", help="No spray when using file for username and password (user1 => password1, user2 => password2)")
86+
credential_group.add_argument("--continue-on-success", action="store_true", help="continues authentication attempts even after successes")
87+
credential_group.add_argument("--gfail-limit", metavar="LIMIT", type=int, help="max number of global failed login attempts")
88+
credential_group.add_argument("--ufail-limit", metavar="LIMIT", type=int, help="max number of failed login attempts per username")
89+
credential_group.add_argument("--fail-limit", metavar="LIMIT", type=int, help="max number of failed login attempts per host")
90+
91+
kerberos_group = std_parser.add_argument_group("Kerberos", "Options for Kerberos authentication")
92+
kerberos_group.add_argument("-k", "--kerberos", action="store_true", help="Use Kerberos authentication")
93+
kerberos_group.add_argument("--use-kcache", action="store_true", help="Use Kerberos authentication from ccache file (KRB5CCNAME)")
94+
kerberos_group.add_argument("--aesKey", metavar="AESKEY", nargs="+", help="AES key to use for Kerberos Authentication (128 or 256 bits)")
95+
kerberos_group.add_argument("--kdcHost", metavar="KDCHOST", help="FQDN of the domain controller. If omitted it will use the domain part (FQDN) specified in the target parameter")
96+
97+
server_group = std_parser.add_argument_group("Servers", "Options for nxc servers")
98+
server_group.add_argument("--server", choices={"http", "https"}, default="https", help="use the selected server")
99+
server_group.add_argument("--server-host", type=str, default="0.0.0.0", metavar="HOST", help="IP to bind the server to")
100+
server_group.add_argument("--server-port", metavar="PORT", type=int, help="start the server on the specified port")
101+
server_group.add_argument("--connectback-host", type=str, metavar="CHOST", help="IP for the remote system to connect back to")
97102

98103
p_loader = ProtocolLoader()
99104
protocols = p_loader.get_protocols()

nxc/helpers/args.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from argparse import ArgumentDefaultsHelpFormatter, SUPPRESS, OPTIONAL, ZERO_OR_MORE
2+
3+
class DisplayDefaultsNotNone(ArgumentDefaultsHelpFormatter):
4+
def _get_help_string(self, action):
5+
help_string = action.help
6+
if "%(default)" not in action.help and action.default is not SUPPRESS:
7+
defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
8+
if (action.option_strings or action.nargs in defaulting_nargs) and action.default: # Only add default info if it's not None
9+
help_string += " (default: %(default)s)" # NORUFF
10+
return help_string

0 commit comments

Comments
 (0)