Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
e4d9715
feat(kerberoasting): allow for specifying specific users to kerberoast
Marshall-Hallenbeck Jul 29, 2025
71d8aa0
refactor(args): move get_conditional_access to central file
Marshall-Hallenbeck Aug 2, 2025
fcba942
fix(kerberoast): require kerberoasting arg when using kerberoast-users
Marshall-Hallenbeck Aug 2, 2025
35bc7d9
feat(kerberoast): add in kerberoast as alias to kerberoasting
Marshall-Hallenbeck Aug 2, 2025
94f8cbd
Merge branch 'main' into marshall-kerberoast-user-list
Marshall-Hallenbeck Aug 13, 2025
e5af642
chore(ruff): fix stupid empty line
Marshall-Hallenbeck Aug 13, 2025
826a502
Merge branch 'main' into marshall-kerberoast-user-list
Marshall-Hallenbeck Aug 17, 2025
722fa0c
fix: fail cleanly if file cannot be opened
Marshall-Hallenbeck Aug 17, 2025
7b729af
feat(kerberoasting): allow for specifying specific users to kerberoast
Marshall-Hallenbeck Jul 29, 2025
1ccd674
refactor(args): move get_conditional_access to central file
Marshall-Hallenbeck Aug 2, 2025
1906919
fix(kerberoast): require kerberoasting arg when using kerberoast-users
Marshall-Hallenbeck Aug 2, 2025
76ce823
feat(kerberoast): add in kerberoast as alias to kerberoasting
Marshall-Hallenbeck Aug 2, 2025
c522c27
chore(ruff): fix stupid empty line
Marshall-Hallenbeck Aug 13, 2025
57edc29
Update Masky module to 0.2.1
Z4kSec Aug 16, 2025
a1a3a5d
Update masky
NeffIsBack Aug 16, 2025
ea6fab4
Fix lock file
NeffIsBack Aug 16, 2025
5366a1b
Added the lockscreendoors module
Aug 2, 2025
28f5bd1
added credits
Aug 2, 2025
2304679
ruff changes
Aug 2, 2025
352fef4
Added lockscreendoors
Aug 2, 2025
18794f9
Fixed issues for PR
Aug 4, 2025
458b113
Added and removed lock screen executables
Aug 4, 2025
4237939
Fixed support for Win server 2008 and multiple descriptions
Aug 6, 2025
055934e
format expected descriptions as plain string in output
Aug 6, 2025
005af59
Formatting
NeffIsBack Aug 16, 2025
81997e6
Formatting
NeffIsBack Aug 16, 2025
e60aa93
Add debug log on parsing errors
NeffIsBack Aug 16, 2025
1f313ca
Formatting and remove unnecessary check
NeffIsBack Aug 16, 2025
77d00bb
Don't skip silently, bug provide a debug log
NeffIsBack Aug 16, 2025
e7d9a4a
Add 'No options available' to the module and the example module
NeffIsBack Aug 16, 2025
a982386
fix: fail cleanly if file cannot be opened
Marshall-Hallenbeck Aug 17, 2025
f616583
Resolve merge conflicts: update poetry.lock, ssh proto_args, and fix …
Marshall-Hallenbeck Aug 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions nxc/helpers/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,18 @@ def __call__(self, parser, namespace, values, option_string=None):
# Set an attribute to track whether the value was explicitly set
setattr(namespace, self.dest, values)
setattr(namespace, f"{self.dest}_explicitly_set", True)


def get_conditional_action(baseAction):
class ConditionalAction(baseAction):
def __init__(self, option_strings, dest, **kwargs):
x = kwargs.pop("make_required", [])
super().__init__(option_strings, dest, **kwargs)
self.make_required = x

def __call__(self, parser, namespace, values, option_string=None):
for x in self.make_required:
x.required = True
super().__call__(parser, namespace, values, option_string)

return ConditionalAction
23 changes: 21 additions & 2 deletions nxc/protocols/ldap.py
Original file line number Diff line number Diff line change
Expand Up @@ -1031,8 +1031,27 @@ def kerberoasting(self):
f.write(line + "\n")
return

# Building the search filter
searchFilter = "(&(servicePrincipalName=*)(!(objectCategory=computer)))"
if self.args.kerberoast_users:
target_usernames = []
for item in self.args.kerberoast_users:
if os.path.isfile(item):
try:
with open(item, encoding="utf-8") as f:
target_usernames.extend(line.strip() for line in f if line.strip())
except Exception as e:
self.logger.fail(f"Failed to read file '{item}': {e}")
else:
target_usernames.append(item.strip())

