writable-sys-path-dll-hijacking-privesc.md (8762B)
1 --- 2 title: "Writable Sys Path +Dll Hijacking Privesc" 3 section: "Windows" 4 sectionSlug: "windows-hardening" 5 sourcePath: "src/windows-hardening/windows-local-privilege-escalation/dll-hijacking/writable-sys-path-dll-hijacking-privesc.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/windows-hardening/windows-local-privilege-escalation/dll-hijacking/writable-sys-path-dll-hijacking-privesc.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # Writable Sys Path +Dll Hijacking Privesc 14 15 ## Introduction 16 17 If you can **write to a directory in the system-wide `PATH`** (not merely your user `PATH`), you may be able to **escalate privileges** on the system. 18 19 This can be abused through **DLL hijacking** when a more-privileged service or process tries to load a DLL that does not exist in its earlier search locations and eventually searches the writable system `PATH` directory. 20 21 For more information about **DLL hijacking**, see: 22 23 24 [.](/hacktricks/windows-hardening/windows-local-privilege-escalation/dll-hijacking/overview) 25 26 ## Privesc with Dll Hijacking 27 28 ### Finding a Missing DLL 29 30 First, **identify a process** running with **more privileges** that tries to **load a DLL from a writable system `PATH` directory**. 31 32 Remember that this technique depends on a **Machine/System PATH** entry, not only on your **User PATH**. Therefore, before spending time on Procmon, it's worth enumerating the **Machine PATH** entries and checking which ones are writable:<sup>[[1]](#references)</sup> 33 34 ```powershell 35 $machinePath = [Environment]::GetEnvironmentVariable("Path", "Machine") -split ';' | Where-Object { $_ } 36 $machinePath | ForEach-Object { 37 $path = $_.Trim() 38 if ($path) { 39 Write-Host "`n[*] $path" 40 icacls $path 2>$null 41 } 42 } 43 ``` 44 45 The problem in these cases is that those processes are probably already running. To identify DLLs that services try and fail to load, launch Procmon as early as possible (before the processes start), then: 46 47 - **Create** the folder `C:\privesc_hijacking` and add the path `C:\privesc_hijacking` to **System Path env variable**. You can do this **manually** or with **PS**: 48 49 ```bash 50 # Set the folder path to create and check events for 51 $folderPath = "C:\privesc_hijacking" 52 53 # Create the folder if it does not exist 54 if (!(Test-Path $folderPath -PathType Container)) { 55 New-Item -ItemType Directory -Path $folderPath | Out-Null 56 } 57 58 # Set the folder path in the System environment variable PATH 59 $envPath = [Environment]::GetEnvironmentVariable("PATH", "Machine") 60 if ($envPath -notlike "*$folderPath*") { 61 $newPath = "$envPath;$folderPath" 62 [Environment]::SetEnvironmentVariable("PATH", $newPath, "Machine") 63 } 64 ``` 65 66 - Launch **`procmon`** and go to **`Options`** --> **`Enable boot logging`** and press **`OK`** in the prompt. 67 - Then, **reboot**. When the computer is restarted **`procmon`** will start **recording** events asap. 68 - Once **Windows** is **started execute `procmon`** again, it'll tell you that it has been running and will **ask you if you want to store** the events in a file. Say **yes** and **store the events in a file**. 69 - **After** the **file** is **generated**, **close** the opened **`procmon`** window and **open the events file**. 70 - Add these **filters** to find all DLLs that a **process tried to load** from the writable System Path folder: 71 72 <figure><img src="https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28945%29.png" alt=""><figcaption></figcaption></figure> 73 74 > [!TIP] 75 > **Boot logging is only required for services that start too early** to observe otherwise. If you can **trigger the target service/program on demand** (for example, by interacting with its COM interface, restarting the service, or relaunching a scheduled task), it is usually faster to keep a normal Procmon capture with filters such as **`Path contains .dll`**, **`Result is NAME NOT FOUND`**, and **`Path begins with <writable_machine_path>`**. 76 77 ### Missed Dlls 78 79 Running this in a free **virtual (vmware) Windows 11 machine** I got these results: 80 81 <figure><img src="https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28607%29.png" alt=""><figcaption></figcaption></figure> 82 83 In this case, ignore the `.exe` results. The missing-DLL probes came from: 84 85 | Service | Dll | CMD line | 86 | ------------------------------- | ------------------ | -------------------------------------------------------------------- | 87 | Task Scheduler (Schedule) | WptsExtensions.dll | `C:\Windows\system32\svchost.exe -k netsvcs -p -s Schedule` | 88 | Diagnostic Policy Service (DPS) | Unknown.DLL | `C:\Windows\System32\svchost.exe -k LocalServiceNoNetwork -p -s DPS` | 89 | ??? | SharedRes.dll | `C:\Windows\system32\svchost.exe -k UnistackSvcGroup` | 90 91 The following example uses the technique described in this article about [**abusing `WptsExtensions.dll` for privilege escalation**](https://juggernaut-sec.com/dll-hijacking/#Windows_10_Phantom_DLL_Hijacking_-_WptsExtensionsdll).<sup>[[3]](#references)</sup> 92 93 ### Other candidates worth triaging 94 95 `WptsExtensions.dll` is a good example, but it is not the only recurring **phantom DLL** that shows up in privileged services. Modern hunting rules and public hijack catalogs still track names such as:<sup>[[2]](#references)</sup> 96 97 | Service / Scenario | Missing DLL | Notes | 98 | --- | --- | --- | 99 | Task Scheduler (`Schedule`) | `WptsExtensions.dll` | Classic **SYSTEM** candidate on client systems. Good when the writable directory is in the **Machine PATH** and the service probes the DLL during startup. | 100 | NetMan on Windows Server | `wlanhlp.dll` / `wlanapi.dll` | Interesting on **server editions** because the service runs as **SYSTEM** and can be **triggered on demand by a normal user** in some builds, making it better than reboot-only cases. | 101 | Connected Devices Platform Service (`CDPSvc`) | `cdpsgshims.dll` | Usually yields **`NT AUTHORITY\LOCAL SERVICE`** first. That is often still enough because the token has **`SeImpersonatePrivilege`**, so you can chain it with [RoguePotato / PrintSpoofer](/hacktricks/windows-hardening/windows-local-privilege-escalation/roguepotato-and-printspoofer). | 102 103 Treat these names as **triage hints**, not guaranteed wins: they are **SKU/build dependent**, and Microsoft may change the behavior between releases. The important takeaway is to look for **missing DLLs in privileged services that traverse the Machine PATH**, especially if the service can be **re-triggered without rebooting**. 104 105 ### Exploitation 106 107 To **escalate privileges**, hijack **`WptsExtensions.dll`**. Once the **path** and **name** are known, generate the malicious DLL. 108 109 You can [**try to use any of these examples**](#creating-and-compiling-dlls). You could run payloads such as: get a rev shell, add a user, execute a beacon... 110 111 > [!WARNING] 112 > Note that **not all services run** as **`NT AUTHORITY\SYSTEM`**. Some run as **`NT AUTHORITY\LOCAL SERVICE`**, which has **fewer privileges**, so abusing one of these services may not let you create a new user.\ 113 > However, that account has the **`SeImpersonatePrivilege`** user right, so you can use the [**Potato suite to escalate privileges**](/hacktricks/windows-hardening/windows-local-privilege-escalation/roguepotato-and-printspoofer). In this case, a reverse shell is a better option than trying to create a user. 114 115 At the moment of writing the **Task Scheduler** service is run with **Nt AUTHORITY\SYSTEM**. 116 117 Having **generated the malicious Dll** (_in my case I used x64 rev shell and I got a shell back but defender killed it because it was from msfvenom_), save it in the writable System Path with the name **WptsExtensions.dll** and **restart** the computer (or restart the service or do whatever it takes to rerun the affected service/program). 118 119 When the service is re-started, the **dll should be loaded and executed** (you can **reuse** the **procmon** trick to check if the **library was loaded as expected**). 120 121 ## References 122 123 - [1] [Windows DLL Hijacking (Hopefully) Clarified](https://itm4n.github.io/windows-dll-hijacking-clarified/) 124 - [2] [Suspicious DLL Loaded for Persistence or Privilege Escalation](https://www.elastic.co/guide/en/security/current/suspicious-dll-loaded-for-persistence-or-privilege-escalation.html) 125 - [3] [DLL Hijacking – Windows Privilege Escalation](https://juggernaut-sec.com/dll-hijacking/#Windows_10_Phantom_DLL_Hijacking_-_WptsExtensionsdll)