daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

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)