Blog

Active Directory penetration testing with autonomous AI: BloodHound, Kerberoasting, DCSync and ADCS

How the Darkmoon active-directory agent runs AD penetration testing end to end: BloodHound attack paths, AS-REP and Kerberoasting, DCSync, and ADCS ESC1 to ESC16.

· 9 min read

Active Directory is still the shortest path from a single foothold to full domain compromise. The techniques that get you there have not changed much in a decade: roast a service account, crack the hash offline, walk the trust relationships BloodHound draws for you, and finish on a Domain Controller with a DCSync. What has changed is that a human no longer has to sit at the keyboard chaining those steps by hand. The interesting work in an AD engagement is the routing decision, which vector to try next given what the last one returned, and that is exactly what an autonomous agent is good at.

This is a walk through how the Darkmoon active-directory agent runs an internal AD test end to end, and how its companion pki-adcs agent handles the certificate plane. Both are specialist sub agents in the platform, and both run every command through a controlled MCP tool layer rather than a raw shell. Everything below traces to what those two agents actually do.

Authorized testing only

Every technique in this article is offensive and state changing. Run it only against an estate you own or are contracted in writing to test, inside an agreed scope, and never against production identity infrastructure without explicit authorization. Certificate issuance and credential dumping leave permanent artifacts. Get the scope in writing first.

Why AD is still the fastest path to domain compromise

An AD domain is a single graph of who can act as whom. Kerberos and NTLM were built for convenience inside that graph, so most of the abuse is not a memory corruption bug, it is a feature used the way an attacker reads it. A user without Kerberos pre authentication hands you a crackable hash to anyone who asks. A service account with a weak password and a registered SPN does the same. An over privileged group membership, a misconfigured ACL, an unconstrained delegation, a certificate template that lets a low privilege user request a certificate for someone else, each is a legitimate configuration that also happens to be an edge in the compromise graph. That is why AD rewards patience and coverage over cleverness, and why it maps so well to an agent that never gets bored re running the same disciplined sweep across every host and identity.

How the active-directory agent maps the domain

The agent starts unauthenticated and works in phases. Network and domain discovery first: live hosts, Domain Controllers, and the domain name pulled from SMB, the LDAP banner, the Kerberos realm and DNS SRV records. Then unauthenticated enumeration with netexec (the tool formerly known as crackmapexec): SMB null sessions and share listings, signing status, an anonymous LDAP bind attempt, and Kerberos user enumeration where the domain allows it.

Once it holds a valid domain credential, whether one the operator provided or one it recovered, it runs the authenticated sweep. That means a netexec smb domain sweep to find where the credential is local admin, session enumeration, privileged group and delegation discovery, SPN enumeration, and a full BloodHound collection with bloodhound-python. BloodHound is the pivot point: it turns the raw LDAP dump into attack paths, the shortest routes from the identity you hold to Domain Admin, and the agent reads those paths to decide what to escalate next rather than guessing.

# unauthenticated enumeration
netexec smb <dc-ip> --shares --sessions
netexec ldap <dc-ip> --users        # anonymous bind, user list if permitted

# authenticated collection, once a credential is held
netexec smb <subnet> -u <user> -p <pass>          # where am I local admin
bloodhound-python -u <user> -p <pass> -d <domain> -c All -ns <dc-ip>

Every command carries its own bound. The executor refuses anything with no natural end, a full -p- sweep against a host that drops packets, a cat on a live socket, a credential attack over a multi million entry wordlist. Each command runs under a timeout, and when one is refused or killed the agent retries once with a smaller scope, then changes angle, then declares the vector not exploitable and moves on. That discipline is what keeps a single stuck command from freezing the whole campaign and losing every finding that would have come after it.

AS-REP roasting and Kerberoasting, bounded and proven

Two roasting techniques do most of the early credential work, and both are offline attacks: the agent asks the DC for material it is entitled to receive, then cracks it away from the network so it never touches an account lockout counter.

  • AS-REP roasting. Any account with Kerberos pre authentication disabled will return an encrypted AS-REP to an unauthenticated request. That blob is crackable offline. The agent collects the roastable accounts during enumeration and feeds the hashes to hashcat or john.
  • Kerberoasting. With any valid domain credential, the agent requests service tickets for accounts that carry a registered SPN using the Impacket GetUserSPNs.py. The ticket is encrypted with the service account password, so a weak password cracks offline and hands over that account.

The bound matters as much as the technique. The agent's own rule is explicit: the finding you want from an authentication endpoint is that it accepts unlimited attempts, and 11 requests prove that, 14 million prove nothing more. It never grinds a full keyspace against a live service. Roasting sidesteps the question entirely because the cracking happens offline, but the same restraint governs any spray: a capped candidate list built from what the target already disclosed, never rockyou against a login prompt.