self.logger.info(f"Targeting specific users for kerberoasting: {', '.join(target_usernames)}")

# build search filter for specific users
user_filter = "".join([f"(sAMAccountName={username})" for username in target_usernames])
searchFilter = f"(&(servicePrincipalName=*)(!(objectCategory=computer))(|{user_filter}))"
else:
# default to all
searchFilter = "(&(servicePrincipalName=*)(!(objectCategory=computer)))"

attributes = [
"sAMAccountName",
"userAccountControl",
Expand Down
9 changes: 7 additions & 2 deletions nxc/protocols/ldap/proto_args.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from nxc.helpers.args import DefaultTrackingAction, DisplayDefaultsNotNone
from nxc.helpers.args import DefaultTrackingAction, DisplayDefaultsNotNone, get_conditional_action
from argparse import _StoreAction


def proto_args(parser, parents):
Expand All @@ -12,9 +13,13 @@ def proto_args(parser, parents):

egroup = ldap_parser.add_argument_group("Retrieve hash on the remote DC", "Options to get hashes from Kerberos")
egroup.add_argument("--asreproast", help="Output AS_REP response to crack with hashcat to file")
egroup.add_argument("--kerberoasting", help="Output TGS ticket to crack with hashcat to file")
kerberoasting_arg = egroup.add_argument("--kerberoasting", "--kerberoast", help="Output TGS ticket to crack with hashcat to file")
kerberoast_users_arg = egroup.add_argument("--kerberoast-users", nargs="+", dest="kerberoast_users", action=get_conditional_action(_StoreAction), make_required=[], help="Target specific users for kerberoasting (usernames or file containing usernames)")
egroup.add_argument("--no-preauth-targets", nargs=1, dest="no_preauth_targets", help="Targeted kerberoastable users")

# Make kerberoast-users require kerberoasting
kerberoast_users_arg.make_required = [kerberoasting_arg]

vgroup = ldap_parser.add_argument_group("Retrieve useful information on the domain")
vgroup.add_argument("--base-dn", metavar="BASE_DN", dest="base_dn", type=str, default=None, help="base DN for search queries")
vgroup.add_argument("--query", nargs=2, help="Query LDAP with a custom filter and attributes")
Expand Down
17 changes: 1 addition & 16 deletions nxc/protocols/smb/proto_args.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from argparse import _StoreTrueAction
from nxc.helpers.args import DisplayDefaultsNotNone, DefaultTrackingAction
from nxc.helpers.args import DisplayDefaultsNotNone, DefaultTrackingAction, get_conditional_action


def proto_args(parser, parents):
Expand Down Expand Up @@ -98,18 +98,3 @@ def proto_args(parser, parents):
posh_group.add_argument("--no-encode", action="store_true", default=False, help="Do not encode the PowerShell command ran on target")

return parser


def get_conditional_action(baseAction):
class ConditionalAction(baseAction):
def __init__(self, option_strings, dest, **kwargs):
x = kwargs.pop("make_required", [])
super().__init__(option_strings, dest, **kwargs)
self.make_required = x

def __call__(self, parser, namespace, values, option_string=None):
for x in self.make_required:
x.required = True
super().__call__(parser, namespace, values, option_string)

return ConditionalAction
17 changes: 1 addition & 16 deletions nxc/protocols/ssh/proto_args.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from argparse import _StoreAction
from nxc.helpers.args import DisplayDefaultsNotNone
from nxc.helpers.args import DisplayDefaultsNotNone, get_conditional_action


def proto_args(parser, parents):
Expand All @@ -22,18 +22,3 @@ def proto_args(parser, parents):
cgroup.add_argument("-x", metavar="COMMAND", dest="execute", help="execute the specified command")

return parser


def get_conditional_action(baseAction):
class ConditionalAction(baseAction):
def __init__(self, option_strings, dest, **kwargs):
x = kwargs.pop("make_required", [])
super().__init__(option_strings, dest, **kwargs)
self.make_required = x

def __call__(self, parser, namespace, values, option_string=None):
for x in self.make_required:
x.required = True
super().__call__(parser, namespace, values, option_string)

return ConditionalAction
2 changes: 1 addition & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading