Skip to content

Add USER option to maq module to enumerate per-user machine join count#1184

Open
PvUL00 wants to merge 5 commits into
Pennyw0rth:mainfrom
PvUL00:feat/add-maq-options
Open

Add USER option to maq module to enumerate per-user machine join count#1184
PvUL00 wants to merge 5 commits into
Pennyw0rth:mainfrom
PvUL00:feat/add-maq-options

Conversation

@PvUL00
Copy link
Copy Markdown

@PvUL00 PvUL00 commented Apr 1, 2026

Description

Adds a USER option that queries how many computers a given user has already joined to the domain, compared against the MachineAccountQuota. Detection covers both SAMR domain joins (ms-DS-CreatorSID) and direct LDAP creation such as addcomputer.py (nTSecurityDescriptor owner SID).

Two detection methods are used to cover all creation paths:

  1. ms-DS-CreatorSID — set by the DC for computers joined via SAMR (standard Windows domain join)
  2. nTSecurityDescriptor owner SID — set for computers created via direct LDAP (e.g. addcomputer.py)

The LDAP query uses LDAP_SERVER_SD_FLAGS_OID (1.2.840.113556.1.4.801) with OWNER_SECURITY_INFORMATION=1 to retrieve only the owner portion of the security descriptor.

Usage:

MAQ only (unchanged behaviour)
nxc ldap <DC> -u <user> -p <pass> -M maq

MAQ + machine join count for a specific user
nxc ldap <DC> -u <user> -p <pass> -M maq -o USER=<username>

This module was built with the assistance of Claude Code (claude-sonnet-4-6). All code was reviewed and tested against a live AD lab.

Type of change

Insert an "x" inside the brackets for relevant items (do not delete options)

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Deprecation of feature or functionality
  • This change requires a documentation update
  • This requires a third party update (such as Impacket, Dploot, lsassy, etc)
  • This PR was created with the assistance of AI (list what type of assistance, tool(s)/model(s) in the description)

Setup guide for the review

  • Python 3.11, Linux (Exegol)
    • Tested against Windows Server 2019 DC (GOAD mini lab)
    • No additional software, GPO changes or registry settings required
    • To test: create a machine account then query the count:
      addcomputer.py -computer-name 'SHUTDOWN$' -computer-pass 'Password1!' -dc-host DC -domain-netbios LAB lab.local/user:pass

nxc ldap -u user -p pass -M maq -o USER=user
Expected:
Machines joined by 'user': 1/10 (remaining quota: 9)
Computer: SHUTDOWN

Screenshots (if appropriate):

Before :

image

After :
image

Checklist:

Insert an "x" inside the brackets for completed and relevant items (do not delete options)

  • I have ran Ruff against my changes (poetry: poetry run ruff check ., use --fix to automatically fix what it can)
  • I have added or updated the tests/e2e_commands.txt file if necessary (new modules or features are required to be added to the e2e tests)
  • If reliant on changes of third party dependencies, such as Impacket, dploot, lsassy, etc, I have linked the relevant PRs in those projects
  • I have linked relevant sources that describes the added technique (blog posts, documentation, etc)
  • I have performed a self-review of my own code (not an AI review)
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (PR here: https://github.com/Pennyw0rth/NetExec-Wiki)

Adds a USER option that queries how many computers a given user has
already joined to the domain, compared against the MachineAccountQuota.
Detection covers both SAMR domain joins (ms-DS-CreatorSID) and direct
LDAP creation such as addcomputer.py (nTSecurityDescriptor owner SID).
PvUL00 added 2 commits April 7, 2026 00:35
Signed-off-by: PvUL00 <166558777+PvUL00@users.noreply.github.com>
Signed-off-by: PvUL00 <166558777+PvUL00@users.noreply.github.com>
@NeffIsBack NeffIsBack added the enhancement New feature or request label Apr 18, 2026
Copy link
Copy Markdown
Member

@NeffIsBack NeffIsBack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!

Comment thread nxc/modules/maq.py Outdated
Comment thread nxc/modules/maq.py Outdated
Comment thread nxc/modules/maq.py Outdated
Comment thread nxc/modules/maq.py Outdated
# Method 1: ms-DS-CreatorSID — set by DC for SAMR domain joins
raw_sid = comp.get("ms-DS-CreatorSID")
if raw_sid is not None:
creator_sid = _sid_to_str(raw_sid) if isinstance(raw_sid, bytes) else raw_sid
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you get raw bytes for the sid? I think this should have been parsed by the ldap attribute parser

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The isinstance check has been removed and replaced with a direct call to sid_to_str (imported from nxc.parsers.ldap_results) which is the same function the attribute parser uses for objectSid.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, since this attribute should always be an SID we should add that to the attribute parser itself, so that it does not have to be called by external scripts (the module in this case).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, ms-DS-CreatorSID has been added to parse_result_attributes in nxc/parsers/ldap_results.py and the manual sid_to_str call removed from the module

Comment thread nxc/modules/maq.py Outdated
@PvUL00 PvUL00 requested a review from NeffIsBack April 20, 2026 11:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants