Language: English | 简体中文 | Français
Current release: v0.5.28
A dMSA forge for authorized BadSuccessor LDAP workflows: assess, add, verify, and delete.
Designed around signed LDAP 389, atomic dMSA creation, post-add verification, concise operator help, project profiles, and structured reporting.
This project is based on Impacket examples/badsuccessor.py and keeps the upstream attribution and licensing context. This version is heavily refactored by RedteamNotes to make LDAP 389 with signing, atomic dMSA creation, and post-add verification explicit and reproducible.
Use only in environments where you have explicit authorization.
- Uses Impacket native
LDAPConnectiondirectly;ldap3is not a runtime dependency. - Supports signed LDAP on port 389 for environments that enforce LDAP signing and have unusable LDAPS.
- Writes dMSA core attributes in the initial AddRequest, including
msDS-GroupMSAMembership,msDS-ManagedAccountPrecededByLink, andmsDS-DelegatedMSAState. - Verifies the object by reading it back from the DC after add.
- Parses
msDS-GroupMSAMembershipas a binary security descriptor and prints a readable summary instead of raw bytes. - Adds
verifyas a read-only action. - Modernizes the operator experience with task-named commands, concise contextual help, inferred defaults, next-step suggestions, and structured reports.
- Adds safer preflight and reporting workflows: dry-run plans, scope guardrails, redacted structured output, readiness checks, and clearer failure diagnostics.
- Keeps output honest: LDAP verification success does not mean KDC readiness.
From GitHub with pipx:
pipx install git+https://github.com/RedteamNotes/dmsa-forge.gitOr clone and install from a local checkout:
git clone https://github.com/RedteamNotes/dmsa-forge.git
python -m venv dmsa-forge/.venv
source dmsa-forge/.venv/bin/activate
python -m pip install ./dmsa-forgeAfter installation, run:
dmsaforge -hUpdate the active environment when a new release is available:
dmsaforge updateupdate compares the installed version with the target release first. If the versions match, it skips pip; if they differ, it updates regardless of whether the target version is higher or lower. Use dmsaforge update --force only when you deliberately want to run pip without the version check.
Useful help entry points:
dmsaforge add -h
dmsaforge update --dry-runFor source-checkout use without installation, run ./dmsaforge.py.
Examples and generated next steps use long options by default. Short aliases such as -m, -p, -d, -o, and -t remain available for interactive use.
Preview an add with the safe profile. Commands in this README are intentionally shown as one-line, copy-ready examples; if you use a local wrapper such as proxychains -f chain1080.conf -q, place it before dmsaforge.
dmsaforge plan add redteamnotes.com/operator:'PASSWORD' --profile safe --ou 'OU=Dev,DC=redteamnotes,DC=com' --dmsa-name redpen --target-account 'Administrator' --principals-allowed '<SID_OR_NAME>'By default, DOMAIN/user infers --scope-domain, --scope-base-dn, and --base-dn; LDAP/389 is the default method and port; --dns-hostname is inferred from --dmsa-name and the account domain. For add, explicitly choose both the predecessor account with --target-account and the managed-password reader with --principals-allowed.
The templates use redpen as a suggested dMSA name and Administrator as a common predecessor-account example. Replace either value when the authorized chain targets a different object.
These templates keep each command on one line for paste, terminal history, and repeatable runbooks. Replace placeholders before use.
Assess OU rights:
dmsaforge assess redteamnotes.com/operator:'PASSWORD' --dc-host dc.redteamnotes.comPre-add verify:
dmsaforge verify redteamnotes.com/operator:'PASSWORD' --dc-host dc.redteamnotes.com --ou 'OU=Dev,DC=redteamnotes,DC=com' --dmsa-name redpenPlan add:
dmsaforge plan add redteamnotes.com/operator:'PASSWORD' --dc-host dc.redteamnotes.com --ou 'OU=Dev,DC=redteamnotes,DC=com' --dmsa-name redpen --target-account 'Administrator' --principals-allowed '<SID_OR_NAME>'Add:
dmsaforge add redteamnotes.com/operator:'PASSWORD' --dc-host dc.redteamnotes.com --ou 'OU=Dev,DC=redteamnotes,DC=com' --dmsa-name redpen --target-account 'Administrator' --principals-allowed '<SID_OR_NAME>'Post-add verify:
dmsaforge verify redteamnotes.com/operator:'PASSWORD' --dc-host dc.redteamnotes.com --ou 'OU=Dev,DC=redteamnotes,DC=com' --dmsa-name redpenDelete when finished:
dmsaforge delete redteamnotes.com/operator:'PASSWORD' --dc-host dc.redteamnotes.com --ou 'OU=Dev,DC=redteamnotes,DC=com' --dmsa-name redpen --yesAfter a verified add or verify, Next steps includes concrete external Kerberos commands. The generated flow starts with Rubeus hash, then uses the printed AES256 value for asktgt, then runs the dMSA asktgs request.
Target account resolution is LDAP-search based. --target-account writes msDS-ManagedAccountPrecededByLink; --principals-allowed writes the SID used in msDS-GroupMSAMembership. Assessment-generated next steps can fill the discovered principal SID, but the target account remains an explicit operator choice.
Safety controls:
- Use
dmsaforge plan ACTION ...,--dry-run, or--planto validate options and print the planned LDAP operations without opening an LDAP connection. JSON reports include the planned BadSuccessor attribute values for add workflows using their canonical LDAP names. - Use
--profile safefor a redacted dry-run preset,--profile reportfor JSON reports, or--profile cifor quiet JSON/no-banner output. DOMAIN/userinfers--scope-domain,--scope-base-dn, and--base-dn; a valid--scope-base-dncan also supply the default base DN. Override with explicit flags when the authorized scope differs.- LDAP/389 is tried first when
--methodand--portare omitted. If that transport connection fails, dMSA Forge can try LDAPS/636 and records the attempted candidates in terminal output and JSON/text reports. Authentication failures stop immediately and are not retried as LDAPS. A lone--port 636infers LDAPS; pin both method and port to require an exact pair. - LDAP operations use a default 30-second socket timeout. Override with
--timeout SECONDSonly when the authorized network path requires it. --dns-hostnamedefaults to<dmsa-name>.<account-domain>when--dmsa-nameis set.- Use
--dc-hostfor a specific DC hostname and--dc-iponly when DNS or routing requires an IP override. Automatic DC IP resolution never probes the network; multicast, loopback, link-local, unspecified, broadcast, and reserved DNS results are rejected so proxy DNS placeholders such as224.0.0.1do not become Kerberos/dc:values. - For
assess,--ounarrows the OU assessment base. The Domain Controller prerequisite check is best-effort; if it fails, the OU assessment continues and records a warning. - Target account and
--principals-allowedname resolution prefer exactsAMAccountName/UPN/CN matches. Ambiguous LDAP results fail closed with a prompt to pass a full DN or SID. deleterequires--yes. Useadd,verify, anddeleteas the object lifecycle commands.- Local output is redacted by default.
--no-redactrequires--debug. - Use
--jsonfor structured reports and--output FILEto write the report with file mode0600. - Use
--output-onlyfor ultra-quiet operation. It enables--quiet,--no-banner, and defaults to--jsonunless--outputis provided. When--outputis used, the output file is written as JSON. - Use
--quietfor warning/error-only terminal output. - Use
--no-bannerwhen embedding the tool in local scripts. - Use
--leanfor reduced local output and lighter assessment defaults (--minimal,--quiet,--skip-dc-prereq,--no-banner).
Structured JSON reports include schema_version so automation can pin parsing behavior.
Human terminal output uses compact section headers: Run context:, Progress:, Findings:, and Next steps:. Warnings and errors keep their [!] / [-] severity markers and use color only when the terminal supports it; JSON, quiet, and output-only modes stay machine-clean.
Assessment modes:
assessdefaults to OU security descriptor analysis.- Assessment results list principals with BadSuccessor-relevant OU rights, namely principals that can create dMSA objects or control the listed OUs. The tool also compares those SIDs with the bound account's
objectSidandtokenGroupsand marks whether each row applies to the current bind; iftokenGroupsis unavailable, group-grant matches are reported asunknown. - Use
--summaryfor a lightweight OU-only listing.--include-security-descriptorexplicitly selects the default analysis mode. - Add
--resolve-namesto resolve matching SIDs to names. - Use
--minimalto avoid broad assessment analysis, name resolution, and extra Kerberos command output. - Add
--skip-dc-prereqforassessto skip the prerequisite Domain Controller OS check.
Advanced and compatibility details live in assets/advanced.md.
Tests:
python -m unittest discover -s testsThis tool verifies the LDAP object state only. It does not verify KDC readiness and does not execute Rubeus.
Use IPv4 explicitly for downstream Kerberos dMSA requests, for example /dc:<DC_IPV4>, to avoid accidental IPv6 link-local resolution.
The tool does not sleep after add by default. Use --verify-attempts N and --verify-delay SECONDS for explicit LDAP verification retries, and --kdc-wait SECONDS when you intentionally want a delay.
Upstream basis:
- Impacket
examples/badsuccessor.py - Original author: Ilya Yatsenko (
@fulc2um) - Impacket copyright: Fortra, LLC and affiliates
Modifications:
- RedteamNotes
See NOTICE.md for source and licensing notes.
License: modified Apache Software License 1.1 terms inherited from Impacket; see LICENSE.
