Skip to content

Conversation

@5epi0l
Copy link

@5epi0l 5epi0l commented Nov 18, 2025

Description

This pull request adds a new tombfind module to NetExec that allows operators to enumerate tombstoned (deleted but recoverable) Active Directory objects via LDAP.
It supports both NTLM and Kerberos authentication and works against any domain functional level that exposes the CN=Deleted Objects container.

This contribution does not introduce any breaking changes to existing NetExec functionality. Instead, it adds a dedicated LDAP module that expands the framework’s enumeration and recovery capabilities for domain controllers

The implementation relies solely on existing project dependencies, including Impacket, and does not introduce any new third-party libraries. The module includes clear in-line documentation, structured error handling, and follows the established NetExec module patterns.

Where Kerberos-related operations are required, the module leverages Impacket’s native cryptographic and ASN.1 classes, ensuring consistency with the rest of the codebase.

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)

Setup guide for the review

  • Environment:
    • Python 3.11 (recommended) on Linux or Windows.
    • Ensure impacket is installed and all NetExec dependencies are satisfied (poetry install).
  • Pre-requisites:
    • You'd need Domain Admin credentials or, another account capable of reviewing TombStoned Users
  • Testing Steps:
    • Run: netexec ldap <dc-ip> -u <username> -p <password> -M tombfind to enumerate all tombstoned users.
    • Optionally, run with -o OUTPUT=<filename> to write the output to a file
    • For ticket forging, validate that .ccache files are generated and can be used with export KRB5CCNAME=... and relevant Kerberos tooling.
  • Bug/feature reproduction:
    • For testing, run the module in an environment containing atleast one tombstoned object.

Screenshots (if appropriate):

Pass The Hash

image

Kerberos and output to a file

image

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)

@NeffIsBack
Copy link
Member

Hi and thanks for your work!

However, i fear this is duplicate to #736. You could check if the implementation matches your idea and give input if you find issues/features are missing which you have implemented.

@NeffIsBack NeffIsBack added the duplicate This issue or pull request already exists label Nov 19, 2025
@5epi0l
Copy link
Author

5epi0l commented Nov 20, 2025

Hi, thanks again for the review.

I compared my implementation with PR #736 as suggested. Functionality-wise they overlap, and the PR #736 extends on it by adding the capability to restore objects, but there are still a couple meaningful differences:
• My module formats the output in a cleaner and more readable way, which makes it easier to use during engagements.
• My module also provides LDAP page size control, which can be useful in larger environments or when dealing with many deleted objects.
• If useful, I’d be happy to adapt my “finding” logic and formatting improvements into the existing PR, or collaborate so the maintainers can take the best parts of both.

If the team prefers using #736 as the base, no problem — just let me know if my output formatting, page size control, or code structure would be beneficial, and I can help merge it in.

Thanks for the time and the feedback.

@NeffIsBack
Copy link
Member

As #736 is the first PR i think we should go forward with this one, but please feel free to discuss/collaborate with the author to implement changes you feel are superior in your implementation. I haven't looked at the structure that much, so i can't say which approach i like better.
Regarding the page size control, either way LDAP queries should use the search() function of the NetExec LDAP connection object which wraps the impacket search function and adds logic for size control, errors etc.

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

Labels

duplicate This issue or pull request already exists

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants