Skip to content

feat(smb): add generic --export flag for enumeration commands#1101

Open
H1DroZz wants to merge 4 commits intoPennyw0rth:mainfrom
H1DroZz:feature/rid-users-export
Open

feat(smb): add generic --export flag for enumeration commands#1101
H1DroZz wants to merge 4 commits intoPennyw0rth:mainfrom
H1DroZz:feature/rid-users-export

Conversation

@H1DroZz
Copy link
Copy Markdown

@H1DroZz H1DroZz commented Feb 9, 2026

Description

This PR aligns SMB export behavior with review feedback from #1101 by enforcing:

  • one function per enumeration logic (--users, --rid-brute)
  • one shared export path (--export FILE)

Instead of maintaining command-specific export handlers, enumeration functions now return data and reuse a single export routine.

What Changed

  • Added/used a single SMB export logic for supported enumerations through --export.
  • Updated --users flow to enumerate first, then export via the shared export path.
  • Updated --rid-brute flow to enumerate first, then export only SidTypeUser usernames (excluding machine accounts ending with $).
  • Removed SMB-specific dedicated export paths/functions that duplicated logic.
  • Removed SMB --users-export argument in favor of the unified --users --export pattern.
  • Fixed SAMR user dump data propagation so --users --export exports the actual enumerated list.
  • Updated E2E commands accordingly, including an explicit higher RID-range export scenario (--rid-brute 10000 --export ...).

Supported Commands (SMB)

  • --users --export <file>
    Exports enumerated domain users from SAMR user enumeration.
  • --rid-brute [MAX_RID] --export <file>
    Exports SidTypeUser usernames found via RID bruteforce (machine accounts excluded).

Notes

  • --rid-brute coverage depends on MAX_RID.
    Some users may be missed with low RID ceilings; using a higher value (for example 10000) can be required depending on environment.

Validation Performed

  • --users --export validated: exported user count matches enumeration output.
  • --rid-brute --export validated: exports filtered user-only results as expected.
  • Real-world validation confirmed behavior with default and extended RID ranges.

Type of Change

  • Refactor (non-breaking behavior improvement for SMB export architecture)
  • Feature behavior consolidation (--export as single export path)
  • Test update (E2E command coverage)

Setup Guide for Review

Python: 3.10+
OS: Linux
Target: Windows Domain Controller

Examples:

# Export users from SAMR enumeration
netexec smb 10.129.12.155 -u 'pentest' -p 'p3nt3st2025!&' --users --export users.txt    
SMB         10.129.12.155   445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:pirate.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         10.129.12.155   445    DC01             [+] pirate.htb\pentest:p3nt3st2025!& 
SMB         10.129.12.155   445    DC01             -Username-                    -Last PW Set-       -BadPW- -Description-                                               
SMB         10.129.12.155   445    DC01             Administrator                 2025-06-08 14:32:36 0       Built-in account for administering the computer/domain 
SMB         10.129.12.155   445    DC01             Guest                         <never>             0       Built-in account for guest access to the computer/domain 
SMB         10.129.12.155   445    DC01             krbtgt                        2025-06-08 14:40:29 0       Key Distribution Center Service Account 
SMB         10.129.12.155   445    DC01             a.white_adm                   2026-01-16 00:36:34 0        
SMB         10.129.12.155   445    DC01             a.white                       2025-06-08 19:33:01 0        
SMB         10.129.12.155   445    DC01             pentest                       2025-06-09 13:40:23 0        
SMB         10.129.12.155   445    DC01             j.sparrow                     2025-06-09 15:08:44 0        
SMB         10.129.12.155   445    DC01             [*] Enumerated 7 local users: PIRATE
SMB         10.129.12.155   445    DC01             [+] Exported 7 users to users.txt


# Export users from RID bruteforce (default max rid)
nxc smb <target> -u <user> -p <password> --rid-brute --export /tmp/rid_users.txt

