Skip to Main Content
October 12, 2023

A Hitch-hacker's Guide to DACL-Based Detections (Part 2)

Written by Megan Nilsen and Andrew Schwartz
Active Directory Security Review Purple Team Adversarial Detection & Countermeasures Research Security Testing & Analysis Threat Hunting

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:

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: 

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:

Image001

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.

Image002

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.

Image003

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
Image004 1

Figure 4 - Basic Detection for SamAccountName (1)

Image005 2

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
Image006

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
Image007

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
Image008 1

Figure 8 - Detection with Event IDs 5136, 4624 and 4662 (1)

Image009 2

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!”
Image010

Figure 10 - Modifying the Description Object

Flipping back to ADUC we can quickly confirm that the changes were successfully made to the description field.

Image011

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
Image012

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
Image013

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
Image014 1

Figure 14 - Detection with Event IDs 5136, 4662, 4624 (1)

Image015 2

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
Image016

Figure 16 - Modifying the DisplayName Object

Image017

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
Image018

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
Image019

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
Image020 1

Figure 20 - Detection with Event IDs 5136, 4624 and 4662 (1)

Image021 2

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
Image022

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)

Image023

Figure 23 - Disabling the Machine Account

Image024

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
Image025

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.

Image026

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
Image027 1

Figure 27 - Detection with Event IDs 4624 and 5136 (1)

Image028 2

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
Image029 1

Figure 29 - Detection with Event IDs 5136, 4662, 4624 (1)

Image030 2

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
Image031

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.

Image032

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.

Image033

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.

Image034

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.

Image035

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
Image036

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:

Image037

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.

Image038

Figure 38 - UAC 4096

Thus, we can read through the 'Value' field of this detection like so:

Screenshot 2023 10 10 at 12 17 11 PM

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
Image039

Figure 39 - Modifying the DnsHostName Attribute

We can confirm the change was successfully made in AD by checking the Attribute Editor panel of ADUC.

 

Image040

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
Image041 1

Figure 41 - Detection with Event IDs 5136 and 4624 (1)

Image042 2

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
Image043 1

Figure 43 - Detection with Event IDs 5136, 4662, and 4624 (1)

Image044 2

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
Image045

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
Image046

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.

Image047

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
Image048 1

Figure 48 - Detection with Event IDs 5136 and 4624 (1)

Image049 2

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
Image050 1

Figure 50 - Detection with Event IDs 5136, 4662, and 4624 (1)

Image051 2

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’
Image052

Figure 52 - Modifying the userParameters Attribute

Image053

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
Image054 1

Figure 54 - Detection with Event IDs 5136 and 4624 (1)

Image055 2

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
Image056 1

Figure 56 - Detection with Event IDs 5136, 4662, 4624 (1)

Image057 2

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
Image058

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.

Image059

Figure 59 - Modifying the altSecurityIdentities Object

Image060

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
Image061 1

Figure 61 - Detection with Event IDs 5136 and 4624 (1)

Image062 2

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
Image063 1

Figure 63 - Detection with Event IDs 5136, 4662, and 4624 (1)

Image064 2

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
Image065

Figure 65 - Modifying the mSMQSignCertificates Object

Image066

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
Image067 1

Figure 67 - Detection with Event IDs 5136 and 4624 (1)

Image068 2

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
Image069 1

Figure 69 - Detection with Event IDs 5136, 4662, and 4624 (1)

Image070 2

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.

Image071

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.

Image072

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.

Image073

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
Image074 1

Figure 74 - Detection with Event IDs 5136 and 4624 (1)

Image075 2

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
Image076 1

Figure 76 - Detection with Event ID 5136, 4662, and 4624 (1)

Image077 2

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

https://stackoverflow.com/questions/39226518/filtering-only-second-account-name-in-windows-event-log-using-a-regex

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

https://learn.microsoft.com/en-us/troubleshoot/windows-server/identity/useraccountcontrol-manipulate-account-properties

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

https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-ada3/8710a141-a607-4b14-9d7c-f6370bff9b96

Alt-Security-Identities:

https://learn.microsoft.com/en-us/windows/win32/adschema/a-altsecurityidentities

https://www.riskinsight-wavestone.com/en/2021/06/microsoft-adcs-abusing-pki-in-active-directory-environment/#section-3-4

https://specterops.io/wp-content/uploads/sites/3/2022/06/an_ace_up_the_sleeve.pdf

https://wald0.com/?p=179

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