A Hitch-hacker's Guide to DACL-Based Detections (Part 2)
This blog series was co-authored by Security Consultant Megan Nilsen and TAC Practice Lead Andrew Schwartz.
1 Introduction
This is a continuation of A Hitch-hacker's Guide to DACL-Based Detections (Part 1).
In this post, we will continue to explore Active Directory (AD) attributes that an attacker or adversary may modify within a target environment to gain further access. As the first part of this series walked through the attacks and built detections for the DACL abuse mind-map from The Hacker Recipes, this post will explore additional attributes, with a focus on those that can be modified via Kevin Robertson’s PowerMad tool. It should be noted that the tool attack techniques are important, but we are more focused on the underlying techniques of modifiable attributes and the detections surrounding them.
Just as Part 1 established, a couple of key reminders:
- We are operating under the assumption that the adversary already has a foothold within the domain and has acquired the appropriate access they need to make modifications to the objects we will discuss.
- Post-exploitation is not a focus.
- Intelligence applied to adversary attribution has not been mapped.
- A subset of Windows Event logging has been used, and not all the possible telemetry data points within this data set have been analyzed.
2 Logging Setup
We will make use of our Imposter-Granola machine account, which was created via Kevin Robertson's PowerMad in Part 1. Additionally, for telemetry purposes, we will rely on setting an 'Auditing' SACL on each of these attributes and the following Windows Event IDs:
Configuring a SACL is an additional step that must be taken even if the above listed Windows Events are currently being ingested.
Please refer to Part 1A and Part 1B on how to enable and configure the logging setup of the SACL and how to enable/ingest the above Windows Event IDs.
3 Blog Format
Due to the length of this post and the number of attributes covered, it is important to remember a couple of key formatting guidelines from Part 1 as we step through this post.
Each section will contain the following headings:
- Name of the Attribute (CN of the attribute)
- Background
- Will cover a brief overview of what the attribute (LDAP-Display-Name) is and the relevant links to Microsoft documentation
- Modifying the Attribute (Attack)
- Will cover how the “attack” was performed, including relevant setup for modifying the attribute in question, screenshots/commands, and tools used
- If additional auditing was enabled for building the detection, it will also likely be covered here-- or, if additional set up was more complex, will be broken out into a preceding or subsequent heading.
- Building the Detections
- Will cover a variety of detections that will include a range of complexity
- As was stated in the introduction, not all the possible telemetry data points within this data set have been analyzed. However, we have tried our best to cover the Event IDs that are most accessible and prominent for building out detections.
- Where necessary, we will provide a flow of logic for detections that involve more complexity or additional information to interpret what is being shown. However, most detections will follow a similar format, and will not be explained in further detail.
4 Write Attributes and PowerMad
The following sections all leverage the tool PowerMad, and more specifically will use the Set-MachineAccountAttribute cmdlet to modify AD a computer object within AD.
Per the ReadME.md file on the PowerMad GitHub, the Set-MachineAccountAttribute cmdlet allows us to modify the following attributes:
- AccountDisabled (ADS_UF_ACCOUNTDISABLE (0x00000002)
- Description
- Display-Name
- DNS-Host-Name
- SAM-Account-Name
- ServicePrincipalName (covered in Part 1A)
- User-Account-Control
- User-Parameters
However, although not specified in the documentation, PowerMad can modify most attributes for a Machine account.
As such, we will also be building detections for the following attributes:
- Alt-Security-Identities
- ms-DS-Additional-Dns-Host-Name
- ms-DS-Allowed-To-Delegate-To (covered in Part 1A)
- MSMQ-Sign-Certificates
- MSMQ-Digests
- MsTSInitalProgram (covered in Part 1A)
- ntSecurityDescriptor
- ScriptPath (covered in Part 1A)
4.1 SAM-Account-Name
4.1.1 Background
The SamAccountName is generated upon account creation, and should not be frequently changed within an AD domain. A change to SamAccountName could indicate that an attacker is present on the network and may be attempting to hide their presence or mimic another legitimate account.
The original SamAccountName for the IMPOSTER-GRANOLA$ Machine account:
Figure 1 - SamAccountName Before Modification
4.1.2 Modifying the Attribute (Attack)
The PowerMad command we will run for the modification looks like the following:
Set-MachineAccountAttribute -MachineName IMPOSTER-GRANOLA -Attribute SamAccountName -Value VERYEVILMACHINE
Note: The 'MachineName parameter didn’t work properly. If you receive an error, remove the '-MachineName IMPOSTER-GRANOLA' portion of the command and simply type in the account name at the prompt.
Figure 2 - PowerMad Modification SamAccountName
Using PowerShell to query the attributes of the IMPOSTER-GRANOLA$ machine account, we can see that the query will error out because it can no longer find a computer name with the specified SamAccountName. However, if we look within ADUC, we can see that the display name has stayed the same, but the SamAccountName has been successfully changed.
Figure 3 - SamAccountName Post Modification
Now that the modification/attack is completed, we should have the logs within Splunk.
4.1.3 Building the Detections
4.1.3.1 Detection With Event ID 5136
index=main EventCode=5136 Class=computer LDAP_Display_Name=sAMAccountName
| table time, EventCode, Class, DN, LogonID, Type, LDAP_Display_Name, Value
Figure 4 - Basic Detection for SamAccountName (1)
Figure 5 - Basic Detection for SamAccountName (2)
4.1.3.2 Detection with Event ID 4742
index=main AND EventCode=4742 SAM_Account_Name!="-"
| rex field=Message "(?<Changed_Account>(?ms)Account\s+Name.*?(Account\s+Name:\s+)(\w+….......))"
| table time, ChangedAccount, SAM_Account_Name, Logon_ID
Figure 6 - Basic Detection with Event ID 4742
4.1.3.3 Detection with Event IDs 4781 and 4624
Index=main ((EventCode=4781) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM"))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| eval Old_Account=if(EventCode==4781,mvindex(Old_Account_Name,-1),mvindex(Old_Account_Name,-1))
| eval New_Account=if(EventCode==4781,mvindex(New_Account_Name,-1),mvindex(New_Account_Name,-1))
| join type=outer Logon_ID
[ search (EventCode=4781) OR (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Old_Account_Name, New_Account_Name,Source_Network_Address]
| table time, ModAccount, Logon_ID, Old_Account, New_Account, Source_Network_Address
| where len(New_Account)>0 and len(Old_Account)>0
Figure 7 - Detection Using Event IDs 4781 and 4624
4.1.3.4 Detection With Event IDs 5136, 4624 and 4662
index=main ((EventCode=5136 AND LDAP_Display_Name=samAccountName) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM") OR (EventCode=4662 AND Access_Mask=0x20 ))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| eval Changed_Account=if(EventCode==5136,mvindex(Value,-1), mvindex(Value,-1))
| join type=outer Logon_ID
[ search (EventCode=5136) OR (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address ]
| join type=outer Logon_ID
[ search index=main Account_Name!=*$ EventCode=4662 Access_Mask = 0x20
| eval Props=Properties
| eval AccessMask=Access_Mask
| eval ObjectType=Object_Type
| eval ObjectName=Object_Name
| rex field=Message "(?<Object_Properties>(?ms)(?<=)Properties:(.*?)(?=Additional\s+))"
|table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName, Object_Properties]
| table time, ModAccount, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Changed_Account, AccessMask, Props, Object_Properties
| where len(Class)>0
| stats values by time, ChangedAccount
Figure 8 - Detection with Event IDs 5136, 4624 and 4662 (1)
Figure 9 - Detection with Event IDs 5136, 4624 and 4662 (2)
4.2 Description
4.2.1 Background
The description attribute contains a displayed description for an object that is set by AD administrators. Although less common in today’s more security conscious environment, attackers have sometimes been able to leverage passwords or other sensitive data that were either mistakenly or intentionally stored in the description field by administrators.
As a supplemental note, we understand that it is unlikely that attackers will modify the description attribute of computers or accounts. However, we believe that tracking this attribute may have benefits in environmental baselining, as well as ensuring the auditing and tracking of sensitive information potentially added to descriptions by Administrators.
4.2.2 Modifying the Attribute (Attack)
Like SamAccountName, changing the description utilizes the same PowerMad cmdlet. The only two (2) values that we are changing are the Attribute parameter and the Value.
Set-MachineAccountAttribute -MachineName IMPOSTER-GRANOLA -Attribute Description -Value "Breakfast Time!”
Figure 10 - Modifying the Description Object
Flipping back to ADUC we can quickly confirm that the changes were successfully made to the description field.
Figure 11 - Description Field Post Modification
4.2.3 Building the Detections
4.2.3.1 Detection with Event ID 5136
index=main EventCode=5136 Class=computer LDAP_Display_Name=description
| table time, EventCode, Class, DN, LogonID, Type, LDAP_Display_Name, Value
Figure 12 - Basic Query Using Event ID 5136
4.2.3.2 Detection with Event IDs 5136 and 4624
index=main EventCode=5136 Class=computer LDAP_Display_Name=description
| table time, EventCode, Class, DN, LogonID, Type, LDAP_Display_Name, Value
index=main ((EventCode=5136 AND LDAP_Display_Name=description) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM"))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| join type=outer Logon_ID
[ search (EventCode=5136) OR (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address]
| table time, EventCode, ModAccount, Source_Network_Address, Class, DN, Logon_ID, Type, LDAP_Display_Name, Value
| where len(Class)>0
Figure 13 - Complex Query Using Event IDs 5136 and 4624
Note: This can also be detected through Event ID 4742 as with the SamAccountName detections. However, because 'description' is not included in the list of attributes contained within the Event ID natively, the only way to identify the change is by correlating it with its respective logon ID and Event 5136.
4.2.3.3 Detection with Event IDs 5136, 4624 and 4662
index=main ((EventCode=5136 AND LDAP_Display_Name=description) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM") OR (EventCode=4662 AND Access_Mask=0x20))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| eval Changed_Account=if(EventCode==5136,mvindex(Value,-1), mvindex(Value,-1))
| join type=outer Logon_ID
[ search (EventCode=5136) OR (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address ]
| join type=outer Logon_ID
[ search index=main Account_Name!=*$ EventCode=4662 Access_Mask = 0x20
| eval Props=Properties
| eval AccessMask=Access_Mask
| eval ObjectType=Object_Type
| eval ObjectName=Object_Name
| rex field=Message "(?<Object_Properties>(?ms)(?<=)Properties:(.*?)(?=Additional\s+))"
|table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName, Object_Properties]
| table time, ModAccount, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Changed_Account, AccessMask, Props, Object_Properties
| where len(Class)>0
| stats values by time, ChangedAccount
Figure 14 - Detection with Event IDs 5136, 4662, 4624 (1)
Figure 15 - Detection with Event IDs 5136, 4662, 4624 (2)
4.3 Display-Name
The displayName attribute shows the display name of the object. Typically, this differs from the format of the username.
As with the description attribute, we recognize that this attribute may not necessarily be modified by an attacker during compromise. However, once again, we believe that tracking this attribute may have benefits in environmental baselining, as well as ensuring the auditing and tracking of sensitive information potentially added to descriptions by Administrators.
4.3.1 Modifying the Attribute (Attack)
Set-MachineAccountAttribute -MachineName IMPOSTER-GRANOLA -Attribute DisplayName -Value IMPOSTER-AIRFRYER
Figure 16 - Modifying the DisplayName Object
Figure 17 - DisplayName Attribute After Modification
4.3.2 Building The Detections
4.3.2.1 Detection with Event ID 5136
index=main EventCode=5136 Class=computer LDAP_Display_Name=DisplayName
| table time, EventCode, Class, DN, LogonID, Type, LDAP_Display_Name, Value
Figure 18 - Basic Detection with Event ID 5136
4.3.2.2 Detection with Event IDs 5136 and 4624
index=main ((EventCode=5136 AND LDAP_Display_Name=DisplayName) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM"))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| join type=outer Logon_ID
[ search (EventCode=5136) OR (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address]
| table time, EventCode, ModAccount, Source_Network_Address, Class, DN, Logon_ID, Type, LDAP_Display_Name, Value
| where len(Class)>0
Figure 19 - Detection with Event IDs 5136 and 4624
4.3.2.3 Detection with Event IDs 5136, 4624 and 4662
index=main ((EventCode=5136 AND LDAP_Display_Name=displayName) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM") OR (EventCode=4662 AND Access_Mask=0x20))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| eval Changed_Account=if(EventCode==5136,mvindex(Value,-1), mvindex(Value,-1))
| join type=outer Logon_ID
[ search (EventCode=5136) OR (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address ]
| join type=outer Logon_ID
[ search index=main Account_Name!=*$ EventCode=4662 Access_Mask = 0x20
| eval Props=Properties
| eval AccessMask=Access_Mask
| eval ObjectType=Object_Type
| eval ObjectName=Object_Name
| rex field=Message "(?<Object_Properties>(?ms)(?<=)Properties:(.*?)(?=Additional\s+))"
|table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName, Object_Properties]
| table time, ModAccount, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Changed_Account, AccessMask, Props, Object_Properties
| where len(Class)>0
| stats values by time, ChangedAccount
Figure 20 - Detection with Event IDs 5136, 4624 and 4662 (1)
Figure 21 - Detection with Event IDs 5136, 4624 and 4662 (2)
4.3.2.4 Detection with Event ID 4742
index=main AND EventCode=4742 Display_Name!="-" | rex field=Message "(?<Changed_Account>(?ms)Account\s+Name.*?(Account\s+Name:\s+)(\w+..........))"
| table time, ChangedAccount, Logon_ID, Display_Name
Figure 22 - Detection with Event ID 4742
4.4 User-Account-Control and AccountDisabled (ADS_UF_ACCOUNTDISABLE (0x00000002))
4.4.1 Background
The userAccountControl attribute stores the flags that control the behavior of the object.
These two (2) objects have been grouped together because the object changes we make to disable the computer account are stored within the userAccountControl attribute; thus, we are by proxy making a change to the userAccountControl attribute itself.
4.4.2 Modifying the Attributes (Attack)
Figure 23 - Disabling the Machine Account
Figure 24 - AccountDisabled Attribute After Modification
4.4.3 Building the Detections
4.4.3.1 Detection with Event ID 5136
index=main EventCode=5136 Class=computer
| table time, EventCode, Class, DN, LogonID, Type, LDAP_Display_Name, Value
Figure 25 - Basic Object Modification Detection Query
*Note: The previous and current queries are all looking for modifications to a computer object. If the account for which you are seeking to build a detection is a user object, make sure to modify the 'Class' parameter within the detections so it will pick up the changes made to user objects. This will apply to all detections built that specify a 'class'.
Reviewing the change in ADUC within the Attribute Editor mode, we can confirm that disabling the account was applied to the userAccessControl attribute.
Figure 26 - userAccountControl/AccountDisabled Post Modification
4.4.3.2 Detection with Event IDs 5136 and 4624
index=main ((EventCode=5136 AND LDAP_Display_Name=userAccountControl) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM"))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| join type=outer Logon_ID
[ search (EventCode=5136) OR (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address]
| table time, EventCode, ModAccount, Source_Network_Address, Class, DN, Logon_ID, Type, LDAP_Display_Name, Value
| where len(Class)>0
Figure 27 - Detection with Event IDs 4624 and 5136 (1)
Figure 28 - Detection with Event IDs 4624 and 5136 (2)
4.4.3.3 Detection with Event IDs 5136, 4624 and 4662
index=main ((EventCode=5136 AND LDAP_Display_Name=userAccountControl) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM") OR (EventCode=4662 AND Access_Mask=0x20))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| eval Changed_Account=if(EventCode==5136,mvindex(Value,-1), mvindex(Value,-1))
| join type=outer Logon_ID
[ search (EventCode=5136) OR (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address ]
| join type=outer Logon_ID
[ search index=main Account_Name!=*$ EventCode=4662 Access_Mask = 0x20
| eval Props=Properties
| eval AccessMask=Access_Mask
| eval ObjectType=Object_Type
| eval ObjectName=Object_Name
| rex field=Message "(?<Object_Properties>(?ms)(?<=)Properties:(.*?)(?=Additional\s+))"
|table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName, Object_Properties]
| table time, ModAccount, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Changed_Account, AccessMask, Props, Object_Properties
| where len(Class)>0
| stats values by time, ChangedAccount
Figure 29 - Detection with Event IDs 5136, 4662, 4624 (1)
Figure 30 - Detection with Event IDs 5136, 4662, 4624 (2)
4.4.3.4 Detection with Event IDs 4725, 4742, and 4624
index=main ((EventCode=4742) OR (EventCode=4725) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM"))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| eval Account_Status=if(EventCode==4725,mvindex(Message,-1), mvindex(Message,-1))
| eval Account_Info=if(EventCode==4742,mvindex(Message,-1), mvindex(Message,-1))
| rex field=Account_Status "(?<Status>(A user account was disabled.))"
| rex field=Account_Info "(?<Changed_Account>(?ms)..........................................................................Account\s+Name.*?(Account\s+Name:\s+)(\w+..........))"
| join type=outer Logon_ID
[ search (EventCode=4742)
| stats count by Logon_ID, Old_UAC_Value, New_UAC_Value
| table Account_Name,Logon_ID,Message, Old_UAC_Value, New_UAC_Value ]
| join type=outer Logon_ID
[ search (EventCode=4725)
| stats count by Logon_ID
| table Account_Name,Logon_ID, Message ]
| join type=outer Logon_ID
[ search (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address,]
| table time, ChangedAccount, Source_Network_Address, Logon_ID, Old_UAC_Value, New_UAC_Value, Status
| stats values by time, ChangedAccount,Source_Network_Address, Logon_ID, Status, Old_UAC_Value, New_UAC_Value
| table time, ChangedAccount, Source_Network_Address, Logon_ID, Old_UAC_Value, New_UAC_Value, Status
Figure 31 - Detection with Event IDs 4725, 4742 and 4624
4.4.4 Modifying the User-Account-Control Attribute
Now, using PowerMad again, let's make a change to the userAccountControl attribute directly.
Modifying the userAccountControl attribute requires a little work to understand how to modify it correctly. You must use the Microsoft defined 'property flag' value in hexadecimal to apply the change. If you attempt to modify via the property flag name, you will receive an error message.
Figure 32 - Failed userAccountControl Modification Example
Microsoft provides a list of most property flags and their hexadecimal values here.
For this experiment, we will make a change to PASSWD_NOTREQD, using hexadecimal flag 0x0020
to correctly apply the change to theuserAccountControl attribute.
Figure 33 - Modification to userAccountControl Attribute (Success)
Looking back at ADUC, we can see the userAccountControl value has been changed successfully.
Note: The change made to UAC also by default reenabled the account and applied the NORMAL_ACCOUNT UAC property flags to the Machine Account.
Figure 34 - userAccountControl Post Modification
4.4.5 Confirming the Detections
Back in Splunk, we can see that our previous query relying on 5136 still picks up this change without any additional modifications.
Figure 35 - userAccountControl Detection Post Modification Confirmation
4.4.5.1Detection with Event IDs 4738 and 4624
index=main AND Logon_ID=0xC19D5 EventCode=4738
| rex field=Message "(?<Account_Control>(?ms)\s+User\s+Account\s+Control.*?(\w+.....................................................................................................................))"
| rex field=Message "(?<Changed_Account>(?ms)..........................................................................Account\s+Name.*?(Account\s+Name:\s+)(\w+..........))"
| table time,LogonID,Old_UAC_Value, New_UAC_Value, Account_Control, Changed_Account
| join type=outer Logon_ID
[ search (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address,]
| table time, ChangedAccount, Source_Network_Address, Logon_ID, Old_UAC_Value, New_UAC_Value, Account_Control
Figure 36 - Detection with Event IDs 4738 and 4624
4.4.6 Understanding the 'Value' Field
There is another important call-out for this section that, at first glance, tends to make the detections that utilize Event ID 5136 less specific. To more plainly understand what changes are being made, we must identify and interpret the UAC property flags.
If we take another look back at our query that picks up our changes to the UAC attribute, we can see the 'Value' column:
Figure 37 - Value Field Call-Out
In this case, the 'Value' field directly pertains to the UAC property flag 'Value in Decimal'.
For example, if we look at the original UAC property, we can see that the 'Value" is equal to 4096, which maps to the first value deleted in our 'Value' column within our query.
Figure 38 - UAC 4096
Thus, we can read through the 'Value' field of this detection like so:
4.5 DNS-Host-Name
4.5.1 Background
The dNSHostName attribute stores the registered DNS name of a computer object.
4.5.2 Modifying the Attribute (Attack)
Set-MachineAccountAttribute -Attribute DnsHostName -Value IMPOSTER-DEVICE.IMPOSTERDOMAIN.LOCAL
Figure 39 - Modifying the DnsHostName Attribute
We can confirm the change was successfully made in AD by checking the Attribute Editor panel of ADUC.
Figure 40 - DnsHostName Post Modification
4.5.3 Building The Detections
4.5.3.1 Detection with Event IDs 5136 and 4624
index=main ((EventCode=5136 AND LDAP_Display_Name=dNSHostName) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM"))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| join type=outer Logon_ID
[ search (EventCode=5136) OR (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address]
| table time, EventCode, ModAccount, Source_Network_Address, Class, DN, Logon_ID, Type, LDAP_Display_Name, Value
| where len(Class)>0
Figure 41 - Detection with Event IDs 5136 and 4624 (1)
Figure 42 - Detection with Event IDs 5136 and 4624 (2)
4.5.3.2 Detection with Event IDs 5136, 4624, and 4662
index=main ((EventCode=5136 AND LDAP_Display_Name=dnsHostName) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM") OR (EventCode=4662 AND Access_Mask=0x20))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| eval Changed_Account=if(EventCode==5136,mvindex(Value,-1), mvindex(Value,-1))
| join type=outer Logon_ID
[ search (EventCode=5136) OR (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address ]
| join type=outer Logon_ID
[ search index=main Account_Name!=*$ EventCode=4662 Access_Mask = 0x20
| eval Props=Properties
| eval AccessMask=Access_Mask
| eval ObjectType=Object_Type
| eval ObjectName=Object_Name
| rex field=Message "(?<Object_Properties>(?ms)(?<=)Properties:(.*?)(?=Additional\s+))"
|table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName, Object_Properties]
| table time, ModAccount, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Changed_Account, AccessMask, Props, Object_Properties
| where len(Class)>0
| stats values by time, ChangedAccount
Figure 43 - Detection with Event IDs 5136, 4662, and 4624 (1)
Figure 44 - Detection with Event IDs 5136, 4662, and 4624 (2)
4.5.3.3 Detection with Event ID 4742
index=main EventCode=4742 DNS_Host_Name!="-"
| rex field=Message "(?<Account>(?ms)..........................................................................Account\s+Name.*?(Account\s+Name:\s+)(\w+..........))"
| table time, Account, LogonID, DNS_Host_Name
Figure 45 - Detection With Event ID 4742
4.6 ms-DS-Additional-Dns-Host-Name
4.6.1 Background
The msDS-AddtionalDnsHostName attribute stores an additional DNS host name of a computer object, if present. This attribute should only be legitimately updated when a computer object is renamed.
4.6.2 Modifying the Attribute (Attack)
Set-MachineAccountAttribute -Attribute msDS-AdditionalDnsHostName -Value IMPOSTER-MICROWAVE.IMPOSTERDOMAIN.LOCAL
Figure 46 - Modifying the msDS-AdditionalDnsHostName Attribute
We can confirm the modification was appropriately applied by viewing the Attribute Editor for the object within ADUC.
Figure 47 - msDS-AdditionalDnsHostName Post Modification
4.6.3 Building the Detections
4.6.3.1 Detection with Event IDs 5136 and 4624
index=main ((EventCode=5136 AND LDAP_Display_Name=msDS-AdditionalDnsHostName) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM"))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| join type=outer Logon_ID
[ search (EventCode=5136) OR (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address]
| table time, EventCode, ModAccount, Source_Network_Address, Class, DN, Logon_ID, Type, LDAP_Display_Name, Value
| where len(Class)>0
Figure 48 - Detection with Event IDs 5136 and 4624 (1)
Figure 49 - Detection with Event IDs 5136 and 4624 (2)
4.6.3.2 Detection with Event IDs 5136, 4624 and 4662
index=main ((EventCode=5136 AND LDAP_Display_Name=msDS-AdditionalDnsHostName) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM") OR (EventCode=4662 AND Access_Mask=0x20))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| eval Changed_Account=if(EventCode==5136,mvindex(Value,-1), mvindex(Value,-1))
| join type=outer Logon_ID
[ search (EventCode=5136) OR (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address ]
| join type=outer Logon_ID
[ search index=main Account_Name!=*$ EventCode=4662 Access_Mask = 0x20
| eval Props=Properties
| eval AccessMask=Access_Mask
| eval ObjectType=Object_Type
| eval ObjectName=Object_Name
| rex field=Message "(?<Object_Properties>(?ms)(?<=)Properties:(.*?)(?=Additional\s+))"
|table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName, Object_Properties]
| table time, ModAccount, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Changed_Account, AccessMask, Props, Object_Properties
| where len(Class)>0
| stats values by time, ChangedAccount
Figure 50 - Detection with Event IDs 5136, 4662, and 4624 (1)
Figure 51 - Detection with Event IDs 5136, 4662, and 4624 (2)
4.7 User-Parameters
4.7.1 Background
The userParameters attribute stores a Unicode string that is utilized by applications to retrieve user session configuration data.
4.7.2 Modifying the Attribute (Attack)
Set-MachineAccountAttribute -Attribute userParameters -Value ‘Some Application String Here’
Figure 52 - Modifying the userParameters Attribute
Figure 53 - userParameters Post Modification
4.7.3 Building the Detections
4.7.3.1 Detection with Event IDs 5136 and 4624
index=main ((EventCode=5136 AND LDAP_Display_Name=userParameters) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM"))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| join type=outer Logon_ID
[ search (EventCode=5136) OR (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address]
| table time, EventCode, ModAccount, Source_Network_Address, Class, DN, Logon_ID, Type, LDAP_Display_Name, Value
| where len(Class)>0
Figure 54 - Detection with Event IDs 5136 and 4624 (1)
Figure 55 - Detection with Event IDs 5136 and 4624 (2)
4.7.3.2 Detection with Event IDs 5136, 4624 and 4662
index=main ((EventCode=5136 AND LDAP_Display_Name=userParameters) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM") OR (EventCode=4662 AND Access_Mask=0x20))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| eval Changed_Value=if(EventCode==5136,mvindex(Value,-1), mvindex(Value,-1))
| join type=outer Logon_ID
[ search (EventCode=5136) OR (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address ]
| join type=outer Logon_ID
[ search index=main Account_Name!=*$ EventCode=4662 Access_Mask = 0x20
| eval Props=Properties
| eval AccessMask=Access_Mask
| eval ObjectType=Object_Type
| eval ObjectName=Object_Name
| rex field=Message "(?<Object_Properties>(?ms)(?<=)Properties:(.*?)(?=Additional\s+))"
|table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName, Object_Properties]
| table time, ModAccount, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Changed_Value, AccessMask, Props, Object_Properties
| where len(Class)>0
| stats values by time, ChangedValue
Figure 56 - Detection with Event IDs 5136, 4662, 4624 (1)
Figure 57 - Detection with Event IDs 5136, 4662, 4624 (2)
4.7.3.3 Detection with Event ID 4742
This can also be detected with Event ID 4742, but in this case, it’s rather unhelpful, given that it tracks an object that has been changed, but the change to userParameters is not displayed.
index=main EventCode=4742 User_Parameters!="-"
| rex field=Message "(?<Account>(?ms)..........................................................................Account\s+Name.*?(Account\s+Name:\s+)(\w+..........))"
| table time, Account, LogonID, User_Parameters
Figure 58 - Detection with Event ID 4742
4.8 Alt-Security-Identities
4.8.1 Background
The altSecurityIdentities attribute stores mappings for X.509 certificates/external Kerberos user accounts to an object, allowing an alternate means of authentication.
4.8.2 Modifying the Attribute (Attack)
Set-MachineAccountAttribute -Attribute altSecurityIdentities -Value ‘{X509:<I> DC=LOCAL, DC=BREAKFASTLAND, CN=BREAKFASTLAND-CA-01<S>DC-LOCAL, DC=BREAKFASTLAND, CN=Users, CN=dacled.egg}”
Note: the above command is not a functional attack within the lab environment. A change was made in this case to specifically trigger a modification to the attribute, and like most sections within this blog series, our focus is on building detections for the attribute modifications and not on the attacks themselves.
Figure 59 - Modifying the altSecurityIdentities Object
Figure 60 - Object Post Modification
4.8.3 Building the Detections
4.8.3.1 Detection with Event IDs 5136 and 4624
index=main ((EventCode=5136 AND LDAP_Display_Name=altSecurityIdentities) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM"))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| join type=outer Logon_ID
[ search (EventCode=5136) OR (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address ]
| table time, EventCode, ModAccount, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Value
| where len(Class)>0
Figure 61 - Detection with Event IDs 5136 and 4624 (1)
Figure 62 - Detection with Event IDs 5136 and 4624 (2)
4.8.3.2 Detection with Event IDs 5136, 4624, and 4662
index=main ((EventCode=5136 AND LDAP_Display_Name=altSecurityIdentities) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM") OR (EventCode=4662 AND Access_Mask=0x20))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| eval Changed_Value=if(EventCode==5136,mvindex(Value,-1), mvindex(Value,-1))
| join type=outer Logon_ID
[ search (EventCode=5136) OR (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address ]
| join type=outer Logon_ID
[ search index=main Account_Name!=*$ EventCode=4662 Access_Mask = 0x20
| eval Props=Properties
| eval AccessMask=Access_Mask
| eval ObjectType=Object_Type
| eval ObjectName=Object_Name
| rex field=Message "(?<Object_Properties>(?ms)(?<=)Properties:(.*?)(?=Additional\s+))"
|table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName, Object_Properties]
| table _time, Mod_Account, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Changed_Value, AccessMask, Props, Object_Properties
| where len(Class)>0
| stats values by _time, Changed_Value, Logon_ID
Figure 63 - Detection with Event IDs 5136, 4662, and 4624 (1)
Figure 64 - Detection with Event IDs 5136, 4662, and 4624 (2)
4.9 MSMQ-Sign-Certificates
4.9.1 Background
mSMQSignCertificates is a blob type attribute that stores certificate values.
4.9.2 Modifying the Attribute (Attack)
For this attribute, it is important to note that we will be 'attacking' the objects attribute two (2) different ways. The first method will leverage PowerMad to modify the object to the Boolean value of True. The second method will leverage a proof-of-concept script written by Will Schroeder (@harmj0y) in this blog.
As before, we will modify the mSMQSignCertificates attribute with the following PowerMad command:
Set-MachineAccountAttribute -Attribute mSMQSignCertificates -Value $true
Figure 65 - Modifying the mSMQSignCertificates Object
Figure 66 - mSMQSignCertificates Post Modification
4.9.3 Building the Detections
4.9.3.1 Detection with Event IDs 5136 and 4624
index=main ((EventCode=5136 AND LDAP_Display_Name=mSMQSignCertificates) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM"))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| join type=outer Logon_ID
[ search (EventCode=5136) OR (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address ]
| table _time, EventCode, Mod_Account, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Value
| where len(Class)>0
Figure 67 - Detection with Event IDs 5136 and 4624 (1)
Figure 68 - Detection with Event IDs 5136 and 4624 (2)
4.9.3.2 Detection with Event IDs 5136, 4624, and 4662
index=main ((EventCode=5136 AND LDAP_Display_Name=mSMQSignCertificates) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM") OR (EventCode=4662 AND Access_Mask=0x20))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| eval Changed_Value=if(EventCode==5136,mvindex(Value,-1), mvindex(Value,-1))
| join type=outer Logon_ID
[ search (EventCode=5136) OR (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address ]
| join type=outer Logon_ID
[ search index=main Account_Name!=*$ EventCode=4662 Access_Mask = 0x20
| eval Props=Properties
| eval AccessMask=Access_Mask
| eval ObjectType=Object_Type
| eval ObjectName=Object_Name
| rex field=Message "(?<Object_Properties>(?ms)(?<=)Properties:(.*?)(?=Additional\s+))"
|table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName, Object_Properties]
| table _time, Mod_Account, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Changed_Value, AccessMask, Props, Object_Properties
| where len(Class)>0
| stats values by _time, Changed_Value, Logon_ID
Figure 69 - Detection with Event IDs 5136, 4662, and 4624 (1)
Figure 70 - Detection with Event IDs 5136, 4662, and 4624 (2)
4.9.4 Utilizing POC Script for Object Modification
As stated earlier, we can also utilize HarmJ0y’s POC script to modify this attribute, and the previously built detection will pick it up.
Figure 71 - POC Script Attribute Modification
4.10 MSMQ-Digests
4.10.1 Background
The mSQMDigests attribute stores an array of corresponding 16-byte hexadecimal digest strings of an MD5 hash of the certificate stored within the mSMQSignCertificates attribute.
4.10.2 Modifying the Attribute (Attack)
Likely due to the reliance on mSMQSignCertificates, we were unable modify this attribute successfully with PowerMad.
Figure 72 - Failed PowerMad Modification
However, we were able to modify the mSMQDigests attribute through ADUC with a 16 byte value pulled from the hexadecimal string to trigger the change to the attribute.
Figure 73 - Modifying mSMQDigests Through ADUC
4.10.3 Building the Detections
4.10.3.1 Detection with Event IDs 5136 and 4624
index=main ((EventCode=5136 AND LDAP_Display_Name=mSMQDigests) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM"))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| join type=outer Logon_ID
[ search (EventCode=5136) OR (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address ]
| table _time, EventCode, Mod_Account, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Value
| where len(Class)>0
Figure 74 - Detection with Event IDs 5136 and 4624 (1)
Figure 75 - Detection with Event IDs 5136 and 4624 (2)
4.10.3.2 Detection with Event IDs 5136, 4624 and 4662
index=main ((EventCode=5136 AND LDAP_Display_Name=mSMQDigests) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM") OR (EventCode=4662 AND Access_Mask=0x20))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| eval Changed_Value=if(EventCode==5136,mvindex(Value,-1), mvindex(Value,-1))
| join type=outer Logon_ID
[ search (EventCode=5136) OR (EventCode=4624)
| stats count by Logon_ID, Account_Name, Source_Network_Address
| table Account_Name,Logon_ID, Source_Network_Address ]
| join type=outer Logon_ID
[ search index=main Account_Name!=*$ EventCode=4662 Access_Mask = 0x20
| eval Props=Properties
| eval AccessMask=Access_Mask
| eval ObjectType=Object_Type
| eval ObjectName=Object_Name
| rex field=Message "(?<Object_Properties>(?ms)(?<=)Properties:(.*?)(?=Additional\s+))"
|table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName, Object_Properties]
| table _time, Mod_Account, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Changed_Value, AccessMask, Props, Object_Properties
| where len(Class)>0
| stats values by _time, Changed_Value, Logon_ID
Figure 76 - Detection with Event ID 5136, 4662, and 4624 (1)
Figure 77 - Detection with Event ID 5136, 4662, and 4624 (2)
5 Conclusion
As you may have noticed, many of the queries use the same 'template query', where the only value changed in the query is the attribute that we have modified. This template query can be used to track changes for most AD attributes. Feel free to experiment with it, perhaps by adding multiple attributes to a single detection (e.g., track samAccountName, description, and displayName all in the same query) or by changing the joins/table columns to customize the table view to what’s going to be most valuable for your environment and detection needs.
Also, note that this post is mainly dealing with modifications to objects of a computer, and we didn’t do much in terms of modifying user objects. That said, in most cases, as long as Class is not specified as computer, detections built using Event ID 5136 will still pick up on changes to user objects. However, in cases where we used Event ID 4742, ensure you switch the Event ID in question to 4738 (a user object was modified).
This blog would not have been possible without help from the following people:
Charlie Bromberg (@_nwodtuhs)
Jonathan Johnson (@jsecurity101)
Jim Sykora (@jimsycurity)
Kevin Clark (@GuhnooPlusLinux)
And finally, stayed tuned for our third and final part of this blog series.
Thanks for reading!
6 References
https://www.thehacker.recipes/ad/movement/dacl
PowerMad References:
https://github.com/Kevin-Robertson/Powermad
Windows Events:
https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4662
https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4624
https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-5145
https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4742
https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4738
Sam-Account-Name:
https://learn.microsoft.com/en-us/windows/win32/adschema/a-samaccountname
Description:
https://learn.microsoft.com/en-us/windows/win32/adschema/a-description
Display-Name:
https://learn.microsoft.com/en-us/windows/win32/adschema/a-displayname
User-Account-Control/AccountDisbled:
https://learn.microsoft.com/en-us/windows/win32/adschema/a-useraccountcontrol
DNS-Host-Name:
https://learn.microsoft.com/en-us/windows/win32/adschema/a-dnshostname
Ms-DS-Additional-Dns-Host-Name:
https://learn.microsoft.com/en-us/windows/win32/adschema/a-msds-additionaldnshostname
User-Parameters:
https://learn.microsoft.com/en-us/windows/win32/adschema/a-userparameters
Alt-Security-Identities:
https://learn.microsoft.com/en-us/windows/win32/adschema/a-altsecurityidentities
https://specterops.io/wp-content/uploads/sites/3/2022/06/an_ace_up_the_sleeve.pdf
https://labs.withsecure.com/tools/sharpgpoabuse
https://eladshamir.com/2023/01/25/RODCs.html
https://www.rapid7.com/blog/post/2023/06/02/metasploit-weekly-wrap-up-12/
MSMQ-Sign-Certificates:
https://learn.microsoft.com/en-us/windows/win32/adschema/a-msmqsigncertificates
https://blog.harmj0y.net/powershell/command-and-control-using-active-directory/
https://gist.github.com/HarmJ0y/a219057e9d2faedf69d32e04c0f1874f
MSMQ-Digests:
https://learn.microsoft.com/en-us/windows/win32/adschema/a-msmqdigests