# Export users from RID bruteforce with extended range
netexec smb 10.129.12.155 -u 'pentest' -p 'p3nt3st2025!&' --rid-brute 10000 --export rid_users.txt
SMB         10.129.12.155   445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:pirate.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         10.129.12.155   445    DC01             [+] pirate.htb\pentest:p3nt3st2025!& 
SMB         10.129.12.155   445    DC01             498: PIRATE\Enterprise Read-only Domain Controllers (SidTypeGroup)
SMB         10.129.12.155   445    DC01             500: PIRATE\Administrator (SidTypeUser)
SMB         10.129.12.155   445    DC01             501: PIRATE\Guest (SidTypeUser)
SMB         10.129.12.155   445    DC01             502: PIRATE\krbtgt (SidTypeUser)
SMB         10.129.12.155   445    DC01             512: PIRATE\Domain Admins (SidTypeGroup)
SMB         10.129.12.155   445    DC01             513: PIRATE\Domain Users (SidTypeGroup)
SMB         10.129.12.155   445    DC01             514: PIRATE\Domain Guests (SidTypeGroup)
SMB         10.129.12.155   445    DC01             515: PIRATE\Domain Computers (SidTypeGroup)
SMB         10.129.12.155   445    DC01             516: PIRATE\Domain Controllers (SidTypeGroup)
SMB         10.129.12.155   445    DC01             517: PIRATE\Cert Publishers (SidTypeAlias)
SMB         10.129.12.155   445    DC01             518: PIRATE\Schema Admins (SidTypeGroup)
SMB         10.129.12.155   445    DC01             519: PIRATE\Enterprise Admins (SidTypeGroup)
SMB         10.129.12.155   445    DC01             520: PIRATE\Group Policy Creator Owners (SidTypeGroup)
SMB         10.129.12.155   445    DC01             521: PIRATE\Read-only Domain Controllers (SidTypeGroup)
SMB         10.129.12.155   445    DC01             522: PIRATE\Cloneable Domain Controllers (SidTypeGroup)
SMB         10.129.12.155   445    DC01             525: PIRATE\Protected Users (SidTypeGroup)
SMB         10.129.12.155   445    DC01             526: PIRATE\Key Admins (SidTypeGroup)
SMB         10.129.12.155   445    DC01             527: PIRATE\Enterprise Key Admins (SidTypeGroup)
SMB         10.129.12.155   445    DC01             553: PIRATE\RAS and IAS Servers (SidTypeAlias)
SMB         10.129.12.155   445    DC01             571: PIRATE\Allowed RODC Password Replication Group (SidTypeAlias)
SMB         10.129.12.155   445    DC01             572: PIRATE\Denied RODC Password Replication Group (SidTypeAlias)
SMB         10.129.12.155   445    DC01             1000: PIRATE\DC01$ (SidTypeUser)
SMB         10.129.12.155   445    DC01             1101: PIRATE\DnsAdmins (SidTypeAlias)
SMB         10.129.12.155   445    DC01             1102: PIRATE\DnsUpdateProxy (SidTypeGroup)
SMB         10.129.12.155   445    DC01             1103: PIRATE\IT (SidTypeGroup)
SMB         10.129.12.155   445    DC01             1104: PIRATE\a.white_adm (SidTypeUser)
SMB         10.129.12.155   445    DC01             3101: PIRATE\a.white (SidTypeUser)
SMB         10.129.12.155   445    DC01             3102: PIRATE\WEB01$ (SidTypeUser)
SMB         10.129.12.155   445    DC01             4101: PIRATE\Domain Secure Servers (SidTypeGroup)
SMB         10.129.12.155   445    DC01             4102: PIRATE\MS01$ (SidTypeUser)
SMB         10.129.12.155   445    DC01             4103: PIRATE\EXCH01$ (SidTypeUser)
SMB         10.129.12.155   445    DC01             4105: PIRATE\gMSA_ADCS_prod$ (SidTypeUser)
SMB         10.129.12.155   445    DC01             4106: PIRATE\pentest (SidTypeUser)
SMB         10.129.12.155   445    DC01             4108: PIRATE\gMSA_ADFS_prod$ (SidTypeUser)
SMB         10.129.12.155   445    DC01             4110: PIRATE\j.sparrow (SidTypeUser)
SMB         10.129.12.155   445    DC01             [+] Exported 7 users to rid_users.txt

Checklist:

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

  • I have ran Ruff against my changes (via poetry: poetry run python -m ruff check . --preview, 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)
  • New and existing e2e tests pass locally with my changes
  • 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 performed a self-review of my own code
  • 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)

- Add --rid-users-export argument in proto_args.py
- Implement rid_users_export() method in smb.py
- Filter and export only SidTypeUser entries
- Add E2E test
@NeffIsBack
Copy link
Copy Markdown
Member

Hi and thanks for the PR.

I don't think we should add even more --...export args, specifically naming the --users-export arg was probably already going in the wrong direction. In contrast, we should just implement an --export flag that just takes the output of the previously ran commands (that are supported) and dump it to file. How that should look like in detail remains to be figured out, maybe a decorator or something similar.

@NeffIsBack
Copy link
Copy Markdown
Member

@H1DroZz do you have the time to implement that change?

Add --export FILE argument to SMB protocol that works alongside
--rid-brute and --users, replacing the need for command-specific
export flags. Filters SidTypeUser entries (excluding machine accounts)
when exporting from --rid-brute.
@H1DroZz
Copy link
Copy Markdown
Author

H1DroZz commented Mar 17, 2026

@H1DroZz do you have the time to implement that change?

Hello, it's done.

Following your feedback, I replaced --rid-users-export with a generic --export flag that works alongside both --rid-brute and --users.

While implementing this, I noticed --users-export follows the same pattern you pointed out. Would you like me to deprecate it in favor of --export as well, or would you prefer to keep it for backward compatibility?

Have a nice day

@H1DroZz H1DroZz changed the title feat(smb): add --rid-users-export option to export RID enumerated users feat(smb): add generic --export flag for enumeration commands Mar 17, 2026
@NeffIsBack
Copy link
Copy Markdown
Member

While implementing this, I noticed --users-export follows the same pattern you pointed out. Would you like me to deprecate it in favor of --export as well, or would you prefer to keep it for backward compatibility?

Have a nice day

Yes please, we should deprecate the --users-export afterwards.

Thanks you too :)

@H1DroZz
Copy link
Copy Markdown
Author

H1DroZz commented Mar 19, 2026

Hello @NeffIsBack I've implemented the deprecation of --users-export as requested. The flag still works for backward compatibility but now displays a deprecation warning directing users to --users --export.

Let me know if this approach looks good to you or if you'd like any adjustments!

Have a nice day

@NeffIsBack
Copy link
Copy Markdown
Member

So currently we have multiple functions for each flag that is exported. The goal is to have only one function per enumeration logic (e.g. --users or --brute-rid) and then one --export flag function/logic. My idea for such a construct would be to have the base function of the enumeration calls doing the enumeration logic and at the end when we have the data as e.g. list do something like:

if self.args.export:
  self.export(data)

for each of the enumeration functions. The export function would then simply dump the input data to file.

- use a single --export-backed helper in smb protocol

- remove deprecated SMB --users-export argument and dedicated handlers

- fix SAMR user dump return path so --users --export exports real results

- add e2e command for --rid-brute 10000 --export
@NeffIsBack
Copy link
Copy Markdown
Member

@Marshall-Hallenbeck the template runner crashed here as well

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants