Short answer: Windows can tell you who changed an Active Directory object, what changed (including the old and new value) and when, but only if two things are in place: the Directory Service Changes audit policy on your domain controllers, and a SACL (auditing entry) on the objects you care about. The machine and IP address the change came from are not in the change event itself: you get them by matching the change to the administrator’s logon event on the same DC.
Tested on Windows Server 2025. We ran every step on 6 October 2026 on a Windows Server 2025 Standard domain controller (build 26100.33438, September 2026 update, Windows PowerShell 5.1) and a Windows 11 Pro member PC in our lab domain contoso.com. Results from that lab are quoted in each section.
Table of Contents
What you can and cannot find out
| Question | Where the answer comes from |
|---|---|
| Who made the change | Subject fields of the change event (SubjectUserName, SubjectDomainName) |
| What object, which attribute | 5136: ObjectDN, ObjectClass, AttributeLDAPDisplayName |
| Old and new value | Two 5136 events sharing one OpCorrelationID: “Value Deleted” holds the old value, “Value Added” the new one |
| When | Event time on the DC that processed the change |
| From which computer / IP | Not in the change event. Match SubjectLogonId to the TargetLogonId of a 4624 logon on the same DC; WorkstationName and IpAddress may still be empty |
Two limits to accept from the start: each DC logs only the changes it processed, so you search every DC (or a central collector); and events that have rolled out of the Security log are gone.
Audit policy vs SACL: why turning on auditing is not enough
The audit policy decides which categories of activity a domain controller is willing to record, for example DS Access → Audit Directory Service Changes. The SACL (system access control list) on each directory object decides which operations on that object actually produce an event. Think of the policy as switching the cameras on and the SACL as pointing them at specific doors.
Microsoft’s reference for Audit Directory Service Changes is explicit: events 5136, 5137, 5139 and 5141 are generated only for objects whose SACL has a matching entry. A Write entry on the object produces 5136; a Create entry on the parent container produces 5137 and 5139; a Delete entry on the object produces 5141. Account-management events (4720, 4724, 4728 and the rest) come from their own subcategories and do not need object SACLs.
Whether your domain already carries a default SACL that audits these changes depends on how and when it was built. Do not assume it: read it (next section). On our brand-new Windows Server 2025 domain the domain root carried five default audit entries (Everyone: write property, DACL and owner changes on the root object itself, plus two inherited write-property entries), and a newly created OU inherited only those two write-property entries. That is not enough to log user and group changes in your OUs, which is why the next steps add your own.
Step 1: read-only check of what you have now
READ ONLY: nothing in this step changes the domain controller.
Effective audit policy on the DC (run in an elevated prompt on each DC):
auditpol /get /category:*
# just the subcategories this guide uses
auditpol /get /subcategory:"Directory Service Changes","User Account Management","Security Group Management","Computer Account Management","Logon"
Security log size, mode and how far back it currently reaches:
Get-WinEvent -ListLog Security | Select-Object LogName, MaximumSizeInBytes, RecordCount, LogMode
Get-WinEvent -LogName Security -MaxEvents 1 -Oldest | Select-Object TimeCreated
Are change events already being written?
Get-WinEvent -FilterHashtable @{ LogName = "Security"; Id = 5136,5137,5139,5141,4720,4724,4728,4732,4756 } -MaxEvents 20 |
Select-Object TimeCreated, Id, MachineName | Format-Table -AutoSize
Which GPO sets the audit policy today (look for Advanced Audit Policy Configuration in the report):
gpresult /h C:\Temp\dc-gpresult.html
From our lab DC after the policy below was applied:
PS> auditpol /get /category:"DS Access","Account Management"
Account Management
Computer Account Management Success and Failure
Application Group Management No Auditing
Distribution Group Management No Auditing
Security Group Management Success and Failure
User Account Management Success and Failure
Other Account Management Events No Auditing
DS Access
Directory Service Replication No Auditing
Directory Service Changes Success and Failure
Directory Service Access Success
Detailed Directory Service Replication No Auditing
On a fresh domain, before any change, Directory Service Changes was No Auditing: without this step you get no 5136/5137/5139 events at all.
Step 2: a dedicated auditing GPO for domain controllers
Keep auditing in its own GPO linked to the Domain Controllers OU, not in the Default Domain Policy or Default Domain Controllers Policy. It is easy to review, to change and to roll back.
Domain Controllers (OU)
└── Domain Controllers - AD Auditing (new GPO)
CHANGE: the settings below change what every domain controller logs. Check the Security log capacity (Step 5) first.
In the new GPO: Computer Configuration → Policies → Windows Settings → Security Settings → Advanced Audit Policy Configuration → Audit Policies.
| Category → subcategory | Setting | Gives you |
|---|---|---|
| DS Access → Audit Directory Service Changes | Success | 5136, 5137, 5139, 5141 (with SACLs) |
| Account Management → Audit User Account Management | Success and Failure | 4720, 4722, 4723, 4724, 4725, 4726, 4738, 4767 |
| Account Management → Audit Security Group Management | Success | 4728/4729, 4732/4733, 4756/4757 |
| Account Management → Audit Computer Account Management | Success | 4741, 4742, 4743 |
| Logon/Logoff → Audit Logon | Success and Failure | 4624 (needed to find the source computer) |
These match the per-subcategory domain controller recommendations on Microsoft Learn. Also set Security Options → Audit: Force audit policy subcategory settings to override audit policy category settings to Enabled, so the advanced settings are not overridden by legacy category settings. Do not enable every subcategory “just in case”: Directory Service Access, Kerberos and Credential Validation can be very noisy on a busy DC.
Verify on a DC after gpupdate /force:
auditpol /get /subcategory:"Directory Service Changes","User Account Management","Security Group Management","Computer Account Management","Logon"
Roll back: unlink or disable the GPO and run gpupdate /force; the previous policy applies again. To be certain, set the subcategories back explicitly in the GPO (or with auditpol /set /subcategory:"Directory Service Changes" /success:disable /failure:disable) instead of relying on the unlink alone, and confirm with auditpol /get.
Step 3: scoped SACLs on what matters
Auditing every write on every object in a large directory produces a lot of events. Start with what an incident review actually needs:
- the OUs that hold your users, groups and workstations (for example
OU=Staff,OU=Workstations); - privileged groups: Domain Admins, Enterprise Admins, Schema Admins, Administrators;
- OUs with delegated admin, service and break-glass accounts.
CHANGE: this adds auditing entries to directory objects. It does not change permissions (the DACL).
In AD Users and Computers: enable View → Advanced Features, open the OU’s Properties → Security → Advanced → Auditing, then Add: principal Everyone, type Success, applies to Descendant User objects (repeat for Group and Computer objects), permissions Write all properties, Delete; on the OU itself also Create and Delete child objects so creations, moves and deletions are recorded. In our lab, one entry on the OU (Everyone, Success, Write all properties, Create all child objects, Delete all child objects, applies to this object and all descendants) produced 5136 for attribute changes, 5137 for new objects and 5139 for moves. Deleting a test group did not produce 5141 even after we added Delete and Delete subtree; the deletion was still recorded as 4730 under Account Management, so keep that subcategory on. Inherited audit entries reach existing child objects after a short delay, so wait a minute before testing.
Verify the SACL is in place:
Import-Module ActiveDirectory
(Get-Acl -Path "AD:\OU=Staff,DC=contoso,DC=com" -Audit).Audit |
Format-Table IdentityReference, ActiveDirectoryRights, AuditFlags, InheritanceType, InheritedObjectType -AutoSize
On Windows Server 2025 (Get-Acl -Audit 'AD:\OU=Lab,DC=contoso,DC=com').Audit returned the audit entries as expected (it needs the ActiveDirectory module for the AD: drive). In our lab it listed the new entry plus the two inherited write-property entries.
Roll back: remove the auditing entries you added in the same Auditing tab.
Step 4: test it with a harmless change
Use a dedicated test user and test group, never a real admin account. With a delegated helpdesk account (CONTOSO\ADuser in this example), from an admin workstation:
- create
Test UserinOU=Sales; - change its
telephoneNumberfrom 555-0100 to 555-0199; - reset its password;
- disable and re-enable it;
- add it to and remove it from a test security group;
- move it to another OU, then delete it.
Then look on the DC that handled the changes:
Get-WinEvent -FilterHashtable @{ LogName = "Security"; Id = 5136,5137,5139,5141,4720,4722,4724,4725,4728,4729,4726; StartTime = (Get-Date).AddHours(-1) } |
Select-Object TimeCreated, Id, @{n="Message";e={ ($_.Message -split "`n")[0] }} | Format-Table -AutoSize
Events our single lab DC logged for one phone-number change plus creating, moving and deleting a test group: 5136 (×5, one per attribute value), 5137, 5139, 4727 (group created), 4730 (group deleted), plus logon noise (4624, 4634, 4648, 4672) and 4662. With several DCs, the event is logged by the DC that handled the change, so collect from all of them.
Reading an attribute change (5136)
For the telephone number change you should see two 5136 events with the same OpCorrelationID: one with OperationType Value Deleted (AttributeValue = 555-0100, the old value) and one with Value Added (AttributeValue = 555-0199, the new value). The actor is in SubjectUserName / SubjectDomainName, the target in ObjectDN and ObjectClass, the attribute in AttributeLDAPDisplayName, and the logon session in SubjectLogonId.
Get-WinEvent -FilterHashtable @{ LogName = "Security"; Id = 5136; StartTime = (Get-Date).AddHours(-1) } | ForEach-Object {
$d = @{}; ([xml]$_.ToXml()).Event.EventData.Data | ForEach-Object { $d[$_.Name] = $_."#text" }
[pscustomobject]@{ Time = $_.TimeCreated; Actor = "$($d.SubjectDomainName)\$($d.SubjectUserName)"; Object = $d.ObjectDN
Attribute = $d.AttributeLDAPDisplayName; Operation = $d.OperationType; Value = $d.AttributeValue
Correlation = $d.OpCorrelationID; LogonId = $d.SubjectLogonId }
} | Format-Table -AutoSize
Long string values are truncated in the event, and binary values are shown as <binary>. The real pair from our lab, as stored in the event XML:
SubjectUserName=Administrator; ObjectDN=CN=Bob Smith,OU=Users,OU=Lab,DC=contoso,DC=com; AttributeLDAPDisplayName=telephoneNumber; AttributeValue=+1 555 0199; OperationType=%%14675
SubjectUserName=Administrator; ObjectDN=CN=Bob Smith,OU=Users,OU=Lab,DC=contoso,DC=com; AttributeLDAPDisplayName=telephoneNumber; AttributeValue=+1 555 0123; OperationType=%%14674
%%14675 is “Value Deleted” (the old value) and %%14674 is “Value Added” (the new one). Event Viewer shows the words; the XML and Get-WinEvent give you the codes.
Who added this account to Domain Admins?
Group membership changes come from Security Group Management: 4728/4729 for global groups, 4732/4733 for domain local (and built-in local) groups, 4756/4757 for universal groups. Domain Admins is a global group, so look for 4728. In these events TargetUserName is the group, MemberName (a DN) and MemberSid identify the account that was added, and the Subject fields are who did it.
Get-WinEvent -FilterHashtable @{ LogName = "Security"; Id = 4728,4732,4756; StartTime = (Get-Date).AddDays(-30) } | ForEach-Object {
$d = @{}; ([xml]$_.ToXml()).Event.EventData.Data | ForEach-Object { $d[$_.Name] = $_."#text" }
[pscustomobject]@{ Time = $_.TimeCreated; By = "$($d.SubjectDomainName)\$($d.SubjectUserName)"; Group = $d.TargetUserName; Added = $d.MemberName; LogonId = $d.SubjectLogonId }
} | Where-Object Group -in "Domain Admins","Enterprise Admins","Schema Admins","Administrators" | Format-Table -AutoSize
On Windows Server 2025 event 4728 carries these fields: MemberName, MemberSid, TargetUserName (the group), TargetDomainName, TargetSid, SubjectUserSid, SubjectUserName, SubjectDomainName, SubjectLogonId and PrivilegeList.
Who reset this user’s password?
4724 means someone reset the account’s password (no old password needed, typically an admin or helpdesk). 4723 means the user changed their own password, supplying the old one; there Subject and Target are usually the same account. In 4724 the Subject fields are the person who reset it and TargetUserName is the account.
Get-WinEvent -FilterHashtable @{ LogName = "Security"; Id = 4723,4724; StartTime = (Get-Date).AddDays(-7) } | ForEach-Object {
$d = @{}; ([xml]$_.ToXml()).Event.EventData.Data | ForEach-Object { $d[$_.Name] = $_."#text" }
[pscustomobject]@{ Time = $_.TimeCreated; Event = $_.Id; By = "$($d.SubjectDomainName)\$($d.SubjectUserName)"; Account = $d.TargetUserName }
} | Format-Table -AutoSize
Finding the source computer and IP
The change events do not contain the administrator’s workstation. To find it, take the SubjectLogonId from the change event and look for a 4624 logon on the same DC whose TargetLogonId has the same value. That logon carries WorkstationName, IpAddress, IpPort and LogonType.
$logonId = "0x1A2B3C" # SubjectLogonId from the change event
Get-WinEvent -LogName Security -FilterXPath "*[System[(EventID=4624)]] and *[EventData[Data[@Name='TargetLogonId']='$logonId']]" -MaxEvents 5 | ForEach-Object {
$d = @{}; ([xml]$_.ToXml()).Event.EventData.Data | ForEach-Object { $d[$_.Name] = $_."#text" }
[pscustomobject]@{ Time = $_.TimeCreated; Account = $d.TargetUserName; LogonType = $d.LogonType; Workstation = $d.WorkstationName; IP = $d.IpAddress }
}
Expect gaps: Kerberos network logons often have no WorkstationName, NTLM logons often lack IP details, and the logon may have happened before your Security log starts. When there is no matching 4624, record the source as unknown rather than guessing.
Keep the evidence: Security log retention
Auditing is useless if the Security log overwrites last week’s events before anyone looks. Older Microsoft documentation gives 20 MB as the default; on our new Windows Server 2025 DC wevtutil gl Security showed maxSize: 134217728 (128 MB). Even that filled from 12:50 to 14:30 on the lab DC, mostly with internet password-guessing against its open SSH port, so a production DC needs far more or a collector. There is no universal right size: it depends on the number of DCs, users, authentication volume, how much you audit and how long you must keep it. Microsoft’s rule of thumb is roughly 500 bytes per event × events per day × days to keep.
Set it in the auditing GPO under Computer Configuration → Administrative Templates → Windows Components → Event Log Service → Security → Specify the maximum log file size (KB), and measure how many days the log actually covers afterwards (the oldest-event command in Step 1).
For longer retention or several DCs, forward the events to a central collector with Windows Event Forwarding (source-initiated subscriptions set by GPO), or to a SIEM such as Microsoft Sentinel. The local log is still the buffer: if it wraps before events are forwarded, they are lost.
Turn the events into a report
Once auditing is in place, correlating hundreds of Security events by hand gets tedious. The free AD Change Audit Reporter reads these events (read-only), pairs old and new values, adds the source workstation when a matching logon exists, and exports CSV for incident notes.
Frequently asked questions
Why do I see 4738 “A user account was changed” but no 5136?
4738 comes from User Account Management and needs no SACL, but it only shows new values for a fixed set of fields. 5136 (with old and new values) appears only when the object has a matching SACL entry and Directory Service Changes is enabled.
Do I need to search every domain controller?
Yes. Each DC logs the changes it processed itself. Search them all, or forward their Security logs to one collector.
Can I find which computer a change came from?
Often, by matching the change event’s SubjectLogonId to a 4624 logon on the same DC. It is not guaranteed: some logons carry no workstation name or IP, and older logons may already be overwritten.
Will this slow down my domain controllers?
The subcategories in Step 2 with scoped SACLs are normal practice. Event volume, and therefore log size, is the real cost: measure it after enabling and adjust the SACL scope.
Sources: Microsoft Learn: Audit Directory Service Changes, event pages 5136, 5137, 5139, 5141, 4720, 4723, 4724, 4732, 4738, 4624, Audit Policy Recommendations, Windows Event Forwarding.