Case file TH-008. The domain admin passwords were changed on Friday. By Monday, the attacker was back in with full domain dominance — and nobody had phished anyone or exploited anything new over the weekend. The evidence was hiding in plain sight in the directory replication logs: a helpdesk workstation in HR had been quietly asking the domain controller for every password hash in the domain, and the domain controller had been politely handing them over.
This is DCSync. An attacker who holds the DS-Replication-Get-Changes and DS-Replication-Get-Changes-All extended rights — on the domain object, on a user, or via membership in a privileged group — can impersonate a domain controller and request replication of credentials, including the krbtgt account. Mimikatz's lsadump::dcsync turned this into a one-liner years ago, and it remains the quietest way to steal an entire directory: no LSASS access, no malware on the DC, just a legitimate protocol doing exactly what it was designed to do.
This hunt looks for replication that comes from somewhere it shouldn't.
The hypothesis
If an attacker is stealing credentials via DCSync, then directory replication traffic will originate from a host or account that is not a legitimate domain controller or sync engine — and that source will have no historical baseline of replication activity, or will suddenly replicate far outside its normal pattern.
Data you'll need
| Source | What it gives you |
|---|---|
IdentityDirectoryEvents (ActionType == "Directory Services replication") | Defender for Identity's view of every replication request: source device, IP, and actor account. |
| SecurityEvent, Event ID 4662 on DCs | Object-access audit showing the replication extended rights GUIDs being exercised — the ground truth. |
| Defender for Identity alerts | "Suspected DCSync attack (replication of directory services)" — useful, but don't rely on it alone. |
Splunk: index=wineventlog | Forwarded DC security logs; filter 4662 on the two replication GUIDs below. |
Prerequisite that decides everything: Event 4662 only fires if Audit Directory Service Access is enabled on your domain controllers. If it isn't, the KQL hunt on IdentityDirectoryEvents is your primary lens — verify the auditing gap and fix it as part of the response.
Hunting with KQL
This query builds a 30-day baseline of who replicates normally, then flags any replication in the last day from a source with no such history — excluding your known DCs and sync accounts.
// Hunt H-DCSYNC-01: replication from sources with no historical baseline
let KnownDCs = dynamic(["DC01", "DC02"]); // <-- fill in yours
let KnownSyncAccounts = dynamic(["MSOL_", "ADSync", "svc-backup"]);
let Baseline =
IdentityDirectoryEvents
| where Timestamp between (ago(30d) .. ago(1d))
| where ActionType == "Directory Services replication"
| extend Actor = tostring(parse_json(AdditionalFields)["ACTOR.ACCOUNT"])
| summarize SyncCount = count(), ActiveDays = dcount(startofday(Timestamp))
by DeviceName, IPAddress, Actor
| where SyncCount > 10 or ActiveDays > 5;
IdentityDirectoryEvents
| where Timestamp > ago(1d)
| where ActionType == "Directory Services replication"
| extend Actor = tostring(parse_json(AdditionalFields)["ACTOR.ACCOUNT"])
| where isnotempty(Actor)
| where DeviceName !in (KnownDCs)
| where not(Actor has_any (KnownSyncAccounts))
| join kind=leftanti (Baseline) on DeviceName, IPAddress, Actor
| summarize Syncs = count(), FirstSeen = min(Timestamp), LastSeen = max(Timestamp),
Targets = make_set(DestinationDeviceName, 20)
by DeviceName, IPAddress, Actor
| order by Syncs desc
What this does, in plain English: it learns what normal replication looks like for a month — domain controllers replicating with each other, Entra Connect syncing — and then asks a simple question about the last 24 hours: who replicated that has never (or barely ever) done so before, and isn't on the allowlist? DCSync from an attacker's workstation has no baseline. Legitimate replication always does.
Walkthrough: how the query reads the evidence
ActionType == "Directory Services replication"is Defender for Identity's normalized record of a replication request hitting a DC — the exact operation DCSync abuses.parse_json(AdditionalFields)["ACTOR.ACCOUNT"]extracts the account performing the replication. In a DCSync attack, this is the compromised account, not a machine account.- The
Baselinesubquery is the false-positive killer: anything that replicated more than 10 times (or on more than 5 days) in the last month is, by definition, part of normal operations. join kind=leftantikeeps only current replication sources absent from the baseline — the statistical definition of "new and unexpected."- The allowlists (
KnownDCs,KnownSyncAccounts) handle your environment's known-good replicators; the baseline handles everything else, including the sync tool you forgot was installed.
Example: what a true positive looks like
| Field | Value | Why it matters |
|---|---|---|
DeviceName / IPAddress | WS-HR-114 / 10.4.18.62 | An HR workstation — not a DC, not a sync server, never replicated before |
Actor | svc-print | A print service account with replication rights it should never have |
Syncs / window | 4,812 requests in 20 minutes, 02:10–02:30 | Bulk pull of the directory at 2 AM — the signature of a full DCSync dump |
Targets | DC01 | Replication requested from the primary domain controller |
Hunting with Splunk
The ground-truth version: Windows Event 4662 on the domain controllers, filtered on the two extended-right GUIDs that DCSync must exercise. No GUID match, no replication — this is as close to definitive as log-based detection gets.
index=wineventlog EventCode=4662
| where like(Properties, "%1131f6aa-9c07-11d1-f79f-00c04fc2dcd2%")
OR like(Properties, "%1131f6ad-9c07-11d1-f79f-00c04fc2dcd2%")
| rename ComputerName as dc, SubjectUserName as requestor, IpAddress as src_ip
| stats count as replication_requests, earliest(_time) as first_seen,
latest(_time) as last_seen, values(dc) as dcs by requestor, src_ip
| where NOT match(requestor, "(?i)^(MSOL_|ADSync|svc-backup)")
| sort - replication_requests
What this does, in plain English: it scans DC security logs for anyone exercising the DS-Replication-Get-Changes (...f6aa...) or DS-Replication-Get-Changes-All (...f6ad...) rights, then rolls the events up by requesting account and source IP. High request counts from a non-sync account are DCSync until proven otherwise.
Example hit
requestor=svc-print src_ip=10.4.18.62 replication_requests=4812 first_seen=2026-09-27 02:10:04 last_seen=2026-09-27 02:30:41 dcs=DC01
Validating the hit
- Confirm the source isn't legitimate. Is the device a DC, an Entra Connect server, or a backup product with replication rights? If yes, tune the allowlist. If it's a workstation, escalate.
- Interrogate the actor account. How did
svc-printget replication rights? Check the DACL on the domain object and group memberships — attackers grant themselvesGet-Changes-Allvia DCSync-enabling ACEs, and the grant itself is logged in 4662/5136. - Look for what came after. DCSync is a means, not an end: hunt for Golden Ticket indicators (TGTs with anomalous lifetimes,
krbtgtlogons from unusual hosts), new privileged accounts, and lateral movement from the source workstation. - Scope the theft. A successful DCSync yields every hash, including
krbtgt. Assume full directory compromise for any account that existed during the replication window — scope the response accordingly, not optimistically.
Tuning out false positives
- Entra Connect / AD Connect sync: the
MSOL_andADSyncaccounts replicate constantly by design — allowlist them permanently. - DC-to-DC replication: both endpoints are domain controllers replicating on schedule; the baseline subquery absorbs this automatically.
- New DC promotions: a freshly promoted DC replicates heavily for the first time and has no baseline. Correlate with change records before panicking.
- Backup and DR tools: some backup products request replication rights. They replicate on a schedule from known hosts — allowlist by host and account, never by account alone.
What to do next
- Isolate the source host immediately and disable the compromised account. Treat the workstation as fully compromised.
- Reset the krbtgt password twice to invalidate any Golden Tickets, then force a full password reset across the domain — DCSync means every hash is burned.
- Remove the attacker's foothold: strip the rogue replication ACEs from the domain object DACL and audit privileged group memberships for additions made during the intrusion window.
- Find the entry point: determine how the actor account was compromised in the first place (the DCSync is step three of the attack, not step one) and hunt for persistence — scheduled tasks, new services, shadow credentials.
- Close the visibility gap: enable Audit Directory Service Access on all DCs if it wasn't on, and promote this hunt to a scheduled detection rule.
When the directory itself is the credential store, replication is exfiltration. Watch who asks. — Amit Vijayan
This sample preserves the article’s original text and publication date, restyled for Amit’s personal website. Older material may describe historical tools or techniques.
Read the original article on Blogger