# Kerberoast: request service tickets for SPN accounts, then crack offline
GetUserSPNs.py <domain>/<user>:<pass> -dc-ip <dc-ip> -request -outputfile spns.txt
hashcat -m 13100 spns.txt wordlist.txt        # offline, no lockout risk

# AS-REP roast: no-preauth accounts return a crackable blob
hashcat -m 18200 asrep.txt wordlist.txt

From a cracked hash to DCSync and secretsdump

A cracked service account password rarely is the goal in itself. It is the next identity on the BloodHound path. From there the agent moves laterally with the Impacket suite, Pass the Hash or Pass the Ticket into psexec.py or wmiexec.py to reach local admin on a machine, dumps SAM, LSA secrets and cached credentials, and looks for the edge that leads to replication rights on the domain.

The finish is DCSync. When the agent holds an identity with the replication privileges a Domain Controller grants, it asks the DC to replicate the directory the same way a second DC would, and secretsdump.py returns the NTLM hashes, including krbtgt. Extracting the krbtgt hash is domain compromise, because it is the key behind every Kerberos ticket in the forest. That, or a Domain Admin shell, or an NTDS.dit dump, is the proof the agent records for a full compromise, never an inference from group membership alone.

# lateral movement with a recovered credential or hash
psexec.py <domain>/<user>@<host> -hashes :<nt-hash>

# domain compromise: replicate secrets from the DC
secretsdump.py <domain>/<user>:<pass>@<dc-ip> -just-dc-user krbtgt
# -> krbtgt:502:aad3b435...:<nt hash, in the report>

The certificate crown jewel: the pki-adcs agent and ESC1 to ESC16

If the domain runs Active Directory Certificate Services, the pki-adcs agent takes over the certificate plane, and it is often the cleanest path to domain level access. A certificate that carries a client authentication EKU and a subject you control is a permanent identity. Through PKINIT it converts into a Kerberos TGT, and the same exchange returns the account's NT hash, so one issued certificate is both immediate access and long term persistence that a password reset does not revoke. The named ESC categories from the SpecterOps "Certified Pre Owned" research are the map here, and the agent covers ESC1 through ESC16: vulnerable templates, misconfigured enrollment agents, CA object and registry abuse, and NTLM relay to an enrollment endpoint.

There is no certipy in the toolbox. The agent reaches the same result with netexec, the Impacket scripts, raw LDAP queries and the Python cryptography module that ships with Impacket to build the CSR and parse the PKCS#12. It enumerates every CA, every published template and every enrollment interface first, then proves the escalation by requesting the minimum number of certificates that demonstrates the finding, one per distinct ESC path, for a principal it does not own, and authenticating with the result.

ESC pathWhat the agent abusesProof it records
ESC1Template lets a low priv user set an arbitrary SANCertificate issued for a Domain Admin, then PKINIT to a TGT and NT hash
ESC4Writable template ACLTemplate made vulnerable, ESC1 proof, then the ACL reverted and both operations logged
ESC7CA management rightsA demonstrated CA config change, scoped and recorded
ESC8NTLM relay to the web enrollment endpointA single scoped coercion relayed to enrollment, certificate obtained

The constraints are strict because issuance is state changing and permanent. The agent never bulk enrolls, never revokes a certificate, never stops CertSvc, never modifies the CA registry outside a demonstrated ESC7 proof, and if it rewrites a template ACL for an ESC4 proof it reverts it immediately and records both operations. Relay and coercion happen only when the operator scoped them, a single coercion to a listener under control, never a broadcast.

What EXPLOITED versus CONFIRMED means for each step

Every Darkmoon agent carries the same status qualification rule, and it is adversarial by design: the agent challenges its own claims before it writes them down. Status is assigned by demonstrated impact, not by observation.

StatusBar it has to clearAD example
EXPLOITEDImpact executed end to end: access gained or data extractedkrbtgt hash dumped via DCSync; a TGT minted from an ESC1 certificate
CONFIRMEDImpact demonstrated with the exact request, raw response and extracted data or traceGetUserSPNs.py returns a roastable ticket, cracked offline to a plaintext password
UNCONFIRMEDA real lead, impact not yet demonstrated; severity capped at low, CVSS <= 3.9An anonymous LDAP bind succeeds but no sensitive attribute has been read yet

In practice that means a reachable SMB share or a bare authentication response never gets promoted to a high severity finding on its own. The agent demotes the kind of weak evidence testers routinely over claim, a differential response, an echoed payload, a file served but not executed, and only labels a step CONFIRMED or EXPLOITED once the challenge against it fails. The discipline is the same one we apply to the cloud identity plane, described in autonomous cloud penetration testing: a vector is dispatched on evidence, not on a name that looked promising.

What we do not claim

