Skip to content

Commit 6e7edbd

Browse files
authored
Merge pull request Pennyw0rth#859 from Pennyw0rth/neff-add-module-categories
Add module categories
2 parents 6c482cd + 0bcafed commit 6e7edbd

126 files changed

Lines changed: 328 additions & 44 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

nxc/cli.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,13 @@ def gen_cli_args():
7676
mgroup = module_parser.add_argument_group("Modules", "Options for nxc modules")
7777
mgroup.add_argument("-M", "--module", choices=get_module_names(), action="append", metavar="MODULE", help="module to use")
7878
mgroup.add_argument("-o", metavar="MODULE_OPTION", nargs="+", default=[], dest="module_options", help="module options")
79-
mgroup.add_argument("-L", "--list-modules", action="store_true", help="list available modules")
79+
mgroup.add_argument("-L", "--list-modules", nargs="?", type=str, const="", help="list available modules")
8080
mgroup.add_argument("--options", dest="show_module_options", action="store_true", help="display module options")
8181

8282
subparsers = parser.add_subparsers(title="Available Protocols", dest="protocol")
8383

8484
std_parser = argparse.ArgumentParser(add_help=False, parents=[generic_parser, output_parser, dns_parser], formatter_class=DisplayDefaultsNotNone)
85-
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 or generic_parser.parse_known_args()[0].version) 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)")
85+
std_parser.add_argument("target", nargs="+" if not (module_parser.parse_known_args()[0].list_modules is not None or module_parser.parse_known_args()[0].show_module_options or generic_parser.parse_known_args()[0].version) 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)")
8686
credential_group = std_parser.add_argument_group("Authentication", "Options for authenticating")
8787
credential_group.add_argument("-u", "--username", metavar="USERNAME", dest="username", nargs="+", default=[], help="username(s) or file(s) containing usernames")
8888
credential_group.add_argument("-p", "--password", metavar="PASSWORD", dest="password", nargs="+", default=[], help="password(s) or file(s) containing passwords")

nxc/helpers/misc.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
from enum import Enum
12
import random
23
import string
34
import re
45
import inspect
56
import os
6-
7+
from termcolor import colored
78
from ipaddress import ip_address
9+
from nxc.logger import nxc_logger
810

911

1012
def identify_target_file(target_file):
@@ -145,3 +147,21 @@ def detect_if_ip(target):
145147
return True
146148
except Exception:
147149
return False
150+
151+
152+
def display_modules(args, modules):
153+
for category, color in {CATEGORY.ENUMERATION: "green", CATEGORY.CREDENTIAL_DUMPING: "cyan", CATEGORY.PRIVILEGE_ESCALATION: "magenta"}.items():
154+
# Add category filter for module listing
155+
if args.list_modules and args.list_modules.lower() != category.name.lower():
156+
continue
157+
if len([module for module in modules.values() if module["category"] == category]) > 0:
158+
nxc_logger.highlight(colored(f"{category.name}", color, attrs=["bold"]))
159+
for name, props in sorted(modules.items()):
160+
if props["category"] == category:
161+
nxc_logger.display(f"{name:<25} {props['description']}")
162+
163+
164+
class CATEGORY(Enum):
165+
ENUMERATION = "Enumeration"
166+
CREDENTIAL_DUMPING = "Credential Dumping"
167+
PRIVILEGE_ESCALATION = "Privilege Escalation"

nxc/loaders/moduleloader.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ def module_is_sane(self, module, module_path):
3030
elif not hasattr(module, "description"):
3131
self.logger.fail(f"{module_path} missing the description variable")
3232
module_error = True
33+
elif not hasattr(module, "category"):
34+
self.logger.fail(f"{module_path} missing the category variable")
35+
module_error = True
3336
elif not hasattr(module, "supported_protocols"):
3437
self.logger.fail(f"{module_path} missing the supported_protocols variable")
3538
module_error = True
@@ -92,6 +95,7 @@ def get_module_info(self, module_path):
9295
"description": module_spec.description,
9396
"options": module_spec.options.__doc__,
9497
"supported_protocols": module_spec.supported_protocols,
98+
"category": module_spec.category,
9599
"requires_admin": bool(hasattr(module_spec, "on_admin_login") and callable(module_spec.on_admin_login)),
96100
}
97101
}