This article describes the agent's designed workflow and the techniques it runs, not a single published benchmark with a fixed finding count. The transcripts show the shape of the commands the agent issues, with real secrets redacted, not a specific customer's dump. An autonomous run still depends on the access and scope you give it: no credential recovery is guaranteed against a well configured domain, which is the point, a clean run that finds nothing exploitable is a valid and useful result.

Where the domain credentials actually go

A fair question for anyone running an AI driven tool against their identity estate is whether the domain credentials, hostnames and hashes leave the network. With Darkmoon the platform runs on a local model, and its Privacy Gateway tokenizes sensitive values before anything reaches the model: the model only ever sees deterministic placeholders like HOST_INTERNAL_001 and IP_PRIVATE_001, never your real IPs, hosts or credentials. The real values are rehydrated locally only at the moment a tool runs and masked back out of every result. We are precise about the limits of that: deterministic placeholders leak structure, cardinality and co occurrence by design, and the command gateway is a policy layer, not a sandbox. The honest, fully caveated treatment is in AI pentest without sending data to the LLM, and the option to run the whole thing on your own hardware is covered in the local self hosted AI pentester.

Remediation

  • Enable Kerberos pre authentication on every account and audit for accounts where it is disabled. That closes AS-REP roasting.
  • Give service accounts long random passwords, prefer group managed service accounts (gMSA), and audit registered SPNs. A 25 character random password makes Kerberoasting economically pointless.
  • Review the BloodHound graph yourself. Cut unconstrained delegation, tighten dangerous ACLs, and remove standing membership in privileged groups in favour of just in time access.
  • Restrict who holds directory replication rights so a non DC identity can never run DCSync, and rotate krbtgt twice if you suspect it has ever been exposed.
  • Audit AD CS templates for the ESC conditions: no low privilege enrollee should be able to set an arbitrary SAN or supply a subject, and enrollment endpoints should require channel binding and EPA to defeat NTLM relay.
  • Enforce SMB signing and disable NTLM where you can to shut down relay paths, and monitor for the replication and certificate request patterns these attacks generate.

FAQ

Can AI do Active Directory penetration testing on its own? For the well understood AD techniques, yes. The active-directory agent runs discovery, enumeration, roasting, BloodHound collection, lateral movement and DCSync end to end, and makes the routing decisions itself from what each step returns. It is not a replacement for a skilled operator on a novel or heavily monitored environment, but it covers the mechanical chain faster and more consistently than a human doing it by hand, and it hands you a report where each step is proven.

How does the agent avoid account lockouts and unbounded credential attacks? By design it prefers offline attacks (roasting cracks away from the network) and it treats authentication weakness as a finding to prove, not a keyspace to exhaust. Its own rule is that 11 requests prove an endpoint accepts unlimited attempts and 14 million prove nothing more, and the executor refuses commands that have no natural end. Any spray is a capped list built from disclosed data, never a giant wordlist against a live login.

Does it cover ADCS and certificate template abuse? Yes, through the dedicated pki-adcs agent, which covers ESC1 to ESC16, CA object and registry abuse and NTLM relay to enrollment. It works without certipy, using Impacket, netexec and the Python cryptography module, and it proves the escalation by obtaining and authenticating with a certificate rather than describing the theory.

What is the difference between a CONFIRMED and an EXPLOITED AD finding? CONFIRMED means the impact was demonstrated with the exact request, the raw response and the extracted data or execution trace. EXPLOITED means the impact was executed end to end, access gained or data actually extracted, for example a krbtgt hash pulled with DCSync or a TGT minted from an ESC1 certificate. A lead that is real but not yet demonstrated stays UNCONFIRMED and capped at low severity.

Do domain credentials leave my network? No. The platform runs on a local model and the Privacy Gateway feeds it deterministic placeholders, so the model never sees your real IPs, hosts or credentials; real values are rehydrated locally only when a tool runs. The nuance, that placeholders leak structure and cardinality by design, is documented in full in our privacy write up.

What this proves about autonomous pentesting

The AD compromise chain, from an unauthenticated network to a krbtgt hash, is short, mechanical and almost entirely automatable, which is precisely why it is worth testing continuously rather than once a year. An autonomous agent does not bring a new exploit to the table, it brings coverage and speed: it re runs the same disciplined chain across every host and identity, bounds every credential attack so it never becomes the outage, and records each step at the severity the evidence supports. The related identity work on the cloud side, from Entra ID token abuse to Azure privilege escalation, follows the same discipline. You still decide what to fix. The agent makes sure you are deciding from proof.

Darkmoon is our open source project (GPL-3.0): github.com/ASCIT31/Dark-Moon, docs.

Run it against your own lab

Darkmoon is open source (GPL-3.0) and self hosted. Clone it, point it at a target you own, and read every line.