nxc/modules/adcs.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import re
22
from impacket.ldap import ldap, ldapasn1
33
from impacket.ldap.ldap import LDAPSearchError
4+
from nxc.helpers.misc import CATEGORY
45

56

67
class NXCModule:
@@ -13,6 +14,7 @@ class NXCModule:
1314
name = "adcs"
1415
description = "Find PKI Enrollment Services in Active Directory and Certificate Templates Names"
1516
supported_protocols = ["ldap"]
17+
category = CATEGORY.ENUMERATION
1618

1719
def __init__(self, context=None, module_options=None):
1820
self.context = context

nxc/modules/add-computer.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import sys
44
from impacket.dcerpc.v5 import samr, epm, transport
55
from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_GSS_NEGOTIATE
6+
from nxc.helpers.misc import CATEGORY
67

78

89
class NXCModule:
@@ -16,6 +17,7 @@ class NXCModule:
1617
name = "add-computer"
1718
description = "Adds or deletes a domain computer"
1819
supported_protocols = ["smb"]
20+
category = CATEGORY.PRIVILEGE_ESCALATION
1921

2022
def options(self, context, module_options):
2123
"""

nxc/modules/aws-credentials.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
from nxc.helpers.misc import CATEGORY
2+
3+
14
class NXCModule:
25
"""
36
Search for aws credentials files on linux and windows machines
@@ -8,6 +11,7 @@ class NXCModule:
811
name = "aws-credentials"
912
description = "Search for aws credentials files."
1013
supported_protocols = ["ssh", "smb", "winrm"]
14+
category = CATEGORY.CREDENTIAL_DUMPING
1115

1216
def __init__(self):
1317
self.search_path_linux = "'/home/' '/tmp/'"

nxc/modules/backup_operator.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
from impacket.smbconnection import SessionError
77
from impacket.dcerpc.v5 import transport, rrp
88
from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_GSS_NEGOTIATE
9+
from nxc.helpers.misc import CATEGORY
910
from nxc.paths import NXC_PATH
1011

1112

1213
class NXCModule:
1314
name = "backup_operator"
1415
description = "Exploit user in backup operator group to dump NTDS @mpgn_x64"
1516
supported_protocols = ["smb"]
17+
category = CATEGORY.PRIVILEGE_ESCALATION
1618

1719
def __init__(self, context=None, module_options=None):
1820
self.context = context

nxc/modules/badsuccessor.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from impacket.ldap import ldaptypes
2+
from nxc.helpers.misc import CATEGORY
23
from nxc.parsers.ldap_results import parse_result_attributes
34
from ldap3.protocol.microsoft import security_descriptor_control
45

@@ -79,6 +80,7 @@ class NXCModule:
7980
name = "badsuccessor"
8081
description = "Check if vulnerable to bad successor attack (DMSA)"
8182
supported_protocols = ["ldap"]
83+
category = CATEGORY.ENUMERATION
8284

8385
def __init__(self):
8486
self.context = None

nxc/modules/bitlocker.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
from impacket.dcerpc.v5.dtypes import NULL
44
from impacket.dcerpc.v5.dcomrt import DCOMConnection
55
from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_LEVEL_PKT_PRIVACY
6+
from nxc.helpers.misc import CATEGORY
67

78

89
class NXCModule:
910
name = "bitlocker"
1011
description = "Enumerating BitLocker Status on target(s) If it is enabled or disabled."
1112
supported_protocols = ["smb", "wmi"]
13+
category = CATEGORY.ENUMERATION
1214

1315
def __init__(self, context=None, module_options=None):
1416
self.context = context

nxc/modules/change-password.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import sys
22
from impacket.dcerpc.v5 import samr, epm, transport
33
from impacket.dcerpc.v5.rpcrt import DCERPCException
4+
from nxc.helpers.misc import CATEGORY
45

56

67
class NXCModule:
@@ -12,6 +13,7 @@ class NXCModule:
1213
name = "change-password"
1314
description = "Change or reset user passwords via various protocols"
1415
supported_protocols = ["smb"]
16+
category = CATEGORY.PRIVILEGE_ESCALATION
1517

1618
def options(self, context, module_options):
1719
"""

0 commit comments

Comments
 (0)